On Thu, 9 Aug 2001, Stas Bekman wrote:
> On Thu, 9 Aug 2001, Gary Benson wrote:
>
> > On Thu, 9 Aug 2001, Stas Bekman wrote:
> >
> > > Some methods of extreme programming suggest writing tests even before
> > > the code have been written
> >
> > I tried this once, for the lexical parser in a desktop calculator program
> > I wrote. It is a really liberating experience, and leads to greater
> > experimentation.
>
> the only problem is that usually to write some more advanced tests, you
> actually need to have some working code, since you have to debug the test
> itself.
>
> So I think that if you have this approach you write only the descriptions
> of the tests. Is that how you've done this?
The testing engine was fairly simple: it created an instance of the lexer
class, ran the test input through it and printed out a representation of
the list of tokens that the parser returned.
The tests were much more simple to construct that those in perl-framework,
but mine were unit tests rather than functional tests. The distinction is
important -- anyone who doesn't know the difference should skim through
http://c2.com/cgi/wiki?UnitTests and http://c2.com/cgi/wiki?FunctionalTests
I've attached the array of tests that I used, so that you can get an
idea of what I mean (but feel free to ignore it =))
What generally happens is that the tests evolve with the code. I wrote a
very basic lexer and wrote some tests for it. I added some more tokens to
the lexer, I added tests for those tokens.
The beauty of it all was that a few days later I realised that I had a
problem with the lexer -- the state machine that drove it couldn't cope
with something I wanted to do. After changing the state machine, the
original stuff was processed in a totally different way but the end result
should have been the same. The tester was a phenomenal help during the
changeover.
Once all the tests worked, I _knew_ that:
1. What I wanted the lexer to do was completely covered by the tests
2. The tests worked
and therefore:
3. The lexer did exactly what I wanted it to do.
What I was testing was a very small piece of code, so it was simple for me
to acheive this kind of certainty. To do the same for Apache will not be
a trivial task. It will be better if we can reach the stage where people
write tests for the modules as they write the modules, but we have some
catching up to do first.
Gary
[ Gary Benson, Red Hat Europe ][ [EMAIL PROTECTED] ][ GnuPG 60E8793A ]
my @tests=
(
### Very basic tests =========================================================
###
"", "0 items\n",
" \f\n\r\t\xb", "0 items\n",
";;;", "RCalcSeparator\n" x 3,
"hello world", "RCalcString: `hello'\nRCalcString: `world'\n",
###
#### Test the various commands ###############################################
###
# Command tests are grouped into groups with similar usage; for
# example rm, lock and unlock all have identical command line
# formats, so a test performed on one should be performed on all
# three.
### EXIT and QUIT tests ======================================================
###
# Check they are recognised.
#
"exit", "RCalcCommand: $commands{'RC_COMMAND_EXIT'}\n",
"quit", "RCalcCommand: $commands{'RC_COMMAND_EXIT'}\n",
"\texit\n ", "RCalcCommand: $commands{'RC_COMMAND_EXIT'}\n",
"\tquit\n ", "RCalcCommand: $commands{'RC_COMMAND_EXIT'}\n",
# Check that they bin out if followed by anything.
#
"exit;", $errors{'EXIT_USAGE'},
"quit;", $errors{'QUIT_USAGE'},
"\texit\n ;", $errors{'EXIT_USAGE'},
"\tquit\n ;", $errors{'QUIT_USAGE'},
"exit ; exit", $errors{'EXIT_USAGE'},
"quit ; quit", $errors{'QUIT_USAGE'},
"exit exit", $errors{'EXIT_USAGE'},
"quit quit", $errors{'QUIT_USAGE'},
### MAN, HELP and ? tests ====================================================
###
# Check they are recognised. Man will bomb out since its argument is mandatory.
#
"help", "RCalcCommand: $commands{'RC_COMMAND_HELP'}\n",
"?", "RCalcCommand: $commands{'RC_COMMAND_HELP'}\n",
"man", $errors{'MAN_USAGE'},
# Check that the topics are recognised.
#
"help topic",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
"? topic",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
"man topic",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
# Check that space works.
#
"help topic\t",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
"? topic \n",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
" man topic",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
",
# Check that multiple topics get reprimanded.
#
"help topic topic", $errors{'HELP_USAGE'},
"? topic topic", $errors{'QMARK_USAGE'},
"man topic topic", $errors{'MAN_USAGE'},
# Check that semicolons work.
#
"help topic; exit",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_EXIT'}
",
"? topic; exit",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_EXIT'}
",
"man topic; exit",
"RCalcCommand: $commands{'RC_COMMAND_HELP'}
RCalcString: `topic'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_EXIT'}
",
### LS tests =================================================================
###
# Check that it and its arguments are recognised.
#
"ls",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
",
"ls variables",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSymbol: $symbols{'RC_SYMBOL_VARIABLES'}
",
"ls functions variables commands constants",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSymbol: $symbols{'RC_SYMBOL_FUNCTIONS'}
RCalcSymbol: $symbols{'RC_SYMBOL_VARIABLES'}
RCalcSymbol: $symbols{'RC_SYMBOL_COMMANDS'}
RCalcSymbol: $symbols{'RC_SYMBOL_CONSTANTS'}
",
# Check that semicolons and space are recognised
#
"ls;",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSeparator
",
"\tls \n;\n",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSeparator
",
"ls variables;",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSymbol: $symbols{'RC_SYMBOL_VARIABLES'}
RCalcSeparator
",
"ls functions variables commands constants;",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSymbol: $symbols{'RC_SYMBOL_FUNCTIONS'}
RCalcSymbol: $symbols{'RC_SYMBOL_VARIABLES'}
RCalcSymbol: $symbols{'RC_SYMBOL_COMMANDS'}
RCalcSymbol: $symbols{'RC_SYMBOL_CONSTANTS'}
RCalcSeparator
",
# Check that semicolons reset the parser.
#
"ls functions variables commands ;constants",
"RCalcCommand: $commands{'RC_COMMAND_LS'}
RCalcSymbol: $symbols{'RC_SYMBOL_FUNCTIONS'}
RCalcSymbol: $symbols{'RC_SYMBOL_VARIABLES'}
RCalcSymbol: $symbols{'RC_SYMBOL_COMMANDS'}
RCalcSeparator
RCalcString: `constants'
",
# Check that the usage message is working *and* immediatly aborts.
#
"ls varyables", $errors{'LS_USAGE'},
"ls ; ls varyables", $errors{'LS_USAGE'},
"ls functions varyables commands constants", $errors{'LS_USAGE'},
"ls functions varyables commands constants;", $errors{'LS_USAGE'},
"ls functions varyables commands ; constants", $errors{'LS_USAGE'},
### RM, LOCK and UNLOCK tests ================================================
###
# Check that it is recognised and that it's no-args usage message works.
#
"rm", $errors{'RM_USAGE'},
"rm;", $errors{'RM_USAGE'},
"rm ;", $errors{'RM_USAGE'},
"rm ", $errors{'RM_USAGE'},
"lock", $errors{'LOCK_USAGE'},
"lock;", $errors{'LOCK_USAGE'},
"lock ;", $errors{'LOCK_USAGE'},
"lock ", $errors{'LOCK_USAGE'},
"unlock", $errors{'UNLOCK_USAGE'},
"unlock;", $errors{'UNLOCK_USAGE'},
"unlock ;", $errors{'UNLOCK_USAGE'},
"unlock ", $errors{'UNLOCK_USAGE'},
# Check that varying numbers of arguments are recognised and whitespace works.
#
"rm arg1",
"RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg1'
",
"lock arg1",
"RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg1'
",
"unlock arg1",
"RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg1'
",
"rm arg1 ",
"RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg1'
",
"lock arg1 ",
"RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg1'
",
"unlock arg1 ",
"RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg1'
",
"rm arg1 arg2",
"RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg1'
RCalcString: `arg2'
",
"lock arg1 arg2",
"RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
",
"unlock arg1 arg2",
"RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
",
"rm arg1 arg2 rm",
"RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcString: `rm'
",
"lock arg1 arg2 rm",
"RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcString: `rm'
",
"unlock arg1 arg2 rm",
"RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcString: `rm'
",
# Check that semicolons work.
#
"rm arg1 arg2 ;\trm arg3",
"RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_RM'}
RCalcString: `arg3'
",
"lock arg1 arg2 ;\tlock arg3",
"RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_LOCK'}
RCalcString: `arg3'
",
"unlock arg1 arg2 ;\tunlock arg3",
"RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg1'
RCalcString: `arg2'
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_UNLOCK'}
RCalcString: `arg3'
",
# Check that the usage message aborts properly.
#
"rm arg1 ; rm", $errors{'RM_USAGE'},
"rm arg1 @ ; rm o", $errors{'RM_USAGE'},
"lock arg1 ; lock", $errors{'LOCK_USAGE'},
"lock arg1 @ ; lock o", $errors{'LOCK_USAGE'},
"unlock arg1 ; unlock", $errors{'UNLOCK_USAGE'},
"unlock arg1 @ ; unlock o", $errors{'UNLOCK_USAGE'},
### MODE tests ===============================================================
###
# Check that it and its arguments are recognised.
#
"mode",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
",
"mode deg",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_DEG'}
",
"mode rad",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_RAD'}
",
# Check that semicolons and whitespace are recognised
#
"mode ;",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSeparator
",
"mode deg; ",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_DEG'}
RCalcSeparator
",
"mode\trad ;",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_RAD'}
RCalcSeparator
",
# Check that semicolons reset the parser.
#
"mode; hello",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSeparator
RCalcString: `hello'
",
"mode deg; hello",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_DEG'}
RCalcSeparator
RCalcString: `hello'
",
"mode rad; hello",
"RCalcCommand: $commands{'RC_COMMAND_MODE'}
RCalcSymbol: $symbols{'RC_SYMBOL_RAD'}
RCalcSeparator
RCalcString: `hello'
",
# Check that the usage message is working *and* immediatly aborts.
#
"mode edg", $errors{'MODE_USAGE'},
"mode deg; mode edg", $errors{'MODE_USAGE'},
"mode deg rad", $errors{'MODE_USAGE'},
"mode; mode edg", $errors{'MODE_USAGE'},
### DEG and RAD tests ========================================================
###
# Check they are recognised.
#
"deg", "RCalcCommand: $commands{'RC_COMMAND_DEG'}\n",
"rad", "RCalcCommand: $commands{'RC_COMMAND_RAD'}\n",
# Check that whitespace and semicolons work
#
"\tdeg\n ;",
"RCalcCommand: $commands{'RC_COMMAND_DEG'}
RCalcSeparator
",
"\trad\n ;",
"RCalcCommand: $commands{'RC_COMMAND_RAD'}
RCalcSeparator
",
"deg ; deg",
"RCalcCommand: $commands{'RC_COMMAND_DEG'}
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_DEG'}
",
"rad ; rad",
"RCalcCommand: $commands{'RC_COMMAND_RAD'}
RCalcSeparator
RCalcCommand: $commands{'RC_COMMAND_RAD'}
",
# Check that the usage message is working *and* immediatly aborts.
#
"deg deg", $errors{'DEG_USAGE'},
"rad rad", $errors{'RAD_USAGE'},
"deg deg ; ls", $errors{'DEG_USAGE'},
"rad rad ; ls", $errors{'RAD_USAGE'},
###
#### Test expressions ########################################################
###
# Check that unexpected characters are spotted
"\$", "Parse error at `\$'.\n",
"pies+mash # yum", "Parse error at `#'.\n",
# Check that assignments work
"=", "Parse error at `='.\n",
"=Ta", "Parse error at `='.\n",
"Tb=Ta", "RCalcAssign: `Tb'\nRCalcString: `Ta'\n",
" Tb = Ta ", "RCalcAssign: `Tb'\nRCalcString: `Ta'\n",
"Tb=", "Line ended while expecting expression.\n",
"Ta=Tb=1", "Parse error at `='.\n",
"Ta+Tb=1", "Parse error at `='.\n",
# Check that all symbols (static strings) are working.
"+", "RCalcSymbol: $symbols{'RC_SYMBOL_PLUS'}\n",
"-", "RCalcSymbol: $symbols{'RC_META_SYMBOL_MINUS'}\n",
"*", "RCalcSymbol: $symbols{'RC_SYMBOL_MULTIPLY'}\n",
"/", "RCalcSymbol: $symbols{'RC_SYMBOL_DIVIDE'}\n",
"%", "RCalcSymbol: $symbols{'RC_SYMBOL_MODDIVIDE'}\n",
"**", "RCalcSymbol: $symbols{'RC_SYMBOL_POWER'}\n",
"||", "RCalcSymbol: $symbols{'RC_SYMBOL_PARALLEL'}\n",
"!", "RCalcSymbol: $symbols{'RC_SYMBOL_FACTORIAL'}\n",
"npr", "RCalcSymbol: $symbols{'RC_SYMBOL_NPR'}\n",
"ncr", "RCalcSymbol: $symbols{'RC_SYMBOL_NCR'}\n",
"&", "RCalcSymbol: $symbols{'RC_SYMBOL_AND'}\n",
"|", "RCalcSymbol: $symbols{'RC_SYMBOL_OR'}\n",
"~", "RCalcSymbol: $symbols{'RC_SYMBOL_NOT'}\n",
"<<", "RCalcSymbol: $symbols{'RC_SYMBOL_SHL'}\n",
">>", "RCalcSymbol: $symbols{'RC_SYMBOL_SHR'}\n",
"and", "RCalcSymbol: $symbols{'RC_SYMBOL_AND'}\n",
"or", "RCalcSymbol: $symbols{'RC_SYMBOL_OR'}\n",
"xor", "RCalcSymbol: $symbols{'RC_SYMBOL_XOR'}\n",
"not", "RCalcSymbol: $symbols{'RC_SYMBOL_NOT'}\n",
"shl", "RCalcSymbol: $symbols{'RC_SYMBOL_SHL'}\n",
"shr", "RCalcSymbol: $symbols{'RC_SYMBOL_SHR'}\n",
"(", "RCalcSymbol: $symbols{'RC_SYMBOL_PAREN_L'}\n",
")", "RCalcSymbol: $symbols{'RC_SYMBOL_PAREN_R'}\n",
"int", "RCalcSymbol: $symbols{'RC_SYMBOL_ROUND'}\n",
"round", "RCalcSymbol: $symbols{'RC_SYMBOL_ROUND'}\n",
"floor", "RCalcSymbol: $symbols{'RC_SYMBOL_FLOOR'}\n",
"ceil", "RCalcSymbol: $symbols{'RC_SYMBOL_CEIL'}\n",
"re", "RCalcSymbol: $symbols{'RC_SYMBOL_RE'}\n",
"im", "RCalcSymbol: $symbols{'RC_SYMBOL_IM'}\n",
"mod", "RCalcSymbol: $symbols{'RC_SYMBOL_MOD'}\n",
"arg", "RCalcSymbol: $symbols{'RC_SYMBOL_ARG'}\n",
"abs", "RCalcSymbol: $symbols{'RC_SYMBOL_ABS'}\n",
"ln", "RCalcSymbol: $symbols{'RC_SYMBOL_LN'}\n",
"log10", "RCalcSymbol: $symbols{'RC_SYMBOL_LOG'}\n",
"sqrt", "RCalcSymbol: $symbols{'RC_SYMBOL_SQRT'}\n",
"exp", "RCalcSymbol: $symbols{'RC_SYMBOL_EXP'}\n",
"sin", "RCalcSymbol: $symbols{'RC_SYMBOL_SIN'}\n",
"cos", "RCalcSymbol: $symbols{'RC_SYMBOL_COS'}\n",
"tan", "RCalcSymbol: $symbols{'RC_SYMBOL_TAN'}\n",
"asin", "RCalcSymbol: $symbols{'RC_SYMBOL_ASIN'}\n",
"acos", "RCalcSymbol: $symbols{'RC_SYMBOL_ACOS'}\n",
"atan", "RCalcSymbol: $symbols{'RC_SYMBOL_ATAN'}\n",
"sinh", "RCalcSymbol: $symbols{'RC_SYMBOL_SINH'}\n",
"cosh", "RCalcSymbol: $symbols{'RC_SYMBOL_COSH'}\n",
"tanh", "RCalcSymbol: $symbols{'RC_SYMBOL_TANH'}\n",
"asinh", "RCalcSymbol: $symbols{'RC_SYMBOL_ASINH'}\n",
"acosh", "RCalcSymbol: $symbols{'RC_SYMBOL_ACOSH'}\n",
"atanh", "RCalcSymbol: $symbols{'RC_SYMBOL_ATANH'}\n",
"char", "RCalcSymbol: $symbols{'RC_SYMBOL_CHAR'}\n",
"^", "RCalcSymbol: $symbols{'RC_META_SYMBOL_HAT'}\n",
"log", "RCalcSymbol: $symbols{'RC_META_SYMBOL_LOG'}\n",
# Check that (text) symbols are swallowed as strings when
# concatenated, and not swallowed when separated by space.
"tana", "RCalcString: `tana'\n",
"asina", "RCalcString: `asina'\n",
"aatan", "RCalcString: `aatan'\n",
"aasin", "RCalcString: `aasin'\n",
"tan h", "RCalcSymbol: $symbols{'RC_SYMBOL_TAN'}\nRCalcString: `h'\n",
"asin h", "RCalcSymbol: $symbols{'RC_SYMBOL_ASIN'}\nRCalcString: `h'\n",
# Check the straight octal and decimal numbers are recognised and
# discriminated.
"03345", "RCalcNumber: t8 r1765 i0\n",
"12345", "RCalcNumber: t10 r12345 i0\n",
"0334589", "RCalcNumber: t8 r1765 i0\nRCalcNumber: t10 r89 i0\n",
"033a45", "RCalcNumber: t8 r27 i0\nRCalcString: `a45'\n",
"123a45", "RCalcNumber: t10 r123 i0\nRCalcString: `a45'\n",
# Check that overflow error works on integers.
"4294967295", "RCalcNumber: t10 r4294967295 i0\n",
"4294967296", "Overflow at `4294967296'.\n",
# Check that real and imaginary numbers are recognised.
"1", "RCalcNumber: t10 r1 i0\n",
"1.0", "RCalcNumber: t0 r1 i0\n",
"1.", "Parse error at `.'.\n",
".1", "RCalcNumber: t0 r0.1 i0\n",
".1e3", "RCalcNumber: t0 r100 i0\n",
"1.0e3", "RCalcNumber: t0 r1000 i0\n",
"1.0e+3", "RCalcNumber: t0 r1000 i0\n",
"1.0e-3", "RCalcNumber: t0 r0.001 i0\n",
"1e3", "RCalcNumber: t0 r1000 i0\n",
"1e+3", "RCalcNumber: t0 r1000 i0\n",
"1e-3", "RCalcNumber: t0 r0.001 i0\n",
"j1", "RCalcNumber: t0 r0 i1\n",
"i1.0", "RCalcNumber: t0 r0 i1\n",
"i1.", "Parse error at `.'.\n",
"J.1", "RCalcNumber: t0 r0 i0.1\n",
"i.1e3", "RCalcNumber: t0 r0 i100\n",
"I1.0e3", "RCalcNumber: t0 r0 i1000\n",
"J1.0e+3", "RCalcNumber: t0 r0 i1000\n",
"j1.0e-3", "RCalcNumber: t0 r0 i0.001\n",
"i1e3", "RCalcNumber: t0 r0 i1000\n",
"I1e+3", "RCalcNumber: t0 r0 i1000\n",
"J1e-3", "RCalcNumber: t0 r0 i0.001\n",
"15", "RCalcNumber: t10 r15 i0\n",
"15.0", "RCalcNumber: t0 r15 i0\n",
"15.0e3", "RCalcNumber: t0 r15000 i0\n",
"15.0e+3", "RCalcNumber: t0 r15000 i0\n",
"15.0e-3", "RCalcNumber: t0 r0.015 i0\n",
"15e3", "RCalcNumber: t0 r15000 i0\n",
"15e+3", "RCalcNumber: t0 r15000 i0\n",
"15e-3", "RCalcNumber: t0 r0.015 i0\n",
"j15", "RCalcNumber: t0 r0 i15\n",
"i15.0", "RCalcNumber: t0 r0 i15\n",
"I15.0e3", "RCalcNumber: t0 r0 i15000\n",
"J15.0e+3", "RCalcNumber: t0 r0 i15000\n",
"j15.0e-3", "RCalcNumber: t0 r0 i0.015\n",
"i15e3", "RCalcNumber: t0 r0 i15000\n",
"I15e+3", "RCalcNumber: t0 r0 i15000\n",
"J15e-3", "RCalcNumber: t0 r0 i0.015\n",
"4,0", "RCalcNumber: t0 r4 i0\n",
"j4,0", "RCalcNumber: t0 r0 i4\n",
# Check that under/overflow errors work on real/imaginary numbers.
"1e400", "Overflow at `1e400'.\n",
"1e-400", "Underflow at `1e-400'.\n",
"j1e400", "Overflow at `1e400'.\n",
"i1e-400", "Underflow at `1e-400'.\n",
# Check that the various prefixed forms of numbers are recognised and
# discriminated.
"0xFEDC1234", "RCalcNumber: t16 r4275835444 i0\n",
"0hFEDC1234", "RCalcNumber: t16 r4275835444 i0\n",
"0d98765432", "RCalcNumber: t10 r98765432 i0\n",
"0o76543210", "RCalcNumber: t8 r16434824 i0\n",
"0b11111111", "RCalcNumber: t2 r255 i0\n",
"0xFEDG1234", "RCalcNumber: t16 r4077 i0\nRCalcString: `G1234'\n",
"0hFEDG1234", "RCalcNumber: t16 r4077 i0\nRCalcString: `G1234'\n",
"0d987A5432", "RCalcNumber: t10 r987 i0\nRCalcString: `A5432'\n",
"0o76583210", "RCalcNumber: t8 r501 i0\nRCalcNumber: t10 r83210 i0\n",
"0b11121111", "RCalcNumber: t2 r7 i0\nRCalcNumber: t10 r21111 i0\n",
"0xGEDC1234", "Found `G' while expecting hexadecimal number.\n",
"0hGEDC1234", "Found `G' while expecting hexadecimal number.\n",
"0dA8765432", "Found `A' while expecting decimal number.\n",
"0o86543210", "Found `8' while expecting octal number.\n",
"0b21111111", "Found `2' while expecting binary number.\n",
"0x", "Line ended while expecting hexadecimal number.\n",
"0h", "Line ended while expecting hexadecimal number.\n",
"0d", "Line ended while expecting decimal number.\n",
"0o", "Line ended while expecting octal number.\n",
"0b", "Line ended while expecting binary number.\n",
# Check that base specifiers work
"[EMAIL PROTECTED]", "RCalcBaser: 16\n",
"[EMAIL PROTECTED]", "RCalcBaser: 16\n",
"[EMAIL PROTECTED]", "RCalcBaser: 10\n",
"[EMAIL PROTECTED]", "RCalcBaser: 8\n",
"[EMAIL PROTECTED]", "RCalcBaser: 2\n",
"[EMAIL PROTECTED]", "RCalcBaser: 9\n",
"[EMAIL PROTECTED]", "RCalcBaser: 10\n",
"[EMAIL PROTECTED]", "RCalcBaser: 11\n",
" \@ b ", "RCalcBaser: 2\n",
" \@ 9 ", "RCalcBaser: 9\n",
" \@ b ;", "RCalcBaser: 2\nRCalcSeparator\n",
" \@ 9 ;", "RCalcBaser: 9\nRCalcSeparator\n",
" \@ b x", "Found `x' while expecting `;' or end of line.\n",
" \@ 9 x", "Found `x' while expecting `;' or end of line.\n",
" \@ ", "Line ended while expecting base.\n",
"\@", "Line ended while expecting base.\n",
"\@;", "Found `;' while expecting base.\n",
"[EMAIL PROTECTED]", "Found `c' while expecting base.\n",
"[EMAIL PROTECTED]", "Invalid base `1' - must be between 2-36.\n",
"[EMAIL PROTECTED]", "RCalcBaser: 2\n",
"[EMAIL PROTECTED]", "RCalcBaser: 36\n",
"[EMAIL PROTECTED]", "Invalid base `37' - must be between 2-36.\n",
# Check that based numbers work
"[EMAIL PROTECTED]", "RCalcNumber: t8 r1765 i0\n",
"[EMAIL PROTECTED]", "RCalcNumber: t8 r1765 i0\n",
"[EMAIL PROTECTED]", "RCalcNumber: t16 r4275835444 i0\n",
"[EMAIL PROTECTED]", "RCalcNumber: t16 r4275835444 i0\n",
"[EMAIL PROTECTED]", "RCalcNumber: t11 r1687 i0\n",
"[EMAIL PROTECTED]", "RCalcNumber: t36 r49612 i0\n",
"[ 12A4 \@ 36 ]", "RCalcNumber: t36 r49612 i0\n",
"[EMAIL PROTECTED]", "Invalid base `37' - must be between 2-36.\n",
"[EMAIL PROTECTED]", "Invalid digit `A' in base 10 number.\n",
"[EMAIL PROTECTED]", "Found `\@' while expecting number.\n",
"[", "Line ended while expecting number.\n",
"[ [EMAIL PROTECTED]", "Found `\@' while expecting number.\n",
"[ ", "Line ended while expecting number.\n",
"[12A4 11]", "Found `1' while expecting base specifier.\n",
"[12A411]", "Found `]' while expecting base specifier.\n",
"[12A4", "Line ended while expecting base specifier.\n",
"[EMAIL PROTECTED]", "Found `]' while expecting base.\n",
"[12A4\@", "Line ended while expecting base.\n",
"[12A4 ", "Line ended while expecting base specifier.\n",
"[12A4\@ ] ", "Found `]' while expecting base.\n",
"[12A4\@ ", "Line ended while expecting base.\n",
"[EMAIL PROTECTED]", "Line ended while expecting `]'.\n",
"[EMAIL PROTECTED]", "Found `x' while expecting `]'.\n",
# Check that character constants work.
"'a'", "RCalcNumber: t1 r97 i0\n",
"'A'", "RCalcNumber: t1 r65 i0\n",
"'\"'", "RCalcNumber: t1 r34 i0\n",
"' '", "RCalcNumber: t1 r32 i0\n",
"'\t'", "RCalcNumber: t1 r9 i0\n",
"'a '", "Found ` ' while expecting `''.\n",
"'A '", "Found ` ' while expecting `''.\n",
"'\" '", "Found ` ' while expecting `''.\n",
"' '", "Found ` ' while expecting `''.\n",
"'\t '", "Found ` ' while expecting `''.\n",
"' a'", "Found `a' while expecting `''.\n",
"' A'", "Found `A' while expecting `''.\n",
"' \"'", "Found `\"' while expecting `''.\n",
"''", "Found `'' while expecting character.\n",
"'''", "Found `'' while expecting character.\n",
"';'", "RCalcNumber: t1 r59 i0\n",
"';", "Line ended while expecting `''.\n",
"' ;", "Found `;' while expecting `''.\n",
"'", "Line ended while expecting character.\n",
"'\\a'", "RCalcNumber: t1 r7 i0\n",
"'\\b'", "RCalcNumber: t1 r8 i0\n",
"'\\f'", "RCalcNumber: t1 r12 i0\n",
"'\\n'", "RCalcNumber: t1 r10 i0\n",
"'\\r'", "RCalcNumber: t1 r13 i0\n",
"'\\t'", "RCalcNumber: t1 r9 i0\n",
"'\\v'", "RCalcNumber: t1 r11 i0\n",
"'\\\\'", "RCalcNumber: t1 r92 i0\n",
"'\\?'", "RCalcNumber: t1 r63 i0\n",
"'\\''", "RCalcNumber: t1 r39 i0\n",
"'\\\"'", "RCalcNumber: t1 r34 i0\n",
"'\\0'", "RCalcNumber: t1 r0 i0\n",
"'\\033'", "RCalcNumber: t1 r27 i0\n",
"'\\33'", "RCalcNumber: t1 r27 i0\n",
"'\\x0'", "RCalcNumber: t1 r0 i0\n",
"'\\x1'", "RCalcNumber: t1 r1 i0\n",
"'\\x1B'", "RCalcNumber: t1 r27 i0\n",
"'\\g'", "Parse error at `\\g'.\n",
"'\\0g'", "Found `g' while expecting `''.\n",
"'\\xg'", "Parse error at `\\xg'.\n",
);