The compiler chain is tested with a large number of tests at five
distinct points in the chain:
ScriptLexer-test.cpp tests the lexer by supplying text input and
comparing the resulting stream of tokens.
ScriptParser-text.cpp tests the parser by supplying text input that
is lexed and parsed, and then comparing the resulting abstract
syntax tree. (The tree is converted to a string first, and then
compared.)
method-test.cpp tests the MethodBuilder inteface by issuing calls
and then comparing the byte code output to expected byte codes.
vm-test.cpp test the implementation of the byte codes by directly
building test methods with MethodBuilder and then comparing the
effects of the execution. Some methods are also built with the full
compiler and tested.
compiler-test.cpp tests the compiler by supplying text input that is
lexed, parsed and compiled, and then compares the generated
bytecodes.
This style of testing thoroughly tests the chain, tends to pinpoint
problems well, and effectively controls the otherwise exponential
set of tests a compiler usually needs.
However, the test have some problems. In particular, because
compiler-test.cpp tests for generated code sequences,
implementing any optimizations in the compiler invalidates the
tests. Even a slight change in the register allocator breaks all the
tests. Further, since the expected values are effectively hand-
compiled, there isn't as good of a check on the results as one
would like.
method-test.cpp suffers from similar problems, especially the
register allocation sensitivity.
I'm not sure what can be done about this. The tests could
compare against some more abstract byte code representation
that was register number immune, and tracked values, but this
strikes me as a lot of work, with only some benefit.
Logged In: YES
user_id=219202
compiler-test.cpp has been changed: It now compiles and runs the
methods and tests for the effects of running them. It no longer checks
that the generated code matches some sequence of instructions.