]> git.mdlowis.com Git - archive/dlang.git/commitdiff
Commit initial version (0.1a)
authorMike D. Lowis <mike@mdlowis.com>
Sun, 12 Feb 2012 17:49:55 +0000 (12:49 -0500)
committerMike D. Lowis <mike@mdlowis.com>
Sun, 12 Feb 2012 17:49:55 +0000 (12:49 -0500)
457 files changed:
Doxyfile [new file with mode: 0644]
LICENSE.md [new file with mode: 0644]
README.md [new file with mode: 0644]
build/DUMMY [new file with mode: 0644]
deps/DUMMY [new file with mode: 0644]
docs/DUMMY [new file with mode: 0644]
example.dl [new file with mode: 0644]
rakefile.rb [new file with mode: 0644]
res/DUMMY [new file with mode: 0644]
res/environment.scm [new file with mode: 0644]
source/dllexer/dllexer.cpp [new file with mode: 0644]
source/dllexer/dllexer.h [new file with mode: 0644]
source/dlparser/dlparser.cpp [new file with mode: 0644]
source/dlparser/dlparser.h [new file with mode: 0644]
source/dlparser/macro/macro.c [new file with mode: 0644]
source/dlparser/macro/macro.h [new file with mode: 0644]
source/dlparser/macro/param.c [new file with mode: 0644]
source/dlparser/macro/param.h [new file with mode: 0644]
source/main.cpp [new file with mode: 0644]
source/parse_utils/ast/ast.cpp [new file with mode: 0644]
source/parse_utils/ast/ast.h [new file with mode: 0644]
source/parse_utils/exception/exception.cpp [new file with mode: 0644]
source/parse_utils/exception/exception.h [new file with mode: 0644]
source/parse_utils/lexer/lexer.cpp [new file with mode: 0644]
source/parse_utils/lexer/lexer.h [new file with mode: 0644]
source/parse_utils/lexer/token/token.cpp [new file with mode: 0644]
source/parse_utils/lexer/token/token.h [new file with mode: 0644]
source/parse_utils/parser/btparser/btparser.cpp [new file with mode: 0644]
source/parse_utils/parser/btparser/btparser.h [new file with mode: 0644]
source/parse_utils/parser/llkparser/llkparser.cpp [new file with mode: 0644]
source/parse_utils/parser/llkparser/llkparser.h [new file with mode: 0644]
source/parse_utils/parser/parser.cpp [new file with mode: 0644]
source/parse_utils/parser/parser.h [new file with mode: 0644]
source/parse_utils/visitor/visitor.cpp [new file with mode: 0644]
source/parse_utils/visitor/visitor.h [new file with mode: 0644]
source/visitors/macroapplication/macroapplication.cpp [new file with mode: 0644]
source/visitors/macroapplication/macroapplication.h [new file with mode: 0644]
source/visitors/scheme/scheme.cpp [new file with mode: 0644]
source/visitors/scheme/scheme.h [new file with mode: 0644]
source/visitors/sexp/sexp.cpp [new file with mode: 0644]
source/visitors/sexp/sexp.h [new file with mode: 0644]
tests/source/main.h [new file with mode: 0644]
tests/system/system_tests.dl [new file with mode: 0644]
tools/cxxtest/COPYING [new file with mode: 0644]
tools/cxxtest/README [new file with mode: 0644]
tools/cxxtest/Versions [new file with mode: 0644]
tools/cxxtest/admin/cxxtest.spec [new file with mode: 0644]
tools/cxxtest/admin/jenkins_cxxtest [new file with mode: 0644]
tools/cxxtest/admin/release [new file with mode: 0644]
tools/cxxtest/admin/virtualenv.py [new file with mode: 0644]
tools/cxxtest/bin/cxxtestgen [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/AUTHORS [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/cxxtest.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/default_env/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/default_env/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/default_env/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/eprouvette.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/expanding_#/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/expanding_#/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/need_cpppath/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/printer_propagation/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/README [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/string_cpppath/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/target_syntax/SConstruct [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/target_syntax/TestDef.py [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h [new file with mode: 0644]
tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Descriptions.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/Descriptions.h [new file with mode: 0644]
tools/cxxtest/cxxtest/DummyDescriptions.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/DummyDescriptions.h [new file with mode: 0644]
tools/cxxtest/cxxtest/ErrorFormatter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/ErrorPrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Flags.h [new file with mode: 0644]
tools/cxxtest/cxxtest/GlobalFixture.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/GlobalFixture.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Gui.h [new file with mode: 0644]
tools/cxxtest/cxxtest/LinkedList.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/LinkedList.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Mock.h [new file with mode: 0644]
tools/cxxtest/cxxtest/ParenPrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/QtGui.h [new file with mode: 0644]
tools/cxxtest/cxxtest/RealDescriptions.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/RealDescriptions.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Root.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/SelfTest.h [new file with mode: 0644]
tools/cxxtest/cxxtest/StdHeaders.h [new file with mode: 0644]
tools/cxxtest/cxxtest/StdTestSuite.h [new file with mode: 0644]
tools/cxxtest/cxxtest/StdValueTraits.h [new file with mode: 0644]
tools/cxxtest/cxxtest/StdioFilePrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/StdioPrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TeeListener.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TestListener.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TestMain.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TestRunner.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TestSuite.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/TestSuite.h [new file with mode: 0644]
tools/cxxtest/cxxtest/TestTracker.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/TestTracker.h [new file with mode: 0644]
tools/cxxtest/cxxtest/ValueTraits.cpp [new file with mode: 0644]
tools/cxxtest/cxxtest/ValueTraits.h [new file with mode: 0644]
tools/cxxtest/cxxtest/Win32Gui.h [new file with mode: 0644]
tools/cxxtest/cxxtest/X11Gui.h [new file with mode: 0644]
tools/cxxtest/cxxtest/XUnitPrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/XmlFormatter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/XmlPrinter.h [new file with mode: 0644]
tools/cxxtest/cxxtest/YesNoRunner.h [new file with mode: 0644]
tools/cxxtest/doc/Makefile [new file with mode: 0644]
tools/cxxtest/doc/README.txt [new file with mode: 0644]
tools/cxxtest/doc/catalog.xml [new file with mode: 0644]
tools/cxxtest/doc/epub/README [new file with mode: 0644]
tools/cxxtest/doc/epub/bin/dbtoepub [new file with mode: 0644]
tools/cxxtest/doc/epub/bin/lib/docbook.rb [new file with mode: 0644]
tools/cxxtest/doc/epub/bin/xslt/obfuscate.xsl [new file with mode: 0644]
tools/cxxtest/doc/epub/docbook.xsl [new file with mode: 0644]
tools/cxxtest/doc/examples/Assertions.h [new file with mode: 0644]
tools/cxxtest/doc/examples/BadTestSuite1.h [new file with mode: 0644]
tools/cxxtest/doc/examples/GetGlobals.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/MockTestSuite.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyClass.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite1.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite10.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite11.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite2.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite3.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite4.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite5.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite6.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite7.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite8.h [new file with mode: 0644]
tools/cxxtest/doc/examples/MyTestSuite9.h [new file with mode: 0644]
tools/cxxtest/doc/examples/TMyClass.h [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner10.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner10.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner11.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner11.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner12.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner12.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner13.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner14.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner14.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner15.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner15.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner16.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner16.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner17.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner17.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner18.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner18.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner19.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner19.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner2.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner2.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner20.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner20.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner21.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner21.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner3.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner3.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner4.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner4.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner5.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner5.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner6.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner6.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner7.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner7.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner8.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/buildRunner9.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/cxxtestgen.out [new file with mode: 0644]
tools/cxxtest/doc/examples/exeRunner.out [new file with mode: 0644]
tools/cxxtest/doc/examples/exeRunner.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/exeRunner2.out [new file with mode: 0644]
tools/cxxtest/doc/examples/exeRunner2.sh [new file with mode: 0644]
tools/cxxtest/doc/examples/rand_example.cpp [new file with mode: 0644]
tools/cxxtest/doc/examples/runner10.tpl [new file with mode: 0644]
tools/cxxtest/doc/examples/runner13.MyTestSuite2.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/runner13.help.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/runner13.helpTests.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/runner13.testMultiplication.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt [new file with mode: 0644]
tools/cxxtest/doc/examples/test_examples.py [new file with mode: 0644]
tools/cxxtest/doc/examples/time_mock.cpp [new file with mode: 0644]
tools/cxxtest/doc/examples/time_mock.h [new file with mode: 0644]
tools/cxxtest/doc/examples/time_real.cpp [new file with mode: 0644]
tools/cxxtest/doc/guide.epub [new file with mode: 0644]
tools/cxxtest/doc/guide.html [new file with mode: 0644]
tools/cxxtest/doc/guide.pdf [new file with mode: 0644]
tools/cxxtest/doc/guide.txt [new file with mode: 0644]
tools/cxxtest/doc/include_anchors.py [new file with mode: 0644]
tools/cxxtest/python/README.txt [new file with mode: 0644]
tools/cxxtest/python/convert.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/__init__.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/__init__.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/__release__.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/__release__.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxx_parser.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxx_parser.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_fog.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_fog.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_misc.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_misc.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_parser.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtest_parser.pyc [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtestgen.py [new file with mode: 0644]
tools/cxxtest/python/cxxtest/cxxtestgen.pyc [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/__init__.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/__release__.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/cxx_parser.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/cxxtest_fog.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/cxxtest_misc.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/cxxtest_parser.py [new file with mode: 0644]
tools/cxxtest/python/python3/cxxtest/cxxtestgen.py [new file with mode: 0644]
tools/cxxtest/python/python3/scripts/cxxtestgen [new file with mode: 0644]
tools/cxxtest/python/scripts/cxxtestgen [new file with mode: 0644]
tools/cxxtest/python/setup.py [new file with mode: 0644]
tools/cxxtest/sample/.cvsignore [new file with mode: 0644]
tools/cxxtest/sample/Construct [new file with mode: 0644]
tools/cxxtest/sample/CreatedTest.h [new file with mode: 0644]
tools/cxxtest/sample/DeltaTest.h [new file with mode: 0644]
tools/cxxtest/sample/EnumTraits.h [new file with mode: 0644]
tools/cxxtest/sample/ExceptionTest.h [new file with mode: 0644]
tools/cxxtest/sample/FixtureTest.h [new file with mode: 0644]
tools/cxxtest/sample/Makefile.PL [new file with mode: 0644]
tools/cxxtest/sample/Makefile.bcc32 [new file with mode: 0644]
tools/cxxtest/sample/Makefile.msvc [new file with mode: 0644]
tools/cxxtest/sample/Makefile.unix [new file with mode: 0644]
tools/cxxtest/sample/MessageTest.h [new file with mode: 0644]
tools/cxxtest/sample/SCons/SConstruct [new file with mode: 0644]
tools/cxxtest/sample/SCons/include/stack.h [new file with mode: 0644]
tools/cxxtest/sample/SCons/src/stack.c [new file with mode: 0644]
tools/cxxtest/sample/SCons/tests/stack_test.h [new file with mode: 0644]
tools/cxxtest/sample/SimpleTest.h [new file with mode: 0644]
tools/cxxtest/sample/TraitsTest.h [new file with mode: 0644]
tools/cxxtest/sample/aborter.tpl [new file with mode: 0644]
tools/cxxtest/sample/file_printer.tpl [new file with mode: 0644]
tools/cxxtest/sample/gui/GreenYellowRed.h [new file with mode: 0644]
tools/cxxtest/sample/mock/Dice.cpp [new file with mode: 0644]
tools/cxxtest/sample/mock/Dice.h [new file with mode: 0644]
tools/cxxtest/sample/mock/Makefile [new file with mode: 0644]
tools/cxxtest/sample/mock/MockStdlib.h [new file with mode: 0644]
tools/cxxtest/sample/mock/T/stdlib.h [new file with mode: 0644]
tools/cxxtest/sample/mock/TestDice.h [new file with mode: 0644]
tools/cxxtest/sample/mock/mock_stdlib.cpp [new file with mode: 0644]
tools/cxxtest/sample/mock/real_stdlib.cpp [new file with mode: 0644]
tools/cxxtest/sample/mock/roll.cpp [new file with mode: 0644]
tools/cxxtest/sample/msvc/CxxTest_1_Run.dsp [new file with mode: 0644]
tools/cxxtest/sample/msvc/CxxTest_2_Build.dsp [new file with mode: 0644]
tools/cxxtest/sample/msvc/CxxTest_3_Generate.dsp [new file with mode: 0644]
tools/cxxtest/sample/msvc/CxxTest_Workspace.dsw [new file with mode: 0644]
tools/cxxtest/sample/msvc/FixFiles.bat [new file with mode: 0644]
tools/cxxtest/sample/msvc/Makefile [new file with mode: 0644]
tools/cxxtest/sample/msvc/ReadMe.txt [new file with mode: 0644]
tools/cxxtest/sample/only.tpl [new file with mode: 0644]
tools/cxxtest/sample/parts/.cvsignore [new file with mode: 0644]
tools/cxxtest/sample/parts/Makefile.unix [new file with mode: 0644]
tools/cxxtest/sample/winddk/Makefile [new file with mode: 0644]
tools/cxxtest/sample/winddk/Makefile.inc [new file with mode: 0644]
tools/cxxtest/sample/winddk/RunTests.tpl [new file with mode: 0644]
tools/cxxtest/sample/winddk/SOURCES [new file with mode: 0644]
tools/cxxtest/sample/yes_no_runner.cpp [new file with mode: 0644]
tools/cxxtest/test/.cvsignore [new file with mode: 0644]
tools/cxxtest/test/AborterNoThrow.h [new file with mode: 0644]
tools/cxxtest/test/BadTest.h [new file with mode: 0644]
tools/cxxtest/test/Comments.h [new file with mode: 0644]
tools/cxxtest/test/Comments2.h [new file with mode: 0644]
tools/cxxtest/test/CppTemplateTest.h [new file with mode: 0644]
tools/cxxtest/test/DeepAbort.h [new file with mode: 0644]
tools/cxxtest/test/DefaultAbort.h [new file with mode: 0644]
tools/cxxtest/test/DefaultTraits.h [new file with mode: 0644]
tools/cxxtest/test/DoubleCall.h [new file with mode: 0644]
tools/cxxtest/test/DynamicAbort.h [new file with mode: 0644]
tools/cxxtest/test/DynamicMax.h [new file with mode: 0644]
tools/cxxtest/test/EmptySuite.h [new file with mode: 0644]
tools/cxxtest/test/Exceptions.h [new file with mode: 0644]
tools/cxxtest/test/Factor.h [new file with mode: 0644]
tools/cxxtest/test/ForceNoEh.h [new file with mode: 0644]
tools/cxxtest/test/GfSetUpFails.h [new file with mode: 0644]
tools/cxxtest/test/GfSetUpThrows.h [new file with mode: 0644]
tools/cxxtest/test/GfTearDownFails.h [new file with mode: 0644]
tools/cxxtest/test/GfTearDownThrows.h [new file with mode: 0644]
tools/cxxtest/test/GlobalFixtures.h [new file with mode: 0644]
tools/cxxtest/test/GoodSuite.h [new file with mode: 0644]
tools/cxxtest/test/GuiWait.h [new file with mode: 0644]
tools/cxxtest/test/HaveEH.tpl [new file with mode: 0644]
tools/cxxtest/test/HaveStd.h [new file with mode: 0644]
tools/cxxtest/test/HaveStd.tpl [new file with mode: 0644]
tools/cxxtest/test/IncludeTest.h [new file with mode: 0644]
tools/cxxtest/test/InheritedTest.h [new file with mode: 0644]
tools/cxxtest/test/Int64.h [new file with mode: 0644]
tools/cxxtest/test/LessThanEquals.h [new file with mode: 0644]
tools/cxxtest/test/LongLong.h [new file with mode: 0644]
tools/cxxtest/test/LongTraits.h [new file with mode: 0644]
tools/cxxtest/test/Makefile [new file with mode: 0644]
tools/cxxtest/test/MaxDump.h [new file with mode: 0644]
tools/cxxtest/test/MockTest.h [new file with mode: 0644]
tools/cxxtest/test/NoEh.h [new file with mode: 0644]
tools/cxxtest/test/Part1.h [new file with mode: 0644]
tools/cxxtest/test/Part2.h [new file with mode: 0644]
tools/cxxtest/test/Relation.h [new file with mode: 0644]
tools/cxxtest/test/SameData.h [new file with mode: 0644]
tools/cxxtest/test/SameFiles.h [new file with mode: 0644]
tools/cxxtest/test/SameFilesLonger.h [new file with mode: 0644]
tools/cxxtest/test/SameZero.h [new file with mode: 0644]
tools/cxxtest/test/SetUpWorldError.h [new file with mode: 0644]
tools/cxxtest/test/SetUpWorldFails.h [new file with mode: 0644]
tools/cxxtest/test/SetUpWorldThrows.h [new file with mode: 0644]
tools/cxxtest/test/SimpleInheritedTest.h [new file with mode: 0644]
tools/cxxtest/test/SimpleInheritedTest2.h [new file with mode: 0644]
tools/cxxtest/test/Something.h [new file with mode: 0644]
tools/cxxtest/test/StlTraits.h [new file with mode: 0644]
tools/cxxtest/test/TearDownWorldFails.h [new file with mode: 0644]
tools/cxxtest/test/TearDownWorldThrows.h [new file with mode: 0644]
tools/cxxtest/test/TestNonFinite.h [new file with mode: 0644]
tools/cxxtest/test/ThrowNoStd.h [new file with mode: 0644]
tools/cxxtest/test/ThrowNoStd.tpl [new file with mode: 0644]
tools/cxxtest/test/ThrowsAssert.h [new file with mode: 0644]
tools/cxxtest/test/TraitsTest.h [new file with mode: 0644]
tools/cxxtest/test/Tsm.h [new file with mode: 0644]
tools/cxxtest/test/UserTraits.h [new file with mode: 0644]
tools/cxxtest/test/UserTraits.tpl [new file with mode: 0644]
tools/cxxtest/test/VoidTraits.h [new file with mode: 0644]
tools/cxxtest/test/WideCharTest.h [new file with mode: 0644]
tools/cxxtest/test/WorldFixtures.h [new file with mode: 0644]
tools/cxxtest/test/__init__.py [new file with mode: 0644]
tools/cxxtest/test/abort.out [new file with mode: 0644]
tools/cxxtest/test/activate.tpl [new file with mode: 0644]
tools/cxxtest/test/anything.cpp [new file with mode: 0644]
tools/cxxtest/test/bad.out [new file with mode: 0644]
tools/cxxtest/test/comments.out [new file with mode: 0644]
tools/cxxtest/test/comments2.out [new file with mode: 0644]
tools/cxxtest/test/cxxtest/DummyGui.h [new file with mode: 0644]
tools/cxxtest/test/default_abort.out [new file with mode: 0644]
tools/cxxtest/test/eh_normals.out [new file with mode: 0644]
tools/cxxtest/test/eh_plus_abort.out [new file with mode: 0644]
tools/cxxtest/test/error.out [new file with mode: 0644]
tools/cxxtest/test/factor.out [new file with mode: 0644]
tools/cxxtest/test/fake/.cvsignore [new file with mode: 0644]
tools/cxxtest/test/fake/X11/Xlib.h [new file with mode: 0644]
tools/cxxtest/test/fake/X11/Xutil.h [new file with mode: 0644]
tools/cxxtest/test/fake/commctrl.h [new file with mode: 0644]
tools/cxxtest/test/fake/qapplication.h [new file with mode: 0644]
tools/cxxtest/test/fake/qglobal.h [new file with mode: 0644]
tools/cxxtest/test/fake/qlabel.h [new file with mode: 0644]
tools/cxxtest/test/fake/qlayout.h [new file with mode: 0644]
tools/cxxtest/test/fake/qmessagebox.h [new file with mode: 0644]
tools/cxxtest/test/fake/qpixmap.h [new file with mode: 0644]
tools/cxxtest/test/fake/qprogressbar.h [new file with mode: 0644]
tools/cxxtest/test/fake/qstatusbar.h [new file with mode: 0644]
tools/cxxtest/test/fake/qstring.h [new file with mode: 0644]
tools/cxxtest/test/fake/qwidget.h [new file with mode: 0644]
tools/cxxtest/test/fake/windows.h [new file with mode: 0644]
tools/cxxtest/test/gfsuf.out [new file with mode: 0644]
tools/cxxtest/test/gfsut.out [new file with mode: 0644]
tools/cxxtest/test/gftdf.out [new file with mode: 0644]
tools/cxxtest/test/gftdt.out [new file with mode: 0644]
tools/cxxtest/test/gfxs.out [new file with mode: 0644]
tools/cxxtest/test/good.out [new file with mode: 0644]
tools/cxxtest/test/gui.out [new file with mode: 0644]
tools/cxxtest/test/gui_paren.out [new file with mode: 0644]
tools/cxxtest/test/include.out [new file with mode: 0644]
tools/cxxtest/test/infinite.out [new file with mode: 0644]
tools/cxxtest/test/inheritance.out [new file with mode: 0644]
tools/cxxtest/test/int64.cpp [new file with mode: 0644]
tools/cxxtest/test/int64.out [new file with mode: 0644]
tools/cxxtest/test/longlong.cpp [new file with mode: 0644]
tools/cxxtest/test/longlong.out [new file with mode: 0644]
tools/cxxtest/test/main.cpp [new file with mode: 0644]
tools/cxxtest/test/max.out [new file with mode: 0644]
tools/cxxtest/test/normal.out [new file with mode: 0644]
tools/cxxtest/test/normal.xml [new file with mode: 0644]
tools/cxxtest/test/paren.out [new file with mode: 0644]
tools/cxxtest/test/parts.out [new file with mode: 0644]
tools/cxxtest/test/preamble.out [new file with mode: 0644]
tools/cxxtest/test/preamble.tpl [new file with mode: 0644]
tools/cxxtest/test/runner.out [new file with mode: 0644]
tools/cxxtest/test/simple_inheritance.out [new file with mode: 0644]
tools/cxxtest/test/simple_inheritance2.out [new file with mode: 0644]
tools/cxxtest/test/std.out [new file with mode: 0644]
tools/cxxtest/test/stl.out [new file with mode: 0644]
tools/cxxtest/test/stpltpl.cpp [new file with mode: 0644]
tools/cxxtest/test/suite.out [new file with mode: 0644]
tools/cxxtest/test/suite_test.out [new file with mode: 0644]
tools/cxxtest/test/suwe.out [new file with mode: 0644]
tools/cxxtest/test/suwf.out [new file with mode: 0644]
tools/cxxtest/test/suwt.out [new file with mode: 0644]
tools/cxxtest/test/tdwf.out [new file with mode: 0644]
tools/cxxtest/test/tdwt.out [new file with mode: 0644]
tools/cxxtest/test/template.out [new file with mode: 0644]
tools/cxxtest/test/test_cxxtest.py [new file with mode: 0644]
tools/cxxtest/test/test_doc.py [new file with mode: 0644]
tools/cxxtest/test/throw.out [new file with mode: 0644]
tools/cxxtest/test/tpltpl.cpp [new file with mode: 0644]
tools/cxxtest/test/unit/LinkedList_test.t.h [new file with mode: 0644]
tools/cxxtest/test/unit/SConstruct [new file with mode: 0644]
tools/cxxtest/test/user.out [new file with mode: 0644]
tools/cxxtest/test/wchar.cpp [new file with mode: 0644]
tools/cxxtest/test/wchar.out [new file with mode: 0644]
tools/cxxtest/test/wildcard.out [new file with mode: 0644]
tools/rake_utils/buildconfig.rb [new file with mode: 0644]
tools/rake_utils/plainconfig.rb [new file with mode: 0644]
tools/rake_utils/testconfig.rb [new file with mode: 0644]

diff --git a/Doxyfile b/Doxyfile
new file mode 100644 (file)
index 0000000..b633d17
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1719 @@
+# Doxyfile 1.7.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "DLang"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = v0.1a
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "A functional language with extensible syntax"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is 
+# included in the documentation. The maximum height of the logo should not 
+# exceed 55 pixels and the maximum width should not exceed 200 pixels. 
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs/doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful if your file system 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it 
+# parses. With this tag you can assign which parser to use for a given extension. 
+# Doxygen has a built-in mapping, but you can override or extend it using this 
+# tag. The format is ext=language, where ext is a file extension, and language 
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, 
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make 
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C 
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions 
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also makes the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penalty. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will roughly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 
+# will sort the (brief and detailed) documentation of class members so that 
+# constructors and destructors are listed first. If set to NO (the default) 
+# the constructors will appear in the respective orders defined by 
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a 
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen 
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or macro consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and macros in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
+# by doxygen. The layout file controls the global structure of the generated 
+# output files in an output format independent way. The create the layout file 
+# that represents doxygen's defaults, run doxygen with the -l option. 
+# You can optionally specify a file name after the option, if omitted 
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = source
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh 
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix file system feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty or if 
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) 
+# and it is also possible to disable source filtering for a specific pattern 
+# using *.ext= (so without naming a filter). This option only has effect when 
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS = 
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
+# Doxygen will adjust the colors in the stylesheet and background images 
+# according to this color. Hue is specified as an angle on a colorwheel, 
+# see http://en.wikipedia.org/wiki/Hue for more information. 
+# For instance the value 0 represents red, 60 is yellow, 120 is green, 
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. 
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of 
+# the colors in the HTML output. For a value of 0 the output will use 
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to 
+# the luminance component of the colors in the HTML output. Values below 
+# 100 gradually make the output lighter, whereas values above 100 make 
+# the output darker. The value divided by 100 is the actual gamma applied, 
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, 
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify 
+# the documentation publisher. This should be a reverse domain-name style 
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated 
+# that can be used as input for Qt's qhelpgenerator to generate a 
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to 
+# add. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the 
+# custom filter to add. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> 
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 
+# project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> 
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help 
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before 
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [0,1..20]) 
+# that doxygen will group on one line in the generated HTML documentation. 
+# Note that a value of 0 will completely suppress the enum values from
+# appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = YES
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open 
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images 
+# generated for formulas are transparent PNGs. Transparent PNGs are 
+# not supported properly for IE 6.0, but are supported on all modern browsers. 
+# Note that when changing this option you need to delete any form_*.png files 
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax 
+# (see http://www.mathjax.org) which uses client side Javascript for the 
+# rendering instead of using prerendered bitmaps. Use this if you do not 
+# have LaTeX installed or if you want to formulas look prettier in the HTML 
+# output. When enabled you also need to install MathJax separately and 
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the 
+# HTML output directory using the MATHJAX_RELPATH option. The destination 
+# directory should contain the MathJax.js script. For instance, if the mathjax 
+# directory is located at the same level as the HTML output directory, then 
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing 
+# MathJax, but it is strongly recommended to install a local copy of MathJax 
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box 
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using 
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets 
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
+# implemented using a PHP enabled web server instead of at the web client 
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server 
+# based approach is that it scales better to large projects and allows 
+# full text search. The disadvantages are that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 
+# source code with syntax highlighting in the LaTeX output. 
+# Note that which sources are shown also depends on other settings 
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all references to function-like macros 
+# that are alone on a line, have an all uppercase name, and do not end with a 
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links. 
+# Note that each tag file must have a unique name 
+# (where the name does NOT include the path) 
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option also works with HAVE_DOT disabled, but it is recommended to 
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is 
+# allowed to run in parallel. When set to 0 (the default) doxygen will 
+# base this on the number of processors available in the system. You can set it 
+# explicitly to a value larger than 0 to get control over the balance 
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will write a font called Helvetica to the output 
+# directory and reference it in all dot files that doxygen generates. 
+# When you want a differently looking font you can specify the font name 
+# using DOT_FONTNAME. You need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, svg, gif or svg. 
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that 
+# contain msc files that are included in the documentation (see the 
+# \mscfile command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644 (file)
index 0000000..8de46c8
--- /dev/null
@@ -0,0 +1,24 @@
+
+Copyright (c) 2012, Michael D. Lowis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this 
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, 
+  this list of conditions and the following disclaimer in the documentation 
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..f71fb76
--- /dev/null
+++ b/README.md
@@ -0,0 +1,103 @@
+DLang
+==============================================
+Version:      0.1a
+Created By:   Michael D. Lowis
+Email:        <mike@mdlowis.com>
+
+About This Project
+----------------------------------------------
+
+DLang is an experimental new programming language with arbitrarily extensible 
+syntax. The core of the language provides you the tools you need to get things 
+done while the flexible syntax allows YOU to decide how you want to get it done.
+New domain specific languages can be invented on the fly with ease to solve any 
+problem you encounter.
+
+License
+----------------------------------------------
+
+Unless explicitly stated otherwise, all code and documentation in this project 
+is released under the FreeBSD License. You can find a copy of the license text 
+in the LICENSE.md file.
+
+Requirements For Building
+----------------------------------------------
+
+* Ruby and Rake
+* Chicken Scheme Compiler
+* A C++ compiler
+* Python (For unit test generation)
+
+Build Instructions
+----------------------------------------------
+
+You build dlang with the following command:
+
+       rake release
+
+The resulting binary is placed in 'build/bin'. You can test it with the 
+following commands:
+
+       build/bin/dlang example.dl
+       ./example.exe
+
+Installation
+----------------------------------------------
+
+There are no installation instructions at the moment. This is a work in 
+progress.
+
+Project Files and Directories
+----------------------------------------------
+
+       build/         Output directory for artifacts created during the build.
+       deps/          Libraries and other dependencies the source code may have.
+       docs/          Documentation for the language and the source code.
+       res/           Submodules and files that aren't part of DLang source but it still needs
+       source/        The source for the DLang parser
+       tests/         Unit test and mock files.
+       tools/         Tools required by the build system.
+       Doxyfile       Doxygen documentation generator configuration.
+       example.dl     An example DLang source file.
+       LICENSE.md     The software license notification.
+       rakefile.rb    Script containing the build configuration and tasks.
+       README.md      You're reading this file right now!
+
+Know Issues or Bugs
+----------------------------------------------
+
+This is a non-comprehensive list of known issues and bugs that I intend to fix.
+
+* Memory leeaks like a sieve.
+* Error messages are obtuse and unfriendly.
+* Parser and Lexer have 0 error recovery.
+* Usage prints out full path of binary instead of just the name.
+
+Version History
+----------------------------------------------
+
+### Version 0.1a
+
+Very first version ever. Its buggy, has obtuse error messages, and supports 
+about 1/20 of what I would like to see. Lets call it a proof of concept.
+
+
+Feature Wish List
+----------------------------------------------
+
+This is a list of features are not yet supported, but may be at some point in 
+the future.
+
+* Command line options
+* Overloaded macros.
+* Multi-file support
+* Inline function definition and application
+* Inline array definition and access
+* Inline list definition and access
+
+More Info
+----------------------------------------------
+
+For more info or general questions shoot me an email and I'll try to get back 
+to you in a timely manner.
+
diff --git a/build/DUMMY b/build/DUMMY
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/deps/DUMMY b/deps/DUMMY
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/DUMMY b/docs/DUMMY
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/example.dl b/example.dl
new file mode 100644 (file)
index 0000000..cb01400
--- /dev/null
@@ -0,0 +1,97 @@
+#------------------------------------------------------------------------------
+# Macro Tests
+#------------------------------------------------------------------------------
+# Macro Definitions
+% if ( cond, branch1:Block ) {
+       exec_if( cond, branch1 )
+}
+
+% ifelse ( cond, branch1:Block, branch2:Block ) {
+       exec_if( cond, branch1, branch2 )
+}
+
+% foreach ( lst, fn:Block ) {
+       for_each(fn, lst)
+}
+
+# Macro Uses
+if (1 == 1)
+{
+       print("1 Hello, World!")
+}
+
+if (1 == 0)
+{
+       print("Hello, World!")
+}
+
+ifelse (1 == 1)
+{
+       print("2 Hello, World!")
+}{
+       error("Incorrect branch was taken.")
+}
+
+ifelse (1 == 0)
+{
+       error("Incorrect branch was taken.")
+}{
+       print("3 Hello, World!")
+}
+
+#------------------------------------------------------------------------------
+# Collection Access and Iteration Tests
+#------------------------------------------------------------------------------
+# Accessing elements of lists, vectors, and strings
+lst1 = `(4,5,6)
+print(lst1[0], " Hello, World!")
+
+vec1 = [4,5,6]
+print(vec1[1], " Hello, World!")
+
+str1 = "456"
+print(str1[2], " Hello, World!")
+
+# Iterating over lists, vectors, and strings
+lst_foo = `(7,8,9,10)
+foreach lst_foo { |a|
+       print(a," Hello, World!")
+}
+
+vec_foo = [11,12,13,14,15]
+foreach vec_foo { |a,b|
+       print(b," Hello, World!")
+}
+
+str_foo = "6789"
+foreach str_foo { |a|
+       print(1,a," Hello, World!")
+}
+
+#------------------------------------------------------------------------------
+# Delayed Evaluation
+#------------------------------------------------------------------------------
+% delay ( exp ) {
+       make_promise({ exp })
+}
+
+% force ( prom ) {
+       force( prom )
+}
+
+foo = delay nonexistent_var + 1
+nonexistent_var = 19
+assert( typeof(foo) == Block )
+assert( typeof( force foo ) == Num )
+print( force( foo ), " Hello, World!" )
+
+#------------------------------------------------------------------------------
+# Type Checking Tests
+#------------------------------------------------------------------------------
+assert( typeof( 1.1 ) == Num )
+assert( typeof( 'A' ) == Char )
+assert( typeof( `(1,2,3) ) == List )
+assert( typeof( [1,2,3] ) == Vector )
+assert( typeof( $Foo ) == Symbol )
+assert( typeof( {|a| a + 1} ) == Block )
+
diff --git a/rakefile.rb b/rakefile.rb
new file mode 100644 (file)
index 0000000..54d67af
--- /dev/null
@@ -0,0 +1,68 @@
+include Rake::DSL
+require 'tools/rake_utils/buildconfig.rb'
+require 'tools/rake_utils/testconfig.rb'
+
+#------------------------------------------------------------------------------
+# Configuration Objects
+#------------------------------------------------------------------------------
+# Configuration for the binary artifact
+Binary = BuildConfig.new({
+       :name => 'dlang',
+       :compiler_options => [ '-c', '-Wall', '-Werror' ],
+       :source_files => [ 'source/**/*.c*' ],
+       :include_dirs => [ 'source/**/' ],
+})
+
+# Configuration for the unit tests
+UnitTest = TestConfig.new({
+       :test_files => [ 'tests/source/**.h' ],
+})
+
+#------------------------------------------------------------------------------
+# Release Tasks
+#------------------------------------------------------------------------------
+desc 'Execute a complete build including unit tests and binary'
+task :default => [ :release ]
+
+desc 'Display build configuration info'
+task :config do
+       puts 'Release Configuration'
+       puts '---------------------'
+       puts Binary
+       puts ''
+       puts 'Unit Test Configuration'
+       puts '-----------------------'
+       puts UnitTest
+end
+
+desc 'Build and link the binary'
+task :release => [ Binary.binary_name() ]
+
+task Binary.binary_name() => Binary.directories() + Binary.objects() do
+       Binary.link()
+end
+
+rule(/obj\/.+.o$/ => Binary.obj_src_lookup()) do |t|
+       Binary.compile(t.source,t.name)
+end
+
+#------------------------------------------------------------------------------
+# Testing Tasks
+#------------------------------------------------------------------------------
+desc 'Execute all unit tests'
+task :test => UnitTest.directories() + UnitTest.runners() do
+       UnitTest.run_all_test_runners();
+end
+
+rule '_runner.exe' => UnitTest.bin_obj_lookup() do |t|
+       UnitTest.link([t.source],t.name)
+end
+
+rule( /test\/.+_runner.o$/ => UnitTest.obj_src_lookup() ) do |t|
+       UnitTest.compile(t.source,t.name)
+end
+
+rule '_runner.cpp' => UnitTest.src_test_lookup() do |t|
+       UnitTest.generate_test_runner(t.source,t.name)
+end
+
diff --git a/res/DUMMY b/res/DUMMY
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/environment.scm b/res/environment.scm
new file mode 100644 (file)
index 0000000..499b6d7
--- /dev/null
@@ -0,0 +1,225 @@
+;------------------------------------------------------------------------------
+; Built-in Operators
+;------------------------------------------------------------------------------
+(define ADD +)
+(define SUB -)
+(define MUL *)
+(define DIV /)
+(define NOT not)
+(define EQ equal?)
+(define (NE a b) (not (equal? a b)))
+(define LT <)
+(define GT >)
+(define LTE <=)
+(define GTE >=)
+(define FN_CALL apply)
+(define (ARRY_IDX coll idx)
+  (cond
+       ((list? coll)
+         (list-ref coll idx))
+       ((vector? coll)
+         (vector-ref coll idx))
+       ((string? coll)
+         (string-ref coll idx))))
+
+;------------------------------------------------------------------------------
+; Built-in datatype constructors
+;------------------------------------------------------------------------------
+(define VECTOR vector)
+(define LIST list)
+(define PARAMS list)
+(define (MACRO) '())
+
+;------------------------------------------------------------------------------
+; Import necessary libs
+;------------------------------------------------------------------------------
+(require-extension srfi-1)     ; List library
+(require-extension srfi-13)    ; String library
+(require-extension vector-lib) ; Vector library
+
+;------------------------------------------------------------------------------
+; Built-in Symbols
+;------------------------------------------------------------------------------
+; Null value definition
+(define dl/null '())
+
+; Boolean Value Definitions
+(define dl/true #t)
+(define dl/false #f)
+
+; Type Value Definitions
+(define dl/Num 'dl/Num)
+(define dl/Char 'dl/Char)
+(define dl/List 'dl/List)
+(define dl/Vector 'dl/Vector)
+(define dl/String 'dl/String)
+(define dl/Symbol 'dl/Symbol)
+(define dl/Block 'dl/Block)
+
+;------------------------------------------------------------------------------
+; Built-in Functions
+;------------------------------------------------------------------------------
+; Map existing scheme functions to our namespace
+(define dl/display display)
+(define dl/print print)
+(define dl/error error)
+
+; Map
+(define dl/list_map map)
+(define dl/vector_map vector-map)
+(define dl/string_map string-map)
+
+; for_each function definitions
+(define dl/list_for_each for-each)
+(define dl/vector_for_each vector-for-each)
+(define dl/string_for_each string-for-each)
+
+; any function definitions
+(define dl/list_any any)
+(define dl/vector_any vector-any)
+(define dl/string_any string-any)
+
+; every function definitions
+(define dl/list_every every)
+(define dl/vector_every vector-every)
+(define dl/string_every string-every)
+
+; fold function definitions
+(define dl/list_fold fold)
+(define dl/vector_fold vector-fold)
+(define dl/string_fold string-fold)
+
+; fold_right function definitions
+(define dl/list_fold_right fold-right)
+(define dl/vector_fold_right vector-fold-right)
+(define dl/string_fold_right string-fold-right)
+
+; append function definitions
+(define dl/list_append append)
+(define dl/vector_append vector-append)
+(define dl/string_append string-append)
+
+; concat function definitions
+(define dl/list_concat concatenate)
+(define dl/vector_concat vector-concatenate)
+(define dl/string_concat string-concatenate)
+
+; Define type symbols
+(define (dl/typeof var)
+  (cond
+       ((number? var)    dl/Num)
+       ((char? var)      dl/Char)
+       ((list? var)      dl/List)
+       ((vector? var)    dl/Vector)
+       ((string? var)    dl/String)
+       ((symbol? var)    dl/Symbol)
+       ((procedure? var) dl/Block) ))
+
+(define (dl/assert cnd . msg)
+  ; If condition is false
+  (if (not cnd) 
+       ; If message is defined
+       (if (not (null? msg))
+         ; Display the message
+         (error (car msg))
+         ; Otherwise display a default message
+         (error "Assertion failed.") )))
+
+(define (dl/exec_if a b . c) 
+  (if a 
+       ; call b as function
+       (b)
+       ; If c exists
+       (if (not (null? c))
+         ; Call the head of c as a function
+         ((car c)) )))
+
+(define (dl/map . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply map args))
+               ((vector? ls) (apply vector-map args))
+               ((string? ls) (apply string-map args)) )))
+
+(define (dl/for_each . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply for-each args))
+               ((vector? ls) (apply vector-for-each args))
+               ((string? ls) (apply string-for-each args)) )))
+
+(define (dl/any . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply any args))
+               ((vector? ls) (apply vector-any args))
+               ((string? ls) (apply string-any args)) )))
+
+(define (dl/for_all . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply every args))
+               ((vector? ls) (apply vector-every args))
+               ((string? ls) (apply string-every args)) )))
+
+(define (dl/fold_left . args)
+  (let ((ls (list-ref args 2)))
+       (cond
+               ((list? ls)   (apply fold args))
+               ((vector? ls) (apply vector-fold args))
+               ((string? ls) (apply string-fold args)) )))
+
+(define (dl/fold_right . args)
+  (let ((ls (list-ref args 2)))
+       (cond
+               ((list? ls)   (apply fold-right args))
+               ((vector? ls) (apply vector-fold-right args))
+               ((string? ls) (apply string-fold-right args)) )))
+
+(define (dl/append . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply append args))
+               ((vector? ls) (apply vector-append args))
+               ((string? ls) (apply string-append args)) )))
+
+(define (dl/concat . args)
+  (let ((ls (list-ref args 1)))
+       (cond
+               ((list? ls)   (apply concatenate args))
+               ((vector? ls) (apply vector-concatenate args))
+               ((string? ls) (apply string-concatenate args)) )))
+
+(define (error reason . args)
+      (display "Error: ")
+      (display reason)
+      (for-each (lambda (arg) 
+                  (display " ")
+                 (write arg))
+               args)
+      (newline))
+
+(define dl/error error)
+
+(define dl/make_promise
+  (lambda (proc)
+    (let ((result-ready? #f)
+          (result #f))
+      (lambda ()
+        (if result-ready?
+            result
+            (let ((x (proc)))
+              (if result-ready?
+                  result
+                  (begin (set! result-ready? #t)
+                         (set! result x)
+                         result))))))))
+
+(define dl/force
+  (lambda (object)
+    (object)))
+
+;------------------------------------------------------------------------------
+; Start User Defined Code
+;------------------------------------------------------------------------------
+
diff --git a/source/dllexer/dllexer.cpp b/source/dllexer/dllexer.cpp
new file mode 100644 (file)
index 0000000..3d99498
--- /dev/null
@@ -0,0 +1,316 @@
+#include "dllexer.h"
+#include "exception.h"
+
+using namespace std;
+
+#define NUM_SINGLE_CHAR_MATCHES 14
+SingleCharMatch_T Single_Character_Matches[ NUM_SINGLE_CHAR_MATCHES ] = {
+       { '[', LBRACK }, 
+       { ']', RBRACK }, 
+       { '(', LPAR }, 
+       { ')', RPAR }, 
+       { '{', LBRACE }, 
+       { '}', RBRACE }, 
+       { ',', COMMA }, 
+       { '+', ADD }, 
+       { '-', SUB }, 
+       { '*', MUL }, 
+       { '/', DIV }, 
+       { '`', LIST }, 
+       { '%', MACRO }, 
+       { ':', SEP }, 
+};
+
+bool DLLexer::isWhiteSpace(void)
+{
+       return (current == ' ') ||
+                  (current == '\t') ||
+                  (current == '\r') ||
+                  (current == '\n');
+}
+
+bool DLLexer::isLetter(void)
+{
+       return  ((current >= 'a') && (current <= 'z')) ||
+                       ((current >= 'A') && (current <= 'Z'));
+}
+
+bool DLLexer::isDigit(void)
+{
+       return ((current >= '0') && (current <= '9'));
+}
+
+bool DLLexer::isOperator(void)
+{
+       return (   (current == '=') 
+                       || (current == '!')
+                       || (current == '<')
+                       || (current == '>')
+                       || (current == '|')
+                       || (current == '&'));
+}
+
+bool DLLexer::isStringChar(void)
+{
+       return (    (current != '"')
+                        && (current != '\r')
+                        && (current != '\n'));
+}
+
+Token* DLLexer::next(void)
+{
+       Token* ret = NULL;
+       while ( (!input->eof()) && (ret == NULL) )
+       {
+               if (isWhiteSpace()) 
+               { 
+                       WS(); 
+               }
+               else if(current == '#')
+               {
+                       COMMENT();
+               }
+               else if (isLetter())
+               {
+                       ret = Id();
+               }
+               else if( isOperator() )
+               {
+                       ret = MultiCharOp();
+               }
+               else if (isDigit())
+               {
+                       ret = Number();
+               }
+               else if(current == '\'')
+               {
+                       ret = Char();
+               }
+               else if(current == '"')
+               {
+                       ret = String();
+               }
+               else if(current == '$')
+               {
+                       ret = Symbol();
+               }
+               else
+               {
+                       ret = SingleCharOp();
+               }
+       }
+       return ret;
+}
+
+void DLLexer::WS(void)
+{
+       do
+       {
+               consume();
+       }
+       while(isWhiteSpace());
+}
+
+void DLLexer::COMMENT(void)
+{
+       match('#');
+       do
+       {
+               consume();
+       }
+       while(   (current != '\n')
+             && (current != EOF));
+
+}
+
+Token* DLLexer::Id(void)
+{
+       ostringstream oss;
+       do
+       {
+               oss << current;
+               consume();
+       }
+       while(isLetter() || isDigit() || current == '_');
+       return new Token(ID, oss.str(), line, column);
+}
+
+Token* DLLexer::Number(void)
+{
+       ostringstream oss;
+       do
+       {
+               oss << current;
+               consume();
+       }
+       while(isDigit());
+
+       if(current == '.')
+       {
+               return Decimal(oss);
+       }
+
+       return new Token(NUM, oss.str(), line, column);
+}
+
+Token* DLLexer::Decimal(ostringstream& oss)
+{
+       oss << current;
+       consume();
+       
+       if(!isDigit())
+       {
+               Exception ex(line,column);
+               ex.setMessage("Missing fractional portion of floating point number.");
+               throw ex;
+       }
+       
+       do
+       {
+               oss << current;
+               consume();
+       }
+       while ( isDigit() );
+
+       return new Token(NUM, oss.str(), line, column);
+}
+
+Token* DLLexer::Char(void)
+{
+       ostringstream oss;
+
+       match('\'');
+       if(current != '\'')
+       {
+               oss << current;
+               consume();
+       }
+       else
+       {
+               Exception ex(line,column);
+               ex.setMessage("Invalid character literal.");
+               throw ex;
+       }
+       match('\'');
+
+       return new Token( CHAR, oss.str(), line, column );
+}
+
+Token* DLLexer::String(void)
+{
+       ostringstream oss;
+       match('"');
+       while( isStringChar() )
+       {
+               oss << current;
+               consume();
+       }
+       match('"');
+       return new Token( STRING, oss.str(), line, column );
+}
+
+Token* DLLexer::Symbol(void)
+{
+       ostringstream oss;
+       match('$');
+       do 
+       {
+               oss << current;
+               consume();
+       }
+       while(isLetter() || isDigit() || current == '_');
+       return new Token( SYMBOL, oss.str(), line, column );
+}
+
+Token* DLLexer::SingleCharOp(void)
+{
+       for(int i = 0; i < NUM_SINGLE_CHAR_MATCHES; i++)
+       {
+               if(current == Single_Character_Matches[i].match)
+               {
+                       consume();
+                       return new Token( Single_Character_Matches[i].type, line, column );
+               }
+       }
+       throw Exception(line,column);
+}
+
+Token* DLLexer::MultiCharOp(void)
+{
+       Token* tok = NULL;
+       // save the current token so we can refer back to it
+       char last = current;
+       // remove the current token from the buffer so we cna see the next
+       consume();
+
+       if(last == '=') 
+       {
+               if(current == '=')
+               {
+                       consume();
+                       tok = new Token(EQ, line, column);
+               }
+               else
+               {
+                       tok = new Token(ASSIGN, line, column);
+               }
+       }
+       else if(last == '!')
+       {
+               if(current == '=')
+               {
+                       consume();
+                       tok = new Token(NE, line, column);
+               }
+               else
+               {
+                       tok = new Token(NOT, line, column);
+               }
+       }
+       else if(last == '<')
+       {
+               if(current == '=')
+               {
+                       consume();
+                       tok = new Token(LTE, line, column);
+               }
+               else
+               {
+                       tok = new Token(LT, line, column);
+               }
+       }
+       else if(last == '>')
+       {
+               if(current == '=')
+               {
+                       consume();
+                       tok = new Token(GTE, line, column);
+               }
+               else
+               {
+                       tok = new Token(GT, line, column);
+               }
+       }
+       else if(last == '|')
+       {
+               if(current == '|')
+               {
+                       consume();
+                       tok = new Token(OR, line, column);
+               }
+               else
+               {
+                       tok = new Token(PIPE, line, column);
+               }
+       }
+       else if((last == '&') && (current == '&'))
+       {
+               consume();
+               tok = new Token(AND, line, column);
+       }
+       else
+       {
+               throw Exception(line,column);
+       }
+       return tok;
+}
diff --git a/source/dllexer/dllexer.h b/source/dllexer/dllexer.h
new file mode 100644 (file)
index 0000000..f73eab4
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef DLLEXER_H
+#define DLLEXER_H
+
+#include "lexer.h"
+#include <sstream>
+
+typedef enum TokenTypes
+{
+       // Datatypes
+       ID       = 0,
+       NUM      = 1,
+       CHAR     = 2,
+       STRING   = 3,
+       SYMBOL   = 4,
+       LIST     = 5,
+       VECTOR   = 6,
+       FUNC     = 7,
+
+       // Symbols
+       LBRACK   = 10,
+       RBRACK   = 11,
+       LPAR     = 12,
+       RPAR     = 13,
+       LBRACE   = 14,
+       RBRACE   = 15,
+       COMMA    = 16,
+       PIPE     = 17,
+       
+       // Operators
+       AND      = 20,
+       OR       = 21,
+       NOT      = 22,
+       EQ       = 23,
+       NE       = 24,
+       LT       = 25,
+       GT       = 26,
+       LTE      = 27,
+       GTE      = 28,
+       ASSIGN   = 29,
+       ADD      = 30,
+       SUB      = 31,
+       MUL      = 32,
+       DIV      = 33,
+       
+       // AST "Virtual" Node Types
+       MACRO    = 40,
+       SEP      = 41,
+       PROGRAM  = 42,
+       BLOCK    = 43,
+       FN_CALL  = 44,
+       PARAMS   = 45,
+       ARRY_IDX = 46
+} eTokenTypes;
+
+typedef struct {
+       char match;
+       eTokenTypes type;
+} SingleCharMatch_T;
+
+class DLLexer : public Lexer {
+       public:
+               bool isWhiteSpace(void);
+               bool isLetter(void);
+               bool isDigit(void);
+               bool isOperator(void);
+               bool isStringChar(void);
+               void WS(void);
+               void COMMENT(void);
+
+               Token* next(void);
+               Token* Id(void);
+               Token* Number(void);
+               Token* Decimal(std::ostringstream& oss);
+               Token* Char(void);
+               Token* String(void);
+               Token* Symbol(void);
+               Token* SingleCharOp(void);
+               Token* MultiCharOp(void);
+};
+
+
+
+#endif
diff --git a/source/dlparser/dlparser.cpp b/source/dlparser/dlparser.cpp
new file mode 100644 (file)
index 0000000..690406e
--- /dev/null
@@ -0,0 +1,376 @@
+#include "dlparser.h"
+#include "exception.h"
+
+DLParser::DLParser() : BTParser(new DLLexer()), ast(NULL)
+{
+}
+
+void DLParser::parse(void)
+{
+       ast = Program();
+}
+
+AST* DLParser::getAST(void)
+{
+       return ast;     
+}
+
+bool DLParser::isMacro( Token* token )
+{
+       bool ret = false;
+       if( (token->type() == ID) && (macros.find(token->text()) != macros.end()) )
+       {
+               ret = true;
+       }
+       return ret;
+}
+
+AST* DLParser::parseMacroParam(Param* param)
+{
+       AST* ret = NULL;
+       switch( param->type() )
+       {
+               case ExpTyp:
+                       ret = LogicalExpr();
+                       break;
+
+               case BlockTyp:
+                       ret = FuncLiteral();
+                       break;
+
+               default:
+                       Token* tok = lookaheadToken(1);
+                       ostringstream oss;
+                       oss << "Expected macro parameter type. Expected " << param->type() << ", received " << tok->type() << ".";
+                       Exception ex( tok->line(), tok->column() );
+                       ex.setMessage(oss.str());
+                       break;
+       }
+       return ret;
+}
+
+AST* DLParser::Program(void)
+{
+       AST* node = new AST( PROGRAM );
+       while( lookaheadType(1) != EOF )
+       {
+               node->addChild( Expression() );
+       }
+       return node;
+}
+
+AST* DLParser::Expression(void)
+{
+       AST* ret = NULL;
+       if((lookaheadType(1) == ID) && (lookaheadType(2) == ASSIGN))
+       {
+               AST* id_node = new AST( ID,(char*)(lookaheadToken(1)->text().c_str()) );
+               consume();
+               match(ASSIGN);  
+               ret = new AST( ASSIGN, 2, id_node, Expression());
+       }
+       else if( (lookaheadType(1) == MACRO) && (lookaheadType(2) == ID))
+       {
+               ret = MacroDefinition();
+       }
+       else if( isMacro( lookaheadToken(1) ) )
+       {
+               ret = MacroExpansion();
+       }
+       else
+       {
+               ret = LogicalExpr();
+       }
+       return ret;
+}
+
+AST* DLParser::LogicalExpr(void)
+{
+       AST* ret = CompExpr();
+       while((lookaheadType(1) == AND) || (lookaheadType(1) == OR))
+       {
+               ret = new AST( lookaheadType(1), 1, ret);
+               consume();
+               ret->addChild( CompExpr() );
+       }
+       return ret;
+}
+
+AST* DLParser::CompExpr(void)
+{
+       AST* ret = AddSubExpr();
+       while(   (lookaheadType(1) == EQ)  || (lookaheadType(1) == NE)
+          || (lookaheadType(1) == LT)  || (lookaheadType(1) == GT)
+          || (lookaheadType(1) == LTE) || (lookaheadType(1) == GTE))
+       {
+               ret = new AST( lookaheadType(1), 1, ret);
+               consume();
+               ret->addChild( AddSubExpr() );
+       }
+       return ret;
+}
+
+AST* DLParser::AddSubExpr(void)
+{
+       AST* ret = MulDivExpr();
+       while((lookaheadType(1) == ADD) || (lookaheadType(1) == SUB))
+       {
+               ret = new AST( lookaheadType(1), 1, ret);
+               consume();
+               ret->addChild( MulDivExpr() );
+       }
+       return ret;
+}
+
+AST* DLParser::MulDivExpr(void)
+{
+       AST* ret = UnaryExpr();
+       while((lookaheadType(1) == MUL) || (lookaheadType(1) == DIV))
+       {
+               ret = new AST( lookaheadType(1), 1, ret);
+               consume();
+               ret->addChild( UnaryExpr() );
+       }
+       return ret;
+}
+
+AST* DLParser::UnaryExpr(void)
+{
+       AST* ret = NULL;
+       if(lookaheadType(1) == NOT)
+       {
+               consume();
+               ret = new AST(NOT, 1, GroupExpr() );
+       }
+       else
+       {
+               ret = GroupExpr();
+       }
+       return ret;
+}
+
+AST* DLParser::GroupExpr(void)
+{
+       AST* ret = NULL;
+       if(lookaheadType(1) == LPAR)
+       {
+               match(LPAR);
+               ret = LogicalExpr();
+               match(RPAR);
+       }
+       else
+       {
+               ret = Literal();
+               if( lookaheadType(1) == LPAR )
+               {
+                       match(LPAR);
+                       ret = new AST( FN_CALL, 2, ret, ExpList( LIST, RPAR ) );
+                       match(RPAR);
+               }
+               else if( lookaheadType(1) == LBRACK )
+               {
+                       match(LBRACK);
+                       ret = new AST( ARRY_IDX, 2, ret, LogicalExpr() );
+                       match(RBRACK);
+               }
+       }
+       return ret;
+}
+
+AST* DLParser::Literal(void)
+{
+       AST* node = NULL;
+       switch(lookaheadType(1))
+       {
+               // Literal = VectorLiteral
+               case LBRACK:
+                       node = VectorLiteral();
+                       break;
+
+               // Literal = ListLiteral
+               case LIST:
+                       node = ListLiteral();
+                       break;
+
+               // Literal = FuncLiteral
+               case LBRACE:
+                       node = FuncLiteral();
+                       break;
+
+               // Literal = ID
+               case ID:
+                       node = new AST( ID, lookaheadToken(1)->text() );
+                       consume(); 
+                       break;
+
+               // Literal = NUM
+               case NUM:
+                       node = new AST( NUM, lookaheadToken(1)->text() );
+                       consume();
+                       break;
+
+               // Literal = CHAR
+               case CHAR:
+                       node = new AST( CHAR, lookaheadToken(1)->text() );
+                       consume(); 
+                       break;
+
+               // Literal = STRING
+               case STRING:
+                       node = new AST( STRING, lookaheadToken(1)->text() );
+                       consume(); 
+                       break;
+
+               // Literal = SYMBOL
+               case SYMBOL:
+                       node = new AST( SYMBOL, lookaheadToken(1)->text() );
+                       consume(); 
+                       break;
+
+               default:
+                       Token* tok = lookaheadToken(1);
+                       ostringstream oss;
+                       oss << "Expected literal type, recieved type " << tok->type() << ".";
+                       Exception ex( tok->line(), tok->column() );
+                       ex.setMessage(oss.str());
+                       throw ex;
+       }
+       return node;
+}
+
+AST* DLParser::VectorLiteral(void)
+{
+       AST* ret = NULL;
+       match(LBRACK);
+       ret = ExpList(VECTOR, RBRACK);
+       match(RBRACK);
+       return ret;
+}
+
+AST* DLParser::ListLiteral(void)
+{
+       AST* ret = NULL;
+       match(LIST);
+       match(LPAR);
+       ret = ExpList(LIST, RPAR);
+       match(RPAR);
+       return ret;
+}
+
+AST* DLParser::FuncLiteral(void)
+{
+       AST* ret = NULL;
+       
+       match(LBRACE);
+       if(lookaheadType(1) == PIPE)
+       {
+               match(PIPE);
+               ret = ExpList(PARAMS, PIPE);
+               match(PIPE);
+               ret = new AST(FUNC, 2, ret, ExpBlock(BLOCK,RBRACE));
+       }
+       else
+       {
+               ret = new AST(FUNC, 2, new AST(PARAMS), ExpBlock(BLOCK,RBRACE));
+       }
+       match(RBRACE);  
+       return ret;
+}
+
+// MacroDefinition = '%' ID '(' MacroParamList ')' '{' Expression '}'
+AST* DLParser::MacroDefinition(void)
+{
+       AST* ret = NULL;
+       AST* id = NULL;
+       AST* params = NULL;
+       AST* body = NULL;
+       Macro* macro = NULL;
+       
+       match(MACRO);
+       id = new AST( ID, lookaheadToken(1)->text() );
+       consume(); 
+       match(LPAR);
+       params = MacroParamList();
+       match(RPAR);
+       match(LBRACE);
+       body = Expression();
+       match(RBRACE);
+       ret = new AST( MACRO, 3, id, params, body );
+
+       macro = new Macro( ret );
+       macros.insert( std::pair<std::string,Macro*>(id->text(), macro) );
+
+       return new AST(MACRO);
+}
+
+AST* DLParser::MacroExpansion(void)
+{
+       AST* ret = NULL;
+       Macro* cur_macro = macros[ lookaheadToken(1)->text() ];
+       list<Param*>::const_iterator it = cur_macro->params().begin();
+
+       consume();
+       for(; it != cur_macro->params().end(); it++)
+       {
+               (*it)->setValue( parseMacroParam( *it ) );
+       }
+       ret = cur_macro->apply();
+
+       return ret;
+}
+
+// MacroParamList = MacroParam (',' MacroParam)* 
+AST* DLParser::MacroParamList(void)
+{
+       AST* ret = new AST( PARAMS );
+       ret->addChild( MacroParam() );
+       while(lookaheadType(1) == COMMA)
+       {
+               match(COMMA);
+               ret->addChild( MacroParam() );
+       }
+       return ret;
+}
+
+// MacroParam = ID (':' ID)?
+AST* DLParser::MacroParam(void)
+{
+       AST* ret = new AST( ID, lookaheadToken(1)->text() );
+       consume(); 
+       if( lookaheadType(1) == SEP )
+       {
+               match(SEP);
+               AST* type = new AST( ID, lookaheadToken(1)->text() );
+               consume(); 
+               ret = new AST(SEP, 2, ret, type);
+       }
+       return ret;
+}
+
+// ExpList = (Expression (',' Expression)*)?
+AST* DLParser::ExpList(TokenType_T node_type, TokenType_T terminator)
+{
+       AST* node = new AST( node_type );
+       if(lookaheadType(1) != terminator)
+       {
+               node->addChild( Expression() );
+               while(lookaheadType(1) == COMMA)
+               {
+                       match(COMMA);
+                       node->addChild( Expression() );
+               }
+       }
+       return node;
+}
+
+// ExpBlock = Expression+
+AST* DLParser::ExpBlock(TokenType_T node_type, TokenType_T terminator)
+{
+       AST* node = new AST(node_type);
+       while(lookaheadType(1) != RBRACE)
+       {
+               node->addChild( Expression() );
+       }
+       return node;
+}
+
diff --git a/source/dlparser/dlparser.h b/source/dlparser/dlparser.h
new file mode 100644 (file)
index 0000000..d00d1dd
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef DLPARSER_H
+#define DLPARSER_H 
+
+#include <map>
+#include "btparser.h"
+#include "dllexer.h"
+#include "macro.h"
+
+class DLParser : public BTParser
+{
+       private:
+               AST* ast;
+               std::map<std::string,Macro*> macros;
+       public:
+               DLParser();
+               void parse(void);
+               AST* getAST(void);
+               bool isMacro(Token* token);
+               AST* parseMacroParam(Param* param);
+               
+               /**********************************************************************
+                * EBNF Syntax Grammar
+                *********************************************************************/
+               // Program    = Expression*
+               //
+               // Expression = ID '=' LogicalExpr
+               //            | MacroDefinition
+               //            | $MacroExpansion$
+               //            | LogicalExpr
+               //
+               // LogicalExpr = CompExpr (('&&' | '||') CompExpr)*
+               //
+               // CompExpr = AddSubExpr (('==' | '!=' | '<' | '>' | '<=' | '>=') AddSubExpr)*
+               //
+               // AddSubExpr = MulDivExpr (('+' | '-') MulDivExpr)*
+               //
+               // MulDivExpr = UnaryExpr (('*' | '/') UnaryExpr)*
+               //
+               // UnaryExpr = '!' GroupExpr
+               //           | GroupExpr
+               //            
+               // GroupExpr = '(' LogicalExpr ')'
+               //           | Literal '(' ExpList ')'
+               //           | Literal
+               //
+        // Literal    = VectorLiteral
+               //            | ListLiteral
+               //            | FuncLiteral
+               //            | ID
+               //            | NUM
+               //            | CHAR
+               //            | STRING
+               //            | SYMBOL
+               //
+               // VectorLiteral =  '[' ExpList ']'
+               //
+               // ListLiteral = '`' '(' ExpList ')'
+               //
+               // FuncLiteral = '{' ExpBlock '}'
+               //             |  '{' '|' ExpList '|' ExpBlock '}'
+               //
+               // MacroDefinition = '%' ID '(' MacroParamList ')' '{' Expression '}'
+               //
+               // MacroParamList = MacroParam (',' MacroParam)* 
+               //
+               // MacroParam = ID (':' ID)?
+               //
+               // ExpList    = (GroupExpr (',' GroupExpr)*)?
+               //
+               // ExpBlock   = Expression*
+       private:
+               AST* Program(void);
+               AST* Expression(void);
+               AST* LogicalExpr(void);
+               AST* CompExpr(void);
+               AST* AddSubExpr(void);
+               AST* MulDivExpr(void);
+               AST* UnaryExpr(void);
+               AST* GroupExpr(void);
+               AST* Literal(void);
+               AST* VectorLiteral(void);
+               AST* ListLiteral(void);
+               AST* FuncLiteral(void);
+               AST* MacroDefinition(void);
+               AST* MacroExpansion(void);
+               AST* MacroParamList(void);
+               AST* MacroParam(void);
+               AST* ExpList(TokenType_T node_type, TokenType_T terminator);
+               AST* ExpBlock(TokenType_T node_type, TokenType_T terminator);
+};
+
+#endif
diff --git a/source/dlparser/macro/macro.c b/source/dlparser/macro/macro.c
new file mode 100644 (file)
index 0000000..8542218
--- /dev/null
@@ -0,0 +1,49 @@
+#include "macro.h"
+#include "macroapplication.h"
+
+Macro::Macro(AST* macro_def)
+{
+       list<AST*>::iterator it = macro_def->children()->begin();
+       
+       // Set Name
+       macro_name = (*it++)->text();
+
+       // Set Body
+       setUpParamList( *it++ );
+
+       // Set Params
+       macro_body = (*it++)->clone();
+
+}
+
+Macro::~Macro()
+{
+       delete macro_body;
+}
+
+const std::string& Macro::name(void)
+{
+       return macro_name;
+}
+
+const std::list<Param*>& Macro::params(void)
+{
+       return macro_params;
+}
+
+AST* Macro::apply(void)
+{
+       MacroApplication application(macro_body->clone(), macro_params);
+       application.visit();
+       return application.getAST()->clone();
+}
+
+void Macro::setUpParamList( AST* param_tree )
+{
+       list<AST*>::iterator it = param_tree->children()->begin();
+       for(; it != param_tree->children()->end(); it++)
+       {
+               macro_params.push_back( new Param( *it ) );
+       }
+}
+
diff --git a/source/dlparser/macro/macro.h b/source/dlparser/macro/macro.h
new file mode 100644 (file)
index 0000000..b95d728
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef MACRO_H
+#define MACRO_H
+
+#include <string>
+#include <list>
+#include "param.h"
+#include "ast.h"
+
+class Macro
+{
+       private:
+               std::string macro_name;
+               std::list<Param*> macro_params;
+               AST* macro_body;
+
+               void setUpParamList( AST* param_tree );
+       public:
+               Macro(AST* macro_def);
+               ~Macro();
+
+               const std::string& name(void);
+               const std::list<Param*>& params(void);
+               AST* apply(void);
+};
+
+#endif
diff --git a/source/dlparser/macro/param.c b/source/dlparser/macro/param.c
new file mode 100644 (file)
index 0000000..ac6a8bb
--- /dev/null
@@ -0,0 +1,57 @@
+#include "param.h"
+
+Param::Param(AST* param_def)
+{
+       int children = param_def->children()->size();
+       if( children == 0 )
+       {
+               param_name = param_def->text();
+       }
+       else if( children == 2)
+       {
+               param_name = param_def->children()->front()->text();
+               setType( param_def->children()->front()->text() );
+       }
+       else
+       {
+               // Throw
+       }
+}
+
+Param::~Param()
+{
+       delete param_value;
+}
+
+std::string Param::name(void)
+{
+       return param_name;
+}
+
+ParamType_T Param::type(void)
+{
+       return param_type;
+}
+
+AST* Param::value(void)
+{
+       return param_value;
+}
+
+void Param::setValue(AST* val)
+{
+       param_value = val;
+}
+
+void Param::setType( const std::string& type_string )
+{
+       if ( type_string.compare("Block") == 0 )
+       {
+               param_type = BlockTyp;
+       }
+       else
+       {
+               param_type = ExpTyp;
+       }
+}
+
diff --git a/source/dlparser/macro/param.h b/source/dlparser/macro/param.h
new file mode 100644 (file)
index 0000000..79c209f
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef PARAM
+#define PARAM
+
+#include <string>
+#include "ast.h"
+
+typedef enum {
+       ExpTyp,
+       BlockTyp
+} ParamType_T;
+
+class Param
+{
+       private:
+               std::string param_name;
+               ParamType_T param_type;
+               AST* param_value;
+
+               void setType( const std::string& type_string );
+
+       public:
+               Param(AST* param_def);
+               ~Param();
+
+               std::string name(void);
+               ParamType_T type(void);
+               AST* value(void);
+               void setValue(AST* val);
+};
+
+#endif
diff --git a/source/main.cpp b/source/main.cpp
new file mode 100644 (file)
index 0000000..3c8b8fc
--- /dev/null
@@ -0,0 +1,87 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <sstream>
+#include <fstream>
+#include "dlparser.h"
+#include "sexp.h"
+#include "scheme.h"
+
+using namespace std;
+
+static bool fileExists(char* fname);
+static string createTempFileName(string fname);
+
+int main(int argc, char** argv)
+{
+       int ret = 0;
+
+       if( (argc == 2) && fileExists( argv[1] ) )
+       {
+               string input_fname(argv[1]);
+               string temp_fname = createTempFileName( input_fname );
+               DLParser parser;
+               Scheme* visitor = NULL;
+
+               // Open the input and output files
+               ifstream input(input_fname.c_str());
+               ofstream output(temp_fname.c_str());
+
+               // Parse the file
+               parser.setInput(&input);
+               parser.parse();
+
+               // Translate the AST
+               visitor = new Scheme( parser.getAST() );
+               visitor->visit();
+
+               // Write to a temp file
+               output << visitor->str();
+               cout << visitor->str();
+               output.close();
+
+               // Compile temp file
+               system(("csc " + temp_fname).c_str());
+
+               //// delete temp file
+               remove(temp_fname.c_str());
+       }
+       else
+       {
+               ret = 1;
+       }
+
+       if(ret != 0)
+       {
+               // Print error code specific error
+               cout << "Usage: " << argv[0] << " <filename>\n" << endl;
+               cerr << "Error: No input files." << endl;
+       }
+
+       return ret;
+}
+
+bool fileExists(char* fname)
+{
+       string in_fname(fname);
+       ifstream file(fname,ifstream::in);
+       return (file != NULL);
+}
+
+string createTempFileName(string fname)
+{
+       string ret_str;
+       size_t ext_index = fname.find_last_of('.');
+       // If we did NOT find a match, assume no extension given 
+       if (ext_index == string::npos)
+       {
+               ret_str = fname + ".scm";
+       }
+       // else replace the existing extension
+       else
+       {
+               ret_str = fname;
+               ret_str.replace(ext_index, (ret_str.size() -1), ".scm");
+       }
+       return ret_str;
+}
+
diff --git a/source/parse_utils/ast/ast.cpp b/source/parse_utils/ast/ast.cpp
new file mode 100644 (file)
index 0000000..35d14b7
--- /dev/null
@@ -0,0 +1,113 @@
+#include "ast.h"
+#include <sstream>
+#include <string.h>
+#include <iostream>
+
+AST::AST(ASTNodeType type)
+{
+       node_type = type;
+       node_text = NULL;
+       node_children = new list<AST*>();
+}
+
+AST::~AST()
+{
+       list<AST*>::iterator it = node_children->begin();
+       for(; it != node_children->end(); it++)
+       {
+               delete *(it);
+       }
+       delete node_children;
+       delete node_text;
+}
+
+AST::AST(ASTNodeType type, const char* text)
+{
+       node_type = type;
+       node_text = new string(text);
+       node_children = new list<AST*>();
+}
+
+AST::AST(ASTNodeType type, const std::string& text)
+{
+       node_type = type;
+       node_text = new string(text);
+       node_children = new list<AST*>();
+}
+
+AST::AST(ASTNodeType type, int child_count, ...)
+{
+       va_list arg_list;
+       int i = 0;
+       node_type = type;
+       node_text = NULL;
+       node_children = new list<AST*>();
+       va_start (arg_list, child_count); 
+       for (i = 0; i < child_count ; i++)
+       {
+               node_children->push_back( (AST*)va_arg(arg_list, AST*) );
+       }
+       va_end(arg_list);
+}
+
+AST& AST::operator = (AST& rhs)
+{
+       list<AST*>::iterator it = rhs.children()->begin();
+       node_type = rhs.type();
+       *node_text = rhs.text();
+       node_children->clear();
+
+       for(; it != rhs.children()->end(); it++)
+       {
+               node_children->push_back( (*it)->clone() );
+       }
+
+       return *this;
+}
+
+ASTNodeType AST::type(void)
+{
+       return node_type;
+}
+
+list<AST*>* AST::children(void)
+{
+       return node_children;
+}
+
+string AST::text(void)
+{
+       ostringstream oss;
+       if(node_text != NULL)
+       {
+               oss << node_text->c_str();
+       }
+       return oss.str();
+}
+
+void AST::addChild(AST* node)
+{
+       node_children->push_back(node);
+}
+
+AST* AST::clone(void)
+{
+       AST* new_clone = NULL;
+       list<AST*>::iterator it = node_children->begin();
+
+       if(node_text == NULL)
+       {
+               new_clone = new AST( node_type );
+       }
+       else
+       {
+               new_clone = new AST( node_type, *node_text );
+       }
+       
+       for(; it != node_children->end(); it++)
+       {
+               new_clone->addChild( (*it)->clone() );
+       }
+       return new_clone;
+}
+
diff --git a/source/parse_utils/ast/ast.h b/source/parse_utils/ast/ast.h
new file mode 100644 (file)
index 0000000..3ea3712
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef AST_H
+#define AST_H 
+
+#include <stdarg.h>
+#include <list>
+#include <string>
+
+using namespace std;
+
+typedef unsigned int ASTNodeType;
+
+class AST 
+{
+       protected:
+               ASTNodeType node_type;
+               string*     node_text;
+               list<AST*>* node_children;
+       public:
+               AST(ASTNodeType type);
+               AST(ASTNodeType type, const char* text);
+               AST(ASTNodeType type, const string& text);
+               AST(ASTNodeType type, int child_count, ...);
+               virtual ~AST();
+
+               AST& operator = (AST& rhs);
+
+               ASTNodeType type(void);
+               string      text(void);
+               list<AST*>* children(void);
+               void        addChild(AST* node);
+               AST*        clone(void);
+};
+
+#endif
diff --git a/source/parse_utils/exception/exception.cpp b/source/parse_utils/exception/exception.cpp
new file mode 100644 (file)
index 0000000..cd4931b
--- /dev/null
@@ -0,0 +1,25 @@
+#include <sstream>
+#include "exception.h"
+
+Exception::Exception(int line, int column) throw() : std::exception(), ex_line(line), ex_column(column)
+{
+}
+
+const char* Exception::what() const throw()
+{
+       std::ostringstream oss;
+       oss << "(ln " << ex_line << ", col " << ex_column << "): ";
+       oss << ((Exception*)this)->message() << std::endl;
+       return oss.str().c_str();
+}
+
+void Exception::setMessage(std::string msg) throw()
+{
+       ex_msg = msg;
+}
+
+std::string& Exception::message(void) throw()
+{
+       return ex_msg;
+}
+
diff --git a/source/parse_utils/exception/exception.h b/source/parse_utils/exception/exception.h
new file mode 100644 (file)
index 0000000..93679d2
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef EXCEPTION_H
+#define EXCEPTION_H 
+
+#include <exception>
+#include <string>
+
+class Exception : public std::exception
+{
+       protected:
+               int ex_line;
+               int ex_column;
+               std::string ex_msg;
+       public:
+               Exception(int line, int column) throw();
+               virtual ~Exception() throw() {};
+               virtual const char* what() const throw();
+               void setMessage(std::string msg) throw();
+               std::string& message(void) throw();
+};
+
+#endif
diff --git a/source/parse_utils/lexer/lexer.cpp b/source/parse_utils/lexer/lexer.cpp
new file mode 100644 (file)
index 0000000..d84c25b
--- /dev/null
@@ -0,0 +1,80 @@
+#include <exception>
+#include "lexer.h"
+#include "exception.h"
+
+using namespace std;
+
+Lexer::Lexer() : line(-1), column(-1)
+{
+}
+
+Lexer::~Lexer()
+{
+}
+
+void Lexer::setInput(char* in)
+{
+       line = 1;
+       column = 0;
+       input = new istringstream( string( in ) );
+       consume();
+}
+
+void Lexer::setInput(string& in)
+{
+       line = 1;
+       column = 0;
+       input = new istringstream( in );
+       consume();
+}
+
+void Lexer::setInput(istream* in)
+{
+       line = 1;
+       column = 0;
+       input = in;
+       consume();
+}
+
+bool Lexer::eof(void)
+{
+       return ((input == NULL) || (input->eof()));
+}
+
+void Lexer::consume(void)
+{
+       if(input->eof())
+       {
+               current = EOF;
+       }
+       else
+       {
+               current = input->get(); 
+               if(current == '\n')
+               {
+                       line++;
+                       column = 0;
+               }
+               else
+               {
+                       column++;
+               }
+       }
+}
+
+void Lexer::match(char x) {
+       if ( current == x)
+       {
+               consume();
+       }
+       else 
+       {
+               ostringstream oss;
+               oss << "Unexpected character. Expected " << x << ", received " << current << ".";
+               Exception ex(line,column);
+               ex.setMessage(oss.str());
+               throw ex;
+       }
+}
+
+
diff --git a/source/parse_utils/lexer/lexer.h b/source/parse_utils/lexer/lexer.h
new file mode 100644 (file)
index 0000000..3b89235
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef LEXER_H
+#define LEXER_H 
+
+#include <iostream>
+#include <sstream>
+#include <cstdio>
+#include "token.h"
+
+class Lexer
+{
+       public:
+               int line;
+               int column;
+               char current;
+               std::istream* input;
+
+               Lexer();
+               virtual ~Lexer();
+               
+               void setInput(char* in);
+               void setInput(std::string& in);
+               void setInput(std::istream* in);
+
+               void consume(void);
+               void match(char x);
+               bool eof(void);
+               virtual Token* next(void) = 0;
+};
+
+#endif
diff --git a/source/parse_utils/lexer/token/token.cpp b/source/parse_utils/lexer/token/token.cpp
new file mode 100644 (file)
index 0000000..9b68106
--- /dev/null
@@ -0,0 +1,30 @@
+#include "token.h"
+
+Token::Token(TokenType_T ttype, std::string ttext, int line, int col) : tok_type(ttype), tok_text(ttext), tok_line(line), tok_col(col)
+{
+}
+
+Token::Token(TokenType_T ttype, int line, int col) : tok_type(ttype), tok_line(line), tok_col(col)
+{
+}
+
+TokenType_T Token::type()
+{
+       return tok_type;
+}
+
+const std::string& Token::text()
+{
+       return tok_text;
+}
+
+int Token::line()
+{
+       return tok_line;
+}
+
+int Token::column()
+{
+       return tok_col;
+}
+
diff --git a/source/parse_utils/lexer/token/token.h b/source/parse_utils/lexer/token/token.h
new file mode 100644 (file)
index 0000000..32381b6
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef TOKEN_H
+#define TOKEN_H 
+
+#include <string>
+
+typedef int TokenType_T;
+
+class Token
+{
+       private:
+               TokenType_T tok_type;
+               std::string tok_text;
+               int tok_line;
+               int tok_col;
+       public:
+               Token(TokenType_T ttype, int line, int col);
+               Token(TokenType_T ttype, std::string ttext, int line, int col);
+               TokenType_T type();
+               const std::string& text();
+               int line();
+               int column();
+};
+
+#endif
diff --git a/source/parse_utils/parser/btparser/btparser.cpp b/source/parse_utils/parser/btparser/btparser.cpp
new file mode 100644 (file)
index 0000000..782174f
--- /dev/null
@@ -0,0 +1,117 @@
+#include "BTParser.h"
+#include "exception.h"
+
+BTParser::BTParser(Lexer* lxer) : lexer(lxer), current(0)
+{
+}
+
+BTParser::~BTParser()
+{
+       if(lexer != NULL)
+       {
+               delete lexer;
+               // Input stream was deleted with the lexer so null it out
+               Parser::setInput((istream*)NULL);
+       }
+}
+
+void BTParser::setInput(char* in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+}
+
+void BTParser::setInput(string& in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+}
+
+void BTParser::setInput(istream* in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+}
+
+void BTParser::consume(void)
+{
+       current++;
+       if((current == lookahead.size()) && !isSpeculating())
+       {
+               current = 0;
+               lookahead.clear();
+       }
+       sync(1);
+}
+
+void BTParser::sync(unsigned int i)
+{
+       unsigned int next_index = current + i - 1;
+       unsigned int max_index = (lookahead.size() == 0) ? 0 : (lookahead.size() - 1);
+       if( next_index >= max_index )
+       {
+               fill( next_index - max_index); 
+       }
+}
+
+void BTParser::fill(unsigned int n)
+{
+       unsigned int i = 0;
+       for (i = 0; i <= n; i++)
+       {
+               lookahead.push_back( lexer->next() );
+       }
+}
+
+void BTParser::match(TokenType_T type)
+{
+       if( lookaheadType(1) == type )
+       {
+               consume();
+       }
+       else
+       {
+               Token* tok = lookaheadToken(1);
+               ostringstream oss;
+               oss << "Expected token type. Expected " << type << ", received " << tok->type() << ".";
+               Exception ex( tok->line(), tok->column() );
+               ex.setMessage(oss.str());
+       }
+}
+
+Token* BTParser::lookaheadToken(unsigned int i)
+{
+       sync(i);
+       return lookahead.at( current + i - 1 );
+}
+
+TokenType_T BTParser::lookaheadType(unsigned int i)
+{
+
+       Token* tok = lookaheadToken(i);
+       return (tok != NULL) ? tok->type() : EOF;
+}
+
+unsigned int BTParser::mark(void)
+{
+       markers.push_back(current);
+       return current;
+}
+
+void BTParser::release(void)
+{
+       unsigned int marker = markers.back();
+       markers.pop_back();
+       seek(marker);
+}
+
+void BTParser::seek(unsigned int index)
+{
+       current = index;
+}
+
+bool BTParser::isSpeculating(void)
+{
+       return (markers.size() > 0);
+}
+
diff --git a/source/parse_utils/parser/btparser/btparser.h b/source/parse_utils/parser/btparser/btparser.h
new file mode 100644 (file)
index 0000000..3b032b4
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef BT_PARSER_H
+#define BT_PARSER_H
+
+#include <exception>
+#include <vector>
+#include "parser.h"
+#include "lexer.h"
+#include "ast.h"
+
+class BTParser : public Parser
+{
+       private:
+               Lexer* lexer;
+               unsigned int current;
+               std::vector<unsigned int> markers;
+               std::vector<Token*> lookahead;
+       public:
+               BTParser(Lexer* lxer);
+               ~BTParser();
+
+               void setInput(char* in);
+               void setInput(string& in);
+               void setInput(istream* in);
+
+               void consume(void);
+               void sync(unsigned int i);
+               void fill(unsigned int n);
+               void match(TokenType_T type);
+               Token* lookaheadToken(unsigned int i);
+               TokenType_T lookaheadType(unsigned int i);
+               unsigned int mark(void);
+               void release(void);
+               void seek(unsigned int index);
+               bool isSpeculating(void);
+
+               virtual void parse(void) = 0;
+};
+
+#endif
diff --git a/source/parse_utils/parser/llkparser/llkparser.cpp b/source/parse_utils/parser/llkparser/llkparser.cpp
new file mode 100644 (file)
index 0000000..db86ece
--- /dev/null
@@ -0,0 +1,101 @@
+#include "llkparser.h"
+#include "exception.h"
+
+LLKParser::LLKParser(int k_val, Lexer* lxer) : k(k_val), next(0), lexer(lxer)
+{
+       if ( lexer != NULL )
+       {
+               lookahead = new Token*[k];
+       }
+       else
+       {
+               throw std::exception();
+       }
+}
+
+LLKParser::~LLKParser()
+{
+       if(lexer != NULL)
+       {
+               delete lexer;
+               // Input stream was deleted with th elexer so null it out
+               Parser::setInput((istream*)NULL);
+       }
+       if (lookahead != NULL)
+       {
+               delete[] lookahead;
+       }
+}
+
+void LLKParser::setInput(char* in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+       for (int i = 0; i < k; i++)
+       {
+               consume();
+       }
+}
+
+void LLKParser::setInput(string& in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+       for (int i = 0; i < k; i++)
+       {
+               consume();
+       }
+}
+
+void LLKParser::setInput(istream* in)
+{
+       Parser::setInput(in);
+       lexer->setInput(in);
+       for (int i = 0; i < k; i++)
+       {
+               consume();
+       }
+}
+
+void LLKParser::consume(void)
+{
+       if ( lookahead != NULL )
+       {
+               lookahead[next] = lexer->next();
+               next = (next + 1) % k;
+       }
+}
+
+void LLKParser::match(TokenType_T type)
+{
+       if( lookaheadType(1) == type )
+       {
+               consume();
+       }
+       else
+       {
+               throw std::exception();
+       }
+}
+
+Token* LLKParser::lookaheadToken(int i)
+{
+       Token* ret = NULL;
+       if( lookahead != NULL )
+       {
+               ret = lookahead[(next + i - 1) % k];
+       }
+       return ret; 
+}
+
+TokenType_T LLKParser::lookaheadType(int i)
+{
+       TokenType_T ret = EOF;
+       if( lookahead != NULL )
+       {
+               Token* tok = lookaheadToken(i);
+               ret = (tok != NULL) ? tok->type() : EOF;
+       }
+       return ret;
+}
+
diff --git a/source/parse_utils/parser/llkparser/llkparser.h b/source/parse_utils/parser/llkparser/llkparser.h
new file mode 100644 (file)
index 0000000..ab1fe51
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef LLK_PARSER_H
+#define LLK_PARSER_H
+
+#include <exception>
+#include "parser.h"
+#include "lexer.h"
+#include "ast.h"
+
+class LLKParser : public Parser
+{
+       private:
+               int k;
+               int next;
+               Lexer*  lexer;
+               Token** lookahead;
+       public:
+               LLKParser(int k_val, Lexer* lxer);
+               ~LLKParser();
+
+               void setInput(char* in);
+               void setInput(string& in);
+               void setInput(istream* in);
+
+               void         consume(void);
+               void         match(TokenType_T type);
+               Token*       lookaheadToken(int i);
+               TokenType_T  lookaheadType(int i);
+               virtual void parse(void) = 0;
+};
+
+#endif
diff --git a/source/parse_utils/parser/parser.cpp b/source/parse_utils/parser/parser.cpp
new file mode 100644 (file)
index 0000000..a7eee89
--- /dev/null
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *  Copyright (C) 2001  Michael D. Lowis
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************/
+/******************************************************************************
+ * Includes and Prototypes
+ *****************************************************************************/
+#include <stdio.h>
+#include "parser.h"
+
+using namespace std;
+
+/******************************************************************************
+ * Public Functions
+ *****************************************************************************/
+Parser::Parser() : input(NULL)
+{
+}
+
+Parser::~Parser()
+{
+       if(input != NULL)
+       {
+               delete input;
+       }
+}
+
+void Parser::setInput(char* in)
+{
+       input = new istringstream( string( in ) );
+}
+
+void Parser::setInput(string& in)
+{
+       input = new istringstream( in );
+}
+
+void Parser::setInput(istream* in)
+{
+       input = in;
+}
+
+
diff --git a/source/parse_utils/parser/parser.h b/source/parse_utils/parser/parser.h
new file mode 100644 (file)
index 0000000..929334f
--- /dev/null
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *  Copyright (C) 2001  Michael D. Lowis
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************/
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <string>
+#include <sstream>
+#include "ast.h"
+#include "visitor.h"
+
+using namespace std;
+
+class Parser {
+       private:
+               istream* input;
+       public:
+               Parser();
+               virtual ~Parser();
+               virtual void parse() = 0;
+
+               void setInput(char* in);
+               void setInput(string& in);
+               void setInput(istream* in);
+};
+
+#endif
diff --git a/source/parse_utils/visitor/visitor.cpp b/source/parse_utils/visitor/visitor.cpp
new file mode 100644 (file)
index 0000000..71c3ccf
--- /dev/null
@@ -0,0 +1,35 @@
+#include "visitor.h"
+#include <list>
+
+using namespace std;
+
+void Visitor::visit(AST* cur, int depth)
+{
+       list<AST*>* children;
+       list<AST*>::iterator it;
+       
+       // If we are just starting then use the global tree
+       if(cur == NULL) cur = ast;
+
+       // Execute or pre-walk actions
+       if(depth == 0) beforeVisit( cur, depth );
+
+       // Setup our locals
+       children = cur->children();
+       it = children->begin();
+
+       // Visit the tree
+       beforeChildren(cur,depth);
+       depth++;
+       for(; it != children->end(); it++)
+       {
+               beforeChild( *it, depth );
+               visit( *it, depth );
+               afterChild( *it, depth );
+       }
+       afterChildren(cur,depth);
+
+       // Execute our post-walk actions
+       if(depth == 1) afterVisit( cur, depth );
+}
+
diff --git a/source/parse_utils/visitor/visitor.h b/source/parse_utils/visitor/visitor.h
new file mode 100644 (file)
index 0000000..b93359e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TRANSLATOR_H
+#define TRANSLATOR_H 
+
+#include "ast.h"
+#include <string>
+#include <iostream>
+
+class Visitor {
+       protected:
+               AST* ast;
+       public:
+               Visitor(AST* tree) : ast(tree) {};
+               ~Visitor() { delete ast; }
+               void visit(AST* cur = NULL, int depth = 0);
+       private:
+               virtual void beforeVisit(AST* cur, int depth) = 0;
+               virtual void afterVisit(AST* cur, int depth) = 0;
+               virtual void beforeChildren(AST* cur, int depth) = 0;
+               virtual void afterChildren(AST* cur, int depth) = 0;
+               virtual void beforeChild(AST* cur, int depth) = 0;
+               virtual void afterChild(AST* cur, int depth) = 0;
+};
+
+class VisitorFactory {
+       public:
+               virtual Visitor* createVisitor(AST* root) = 0;
+};
+
+#endif
diff --git a/source/visitors/macroapplication/macroapplication.cpp b/source/visitors/macroapplication/macroapplication.cpp
new file mode 100644 (file)
index 0000000..4cdbf04
--- /dev/null
@@ -0,0 +1,57 @@
+#include "MacroApplication.h"
+#include "dllexer.h"
+
+using namespace std;
+
+Param* MacroApplication::getParamByName(std::string name)
+{
+       Param* ret = NULL;
+       std::list<Param*>::iterator it = macro_params.begin();
+       for(; it != macro_params.end(); it++)
+       {
+               if( (*it)->name().compare( name ) == 0)
+               {
+                       ret = *it;
+                       break;
+               }
+       }
+       return ret;
+}
+
+AST* MacroApplication::getAST(void)
+{
+       return mod_ast;
+}
+
+void MacroApplication::beforeVisit(AST* cur, int depth)
+{
+}
+
+void MacroApplication::afterVisit(AST* cur, int depth)
+{
+}
+
+void MacroApplication::beforeChildren(AST* cur, int depth)
+{
+       if(cur->type() == ID)
+       {
+               Param* param = getParamByName( cur->text() );
+               if( param != NULL )
+               {
+                       (*cur) = *(param->value());
+               }
+       }
+}
+
+void MacroApplication::afterChildren(AST* cur, int depth)
+{
+}
+
+void MacroApplication::beforeChild(AST* cur, int depth)
+{
+}
+
+void MacroApplication::afterChild(AST* cur, int depth)
+{
+}
+
diff --git a/source/visitors/macroapplication/macroapplication.h b/source/visitors/macroapplication/macroapplication.h
new file mode 100644 (file)
index 0000000..0c43449
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef MacroApplication_H
+#define MacroApplication_H 
+
+#include "visitor.h"
+#include <iostream>
+#include <sstream>
+#include "param.h"
+
+class MacroApplication : public Visitor {
+       protected:
+               AST* mod_ast;
+               ostringstream stream;
+               std::list<Param*> macro_params;
+       public:
+               MacroApplication(AST* root,std::list<Param*>& params) : Visitor(root), mod_ast(root), macro_params(params) {};
+               Param* getParamByName(std::string name);
+               AST* getAST(void);
+       private:
+               void beforeVisit(AST* cur, int depth);
+               void afterVisit(AST* cur, int depth);
+               void beforeChildren(AST* cur, int depth);
+               void afterChildren(AST* cur, int depth);
+               void beforeChild(AST* cur, int depth);
+               void afterChild(AST* cur, int depth);
+};
+
+#endif
diff --git a/source/visitors/scheme/scheme.cpp b/source/visitors/scheme/scheme.cpp
new file mode 100644 (file)
index 0000000..8d6e259
--- /dev/null
@@ -0,0 +1,190 @@
+#include <fstream>
+#include "scheme.h"
+
+using namespace std;
+
+Scheme::Scheme(AST* root) : Visitor(root) {
+       ifstream input("res/environment.scm");
+       if (input.is_open())
+       {
+               while ( input.good() )
+               {
+                       string line;
+                       getline(input,line);
+                       stream << line << endl;
+               }
+    }
+    input.close();
+}
+
+string Scheme::str()
+{
+       return stream.str();
+}
+
+string Scheme::typeToString(ASTNodeType type)
+{
+       ostringstream ret;
+
+       switch (type)
+       {
+               case ID:
+                       ret << "ID "; break;
+               case NUM:
+                       ret << "NUM "; break;
+               case CHAR:
+                       ret << "CHAR "; break;
+               case ADD:
+                       ret << "ADD "; break;
+               case SUB:
+                       ret << "SUB "; break;
+               case MUL:
+                       ret << "MUL "; break;
+               case DIV:
+                       ret << "DIV "; break;
+               case AND:
+                       ret << "and "; break;
+               case OR:
+                       ret << "or "; break;
+               case NOT:
+                       ret << "NOT "; break;
+               case EQ:
+                       ret << "EQ "; break;
+               case NE:
+                       ret << "NE "; break;
+               case LT:
+                       ret << "LT "; break;
+               case GT:
+                       ret << "GT "; break;
+               case LTE:
+                       ret << "LTE "; break;
+               case GTE:
+                       ret << "GTE "; break;
+               case MACRO:
+                       ret << "MACRO "; break;
+               case ASSIGN:
+                       ret << "define "; break;
+               case PROGRAM:
+                       ret << "begin "; break;
+               case VECTOR:
+                       ret << "VECTOR "; break;
+               case LIST:
+                       ret << "LIST "; break;
+               case BLOCK:
+                       ret << "begin "; break;
+               case FUNC:
+                       ret << "lambda "; break;
+               case FN_CALL:
+                       ret << "FN_CALL "; break;
+               case ARRY_IDX:
+                       ret << "ARRY_IDX "; break;
+               case PARAMS:
+                       break;
+               default:
+                       ret << type; break;
+       }
+
+       return ret.str();
+}
+
+void Scheme::beforeVisit(AST* cur, int depth)
+{
+}
+
+void Scheme::afterVisit(AST* cur, int depth)
+{
+       stream << endl;
+}
+
+void Scheme::beforeChildren(AST* cur, int depth)
+{
+       if( isDatatype( cur->type() ) )
+       {
+               printDatatype( cur );
+       }
+       else
+       {
+               stream << "(" << typeToString( cur->type() ) << cur->text();
+       }
+}
+
+void Scheme::afterChildren(AST* cur, int depth)
+{
+       if( !isDatatype( cur->type() ) )
+       {
+               stream << ")";
+       }
+}
+
+void Scheme::beforeChild(AST* cur, int depth)
+{
+       stream << endl;
+       for(int i = 0; i< depth; i++)
+       {
+               stream << "  ";
+       }
+}
+
+void Scheme::afterChild(AST* cur, int depth)
+{
+}
+
+bool Scheme::isDatatype(ASTNodeType type)
+{
+       bool ret = false;
+       switch(type)
+       {
+               case ID:
+               case NUM:
+               case CHAR:
+               case STRING:
+               case SYMBOL:
+                       ret = true;
+                       break;
+               default:
+                       break;
+       }
+       return ret;
+}
+
+void Scheme::printDatatype(AST* cur)
+{
+       switch(cur->type())
+       {
+               case ID:
+                       stream << "dl/" << cur->text();
+                       break;
+               case NUM:
+                       stream << cur->text();
+                       break;
+               case CHAR:
+                       charToString( cur->text() );
+                       break;
+               case STRING:
+                       stream << '"' << cur->text() << '"';
+                       break;
+               case SYMBOL:
+                       stream << '\'' << cur->text();
+                       break;
+               default:
+                       break;
+       }
+}
+
+void Scheme::charToString(string ch)
+{
+       switch(ch.at(0))
+       {
+               case ' ':
+                       stream << "#\\space";
+                       break;
+               case '\n':
+                       stream << "#\\newline";
+                       break;
+               case '\r':
+                       stream << "#\\return";
+                       break;
+               default:
+                       stream << "#\\" << ch;
+       }
+}
diff --git a/source/visitors/scheme/scheme.h b/source/visitors/scheme/scheme.h
new file mode 100644 (file)
index 0000000..e477f4c
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef Scheme_H
+#define Scheme_H 
+
+#include <iostream>
+#include <sstream>
+#include "visitor.h"
+#include "dllexer.h"
+
+class Scheme : public Visitor {
+       protected:
+               ostringstream stream;
+       public:
+               Scheme(AST* root);
+               string str();
+               string typeToString(ASTNodeType type);
+               bool isDatatype(ASTNodeType type);
+               void printDatatype(AST* cur);
+               void charToString(string ch);
+       private:
+               void beforeVisit(AST* cur, int depth);
+               void afterVisit(AST* cur, int depth);
+               void beforeChildren(AST* cur, int depth);
+               void afterChildren(AST* cur, int depth);
+               void beforeChild(AST* cur, int depth);
+               void afterChild(AST* cur, int depth);
+};
+
+#endif
diff --git a/source/visitors/sexp/sexp.cpp b/source/visitors/sexp/sexp.cpp
new file mode 100644 (file)
index 0000000..f49d787
--- /dev/null
@@ -0,0 +1,41 @@
+#include "sexp.h"
+
+using namespace std;
+
+string SEXP::str()
+{
+       return stream.str();
+}
+
+void SEXP::beforeVisit(AST* cur, int depth)
+{
+}
+
+void SEXP::afterVisit(AST* cur, int depth)
+{
+       stream << endl;
+}
+
+void SEXP::beforeChildren(AST* cur, int depth)
+{
+       stream << "(" << cur->type() << " " << cur->text();
+}
+
+void SEXP::afterChildren(AST* cur, int depth)
+{
+       stream << ")";
+}
+
+void SEXP::beforeChild(AST* cur, int depth)
+{
+       stream << endl;
+       for(int i = 0; i< depth; i++)
+       {
+               stream << "  ";
+       }
+}
+
+void SEXP::afterChild(AST* cur, int depth)
+{
+}
+
diff --git a/source/visitors/sexp/sexp.h b/source/visitors/sexp/sexp.h
new file mode 100644 (file)
index 0000000..16cf992
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef SEXP_H
+#define SEXP_H 
+
+#include "visitor.h"
+#include <iostream>
+#include <sstream>
+
+class SEXP : public Visitor {
+       protected:
+               ostringstream stream;
+       public:
+               SEXP(AST* root) : Visitor(root) {};
+               string str();
+       private:
+               void beforeVisit(AST* cur, int depth);
+               void afterVisit(AST* cur, int depth);
+               void beforeChildren(AST* cur, int depth);
+               void afterChildren(AST* cur, int depth);
+               void beforeChild(AST* cur, int depth);
+               void afterChild(AST* cur, int depth);
+};
+
+#endif
diff --git a/tests/source/main.h b/tests/source/main.h
new file mode 100644 (file)
index 0000000..359d9a8
--- /dev/null
@@ -0,0 +1,18 @@
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite2 : public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+
+    void testMultiplication(void)
+    {
+        TS_TRACE("Starting multiplication test");
+        TS_ASSERT_EQUALS(2 * 2, 5);
+        TS_TRACE("Finishing multiplication test");
+    }
+};
diff --git a/tests/system/system_tests.dl b/tests/system/system_tests.dl
new file mode 100644 (file)
index 0000000..ce94648
--- /dev/null
@@ -0,0 +1,118 @@
+#------------------------------------------------------------------------------
+# Macro Tests
+#------------------------------------------------------------------------------
+# Macro Definitions
+% if ( cond, branch1:Block ) {
+       exec_if( cond, branch1 )
+}
+
+% ifelse ( cond, branch1:Block, branch2:Block ) {
+       exec_if( cond, branch1, branch2 )
+}
+
+% foreach ( lst, fn:Block ) {
+       for_each(fn, lst)
+}
+
+# Possible New Macro Syntax
+# _     Macro Name
+# Exp   Expression
+# Vctr  Vector
+# Lst   List
+# Blk   Block
+# ID    ID
+# Num   Number
+# Chr   Character
+# Str   String
+# Sym   Symbol
+#% if {
+#      (_ Exp Blk)   : exec_if( $1, $2 ) 
+#      (_ Exp Blk Blk) : exec_if( $1, $2, $3 )
+#}
+#
+#% if {
+#      (_ Exp Blk)   : exec_if( $1, $2 ) 
+#      (_ Exp Blk ID(else) Blk) : exec_if( $1, $2, $3 )
+#}
+
+# Macro Uses
+if (1 == 1)
+{
+       print("1 Hello, World!")
+}
+
+if (1 == 0)
+{
+       print("Hello, World!")
+}
+
+ifelse (1 == 1)
+{
+       print("2 Hello, World!")
+}{
+       error("Incorrect branch was taken.")
+}
+
+ifelse (1 == 0)
+{
+       error("Incorrect branch was taken.")
+}{
+       print("3 Hello, World!")
+}
+
+#------------------------------------------------------------------------------
+# Collection Access and Iteration Tests
+#------------------------------------------------------------------------------
+# Accessing elements of lists, vectors, and strings
+lst1 = `(4,5,6)
+print(lst1[0], " Hello, World!")
+
+vec1 = [4,5,6]
+print(vec1[1], " Hello, World!")
+
+str1 = "456"
+print(str1[2], " Hello, World!")
+
+# Iterating over lists, vectors, and strings
+lst_foo = `(7,8,9,10)
+foreach lst_foo { |a|
+       print(a," Hello, World!")
+}
+
+vec_foo = [11,12,13,14,15]
+foreach vec_foo { |a,b|
+       print(b," Hello, World!")
+}
+
+str_foo = "6789"
+foreach str_foo { |a|
+       print(1,a," Hello, World!")
+}
+
+#------------------------------------------------------------------------------
+# Delayed Evaluation
+#------------------------------------------------------------------------------
+% delay ( exp ) {
+       make_promise({ exp })
+}
+
+% force ( prom ) {
+       force( prom )
+}
+
+foo = delay nonexistent_var + 1
+nonexistent_var = 19
+assert( typeof(foo) == Block )
+assert( typeof( force foo ) == Num )
+print( force( foo ), " Hello, World!" )
+
+#------------------------------------------------------------------------------
+# Type Checking Tests
+#------------------------------------------------------------------------------
+assert( typeof( 1.1 ) == Num )
+assert( typeof( 'A' ) == Char )
+assert( typeof( `(1,2,3) ) == List )
+assert( typeof( [1,2,3] ) == Vector )
+assert( typeof( $Foo ) == Symbol )
+assert( typeof( {|a| a + 1} ) == Block )
+
diff --git a/tools/cxxtest/COPYING b/tools/cxxtest/COPYING
new file mode 100644 (file)
index 0000000..b1e3f5a
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/tools/cxxtest/README b/tools/cxxtest/README
new file mode 100644 (file)
index 0000000..437202c
--- /dev/null
@@ -0,0 +1,42 @@
+Overview
+--------
+
+CxxTest is a unit testing framework for C++ that is similar in
+spirit to JUnit, CppUnit, and xUnit. CxxTest is easy to use because
+it does not require precompiling a CxxTest testing library, it
+employs no advanced features of C++ (e.g. RTTI) and it supports a
+very flexible form of test discovery.
+
+CxxTest is available under the GNU Lesser General Public Licence (LGPL).
+
+A user guide is available in doc/guide.pdf.
+
+
+A Simple Example
+----------------
+
+1. Create a test suite header file:
+
+MyTest.h:
+  #include <cxxtest/TestSuite.h>
+
+  class MyTestSuite : public CxxTest::TestSuite 
+  {
+  public:
+      void testAddition( void )
+      {
+          TS_ASSERT( 1 + 1 > 1 );
+          TS_ASSERT_EQUALS( 1 + 1, 2 );
+      }
+  };
+
+
+2. Generate the tests file:
+
+ # cxxtestgen --error-printer -o tests.cpp MyTestSuite.h
+
+3. Compile and run!
+
+  # g++ -o main main.cpp tests.cpp
+  # ./main
+  Running 1 test(s).OK!
diff --git a/tools/cxxtest/Versions b/tools/cxxtest/Versions
new file mode 100644 (file)
index 0000000..ccc7ad9
--- /dev/null
@@ -0,0 +1,152 @@
+
+CxxTest Releases
+----------------
+
+* Version 4.0.3 (2012-01-07)
+ - Adding support for Python 2.4 - 3.2
+ - Various cleanup of CxxTest root directory
+ - Adding patch that allows the cxxtestgen script to be used when symlinked.
+
+* Version 4.0.2 (2012-01-02)
+ - Bug fix to enable installation of cxxtestgen without the 'setuptools' package
+
+* Version 4.0.1 (2012-01-01)
+ - Documentation updates
+ - Bug fix for installation of cxxtestgen script
+
+* Version 4.0 (2011-12-28)
+ - Perl is no longer used to support CxxTest scripts.  Python is now the only scripting language used by      CxxTest.
+ - The testing scripts have been rewritten using the PyUnit framework.
+ - The installation process for CxxTest now leverages and integrates with the system Python installation.
+ - A more comprehensive C++ parser is now available, which supports testing of templates.
+ - The CxxTest GUI is no longer supported, and the <<ts_warn,TS_WARN>> is deprecated.
+ - CxxTest runners now have a command-line interface that facilitates interative use of the test runner.
+ - A new user guide is now available in PDF, HTML and Ebook formats.
+
+* Version 3.10.1 (2004-12-01)
+ - Improved support for VC7
+ - Fixed clash with some versions of STL
+
+* Version 3.10.0 (2004-11-20)
+ - Added mock framework for global functions
+ - Added TS_ASSERT_THROWS_ASSERT and TS_ASSERT_THROWS_EQUALS
+ - Added CXXTEST_ENUM_TRAITS
+ - Improved support for STL classes (vector, map etc.)
+ - Added support for Digital Mars compiler
+ - Reduced root/part compilation time and binary size
+ - Support C++-style commenting of tests
+
+* Version 3.9.1 (2004-01-19)
+ - Fixed small bug with runner exit code
+ - Embedded test suites are now deprecated
+
+* Version 3.9.0 (2004-01-17)
+ - Added TS_TRACE
+ - Added --no-static-init
+ - CxxTest::setAbortTestOnFail() works even without --abort-on-fail
+
+* Version 3.8.5 (2004-01-08)
+ - Added --no-eh
+ - Added CxxTest::setAbortTestOnFail() and CXXTEST_DEFAULT_ABORT
+ - Added CxxTest::setMaxDumpSize()
+ - Added StdioFilePrinter
+
+* Version 3.8.4 (2003-12-31)
+ - Split distribution into cxxtest and cxxtest-selftest
+ - Added `sample/msvc/FixFiles.bat'
+
+* Version 3.8.3 (2003-12-24)
+ - Added TS_ASSERT_PREDICATE
+ - Template files can now specify where to insert the preamble
+ - Added a sample Visual Studio workspace in `sample/msvc'
+ - Can compile in MSVC with warning level 4
+ - Changed output format slightly
+
+* Version 3.8.1 (2003-12-21)
+ - Fixed small bug when using multiple --part files.
+ - Fixed X11 GUI crash when there's no X server.
+ - Added GlobalFixture::setUpWorld()/tearDownWorld()
+ - Added leaveOnly(), activateAllTests() and `sample/only.tpl'
+ - Should now run without warnings on Sun compiler.
+
+* Version 3.8.0 (2003-12-13)
+ - Fixed bug where `Root.cpp' needed exception handling
+ - Added TS_ASSERT_RELATION
+ - TSM_ macros now also tell you what went wrong
+ - Renamed Win32Gui::free() to avoid clashes
+ - Now compatible with more versions of Borland compiler
+ - Improved the documentation
+
+* Version 3.7.1 (2003-09-29)
+ - Added --version
+ - Compiles with even more exotic g++ warnings
+ - Win32 Gui compiles with UNICODE
+ - Should compile on some more platforms (Sun Forte, HP aCC)
+
+* Version 3.7.0 (2003-09-20)
+ - Added TS_ASSERT_LESS_THAN_EQUALS
+ - Minor cleanups
+
+* Version 3.6.1 (2003-09-15)
+ - Improved QT GUI
+ - Improved portability some more
+
+* Version 3.6.0 (2003-09-04)
+ - Added --longlong
+ - Some portability improvements
+
+* Version 3.5.1 (2003-09-03)
+ - Major internal rewrite of macros
+ - Added TS_ASSERT_SAME_DATA
+ - Added --include option
+ - Added --part and --root to enable splitting the test runner
+ - Added global fixtures
+ - Enhanced Win32 GUI with timers, -keep and -title
+ - Now compiles with strict warnings
+
+* Version 3.1.1 (2003-08-27)
+ - Fixed small bug in TS_ASSERT_THROWS_*()
+
+* Version 3.1.0 (2003-08-23)
+ - Default ValueTraits now dumps value as hex bytes
+ - Fixed double invocation bug (e.g. TS_FAIL(functionWithSideEffects()))
+ - TS_ASSERT_THROWS*() are now "abort on fail"-friendly
+ - Win32 GUI now supports Windows 98 and doesn't need comctl32.lib
+
+* Version 3.0.1 (2003-08-07)
+ - Added simple GUI for X11, Win32 and Qt
+ - Added TS_WARN() macro
+ - Removed --exit-code
+ - Improved samples
+ - Improved support for older (pre-std::) compilers
+ - Made a PDF version of the User's Guide
+
+* Version 2.8.4 (2003-07-21)
+ - Now supports g++-3.3
+ - Added --have-eh
+ - Fixed bug in numberToString()
+
+* Version 2.8.3 (2003-06-30)
+ - Fixed bugs in cxxtestgen.pl
+ - Fixed warning for some compilers in ErrorPrinter/StdioPrinter
+ - Thanks Martin Jost for pointing out these problems!
+
+* Version 2.8.2 (2003-06-10)
+ - Fixed bug when using CXXTEST_ABORT_TEST_ON_FAIL without standard library
+ - Added CXXTEST_USER_TRAITS
+ - Added --abort-on-fail
+
+* Version 2.8.1 (2003-01-16)
+ - Fixed charToString() for negative chars
+
+* Version 2.8.0 (2003-01-13)
+ - Added CXXTEST_ABORT_TEST_ON_FAIL for xUnit-like behaviour
+ - Added `sample/winddk'
+ - Improved ValueTraits
+ - Improved output formatter
+ - Started version history
+
+* Version 2.7.0 (2002-09-29)
+ - Added embedded test suites
+ - Major internal improvements
+
diff --git a/tools/cxxtest/admin/cxxtest.spec b/tools/cxxtest/admin/cxxtest.spec
new file mode 100644 (file)
index 0000000..b25f135
--- /dev/null
@@ -0,0 +1,37 @@
+Name: cxxtest
+Summary: CxxTest Testing Framework for C++
+Version: %{version}
+Release: 1
+Copyright: LGPL
+Group: Development/C++
+Source: cxxtest-%{version}.tar.gz
+BuildRoot: /tmp/cxxtest-build
+BuildArch: noarch
+Prefix: /usr
+
+%description
+CxxTest is a unit testing framework for C++ that is similar in
+spirit to JUnit, CppUnit, and xUnit. CxxTest is easy to use because
+it does not require precompiling a CxxTest testing library, it
+employs no advanced features of C++ (e.g. RTTI) and it supports a
+very flexible form of test discovery.
+
+%prep
+%setup -n cxxtest
+
+%build
+
+%install
+install -m 755 -d $RPM_BUILD_ROOT/usr/bin $RPM_BUILD_ROOT/usr/include/cxxtest
+install -m 755 bin/cxxtestgen $RPM_BUILD_ROOT/usr/bin/
+install -m 644 cxxtest/* $RPM_BUILD_ROOT/usr/include/cxxtest/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%attr(-, root, root) %doc README
+%attr(-, root, root) %doc sample
+%attr(-, root, root) /usr/include/cxxtest
+%attr(-, root, root) /usr/bin/cxxtestgen
+
diff --git a/tools/cxxtest/admin/jenkins_cxxtest b/tools/cxxtest/admin/jenkins_cxxtest
new file mode 100644 (file)
index 0000000..902f595
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+export PATH=$WORKSPACE/vpython/bin:$PATH
+g++ --version
+
+# Setup virtual Python environment
+\rm -Rf vpython
+python cxxtest/admin/virtualenv.py vpython
+#vpy/scripts/vpy_install
+vpython/bin/easy_install nose
+vpython/bin/easy_install unittest2
+vpython/bin/easy_install ply
+vpython/bin/easy_install ordereddict
+vpython/bin/easy_install gcovr
+vpython/bin/easy_install pyutilib.th
+cd cxxtest/python
+../../vpython/bin/python setup.py install
+
+# Cleanup test directory
+cd ../test
+make clean
+cd ../..
+
+# Run tests
+export CXXTEST_GCOV_FLAGS='-fprofile-arcs -ftest-coverage'
+vpython/bin/nosetests -v -v --with-xunit --xunit-file=$WORKSPACE/TEST-cxxtest.xml -w $WORKSPACE/cxxtest/test
+
+# Generate code coverage
+cd cxxtest
+../vpython/bin/gcovr -v -r $WORKSPACE/cxxtest -x -o $WORKSPACE/cxxtest/test/coverage.xml --gcov-filter '.*#test#(\.\.|\^)#cxxtest#.*gcov'
+
+echo "DONE"
+
+# Cleanup old gcov files
+cd $WORKSPACE
+\rm -f *.gcov cxxtest/*.gcov doc/*.gcov doc/examples/*.gcov
+\rm -f *.gcno cxxtest/*.gcno doc/*.gcno doc/examples/*.gcno
+\rm -f *.gcda cxxtest/*.gcda doc/*.gcda doc/examples/*.gcda
+cd $WORKSPACE/cxxtest/test
+make clean
+
diff --git a/tools/cxxtest/admin/release b/tools/cxxtest/admin/release
new file mode 100644 (file)
index 0000000..da657f8
--- /dev/null
@@ -0,0 +1,32 @@
+#! /usr/bin/env python
+
+import subprocess
+import sys
+import os
+
+if len(sys.argv) == 1:
+    print "Must specify release version"
+    sys.exit(1)
+
+rev = sys.argv[1]
+
+if os.path.exists('cxxtest'):
+    subprocess.call('rm -Rf cxxtest', shell=True)
+if os.path.exists(rev):
+    subprocess.call('rm -Rf '+rev, shell=True)
+
+subprocess.call('svn export https://cxxtest.svn.sourceforge.net/svnroot/cxxtest/tags/%s cxxtest' % rev, shell=True)
+
+if not os.path.exists('cxxtest'):
+    print "Error exporting release "+rev
+    sys.exit(1)
+
+os.mkdir(rev)
+
+subprocess.call('tar cvf - cxxtest > %s/cxxtest-%s.tar' % (rev,rev), shell=True)
+subprocess.call('gzip %s/cxxtest-%s.tar' % (rev,rev), shell=True)
+subprocess.call('cp cxxtest/doc/guide.pdf %s/cxxtest-guide-%s.pdf' % (rev,rev), shell=True)
+subprocess.call('cp cxxtest/doc/guide.html %s/cxxtest-guide-%s.html' % (rev,rev), shell=True)
+subprocess.call('cp cxxtest/doc/guide.epub %s/cxxtest-guide-%s.epub' % (rev,rev), shell=True)
+subprocess.call('zip -r %s/cxxtest-%s.zip cxxtest' % (rev,rev), shell=True)
+
diff --git a/tools/cxxtest/admin/virtualenv.py b/tools/cxxtest/admin/virtualenv.py
new file mode 100644 (file)
index 0000000..5b4951d
--- /dev/null
@@ -0,0 +1,2102 @@
+#!/usr/bin/env python
+"""Create a "virtual" Python installation
+"""
+
+# If you change the version here, change it in setup.py
+# and docs/conf.py as well.
+virtualenv_version = "1.7"
+
+import base64
+import sys
+import os
+import optparse
+import re
+import shutil
+import logging
+import tempfile
+import zlib
+import errno
+import distutils.sysconfig
+from distutils.util import strtobool
+
+try:
+    import subprocess
+except ImportError:
+    if sys.version_info <= (2, 3):
+        print('ERROR: %s' % sys.exc_info()[1])
+        print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
+        print('If you copy subprocess.py from a newer version of Python this script will probably work')
+        sys.exit(101)
+    else:
+        raise
+try:
+    set
+except NameError:
+    from sets import Set as set
+try:
+    basestring
+except NameError:
+    basestring = str
+
+try:
+    import ConfigParser
+except ImportError:
+    import configparser as ConfigParser
+
+join = os.path.join
+py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
+
+is_jython = sys.platform.startswith('java')
+is_pypy = hasattr(sys, 'pypy_version_info')
+is_win  = (sys.platform == 'win32')
+abiflags = getattr(sys, 'abiflags', '')
+
+user_dir = os.path.expanduser('~')
+if sys.platform == 'win32':
+    user_dir = os.environ.get('APPDATA', user_dir)  # Use %APPDATA% for roaming
+    default_storage_dir = os.path.join(user_dir, 'virtualenv')
+else:
+    default_storage_dir = os.path.join(user_dir, '.virtualenv')
+default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
+
+if is_pypy:
+    expected_exe = 'pypy'
+elif is_jython:
+    expected_exe = 'jython'
+else:
+    expected_exe = 'python'
+
+
+REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
+                    'fnmatch', 'locale', 'encodings', 'codecs',
+                    'stat', 'UserDict', 'readline', 'copy_reg', 'types',
+                    're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
+                    'zlib']
+
+REQUIRED_FILES = ['lib-dynload', 'config']
+
+majver, minver = sys.version_info[:2]
+if majver == 2:
+    if minver >= 6:
+        REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
+    if minver >= 7:
+        REQUIRED_MODULES.extend(['_weakrefset'])
+    if minver <= 3:
+        REQUIRED_MODULES.extend(['sets', '__future__'])
+elif majver == 3:
+    # Some extra modules are needed for Python 3, but different ones
+    # for different versions.
+    REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
+                             '_weakrefset', 'copyreg', 'tempfile', 'random',
+                             '__future__', 'collections', 'keyword', 'tarfile',
+                             'shutil', 'struct', 'copy'])
+    if minver >= 2:
+        REQUIRED_FILES[-1] = 'config-%s' % majver
+    if minver == 3:
+        # The whole list of 3.3 modules is reproduced below - the current
+        # uncommented ones are required for 3.3 as of now, but more may be
+        # added as 3.3 development continues.
+        REQUIRED_MODULES.extend([
+            #"aifc",
+            #"antigravity",
+            #"argparse",
+            #"ast",
+            #"asynchat",
+            #"asyncore",
+            "base64",
+            #"bdb",
+            #"binhex",
+            "bisect",
+            #"calendar",
+            #"cgi",
+            #"cgitb",
+            #"chunk",
+            #"cmd",
+            #"codeop",
+            #"code",
+            #"colorsys",
+            #"_compat_pickle",
+            #"compileall",
+            #"concurrent",
+            #"configparser",
+            #"contextlib",
+            #"cProfile",
+            #"crypt",
+            #"csv",
+            #"ctypes",
+            #"curses",
+            #"datetime",
+            #"dbm",
+            #"decimal",
+            #"difflib",
+            #"dis",
+            #"doctest",
+            #"dummy_threading",
+            "_dummy_thread",
+            #"email",
+            #"filecmp",
+            #"fileinput",
+            #"formatter",
+            #"fractions",
+            #"ftplib",
+            #"functools",
+            #"getopt",
+            #"getpass",
+            #"gettext",
+            #"glob",
+            #"gzip",
+            "hashlib",
+            "heapq",
+            "hmac",
+            #"html",
+            #"http",
+            #"idlelib",
+            #"imaplib",
+            #"imghdr",
+            #"importlib",
+            #"inspect",
+            #"json",
+            #"lib2to3",
+            #"logging",
+            #"macpath",
+            #"macurl2path",
+            #"mailbox",
+            #"mailcap",
+            #"_markupbase",
+            #"mimetypes",
+            #"modulefinder",
+            #"multiprocessing",
+            #"netrc",
+            #"nntplib",
+            #"nturl2path",
+            #"numbers",
+            #"opcode",
+            #"optparse",
+            #"os2emxpath",
+            #"pdb",
+            #"pickle",
+            #"pickletools",
+            #"pipes",
+            #"pkgutil",
+            #"platform",
+            #"plat-linux2",
+            #"plistlib",
+            #"poplib",
+            #"pprint",
+            #"profile",
+            #"pstats",
+            #"pty",
+            #"pyclbr",
+            #"py_compile",
+            #"pydoc_data",
+            #"pydoc",
+            #"_pyio",
+            #"queue",
+            #"quopri",
+            "reprlib",
+            "rlcompleter",
+            #"runpy",
+            #"sched",
+            #"shelve",
+            #"shlex",
+            #"smtpd",
+            #"smtplib",
+            #"sndhdr",
+            #"socket",
+            #"socketserver",
+            #"sqlite3",
+            #"ssl",
+            #"stringprep",
+            #"string",
+            #"_strptime",
+            #"subprocess",
+            #"sunau",
+            #"symbol",
+            #"symtable",
+            #"sysconfig",
+            #"tabnanny",
+            #"telnetlib",
+            #"test",
+            #"textwrap",
+            #"this",
+            #"_threading_local",
+            #"threading",
+            #"timeit",
+            #"tkinter",
+            #"tokenize",
+            #"token",
+            #"traceback",
+            #"trace",
+            #"tty",
+            #"turtledemo",
+            #"turtle",
+            #"unittest",
+            #"urllib",
+            #"uuid",
+            #"uu",
+            #"wave",
+            "weakref",
+            #"webbrowser",
+            #"wsgiref",
+            #"xdrlib",
+            #"xml",
+            #"xmlrpc",
+            #"zipfile",
+        ])
+
+if is_pypy:
+    # these are needed to correctly display the exceptions that may happen
+    # during the bootstrap
+    REQUIRED_MODULES.extend(['traceback', 'linecache'])
+
+class Logger(object):
+
+    """
+    Logging object for use in command-line script.  Allows ranges of
+    levels, to avoid some redundancy of displayed information.
+    """
+
+    DEBUG = logging.DEBUG
+    INFO = logging.INFO
+    NOTIFY = (logging.INFO+logging.WARN)/2
+    WARN = WARNING = logging.WARN
+    ERROR = logging.ERROR
+    FATAL = logging.FATAL
+
+    LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
+
+    def __init__(self, consumers):
+        self.consumers = consumers
+        self.indent = 0
+        self.in_progress = None
+        self.in_progress_hanging = False
+
+    def debug(self, msg, *args, **kw):
+        self.log(self.DEBUG, msg, *args, **kw)
+    def info(self, msg, *args, **kw):
+        self.log(self.INFO, msg, *args, **kw)
+    def notify(self, msg, *args, **kw):
+        self.log(self.NOTIFY, msg, *args, **kw)
+    def warn(self, msg, *args, **kw):
+        self.log(self.WARN, msg, *args, **kw)
+    def error(self, msg, *args, **kw):
+        self.log(self.WARN, msg, *args, **kw)
+    def fatal(self, msg, *args, **kw):
+        self.log(self.FATAL, msg, *args, **kw)
+    def log(self, level, msg, *args, **kw):
+        if args:
+            if kw:
+                raise TypeError(
+                    "You may give positional or keyword arguments, not both")
+        args = args or kw
+        rendered = None
+        for consumer_level, consumer in self.consumers:
+            if self.level_matches(level, consumer_level):
+                if (self.in_progress_hanging
+                    and consumer in (sys.stdout, sys.stderr)):
+                    self.in_progress_hanging = False
+                    sys.stdout.write('\n')
+                    sys.stdout.flush()
+                if rendered is None:
+                    if args:
+                        rendered = msg % args
+                    else:
+                        rendered = msg
+                    rendered = ' '*self.indent + rendered
+                if hasattr(consumer, 'write'):
+                    consumer.write(rendered+'\n')
+                else:
+                    consumer(rendered)
+
+    def start_progress(self, msg):
+        assert not self.in_progress, (
+            "Tried to start_progress(%r) while in_progress %r"
+            % (msg, self.in_progress))
+        if self.level_matches(self.NOTIFY, self._stdout_level()):
+            sys.stdout.write(msg)
+            sys.stdout.flush()
+            self.in_progress_hanging = True
+        else:
+            self.in_progress_hanging = False
+        self.in_progress = msg
+
+    def end_progress(self, msg='done.'):
+        assert self.in_progress, (
+            "Tried to end_progress without start_progress")
+        if self.stdout_level_matches(self.NOTIFY):
+            if not self.in_progress_hanging:
+                # Some message has been printed out since start_progress
+                sys.stdout.write('...' + self.in_progress + msg + '\n')
+                sys.stdout.flush()
+            else:
+                sys.stdout.write(msg + '\n')
+                sys.stdout.flush()
+        self.in_progress = None
+        self.in_progress_hanging = False
+
+    def show_progress(self):
+        """If we are in a progress scope, and no log messages have been
+        shown, write out another '.'"""
+        if self.in_progress_hanging:
+            sys.stdout.write('.')
+            sys.stdout.flush()
+
+    def stdout_level_matches(self, level):
+        """Returns true if a message at this level will go to stdout"""
+        return self.level_matches(level, self._stdout_level())
+
+    def _stdout_level(self):
+        """Returns the level that stdout runs at"""
+        for level, consumer in self.consumers:
+            if consumer is sys.stdout:
+                return level
+        return self.FATAL
+
+    def level_matches(self, level, consumer_level):
+        """
+        >>> l = Logger([])
+        >>> l.level_matches(3, 4)
+        False
+        >>> l.level_matches(3, 2)
+        True
+        >>> l.level_matches(slice(None, 3), 3)
+        False
+        >>> l.level_matches(slice(None, 3), 2)
+        True
+        >>> l.level_matches(slice(1, 3), 1)
+        True
+        >>> l.level_matches(slice(2, 3), 1)
+        False
+        """
+        if isinstance(level, slice):
+            start, stop = level.start, level.stop
+            if start is not None and start > consumer_level:
+                return False
+            if stop is not None and stop <= consumer_level:
+                return False
+            return True
+        else:
+            return level >= consumer_level
+
+    #@classmethod
+    def level_for_integer(cls, level):
+        levels = cls.LEVELS
+        if level < 0:
+            return levels[0]
+        if level >= len(levels):
+            return levels[-1]
+        return levels[level]
+
+    level_for_integer = classmethod(level_for_integer)
+
+# create a silent logger just to prevent this from being undefined
+# will be overridden with requested verbosity main() is called.
+logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
+
+def mkdir(path):
+    if not os.path.exists(path):
+        logger.info('Creating %s', path)
+        os.makedirs(path)
+    else:
+        logger.info('Directory %s already exists', path)
+
+def copyfileordir(src, dest):
+    if os.path.isdir(src):
+        shutil.copytree(src, dest, True)
+    else:
+        shutil.copy2(src, dest)
+
+def copyfile(src, dest, symlink=True):
+    if not os.path.exists(src):
+        # Some bad symlink in the src
+        logger.warn('Cannot find file %s (bad symlink)', src)
+        return
+    if os.path.exists(dest):
+        logger.debug('File %s already exists', dest)
+        return
+    if not os.path.exists(os.path.dirname(dest)):
+        logger.info('Creating parent directories for %s' % os.path.dirname(dest))
+        os.makedirs(os.path.dirname(dest))
+    if not os.path.islink(src):
+        srcpath = os.path.abspath(src)
+    else:
+        srcpath = os.readlink(src)
+    if symlink and hasattr(os, 'symlink'):
+        logger.info('Symlinking %s', dest)
+        try:
+            os.symlink(srcpath, dest)
+        except (OSError, NotImplementedError):
+            logger.info('Symlinking failed, copying to %s', dest)
+            copyfileordir(src, dest)
+    else:
+        logger.info('Copying to %s', dest)
+        copyfileordir(src, dest)
+
+def writefile(dest, content, overwrite=True):
+    if not os.path.exists(dest):
+        logger.info('Writing %s', dest)
+        f = open(dest, 'wb')
+        f.write(content.encode('utf-8'))
+        f.close()
+        return
+    else:
+        f = open(dest, 'rb')
+        c = f.read()
+        f.close()
+        if c != content:
+            if not overwrite:
+                logger.notify('File %s exists with different content; not overwriting', dest)
+                return
+            logger.notify('Overwriting %s with new content', dest)
+            f = open(dest, 'wb')
+            f.write(content.encode('utf-8'))
+            f.close()
+        else:
+            logger.info('Content %s already in place', dest)
+
+def rmtree(dir):
+    if os.path.exists(dir):
+        logger.notify('Deleting tree %s', dir)
+        shutil.rmtree(dir)
+    else:
+        logger.info('Do not need to delete %s; already gone', dir)
+
+def make_exe(fn):
+    if hasattr(os, 'chmod'):
+        oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
+        newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
+        os.chmod(fn, newmode)
+        logger.info('Changed mode of %s to %s', fn, oct(newmode))
+
+def _find_file(filename, dirs):
+    for dir in dirs:
+        if os.path.exists(join(dir, filename)):
+            return join(dir, filename)
+    return filename
+
+def _install_req(py_executable, unzip=False, distribute=False,
+                 search_dirs=None, never_download=False):
+
+    if search_dirs is None:
+        search_dirs = file_search_dirs()
+
+    if not distribute:
+        setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3]
+        project_name = 'setuptools'
+        bootstrap_script = EZ_SETUP_PY
+        source = None
+    else:
+        setup_fn = None
+        source = 'distribute-0.6.24.tar.gz'
+        project_name = 'distribute'
+        bootstrap_script = DISTRIBUTE_SETUP_PY
+
+    if setup_fn is not None:
+        setup_fn = _find_file(setup_fn, search_dirs)
+
+    if source is not None:
+        source = _find_file(source, search_dirs)
+
+    if is_jython and os._name == 'nt':
+        # Jython's .bat sys.executable can't handle a command line
+        # argument with newlines
+        fd, ez_setup = tempfile.mkstemp('.py')
+        os.write(fd, bootstrap_script)
+        os.close(fd)
+        cmd = [py_executable, ez_setup]
+    else:
+        cmd = [py_executable, '-c', bootstrap_script]
+    if unzip:
+        cmd.append('--always-unzip')
+    env = {}
+    remove_from_env = []
+    if logger.stdout_level_matches(logger.DEBUG):
+        cmd.append('-v')
+
+    old_chdir = os.getcwd()
+    if setup_fn is not None and os.path.exists(setup_fn):
+        logger.info('Using existing %s egg: %s' % (project_name, setup_fn))
+        cmd.append(setup_fn)
+        if os.environ.get('PYTHONPATH'):
+            env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH']
+        else:
+            env['PYTHONPATH'] = setup_fn
+    else:
+        # the source is found, let's chdir
+        if source is not None and os.path.exists(source):
+            logger.info('Using existing %s egg: %s' % (project_name, source))
+            os.chdir(os.path.dirname(source))
+            # in this case, we want to be sure that PYTHONPATH is unset (not
+            # just empty, really unset), else CPython tries to import the
+            # site.py that it's in virtualenv_support
+            remove_from_env.append('PYTHONPATH')
+        else:
+            if never_download:
+                logger.fatal("Can't find any local distributions of %s to install "
+                             "and --never-download is set.  Either re-run virtualenv "
+                             "without the --never-download option, or place a %s "
+                             "distribution (%s) in one of these "
+                             "locations: %r" % (project_name, project_name,
+                                                setup_fn or source,
+                                                search_dirs))
+                sys.exit(1)
+
+            logger.info('No %s egg found; downloading' % project_name)
+        cmd.extend(['--always-copy', '-U', project_name])
+    logger.start_progress('Installing %s...' % project_name)
+    logger.indent += 2
+    cwd = None
+    if project_name == 'distribute':
+        env['DONT_PATCH_SETUPTOOLS'] = 'true'
+
+    def _filter_ez_setup(line):
+        return filter_ez_setup(line, project_name)
+
+    if not os.access(os.getcwd(), os.W_OK):
+        cwd = tempfile.mkdtemp()
+        if source is not None and os.path.exists(source):
+            # the current working dir is hostile, let's copy the
+            # tarball to a temp dir
+            target = os.path.join(cwd, os.path.split(source)[-1])
+            shutil.copy(source, target)
+    try:
+        call_subprocess(cmd, show_stdout=False,
+                        filter_stdout=_filter_ez_setup,
+                        extra_env=env,
+                        remove_from_env=remove_from_env,
+                        cwd=cwd)
+    finally:
+        logger.indent -= 2
+        logger.end_progress()
+        if os.getcwd() != old_chdir:
+            os.chdir(old_chdir)
+        if is_jython and os._name == 'nt':
+            os.remove(ez_setup)
+
+def file_search_dirs():
+    here = os.path.dirname(os.path.abspath(__file__))
+    dirs = ['.', here,
+            join(here, 'virtualenv_support')]
+    if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
+        # Probably some boot script; just in case virtualenv is installed...
+        try:
+            import virtualenv
+        except ImportError:
+            pass
+        else:
+            dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
+    return [d for d in dirs if os.path.isdir(d)]
+
+def install_setuptools(py_executable, unzip=False,
+                       search_dirs=None, never_download=False):
+    _install_req(py_executable, unzip,
+                 search_dirs=search_dirs, never_download=never_download)
+
+def install_distribute(py_executable, unzip=False,
+                       search_dirs=None, never_download=False):
+    _install_req(py_executable, unzip, distribute=True,
+                 search_dirs=search_dirs, never_download=never_download)
+
+_pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I)
+def install_pip(py_executable, search_dirs=None, never_download=False):
+    if search_dirs is None:
+        search_dirs = file_search_dirs()
+
+    filenames = []
+    for dir in search_dirs:
+        filenames.extend([join(dir, fn) for fn in os.listdir(dir)
+                          if _pip_re.search(fn)])
+    filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)]
+    filenames.sort()
+    filenames = [filename for basename, i, filename in filenames]
+    if not filenames:
+        filename = 'pip'
+    else:
+        filename = filenames[-1]
+    easy_install_script = 'easy_install'
+    if sys.platform == 'win32':
+        easy_install_script = 'easy_install-script.py'
+    cmd = [join(os.path.dirname(py_executable), easy_install_script), filename]
+    if sys.platform == 'win32':
+        cmd.insert(0, py_executable)
+    if filename == 'pip':
+        if never_download:
+            logger.fatal("Can't find any local distributions of pip to install "
+                         "and --never-download is set.  Either re-run virtualenv "
+                         "without the --never-download option, or place a pip "
+                         "source distribution (zip/tar.gz/tar.bz2) in one of these "
+                         "locations: %r" % search_dirs)
+            sys.exit(1)
+        logger.info('Installing pip from network...')
+    else:
+        logger.info('Installing existing %s distribution: %s' % (
+                os.path.basename(filename), filename))
+    logger.start_progress('Installing pip...')
+    logger.indent += 2
+    def _filter_setup(line):
+        return filter_ez_setup(line, 'pip')
+    try:
+        call_subprocess(cmd, show_stdout=False,
+                        filter_stdout=_filter_setup)
+    finally:
+        logger.indent -= 2
+        logger.end_progress()
+
+def filter_ez_setup(line, project_name='setuptools'):
+    if not line.strip():
+        return Logger.DEBUG
+    if project_name == 'distribute':
+        for prefix in ('Extracting', 'Now working', 'Installing', 'Before',
+                       'Scanning', 'Setuptools', 'Egg', 'Already',
+                       'running', 'writing', 'reading', 'installing',
+                       'creating', 'copying', 'byte-compiling', 'removing',
+                       'Processing'):
+            if line.startswith(prefix):
+                return Logger.DEBUG
+        return Logger.DEBUG
+    for prefix in ['Reading ', 'Best match', 'Processing setuptools',
+                   'Copying setuptools', 'Adding setuptools',
+                   'Installing ', 'Installed ']:
+        if line.startswith(prefix):
+            return Logger.DEBUG
+    return Logger.INFO
+
+
+class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
+    """
+    Custom help formatter for use in ConfigOptionParser that updates
+    the defaults before expanding them, allowing them to show up correctly
+    in the help listing
+    """
+    def expand_default(self, option):
+        if self.parser is not None:
+            self.parser.update_defaults(self.parser.defaults)
+        return optparse.IndentedHelpFormatter.expand_default(self, option)
+
+
+class ConfigOptionParser(optparse.OptionParser):
+    """
+    Custom option parser which updates its defaults by by checking the
+    configuration files and environmental variables
+    """
+    def __init__(self, *args, **kwargs):
+        self.config = ConfigParser.RawConfigParser()
+        self.files = self.get_config_files()
+        self.config.read(self.files)
+        optparse.OptionParser.__init__(self, *args, **kwargs)
+
+    def get_config_files(self):
+        config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
+        if config_file and os.path.exists(config_file):
+            return [config_file]
+        return [default_config_file]
+
+    def update_defaults(self, defaults):
+        """
+        Updates the given defaults with values from the config files and
+        the environ. Does a little special handling for certain types of
+        options (lists).
+        """
+        # Then go and look for the other sources of configuration:
+        config = {}
+        # 1. config files
+        config.update(dict(self.get_config_section('virtualenv')))
+        # 2. environmental variables
+        config.update(dict(self.get_environ_vars()))
+        # Then set the options with those values
+        for key, val in config.items():
+            key = key.replace('_', '-')
+            if not key.startswith('--'):
+                key = '--%s' % key  # only prefer long opts
+            option = self.get_option(key)
+            if option is not None:
+                # ignore empty values
+                if not val:
+                    continue
+                # handle multiline configs
+                if option.action == 'append':
+                    val = val.split()
+                else:
+                    option.nargs = 1
+                if option.action in ('store_true', 'store_false', 'count'):
+                    val = strtobool(val)
+                try:
+                    val = option.convert_value(key, val)
+                except optparse.OptionValueError:
+                    e = sys.exc_info()[1]
+                    print("An error occured during configuration: %s" % e)
+                    sys.exit(3)
+                defaults[option.dest] = val
+        return defaults
+
+    def get_config_section(self, name):
+        """
+        Get a section of a configuration
+        """
+        if self.config.has_section(name):
+            return self.config.items(name)
+        return []
+
+    def get_environ_vars(self, prefix='VIRTUALENV_'):
+        """
+        Returns a generator with all environmental vars with prefix VIRTUALENV
+        """
+        for key, val in os.environ.items():
+            if key.startswith(prefix):
+                yield (key.replace(prefix, '').lower(), val)
+
+    def get_default_values(self):
+        """
+        Overridding to make updating the defaults after instantiation of
+        the option parser possible, update_defaults() does the dirty work.
+        """
+        if not self.process_default_values:
+            # Old, pre-Optik 1.5 behaviour.
+            return optparse.Values(self.defaults)
+
+        defaults = self.update_defaults(self.defaults.copy()) # ours
+        for option in self._get_all_options():
+            default = defaults.get(option.dest)
+            if isinstance(default, basestring):
+                opt_str = option.get_opt_string()
+                defaults[option.dest] = option.check_value(opt_str, default)
+        return optparse.Values(defaults)
+
+
+def main():
+    parser = ConfigOptionParser(
+        version=virtualenv_version,
+        usage="%prog [OPTIONS] DEST_DIR",
+        formatter=UpdatingDefaultsHelpFormatter())
+
+    parser.add_option(
+        '-v', '--verbose',
+        action='count',
+        dest='verbose',
+        default=0,
+        help="Increase verbosity")
+
+    parser.add_option(
+        '-q', '--quiet',
+        action='count',
+        dest='quiet',
+        default=0,
+        help='Decrease verbosity')
+
+    parser.add_option(
+        '-p', '--python',
+        dest='python',
+        metavar='PYTHON_EXE',
+        help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
+        'interpreter to create the new environment.  The default is the interpreter that '
+        'virtualenv was installed with (%s)' % sys.executable)
+
+    parser.add_option(
+        '--clear',
+        dest='clear',
+        action='store_true',
+        help="Clear out the non-root install and start from scratch")
+
+    parser.add_option(
+        '--no-site-packages',
+        dest='no_site_packages',
+        action='store_true',
+        help="Don't give access to the global site-packages dir to the "
+             "virtual environment")
+
+    parser.add_option(
+        '--system-site-packages',
+        dest='system_site_packages',
+        action='store_true',
+        help="Give access to the global site-packages dir to the "
+             "virtual environment")
+
+    parser.add_option(
+        '--unzip-setuptools',
+        dest='unzip_setuptools',
+        action='store_true',
+        help="Unzip Setuptools or Distribute when installing it")
+
+    parser.add_option(
+        '--relocatable',
+        dest='relocatable',
+        action='store_true',
+        help='Make an EXISTING virtualenv environment relocatable.  '
+        'This fixes up scripts and makes all .pth files relative')
+
+    parser.add_option(
+        '--distribute',
+        dest='use_distribute',
+        action='store_true',
+        help='Use Distribute instead of Setuptools. Set environ variable '
+        'VIRTUALENV_DISTRIBUTE to make it the default ')
+
+    default_search_dirs = file_search_dirs()
+    parser.add_option(
+        '--extra-search-dir',
+        dest="search_dirs",
+        action="append",
+        default=default_search_dirs,
+        help="Directory to look for setuptools/distribute/pip distributions in. "
+        "You can add any number of additional --extra-search-dir paths.")
+
+    parser.add_option(
+        '--never-download',
+        dest="never_download",
+        action="store_true",
+        help="Never download anything from the network.  Instead, virtualenv will fail "
+        "if local distributions of setuptools/distribute/pip are not present.")
+
+    parser.add_option(
+        '--prompt=',
+        dest='prompt',
+        help='Provides an alternative prompt prefix for this environment')
+
+    if 'extend_parser' in globals():
+        extend_parser(parser)
+
+    options, args = parser.parse_args()
+
+    global logger
+
+    if 'adjust_options' in globals():
+        adjust_options(options, args)
+
+    verbosity = options.verbose - options.quiet
+    logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
+
+    if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
+        env = os.environ.copy()
+        interpreter = resolve_interpreter(options.python)
+        if interpreter == sys.executable:
+            logger.warn('Already using interpreter %s' % interpreter)
+        else:
+            logger.notify('Running virtualenv with interpreter %s' % interpreter)
+            env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
+            file = __file__
+            if file.endswith('.pyc'):
+                file = file[:-1]
+            popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
+            raise SystemExit(popen.wait())
+
+    # Force --use-distribute on Python 3, since setuptools is not available.
+    if majver > 2:
+        options.use_distribute = True
+
+    if os.environ.get('PYTHONDONTWRITEBYTECODE') and not options.use_distribute:
+        print(
+            "The PYTHONDONTWRITEBYTECODE environment variable is "
+            "not compatible with setuptools. Either use --distribute "
+            "or unset PYTHONDONTWRITEBYTECODE.")
+        sys.exit(2)
+    if not args:
+        print('You must provide a DEST_DIR')
+        parser.print_help()
+        sys.exit(2)
+    if len(args) > 1:
+        print('There must be only one argument: DEST_DIR (you gave %s)' % (
+            ' '.join(args)))
+        parser.print_help()
+        sys.exit(2)
+
+    home_dir = args[0]
+
+    if os.environ.get('WORKING_ENV'):
+        logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
+        logger.fatal('Please deactivate your workingenv, then re-run this script')
+        sys.exit(3)
+
+    if 'PYTHONHOME' in os.environ:
+        logger.warn('PYTHONHOME is set.  You *must* activate the virtualenv before using it')
+        del os.environ['PYTHONHOME']
+
+    if options.relocatable:
+        make_environment_relocatable(home_dir)
+        return
+
+    if options.no_site_packages:
+        logger.warn('The --no-site-packages flag is deprecated; it is now '
+                    'the default behavior.')
+
+    create_environment(home_dir,
+                       site_packages=options.system_site_packages,
+                       clear=options.clear,
+                       unzip_setuptools=options.unzip_setuptools,
+                       use_distribute=options.use_distribute,
+                       prompt=options.prompt,
+                       search_dirs=options.search_dirs,
+                       never_download=options.never_download)
+    if 'after_install' in globals():
+        after_install(options, home_dir)
+
+def call_subprocess(cmd, show_stdout=True,
+                    filter_stdout=None, cwd=None,
+                    raise_on_returncode=True, extra_env=None,
+                    remove_from_env=None):
+    cmd_parts = []
+    for part in cmd:
+        if len(part) > 45:
+            part = part[:20]+"..."+part[-20:]
+        if ' ' in part or '\n' in part or '"' in part or "'" in part:
+            part = '"%s"' % part.replace('"', '\\"')
+        if hasattr(part, 'decode'):
+            try:
+                part = part.decode(sys.getdefaultencoding())
+            except UnicodeDecodeError:
+                part = part.decode(sys.getfilesystemencoding())
+        cmd_parts.append(part)
+    cmd_desc = ' '.join(cmd_parts)
+    if show_stdout:
+        stdout = None
+    else:
+        stdout = subprocess.PIPE
+    logger.debug("Running command %s" % cmd_desc)
+    if extra_env or remove_from_env:
+        env = os.environ.copy()
+        if extra_env:
+            env.update(extra_env)
+        if remove_from_env:
+            for varname in remove_from_env:
+                env.pop(varname, None)
+    else:
+        env = None
+    try:
+        proc = subprocess.Popen(
+            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
+            cwd=cwd, env=env)
+    except Exception:
+        e = sys.exc_info()[1]
+        logger.fatal(
+            "Error %s while executing command %s" % (e, cmd_desc))
+        raise
+    all_output = []
+    if stdout is not None:
+        stdout = proc.stdout
+        encoding = sys.getdefaultencoding()
+        fs_encoding = sys.getfilesystemencoding()
+        while 1:
+            line = stdout.readline()
+            try:
+                line = line.decode(encoding)
+            except UnicodeDecodeError:
+                line = line.decode(fs_encoding)
+            if not line:
+                break
+            line = line.rstrip()
+            all_output.append(line)
+            if filter_stdout:
+                level = filter_stdout(line)
+                if isinstance(level, tuple):
+                    level, line = level
+                logger.log(level, line)
+                if not logger.stdout_level_matches(level):
+                    logger.show_progress()
+            else:
+                logger.info(line)
+    else:
+        proc.communicate()
+    proc.wait()
+    if proc.returncode:
+        if raise_on_returncode:
+            if all_output:
+                logger.notify('Complete output from command %s:' % cmd_desc)
+                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
+            raise OSError(
+                "Command %s failed with error code %s"
+                % (cmd_desc, proc.returncode))
+        else:
+            logger.warn(
+                "Command %s had error code %s"
+                % (cmd_desc, proc.returncode))
+
+
+def create_environment(home_dir, site_packages=False, clear=False,
+                       unzip_setuptools=False, use_distribute=False,
+                       prompt=None, search_dirs=None, never_download=False):
+    """
+    Creates a new environment in ``home_dir``.
+
+    If ``site_packages`` is true, then the global ``site-packages/``
+    directory will be on the path.
+
+    If ``clear`` is true (default False) then the environment will
+    first be cleared.
+    """
+    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
+
+    py_executable = os.path.abspath(install_python(
+        home_dir, lib_dir, inc_dir, bin_dir,
+        site_packages=site_packages, clear=clear))
+
+    install_distutils(home_dir)
+
+    # use_distribute also is True if VIRTUALENV_DISTRIBUTE env var is set
+    # we also check VIRTUALENV_USE_DISTRIBUTE for backwards compatibility
+    if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'):
+        install_distribute(py_executable, unzip=unzip_setuptools,
+                           search_dirs=search_dirs, never_download=never_download)
+    else:
+        install_setuptools(py_executable, unzip=unzip_setuptools,
+                           search_dirs=search_dirs, never_download=never_download)
+
+    install_pip(py_executable, search_dirs=search_dirs, never_download=never_download)
+
+    install_activate(home_dir, bin_dir, prompt)
+
+def path_locations(home_dir):
+    """Return the path locations for the environment (where libraries are,
+    where scripts go, etc)"""
+    # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
+    # prefix arg is broken: http://bugs.python.org/issue3386
+    if sys.platform == 'win32':
+        # Windows has lots of problems with executables with spaces in
+        # the name; this function will remove them (using the ~1
+        # format):
+        mkdir(home_dir)
+        if ' ' in home_dir:
+            try:
+                import win32api
+            except ImportError:
+                print('Error: the path "%s" has a space in it' % home_dir)
+                print('To handle these kinds of paths, the win32api module must be installed:')
+                print('  http://sourceforge.net/projects/pywin32/')
+                sys.exit(3)
+            home_dir = win32api.GetShortPathName(home_dir)
+        lib_dir = join(home_dir, 'Lib')
+        inc_dir = join(home_dir, 'Include')
+        bin_dir = join(home_dir, 'Scripts')
+    elif is_jython:
+        lib_dir = join(home_dir, 'Lib')
+        inc_dir = join(home_dir, 'Include')
+        bin_dir = join(home_dir, 'bin')
+    elif is_pypy:
+        lib_dir = home_dir
+        inc_dir = join(home_dir, 'include')
+        bin_dir = join(home_dir, 'bin')
+    else:
+        lib_dir = join(home_dir, 'lib', py_version)
+        inc_dir = join(home_dir, 'include', py_version + abiflags)
+        bin_dir = join(home_dir, 'bin')
+    return home_dir, lib_dir, inc_dir, bin_dir
+
+
+def change_prefix(filename, dst_prefix):
+    prefixes = [sys.prefix]
+
+    if sys.platform == "darwin":
+        prefixes.extend((
+            os.path.join("/Library/Python", sys.version[:3], "site-packages"),
+            os.path.join(sys.prefix, "Extras", "lib", "python"),
+            os.path.join("~", "Library", "Python", sys.version[:3], "site-packages")))
+
+    if hasattr(sys, 'real_prefix'):
+        prefixes.append(sys.real_prefix)
+    prefixes = list(map(os.path.abspath, prefixes))
+    filename = os.path.abspath(filename)
+    for src_prefix in prefixes:
+        if filename.startswith(src_prefix):
+            _, relpath = filename.split(src_prefix, 1)
+            assert relpath[0] == os.sep
+            relpath = relpath[1:]
+            return join(dst_prefix, relpath)
+    assert False, "Filename %s does not start with any of these prefixes: %s" % \
+        (filename, prefixes)
+
+def copy_required_modules(dst_prefix):
+    import imp
+    for modname in REQUIRED_MODULES:
+        if modname in sys.builtin_module_names:
+            logger.info("Ignoring built-in bootstrap module: %s" % modname)
+            continue
+        try:
+            f, filename, _ = imp.find_module(modname)
+        except ImportError:
+            logger.info("Cannot import bootstrap module: %s" % modname)
+        else:
+            if f is not None:
+                f.close()
+            dst_filename = change_prefix(filename, dst_prefix)
+            copyfile(filename, dst_filename)
+            if filename.endswith('.pyc'):
+                pyfile = filename[:-1]
+                if os.path.exists(pyfile):
+                    copyfile(pyfile, dst_filename[:-1])
+
+
+def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear):
+    """Install just the base environment, no distutils patches etc"""
+    if sys.executable.startswith(bin_dir):
+        print('Please use the *system* python to run this script')
+        return
+
+    if clear:
+        rmtree(lib_dir)
+        ## FIXME: why not delete it?
+        ## Maybe it should delete everything with #!/path/to/venv/python in it
+        logger.notify('Not deleting %s', bin_dir)
+
+    if hasattr(sys, 'real_prefix'):
+        logger.notify('Using real prefix %r' % sys.real_prefix)
+        prefix = sys.real_prefix
+    else:
+        prefix = sys.prefix
+    mkdir(lib_dir)
+    fix_lib64(lib_dir)
+    fix_local_scheme(home_dir)
+    stdlib_dirs = [os.path.dirname(os.__file__)]
+    if sys.platform == 'win32':
+        stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
+    elif sys.platform == 'darwin':
+        stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
+    if hasattr(os, 'symlink'):
+        logger.info('Symlinking Python bootstrap modules')
+    else:
+        logger.info('Copying Python bootstrap modules')
+    logger.indent += 2
+    try:
+        # copy required files...
+        for stdlib_dir in stdlib_dirs:
+            if not os.path.isdir(stdlib_dir):
+                continue
+            for fn in os.listdir(stdlib_dir):
+                bn = os.path.splitext(fn)[0]
+                if fn != 'site-packages' and bn in REQUIRED_FILES:
+                    copyfile(join(stdlib_dir, fn), join(lib_dir, fn))
+        # ...and modules
+        copy_required_modules(home_dir)
+    finally:
+        logger.indent -= 2
+    mkdir(join(lib_dir, 'site-packages'))
+    import site
+    site_filename = site.__file__
+    if site_filename.endswith('.pyc'):
+        site_filename = site_filename[:-1]
+    elif site_filename.endswith('$py.class'):
+        site_filename = site_filename.replace('$py.class', '.py')
+    site_filename_dst = change_prefix(site_filename, home_dir)
+    site_dir = os.path.dirname(site_filename_dst)
+    writefile(site_filename_dst, SITE_PY)
+    writefile(join(site_dir, 'orig-prefix.txt'), prefix)
+    site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
+    if not site_packages:
+        writefile(site_packages_filename, '')
+    else:
+        if os.path.exists(site_packages_filename):
+            logger.info('Deleting %s' % site_packages_filename)
+            os.unlink(site_packages_filename)
+
+    if is_pypy or is_win:
+        stdinc_dir = join(prefix, 'include')
+    else:
+        stdinc_dir = join(prefix, 'include', py_version + abiflags)
+    if os.path.exists(stdinc_dir):
+        copyfile(stdinc_dir, inc_dir)
+    else:
+        logger.debug('No include dir %s' % stdinc_dir)
+
+    # pypy never uses exec_prefix, just ignore it
+    if sys.exec_prefix != prefix and not is_pypy:
+        if sys.platform == 'win32':
+            exec_dir = join(sys.exec_prefix, 'lib')
+        elif is_jython:
+            exec_dir = join(sys.exec_prefix, 'Lib')
+        else:
+            exec_dir = join(sys.exec_prefix, 'lib', py_version)
+        for fn in os.listdir(exec_dir):
+            copyfile(join(exec_dir, fn), join(lib_dir, fn))
+
+    if is_jython:
+        # Jython has either jython-dev.jar and javalib/ dir, or just
+        # jython.jar
+        for name in 'jython-dev.jar', 'javalib', 'jython.jar':
+            src = join(prefix, name)
+            if os.path.exists(src):
+                copyfile(src, join(home_dir, name))
+        # XXX: registry should always exist after Jython 2.5rc1
+        src = join(prefix, 'registry')
+        if os.path.exists(src):
+            copyfile(src, join(home_dir, 'registry'), symlink=False)
+        copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
+                 symlink=False)
+
+    mkdir(bin_dir)
+    py_executable = join(bin_dir, os.path.basename(sys.executable))
+    if 'Python.framework' in prefix:
+        if re.search(r'/Python(?:-32|-64)*$', py_executable):
+            # The name of the python executable is not quite what
+            # we want, rename it.
+            py_executable = os.path.join(
+                    os.path.dirname(py_executable), 'python')
+
+    logger.notify('New %s executable in %s', expected_exe, py_executable)
+    if sys.executable != py_executable:
+        ## FIXME: could I just hard link?
+        executable = sys.executable
+        if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'):
+            # Cygwin misreports sys.executable sometimes
+            executable += '.exe'
+            py_executable += '.exe'
+            logger.info('Executable actually exists in %s' % executable)
+        shutil.copyfile(executable, py_executable)
+        make_exe(py_executable)
+        if sys.platform == 'win32' or sys.platform == 'cygwin':
+            pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe')
+            if os.path.exists(pythonw):
+                logger.info('Also created pythonw.exe')
+                shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe'))
+        if is_pypy:
+            # make a symlink python --> pypy-c
+            python_executable = os.path.join(os.path.dirname(py_executable), 'python')
+            logger.info('Also created executable %s' % python_executable)
+            copyfile(py_executable, python_executable)
+
+    if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
+        secondary_exe = os.path.join(os.path.dirname(py_executable),
+                                     expected_exe)
+        py_executable_ext = os.path.splitext(py_executable)[1]
+        if py_executable_ext == '.exe':
+            # python2.4 gives an extension of '.4' :P
+            secondary_exe += py_executable_ext
+        if os.path.exists(secondary_exe):
+            logger.warn('Not overwriting existing %s script %s (you must use %s)'
+                        % (expected_exe, secondary_exe, py_executable))
+        else:
+            logger.notify('Also creating executable in %s' % secondary_exe)
+            shutil.copyfile(sys.executable, secondary_exe)
+            make_exe(secondary_exe)
+
+    if 'Python.framework' in prefix:
+        logger.debug('MacOSX Python framework detected')
+
+        # Make sure we use the the embedded interpreter inside
+        # the framework, even if sys.executable points to
+        # the stub executable in ${sys.prefix}/bin
+        # See http://groups.google.com/group/python-virtualenv/
+        #                              browse_thread/thread/17cab2f85da75951
+        original_python = os.path.join(
+            prefix, 'Resources/Python.app/Contents/MacOS/Python')
+        shutil.copy(original_python, py_executable)
+
+        # Copy the framework's dylib into the virtual
+        # environment
+        virtual_lib = os.path.join(home_dir, '.Python')
+
+        if os.path.exists(virtual_lib):
+            os.unlink(virtual_lib)
+        copyfile(
+            os.path.join(prefix, 'Python'),
+            virtual_lib)
+
+        # And then change the install_name of the copied python executable
+        try:
+            call_subprocess(
+                ["install_name_tool", "-change",
+                 os.path.join(prefix, 'Python'),
+                 '@executable_path/../.Python',
+                 py_executable])
+        except:
+            logger.fatal(
+                "Could not call install_name_tool -- you must have Apple's development tools installed")
+            raise
+
+        # Some tools depend on pythonX.Y being present
+        py_executable_version = '%s.%s' % (
+            sys.version_info[0], sys.version_info[1])
+        if not py_executable.endswith(py_executable_version):
+            # symlinking pythonX.Y > python
+            pth = py_executable + '%s.%s' % (
+                    sys.version_info[0], sys.version_info[1])
+            if os.path.exists(pth):
+                os.unlink(pth)
+            os.symlink('python', pth)
+        else:
+            # reverse symlinking python -> pythonX.Y (with --python)
+            pth = join(bin_dir, 'python')
+            if os.path.exists(pth):
+                os.unlink(pth)
+            os.symlink(os.path.basename(py_executable), pth)
+
+    if sys.platform == 'win32' and ' ' in py_executable:
+        # There's a bug with subprocess on Windows when using a first
+        # argument that has a space in it.  Instead we have to quote
+        # the value:
+        py_executable = '"%s"' % py_executable
+    cmd = [py_executable, '-c', """
+import sys
+prefix = sys.prefix
+if sys.version_info[0] == 3:
+    prefix = prefix.encode('utf8')
+if hasattr(sys.stdout, 'detach'):
+    sys.stdout = sys.stdout.detach()
+elif hasattr(sys.stdout, 'buffer'):
+    sys.stdout = sys.stdout.buffer
+sys.stdout.write(prefix)
+"""]
+    logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
+    try:
+        proc = subprocess.Popen(cmd,
+                            stdout=subprocess.PIPE)
+        proc_stdout, proc_stderr = proc.communicate()
+    except OSError:
+        e = sys.exc_info()[1]
+        if e.errno == errno.EACCES:
+            logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e))
+            sys.exit(100)
+        else:
+          raise e
+
+    proc_stdout = proc_stdout.strip().decode("utf-8")
+    proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
+    norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
+    if hasattr(norm_home_dir, 'decode'):
+        norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
+    if proc_stdout != norm_home_dir:
+        logger.fatal(
+            'ERROR: The executable %s is not functioning' % py_executable)
+        logger.fatal(
+            'ERROR: It thinks sys.prefix is %r (should be %r)'
+            % (proc_stdout, norm_home_dir))
+        logger.fatal(
+            'ERROR: virtualenv is not compatible with this system or executable')
+        if sys.platform == 'win32':
+            logger.fatal(
+                'Note: some Windows users have reported this error when they installed Python for "Only this user".  The problem may be resolvable if you install Python "For all users".  (See https://bugs.launchpad.net/virtualenv/+bug/352844)')
+        sys.exit(100)
+    else:
+        logger.info('Got sys.prefix result: %r' % proc_stdout)
+
+    pydistutils = os.path.expanduser('~/.pydistutils.cfg')
+    if os.path.exists(pydistutils):
+        logger.notify('Please make sure you remove any previous custom paths from '
+                      'your %s file.' % pydistutils)
+    ## FIXME: really this should be calculated earlier
+    return py_executable
+
+def install_activate(home_dir, bin_dir, prompt=None):
+    if sys.platform == 'win32' or is_jython and os._name == 'nt':
+        files = {'activate.bat': ACTIVATE_BAT,
+                 'deactivate.bat': DEACTIVATE_BAT}
+        if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin':
+            files['activate'] = ACTIVATE_SH
+    else:
+        files = {'activate': ACTIVATE_SH}
+
+        # suppling activate.fish in addition to, not instead of, the
+        # bash script support.
+        files['activate.fish'] = ACTIVATE_FISH
+
+        # same for csh/tcsh support...
+        files['activate.csh'] = ACTIVATE_CSH
+
+
+
+    files['activate_this.py'] = ACTIVATE_THIS
+    home_dir = os.path.abspath(home_dir)
+    if hasattr(home_dir, 'decode'):
+        home_dir = home_dir.decode(sys.getfilesystemencoding())
+    vname = os.path.basename(home_dir)
+    for name, content in files.items():
+        content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
+        content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname)
+        content = content.replace('__VIRTUAL_ENV__', home_dir)
+        content = content.replace('__VIRTUAL_NAME__', vname)
+        content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
+        writefile(os.path.join(bin_dir, name), content)
+
+def install_distutils(home_dir):
+    distutils_path = change_prefix(distutils.__path__[0], home_dir)
+    mkdir(distutils_path)
+    ## FIXME: maybe this prefix setting should only be put in place if
+    ## there's a local distutils.cfg with a prefix setting?
+    home_dir = os.path.abspath(home_dir)
+    ## FIXME: this is breaking things, removing for now:
+    #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
+    writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
+    writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False)
+
+def fix_local_scheme(home_dir):
+    """
+    Platforms that use the "posix_local" install scheme (like Ubuntu with
+    Python 2.7) need to be given an additional "local" location, sigh.
+    """
+    try:
+        import sysconfig
+    except ImportError:
+        pass
+    else:
+        if sysconfig._get_default_scheme() == 'posix_local':
+            local_path = os.path.join(home_dir, 'local')
+            if not os.path.exists(local_path):
+                os.symlink(os.path.abspath(home_dir), local_path)
+
+def fix_lib64(lib_dir):
+    """
+    Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
+    instead of lib/pythonX.Y.  If this is such a platform we'll just create a
+    symlink so lib64 points to lib
+    """
+    if [p for p in distutils.sysconfig.get_config_vars().values()
+        if isinstance(p, basestring) and 'lib64' in p]:
+        logger.debug('This system uses lib64; symlinking lib64 to lib')
+        assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
+            "Unexpected python lib dir: %r" % lib_dir)
+        lib_parent = os.path.dirname(lib_dir)
+        assert os.path.basename(lib_parent) == 'lib', (
+            "Unexpected parent dir: %r" % lib_parent)
+        copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64'))
+
+def resolve_interpreter(exe):
+    """
+    If the executable given isn't an absolute path, search $PATH for the interpreter
+    """
+    if os.path.abspath(exe) != exe:
+        paths = os.environ.get('PATH', '').split(os.pathsep)
+        for path in paths:
+            if os.path.exists(os.path.join(path, exe)):
+                exe = os.path.join(path, exe)
+                break
+    if not os.path.exists(exe):
+        logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
+        raise SystemExit(3)
+    if not is_executable(exe):
+        logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
+        raise SystemExit(3)
+    return exe
+
+def is_executable(exe):
+    """Checks a file is executable"""
+    return os.access(exe, os.X_OK)
+
+############################################################
+## Relocating the environment:
+
+def make_environment_relocatable(home_dir):
+    """
+    Makes the already-existing environment use relative paths, and takes out
+    the #!-based environment selection in scripts.
+    """
+    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
+    activate_this = os.path.join(bin_dir, 'activate_this.py')
+    if not os.path.exists(activate_this):
+        logger.fatal(
+            'The environment doesn\'t have a file %s -- please re-run virtualenv '
+            'on this environment to update it' % activate_this)
+    fixup_scripts(home_dir)
+    fixup_pth_and_egg_link(home_dir)
+    ## FIXME: need to fix up distutils.cfg
+
+OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
+                  'activate', 'activate.bat', 'activate_this.py']
+
+def fixup_scripts(home_dir):
+    # This is what we expect at the top of scripts:
+    shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir))
+    # This is what we'll put:
+    new_shebang = '#!/usr/bin/env python%s' % sys.version[:3]
+    activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
+    if sys.platform == 'win32':
+        bin_suffix = 'Scripts'
+    else:
+        bin_suffix = 'bin'
+    bin_dir = os.path.join(home_dir, bin_suffix)
+    home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
+    for filename in os.listdir(bin_dir):
+        filename = os.path.join(bin_dir, filename)
+        if not os.path.isfile(filename):
+            # ignore subdirs, e.g. .svn ones.
+            continue
+        f = open(filename, 'rb')
+        lines = f.readlines()
+        f.close()
+        if not lines:
+            logger.warn('Script %s is an empty file' % filename)
+            continue
+        if not lines[0].strip().startswith(shebang):
+            if os.path.basename(filename) in OK_ABS_SCRIPTS:
+                logger.debug('Cannot make script %s relative' % filename)
+            elif lines[0].strip() == new_shebang:
+                logger.info('Script %s has already been made relative' % filename)
+            else:
+                logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
+                            % (filename, shebang))
+            continue
+        logger.notify('Making script %s relative' % filename)
+        lines = [new_shebang+'\n', activate+'\n'] + lines[1:]
+        f = open(filename, 'wb')
+        f.writelines(lines)
+        f.close()
+
+def fixup_pth_and_egg_link(home_dir, sys_path=None):
+    """Makes .pth and .egg-link files use relative paths"""
+    home_dir = os.path.normcase(os.path.abspath(home_dir))
+    if sys_path is None:
+        sys_path = sys.path
+    for path in sys_path:
+        if not path:
+            path = '.'
+        if not os.path.isdir(path):
+            continue
+        path = os.path.normcase(os.path.abspath(path))
+        if not path.startswith(home_dir):
+            logger.debug('Skipping system (non-environment) directory %s' % path)
+            continue
+        for filename in os.listdir(path):
+            filename = os.path.join(path, filename)
+            if filename.endswith('.pth'):
+                if not os.access(filename, os.W_OK):
+                    logger.warn('Cannot write .pth file %s, skipping' % filename)
+                else:
+                    fixup_pth_file(filename)
+            if filename.endswith('.egg-link'):
+                if not os.access(filename, os.W_OK):
+                    logger.warn('Cannot write .egg-link file %s, skipping' % filename)
+                else:
+                    fixup_egg_link(filename)
+
+def fixup_pth_file(filename):
+    lines = []
+    prev_lines = []
+    f = open(filename)
+    prev_lines = f.readlines()
+    f.close()
+    for line in prev_lines:
+        line = line.strip()
+        if (not line or line.startswith('#') or line.startswith('import ')
+            or os.path.abspath(line) != line):
+            lines.append(line)
+        else:
+            new_value = make_relative_path(filename, line)
+            if line != new_value:
+                logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename))
+            lines.append(new_value)
+    if lines == prev_lines:
+        logger.info('No changes to .pth file %s' % filename)
+        return
+    logger.notify('Making paths in .pth file %s relative' % filename)
+    f = open(filename, 'w')
+    f.write('\n'.join(lines) + '\n')
+    f.close()
+
+def fixup_egg_link(filename):
+    f = open(filename)
+    link = f.read().strip()
+    f.close()
+    if os.path.abspath(link) != link:
+        logger.debug('Link in %s already relative' % filename)
+        return
+    new_link = make_relative_path(filename, link)
+    logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
+    f = open(filename, 'w')
+    f.write(new_link)
+    f.close()
+
+def make_relative_path(source, dest, dest_is_directory=True):
+    """
+    Make a filename relative, where the filename is dest, and it is
+    being referred to from the filename source.
+
+        >>> make_relative_path('/usr/share/something/a-file.pth',
+        ...                    '/usr/share/another-place/src/Directory')
+        '../another-place/src/Directory'
+        >>> make_relative_path('/usr/share/something/a-file.pth',
+        ...                    '/home/user/src/Directory')
+        '../../../home/user/src/Directory'
+        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
+        './'
+    """
+    source = os.path.dirname(source)
+    if not dest_is_directory:
+        dest_filename = os.path.basename(dest)
+        dest = os.path.dirname(dest)
+    dest = os.path.normpath(os.path.abspath(dest))
+    source = os.path.normpath(os.path.abspath(source))
+    dest_parts = dest.strip(os.path.sep).split(os.path.sep)
+    source_parts = source.strip(os.path.sep).split(os.path.sep)
+    while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
+        dest_parts.pop(0)
+        source_parts.pop(0)
+    full_parts = ['..']*len(source_parts) + dest_parts
+    if not dest_is_directory:
+        full_parts.append(dest_filename)
+    if not full_parts:
+        # Special case for the current directory (otherwise it'd be '')
+        return './'
+    return os.path.sep.join(full_parts)
+
+
+
+############################################################
+## Bootstrap script creation:
+
+def create_bootstrap_script(extra_text, python_version=''):
+    """
+    Creates a bootstrap script, which is like this script but with
+    extend_parser, adjust_options, and after_install hooks.
+
+    This returns a string that (written to disk of course) can be used
+    as a bootstrap script with your own customizations.  The script
+    will be the standard virtualenv.py script, with your extra text
+    added (your extra text should be Python code).
+
+    If you include these functions, they will be called:
+
+    ``extend_parser(optparse_parser)``:
+        You can add or remove options from the parser here.
+
+    ``adjust_options(options, args)``:
+        You can change options here, or change the args (if you accept
+        different kinds of arguments, be sure you modify ``args`` so it is
+        only ``[DEST_DIR]``).
+
+    ``after_install(options, home_dir)``:
+
+        After everything is installed, this function is called.  This
+        is probably the function you are most likely to use.  An
+        example would be::
+
+            def after_install(options, home_dir):
+                subprocess.call([join(home_dir, 'bin', 'easy_install'),
+                                 'MyPackage'])
+                subprocess.call([join(home_dir, 'bin', 'my-package-script'),
+                                 'setup', home_dir])
+
+        This example immediately installs a package, and runs a setup
+        script from that package.
+
+    If you provide something like ``python_version='2.4'`` then the
+    script will start with ``#!/usr/bin/env python2.4`` instead of
+    ``#!/usr/bin/env python``.  You can use this when the script must
+    be run with a particular Python version.
+    """
+    filename = __file__
+    if filename.endswith('.pyc'):
+        filename = filename[:-1]
+    f = open(filename, 'rb')
+    content = f.read()
+    f.close()
+    py_exe = 'python%s' % python_version
+    content = (('#!/usr/bin/env %s\n' % py_exe)
+               + '## WARNING: This file is generated\n'
+               + content)
+    return content.replace('##EXT' 'END##', extra_text)
+
+##EXTEND##
+
+def convert(s):
+    b = base64.b64decode(s.encode('ascii'))
+    return zlib.decompress(b).decode('utf-8')
+
+##file site.py
+SITE_PY = convert("""
+eJzVPP1z2zaWv/OvwMqTIZXKdD66nR2n7o2TOK3v3MTbpLO5dT06SoIk1hTJEqQV7c3d337vAwAB
+kvLHdvvDaTKxRAIPDw/vGw8YjUanZSnzhdgUiyaTQsmkmq9FmdRrJZZFJep1Wi0Oy6Sqd/B0fpOs
+pBJ1IdROxdgqDoKnv/MTPBWf1qkyKMC3pKmLTVKn8yTLdiLdlEVVy4VYNFWar0Sap3WaZOk/oEWR
+x+Lp78cgOM8FzDxLZSVuZaUArhLFUlzu6nWRi6gpcc7P4z8nL8cToeZVWtbQoNI4A0XWSR3kUi4A
+TWjZKCBlWstDVcp5ukzntuG2aLKFKLNkLsV//RdPjZqGYaCKjdyuZSVFDsgATAmwSsQDvqaVmBcL
+GQvxWs4THICft8QKGNoE10whGfNCZEW+gjnlci6VSqqdiGZNTYAIZbEoAKcUMKjTLAu2RXWjxrCk
+tB5beCQSZg9/MsweME8cv885gOOHPPg5T79MGDZwD4Kr18w2lVymX0SCYOGn/CLnU/0sSpdikS6X
+QIO8HmOTgBFQIktnRyUtx7d6hb47IqwsVyYwhkSUuTG/pB5xcF6LJFPAtk2JNFKE+Vs5S5McqJHf
+wnAAEUgaDI2zSFVtx6HZiQIAVLiONUjJRolok6Q5MOuPyZzQ/luaL4qtGhMFYLWU+LVRtTv/aIAA
+0NohwCTAxTKr2eRZeiOz3RgQ+ATYV1I1WY0CsUgrOa+LKpWKAABqOyG/ANITkVRSk5A508jthOhP
+NElzXFgUMBR4fIkkWaarpiIJE8sUOBe44t2Hn8Tbs9fnp+81jxlgLLOrDeAMUGihHZxgAHHUqOoo
+K0Cg4+AC/4hksUAhW+H4gFfb4OjelQ4imHsZd/s4Cw5k14urh4E51qBMaKyA+v03dJmoNdDnf+5Z
+7yA43UcVmjh/264LkMk82UixTpi/kDOCbzWc7+KyXr8CblAIpwZSKVwcRDBFeEASl2ZRkUtRAotl
+aS7HAVBoRm39VQRWeF/kh7TWHU4ACFWQw0vn2ZhGzCVMtA/rFeoL03hHM9NNArvOm6IixQH8n89J
+F2VJfkM4KmIo/jaTqzTPESHkhSA8CGlgdZMCJy5icUGtSC+YRiJk7cUtUSQa4CVkOuBJ+SXZlJmc
+sPiibr1bjdBgshZmrTPmOGhZk3qlVWunOsh7L+LPHa4jNOt1JQF4M/OEblkUEzEDnU3YlMmGxave
+FsQ5wYA8USfkCWoJffE7UPRUqWYj7UvkFdAsxFDBssiyYgskOw4CIQ6wkTHKPnPCW3gH/wNc/D+T
+9XwdBM5IFrAGhcjvA4VAwCTIXHO1RsLjNs3KXSWT5qwpimohKxrqYcQ+YsQf2BjnGrwvam3UeLq4
+ysUmrVElzbTJTNni5WHN+vEVzxumAZZbEc1M05ZOG5xeVq6TmTQuyUwuURL0Ir2yyw5jBgNjki2u
+xYatDLwDssiULciwYkGls6wlOQEAg4UvydOyyaiRQgYTCQy0KQn+JkGTXmhnCdibzXKAConN9xzs
+D+D2DxCj7ToF+swBAmgY1FKwfLO0rtBBaPVR4Bt905/HB049X2rbxEMukzTTVj7Jg3N6eFZVJL5z
+WWKviSaGghnmNbp2qxzoiGI+Go2CwLhDO2W+Fiqoq90xsIIw40ynsyZFwzedoqnXP1TAowhnYK+b
+bWfhgYYwnd4DlZwuy6rY4Gs7t4+gTGAs7BEciEvSMpIdZI8TXyH5XJVemqZoux12FqiHgsufzt6d
+fz77KE7EVavSJl19dg1jnuUJsDVZBGCqzrCtLoOWqPhS1H3iHZh3YgqwZ9SbxFcmdQO8C6h/qhp6
+DdOYey+Ds/enry/Opj9/PPtp+vH80xkgCHZGBgc0ZTSPDTiMKgbhAK5cqFjb16DXgx68Pv1oHwTT
+VE3LXbmDB2AogYWrCOY7ESE+nGobPE3zZRGOqfGv7ISfsFrRHtfV8dfX4uREhL8mt0kYgNfTNuVF
+/JEE4NOulNC1hj9RocZBsJBLEJYbiSIVPSVPdswdgIjQstCW9dcizc175iN3CJL4iHoADtPpPEuU
+wsbTaQikpQ4DH+gQszuMchJBx3Lndh1rVPBTSViKHLtM8L8BFJMZ9UM0GEW3i2kEAraZJ0pyK5o+
+9JtOUctMp5EeEMSPeBxcJFYcoTBNUMtUKXiixCuodWaqyPAnwke5JZHBYAj1Gi6SDnbi2yRrpIqc
+SQERo6hDRlSNqSIOAqciAtvZLt143KWm4RloBuTLCtB7VYdy+DkADwUUjAm7MDTjaIlphpj+O8cG
+hAM4iSEqaKU6UFificuzS/Hy2YtDdEAgSlxY6njN0aameSPtwyWs1krWDsLcK5yQMIxduixRM+LT
+47thbmK7Mn1WWOolruSmuJULwBYZ2Fll8RO9gVga5jFPYBVBE5MFZ6VnPL0EI0eePUgLWnug3oag
+mPU3S3/A4bvMFagODoWJ1DpOZ+NVVsVtiu7BbKdfgnUD9YY2zrgigbNwHpOhEQMNAX5rjpTayhAU
+WNWwi0l4I0jU8ItWFcYE7gJ16zV9vcmLbT7l2PUE1WQ0tqyLgqWZFxu0S3Ag3oHdACQLCMVaojEU
+cNIFytYhIA/Th+kCZSkaAEBgmhUFWA4sE5zRFDnOw2ERxviVIOGtJFr4WzMEBUeGGA4kehvbB0ZL
+ICSYnFVwVjVoJkNZM81gYIckPtddxBw0+gA6VIzB0EUaGjcy9Ls6BuUsLlyl5PRDG/r582dmG7Wm
+jAgiNsNJo9FfknmLyx2YwhR0gvGhOL9CbLAFdxTANEqzpjj8KIqS/SdYz0st22C5IR6r6/L46Gi7
+3cY6H1BUqyO1PPrzX7755i/PWCcuFsQ/MB1HWnRyLD6id+iDxt8aC/SdWbkOP6a5z40EK5LkR5Hz
+iPh936SLQhwfjq3+RC5uDSv+b5wPUCBTMyhTGWg7ajF6og6fxC/VSDwRkds2GrMnoU2qtWK+1YUe
+dQG2GzyNedHkdegoUiW+AusGMfVCzppVaAf3bKT5AVNFOY0sDxw+v0YMfM4wfGVM8RS1BLEFWnyH
+9D8x2yTkz2gNgeRFE9WLd3fDWswQd/FwebfeoSM0ZoapQu5AifCbPFgAbeO+5OBHO6No9xxn1Hw8
+Q2AsfWCYV7uCEQoO4YJrMXGlzuFq9FFBmrasmkHBuKoRFDS4dTOmtgZHNjJEkOjdmPCcF1a3ADp1
+cn0mojerAC3ccXrWrssKjieEPHAintMTCU7tce/dM17aJssoBdPhUY8qDNhbaLTTBfBlZABMxKj6
+ecQtTWDxobMovAYDwArO2iCDLXvMhG9cH3B0MBpgp57V39ebaTwEAhcp4uzRg6ATyic8QqVAmsrI
+77mPxS1x+4PdaXGIqcwykUirPcLVVR6DQnWnYVqmOepeZ5HieVaAV2y1IjFS+953FihywcdDxkxL
+oCZDSw6n0Ql5e54AhrodJrxWDaYG3MwJYrRJFVk3JNMa/gO3gjISlD4CWhI0C+ahUuZP7F8gc3a+
++sse9rCERoZwm+5zQ3oWQ8Mx7w8EklHnT0AKciBhXxjJdWR1kAGHOQvkCTe8lnulm2DECuTMsSCk
+ZgB3eukFOPgkxj0LklCE/KVWshRfiREsX1dUH6a7/6VcatIGkdOAXAWdbzhxcxFOHuKkk5fwGdrP
+SNDuRlkAB8/A5XFT8y6bG6a1aRJw1n3FbZECjUyZk9HYRfXaEMZN//7pxGnREssMYhjKG8jbhDEj
+jQO73Bo0LLgB4615dyz92M1YYN8oLNQLufkC8V9YpWpeqBAD3F7uwv1orujTxmJ7kc5G8MdbgNH4
+2oMkM52/wCzLPzFI6EEPh6B7k8W0yCKptmkekgLT9Dvxl6aHhyWlZ+SOPlI4dQQTxRzl0bsKBIQ2
+K49AnFATQFQuQ6Xd/j7YO6c4snC5+8hzm6+OX173iTvZl+Gxn+GlOvtSV4nC1cp40VgocLX6BhyV
+LkwuyXd6u1FvR2OYUBUKokjx4eNngYTgTOw22T1u6i3DIzb3zsn7GNRBr91Lrs7siF0AEdSKyChH
+4eM58uHIPnZyd0zsEUAexTB3LIqBpPnkn4Fz10LBGIeLXY55tK7KwA+8/ubr6UBm1EXym69H94zS
+IcaQ2EcdT9COTGUAYnDapkslk4x8DacTZRXzlndsm3LMCp3iP81k1wNOJ37Me2MyWvi95r3A0XwO
+iB4QZhezXyFYVTq/dZukGSXlAY3DQ9RzJs7m1MEwPh6ku1HGnBR4LM8mg6GQunoGCxNyYD/uT0f7
+Racm9zsQkJpPmag+Kgd6A77dP/I21d29w/2yP2ip/yCd9UhA3mxGAwR84BzM3ub//5mwsmJoWlmN
+O1pfybv1vAH2AHW4x825ww3pD827WUvjTLDcKfEUBfSp2NKGNuXycGcCoCzYzxiAg8uot0XfNFXF
+m5sk56WsDnHDbiKwlsd4GlQi1Adz9F7WiIltNqfcqFP5UQypzlBnO+1MwtZPHRbZdWFyJDK/TSvo
+C1olCn/48ONZ2GcAPQx2GgbnrqPhkofbKYT7CKYNNXHCx/RhCj2myz8vVV1X2Seo2TM2GUhNtj5h
+e4lHE7cOr8E9GQhvg5A3YjEinK/l/GYqaXMZ2RS7OknYN/gaMbF7zn6FkEqWVOYEM5lnDdKKHT2s
+T1s2+Zzy8bUEe66LSbG4hLaMOd20zJKViKjzAlMdmhspG3KbVNrbKasCyxdFky6OVulCyN+aJMMw
+Ui6XgAtuluhXMQ9PGQ/xlne9uaxNyXlTpfUOSJCoQu810Qa503C244lGHpK8rcAExC3zY/ERp43v
+mXALQy4TjPoZdpwkxnnYwWwGInfRc3ifF1McdUpVoBNGqr8PTI+D7ggFABgBUJj/aKwzRf4bSa/c
+DS1ac5eoqCU9UrqRbUEeB0KJxhhZ82/66TOiy1t7sFztx3J1N5arLparQSxXPparu7F0RQIX1iZJ
+jCQMJUq6afTBigw3x8HDnCXzNbfD6kCsAgSIojQBnZEpLpL1Mim8n0RASG07G5z0sK2wSLnssCo4
+5apBIvfjpokOHk15s9OZ6jV0Z56K8dn2VZn4fY/imIqJZtSd5W2R1EnsycUqK2YgthbdSQtgIroF
+J5yby2+nM84mdizV6PI/P/3w4T02R1Ajs51O3XAR0bDgVKKnSbVSfWlqg40S2JFa+oUf1E0DPHhg
+JodHOeD/3lJFATKO2NKOeCFK8ACo7sc2c6tjwrDzXJfR6OfM5Ly5cSJGeT1qJ7WHSKeXl29PP52O
+KMU0+t+RKzCGtr50uPiYFrZB339zm1uKYx8Qap1LaY2fOyeP1i1H3G9jDdiO2/vsuvPgxUMM9mBY
+6s/yD6UULAkQKtbJxscQ6sHBz+8KE3r0MYzYKw9zd3LYWbHvHNlzXBRH9IfS3N0B/M01jDGmQADt
+QkUmMmiDqY7St+b1Doo6QB/o6/3uEKwbenUjGZ+idhIDDqBDWdtsv/vn7Quw0VOyfn32/fn7i/PX
+l6effnBcQHTlPnw8eiHOfvwsqB4BDRj7RAluxddY+QKGxT0KIxYF/GswvbFoak5KQq+3Fxd6Z2CD
+hyGwOhZtTgzPuWzGQuMcDWc97UNd74IYZTpAck6dUHkInUrBeGnDJx5UoSto6TDLDJ3VRode+jSR
+OXVE+6gxSB80dknBILikCV5RnXNtosKKd5z0SZwBpLSNtoUIGeWgetvTzn6LyeZ7iTnqDE/azlrR
+X4UuruF1rMoshUjuVWhlSXfDcoyWcfRDu6HKeA1pQKc7jKwb8qz3YoFW61XIc9P9xy2j/dYAhi2D
+vYV555LKEahGF4upRIiNeOcglF/gq116vQYKFgw3lmpcRMN0Kcw+geBarFMIIIAn12B9MU4ACJ2V
+8BPQx052QBZYDRC+2SwO/xpqgvitf/lloHldZYd/FyVEQYJLV8IBYrqN30LgE8tYnH14Nw4ZOSoF
+FX9tsIAcHBLK8jnSTvUyvGM7jZTMlrqewdcH+EL7CfS6072SZaW7D7vGIUrAExWR1/BEGfqFWF5k
+YU9wKuMOaKyNt5jhGTN329t8DsTHtcwyXRF9/vbiDHxHLNdHCeJ9njMYjvMluGWri734DFwHFG7o
+wusK2bhCF5Y29Rex12wwM4siR729OgC7TpT97PfqpTqrJFUu2hFOm2GZgvMYWRnWwiwrs3anDVLY
+bUMUR5lhlpheVlQw6fME8DI9TTgkglgJDwOYNDPvWqZ5bSrksnQOehRULijUCQgJEhdPvBHnFTkn
+eotKmYMy8LDcVelqXWMyHTrHVKSPzX88/Xxx/p4K11+8bL3uAeacUCQw4aKFEyxJw2wHfHHLzJCr
+ptMhntWvEAZqH/jTfcXVECc8QK8fJxbxT/cVn1Q6cSJBngEoqKbsigcGAE63IblpZYFxtXEwftyS
+sxYzHwzlIvFghC4scOfX50TbsmNKKO9jXj5il2JZahpGprNbAtX96DkuS9xWWUTDjeDtkGyZzwy6
+3vTe7Cu2cj89KcRDk4BRv7U/hqlG6jXV03GYbR+3UFirbewvuZMrddrNcxRlIGLkdh67TDashHVz
+5kCvbLcHTHyr0TWSOKjKR7/kI+1heJhYYvfiFNORjk2QEcBMhtSnQxrwodAigAKhatPIkdzJ+OkL
+b46ONbh/jlp3gW38ARShrv2kMwVFBZwIX35jx5FfEVqoR49F6HgqucwLW5eEn+0avcrn/hwHZYCS
+mCh2VZKvZMSwJgbmVz6x96RgSdt6pL5Kr4cMizgH5/TLHg7vy8XwxolBrcMIvXY3ctdVRz55sMHg
+0YM7CeaDr5It6P6yqSNeyWGRHz5ttR/q/RCx2g2a6s3eKMR0zG/hnvVpAQ9SQ8NCD++3gd0i/PDa
+GEfW2sfOKZrQvtAe7LyC0KxWtC3jHF8zvqj1AlqDe9Ka/JF9qgtT7O+Bc0lOTsgC5cFdkN7cRrpB
+J50w4uMxfLYwpfLr9vSGfreQtzIrwPWCqA6r63+11fXj2KZTBuuOfjd2l7vL3TBu9KbF7NiU/6Nn
+pkpYvziX9RGiM5jxuQuzFhlc6l90SJLkN+Qlv/nb+US8ef8T/P9afoC4Co/HTcTfAQ3xpqggvuTz
+nXTwHk8O1Bw4Fo3CM3QEjbYq+I4CdNsuPTrjtog+0uCfZbCaUmAVZ7XhizEARZ4gnXlu/QRTqA+/
+zUmijjdqPMWhRRnpl0iD/Ycr8EDCkW4Zr+tNhvbCyZK0q3k1ujh/c/b+41lcf0EONz9HThbFLwDC
+6eg94gr3wybCPpk3+OTacZx/kFk54DfroNMc1MCgU4QQl5Q20ORLFxIbXCQVZg5EuVsU8xhbAsvz
+2bB6C4702Ikv7zX0npVFWNFY76K13jw+BmqIX7qKaAQNqY+eE/UkhJIZHlLix/Fo2BRPBKW24c/T
+m+3CzYzr0yY0wS6m7awjv7vVhWums4ZnOYnwOrHLYA4gZmmiNrO5ezDtQy70nRmg5WifQy6TJquF
+zEFyKcinywtA07tnyVhCmFXYnNEBK0rTZNtkp5xKm0SJEY46ovPXuCFDGUOIwX9Mbtge4CE30fBp
+WYBOiFL8VDhdVTNfswRzSETUGyg82Kb5yxdhj8I8KEfI89aRhXmi28gYrWSt588PovHV87bSgbLS
+c+8k6bwEq+eyyQGozvLp06cj8W/3ez+MSpwVxQ24ZQB70Gu5oNd7LLeenF2tvmdv3sTAj/O1vIIH
+15Q9t8+bnFKTd3SlBZH2r4ER4tqElhlN+45d5qRdxRvN3II3rLTl+DlP6WYcTC1JVLb6giFMOxlp
+IpYExRAmap6mIacpYD12RYOHwDDNqPlFfgGOTxHMBN/iDhmH2mv0MKlg03KPRedEjAjwiAqoeDQ6
+RUvHoADP6eVOozk9z9O6Pb/wzN081afFa3vhjeYrkWxRMsw8OsRwzhN6rNp62MWdLOpFLMX8yk04
+dmbJr+/DHVgbJK1YLg2m8NAs0ryQ1dyYU1yxdJ7WDhjTDuFwZ7rnh6xPHAygNAL1TlZhYSXavv2T
+XRcX0w+0j3xoRtLlQ7W9O4mTQ0neqaKL43Z8SkNZQlq+NV/GMMp7SmtrT8AbS/xJJ1WxeN274sE9
+R9fk+uoGrt9o73MAOHRdkFWQlh09HeHcUWXhM9PuuXABPxSiE263aVU3STbVNwRM0WGb2o11jac9
+f3XnyULrrYCTX4AHfKhLxcFxMFU2SE+s9DRHAU7EUqcoYvdIk3/6pyzQy3vBvhL4FEiZxdQcxDVJ
+pCvLrvaE4zO+gsBR8QjqK3Nq5iE2wZzd6B17cKcxoaKncNwt5ey1wg0WU5tvPe9uZPCoITuwfC/e
+TLB7cYP47kREzyfiz51AbF7u8OohIMOTRfxkEfo+IXW9On7R2rl+4NuBsBfIy+tHTzdLZzS9cKjG
++v6+uugRA9ANyO4ylYvDJwqxY5x/L1QNpZ3Xfk6lGeMR7ANbdaVPH7dnMujo1Qyiim2r0BzVZvxf
+O4g51qz1EJ8ARaXBFtCeWjeFL53iQ3uzGBYmavT8lUUpmQ5tjuE3vB0E3muCukK1d9NUl5FbsAM5
+AX1WkLfA2oYDQeEjeCikm0xo0b7qbAv/kYvHlen7Nhd7WH7z9V14ugI+WJY/QFCPmE6rP5Cp9rLM
+YxfmAfv19/Pfw3nvLr57NJV0r2FaYSiFhczrhN+gSWzKY5tqMCKJW0GRW96Gn/pm8OAHiyPqpvom
+vGv63P+uuesWgZ252d3tzd0/4OXSQPfdzy9DNOAwTxPiQTXjrcAO6wJXjCe6qGA4Zak/SH63E850
+j1a4D4wpYcAEKLGpxt5ozU0yd79jhcwh32Hqnucb1NWdafcOOHY5/iGKlqsB8Lk94kslHgvNgew3
+0qVUUy4anMrVSk0TvBBtSsEGFbj0vEjjvr6j+6xkonbG68RbQwCE4SZdiuhWGwNjQEDDF7NyfYhz
+PYSgoamK0inLVOmCM0jaxQVwMWeOqL/JTHJd5SiTmPBTTVVWEBWM9PWdXLgwVOvZAjWJjE2ibgzq
+psdE3+aIQ3C1jDkDyPkqjjQ86gAh+GiQczcRFypPp/Yd8Muz9qxzOrEMIfNmI6ukbu/58LdJU/Gd
+MwKd/MQFdlIVrWR2OMVFLLX84SCFyQL7/SvtZHtBxh0HnMdW6z2craiHToE95uy0Y3sMN6df7D1f
+7v0yC7oV1jXytlnLffZuE1gKc2kV6UqdO+C3+iIdvp6RM5voJjh8BHLvnrvyy3OtWmMnxaLhPHMV
+Q//mFDy6S7Z46EK0Hhf0rz7rOPp2fF9vWGbphQZ7GlsqatdqUPG0o43biBor6e6JqP1q6UdG1B78
+B0bU+vo6MDgaH60PBuun7wm9WU24d8G1jAB9pkAk3Nnr3CRmTGbkViND2Jt+Gdm7WFlnOkecjJlA
+juxfEkQg+M435ZZuencymXGHIlpfuujx9xcfXp9eEC2ml6dv/uP0e6pWwfRxx2Y9OOWQF4dM7UOv
+LtZNP+gKg6HBW2wHLlfkwx0aQu99b3N2AMLwQZ6hBe0qMvf1vg69AxH9ToD43dPuQN2nsgch9/wz
+XXzv1hV0ClgD/ZSrDc0vZ8vWPDI7FywO7c6Eed8mk7WM9nJt+xbOqfvrqxPtt+rr+PbkAce2+pRW
+AHPIyF82hWyOEthEJTsq3RvyqWQWj2GZqyxACufSuVKNblNjULV/FX8Fyi7BfTB2GCf2Wltqx+ly
+Ze9rxr2wuYwNQbxzUKP+/FxhX8hsDxWCgBWevjCMETH6T28w2e3YJ0pcHdKJy0NUNtf2F66ZdnL/
+luKma20v3lFcucHbTtB42WTuRqrt0+tAzh9l54ulU+IPmu8I6NyKpwL2Rp+JFeJsJ0IIJPWGIVYN
+Eh31rVkO8mg3HewNrZ6Jw33n8dzzaEI8399w0Tnypnu84B7qnh6qMaeeHAuM5Wv7DtqJ7wgyb+8I
+umnHcz5wT1Ff8Apfb6+eH9tkK/I7vnYUCZXZjBzDfuWUqd15u5vTnZilmlAdE8ZszjFN3eLagco+
+wb4Yp1ervycOMvu+DGnkvR8u8jE9vFurR11MLesdw5RE9ESNaVrO6QaNu30y7k+3VVt9IHxS4wFA
+eioQYCGYnm50Kud2XP4aPdNR4ayhezHdjHvoSAVV0fgcwT2M79fi1+1OJywf1J1RNP25QZcD9ZKD
+cLPvwK3GXkpkv0noTr3lgz0uAB9WHe7//AH9+/VdtvuLu/xq2+rl4AEp9mWxJBArJTokMo9jMDKg
+NyPS1lhHbgQdL6Fo6egyVDs35At0/KjMEG+9pQCDnNmp9gCsUQj+D1/Qrqc=
+""")
+
+##file ez_setup.py
+EZ_SETUP_PY = convert("""
+eJzNWmtv49a1/a5fwSgwJGE0NN8PDzRFmkyBAYrcIo8CFx5XPk+LHYpUSWoctch/v+ucQ1KkZDrt
+RT6UwcQ2ebjPfq6195G+/upwanZlMZvP538sy6ZuKnKwatEcD01Z5rWVFXVD8pw0GRbNPkrrVB6t
+Z1I0VlNax1qM16qnlXUg7DN5EovaPLQPp7X192PdYAHLj1xYzS6rZzLLhXql2UEI2QuLZ5VgTVmd
+rOes2VlZs7ZIwS3CuX5BbajWNuXBKqXZqZN/dzebWbhkVe4t8c+tvm9l+0NZNUrL7VlLvW58a7m6
+sqwS/zhCHYtY9UGwTGbM+iKqGk5Qe59fXavfsYqXz0VeEj7bZ1VVVmurrLR3SGGRvBFVQRrRLzpb
+utabMqzipVWXFj1Z9fFwyE9Z8TRTxpLDoSoPVaZeLw8qCNoPj4+XFjw+2rPZT8pN2q9Mb6wkCqs6
+4vdamcKq7KDNa6OqtTw8VYQP42irZJi1zqtP9ey7D3/65uc//7T964cffvz4P99bG2vu2BFz3Xn/
+6Ocf/qz8qh7tmuZwd3t7OB0y2ySXXVZPt21S1Lc39S3+63e7nVs3ahe79e/9nf8wm+15uOWkIRD4
+Lx2xxfmNt9icum8PJ8/2bfH0tLizFknieYzI1HG90OFJkNA0jWgsvZBFImJksX5FStBJoXFKEhI4
+vghCx5OUJqEQvnTTwI39kNEJKd5YlzAK4zhMeUIinkgWBE7skJQ7sRd7PE1fl9LrEsAAknA3SrlH
+RRS5kvgeiUToiUAm3pRF/lgXSn2XOZLFfpqSyA/jNI1DRngqQ+JEbvKqlF4XPyEJw10eCcY9zwti
+6capjDmJolQSNiElGOsSeU4QEi8QPBCuoCyOpXD8lJBARDIW4atSzn5h1CNuEkKPhBMmJfW4C30c
+n/rUZcHLUthFvlBfejQM/ZRHiGss44DwOHU9CCKpk0xYxC7zBfZwweHJKOYe96QUbuA4qR8F0iPB
+RKSZ64yVYXCHR2jIfeJ4YRSEEeLDXD9xHBI7qfO6mF6bMOZ4ETFKaeLEscfClIQ+SQLfJyHnk54x
+YsJODBdBRFgCX6YxS9IwjD0RiiREOgqasPh1MVGvTSJQSURIJ4KDPCaiwA0gzYORcPhEtAEqY994
+lAiCGnZ9jvdRRl4iYkpCGhJoxMXrYs6R4pGfypQ6EBawwAvS2PEDLpgnmMO8yUi5Y99EAUsD6VMZ
+kxhZ6AuW+MKhHsIdByn1XhfT+4ZKknqu41COMHHUBCQJzn0EPgqcJJoQc4Ez0nGigMqIEI/G3IFa
+8GyAxHYSN2beVKAucCZyIzf1hGB+KINYIGpuxHhEXA9SvXhKygXOSDcBQAF8uUSqEC9MWQop0uUx
+jRM5gVbsAmeEI3gcRInH0jShksbwdOIgex3EPHangu2Pg0SokG4kOYdhYRi6QRK4LAZ+8TRJo3BK
+ygVaUYemru8SRqjvOXAGcC6WQcBCAEXsylel9BYhSST2jHggqfRRUVSmQcQcuAqoJ6YSJhhblCi0
+BvD7HuM0ZbFHmQwAX14kvYTIKbQKxxYJkUqeOFAHBYmMlb4ApocxAIMnbjQV6XBsEZHAKi7BKm7s
+uELAuTHIKaQMhEeiKZQJL2KUcF9GAISAMUKS2A2QONyPKWPc5yGfkBKNLULBJGD5xHUjMFGSBLEH
+EWDMMEhR2lPAGV2wGwsjIsOYwr/oHlANkQNDgsBHgYVkChuisUXUkwmJQw9kD9ilPkjaQai5CCVa
+idCfkBJfwJ2DGMmUcOaTyA1F6LohyhAtRQIInMyX+IIJSCLTMAALcGC5I2kUM+lKD2HAI2+qAuKx
+RQE4lgBvJVoGFGDgB67rSi4S38W/eEqX5KIbclQv5KXwSMrBHyoFAeCJ76jGynldSm8Ro8RPgA3o
+OYLEZ47KWWQbnM3ALJM0kIwtcmPPjQFyCHTKmRs6YeqQMKG+QJ2n4VSk07FF0J0FDpoZV3mYBmkk
+AiapcBLYypypSKcXyIAkQ2MHbvWThEdAJyKEEwG8WOQHU/1dK6W3SAqE1hchcWPqegxhYmHg0hjc
+C+YXU0ySjvmIEZSNKxVqEk9wAJOb+mC2mIaphx4HUn6dDSYCjDf1rKlOd2bg2pF6l2e0m7fQu8/E
+L0xg1Pio73xQI1G7Fg+H62ZcSGv7heQZun2xxa0ldNoWmAfXlhoAVnfagExa3X01M3bjgXmoLp5h
+tmgwLigR+kV7J34xdzHfdcsgp1351aaXct+JfjjLUxfmLkyD79+r6aRuuKgw1y1HK9Q1Vya1FrTz
+4Q2mMIIxjH9lWcu/lHWd0Xww/mGkw9/7P6zmV8JuejNHj1ajv5Q+4pesWXrmfoXgVoV2l3HoxXCo
+F7Xj1eZimFv3am0pqcVmMNCtMSluMapuytpmxwq/mWTqX+AiJ6eNG87aIGFs/ObYlHv4gWG6PGEU
+Lfhtb/bgpEDN9XvyGbHE8PwFriLKQXCeMu1Amp0Z5x9bpR+telcec66mWWJ8PZTWTebFcU9FZTU7
+0lgYhHvBWpaagAvlXUti6u2VOhZcvyKsx5EjHi010i6fdxnbdbsLaK2OJow8a3G7WNlQ0njpUW2p
+5AyOMXaiGh2QPGeYuek5EwRfIyNNgmuVixL+yCtB+OmsPvb4KAfqabfr7dqzCS2mabXU0qjQqrQO
+0ScWrCx4bXzTqXEgSBTlVHhElVXWZAhd8TQ4zzARb+0vC6HPE8zZCDd6wallrnz44vmI0rI9bBCt
+MH2WU5VH7CSMKqbOiLUXdU2ehDngOBfd46POl4pktbB+PNWN2H/4RfmrMIEoLNLgnjnZIFRBizJe
+paAyxpx62F2G6p/PpN4aFIL9G2tx+Py0rURdHism6oVCGLX9vuTHXNTqlGQAoJePTU2g6jjyoHXb
+cnVGEpVym3PRDOqy9dhFCXZlt74otDMGdEViw7OiapbOWm0yALkWqPud3g1Pd2h3zLdtA7PVwLxR
+MkyAAOyXskYO0g9fQPj+pQ6Qhg5pH13vMBJtt8m1nJ81fr+Zv2ldtXrXyh6qMBbwV7Py27KQecaa
+QRxgokFOBstluVzduw9DYhgmxX9KBPOfdufCmCiF5fvNTb3qy7wrb33K+akYc8GckWLRqGrrqwdw
+ok72dPm0J3mqkI5FgSy3rb/kAsnTLb+Sp8pLVTmwScCWTkOZVXWzBmGoSllAwqnLCuvtzwPlF/aF
+vE/Fp2L57bGqIA1IbwTcVBeUtgKhndNc2KR6qu+dh9fp7MWwfpchZzN6VBT7fdn8qQRwD3KI1PWs
+LcR8/OZ6WKv3F5X+oF75Gk7RXFB+HtHpMHsNr75UxL83uapSR6aOWPW7FyhUFy05U4CVl8w0IBos
+jQ1ZY86DdUPxX0qpBpDViX9Hqb/FqOqe2vWaTg3KP54ZcoIFS8N9HfUpCmHNkeRnI1pKGdNG94FC
+BWahHjJrh3zMTdJ23enGGkDX25sanfZNrRrt+bAWLg68TeJD7pAplM+sN+OGsCZfBLTfoAE3FPD3
+MiuWHWF0S424umJKnO6Kvwd3d420Qp/uddRd3dRLI3Z1p4rhmy9lphLoIIhix06dui+2EXqrS6ci
+hyDljbrzUl4+jVap1lvFZfyuurDSfiZVsVR+fvv7XebzkBYrW3CuX8ryG50S6nOSpfgiCvUHzDlA
+2dlO5AfV5X002TboNPpUQSui8l99krNUrpgB5dcWoGqmbu1RzoWAI/EK6lD1uQBd8awglmB4rWv9
+9hDWNSjbs3ZLoHHb0Zx3hMq8y2Z7NlsCEcWd8rAWsydsp5orXgrDNTuEF0o0z2X1ud10bR0MYZS0
+Ie2ncAopNErcAEwVisADTPfoegEknyuxrZxKtAQ0NMBe/Z5RRFKsr1JmALpX7ZPOsrWqpqvX0D/o
+ZG0yNUe2bVIuxOGd+bG86LTG2dnBsKa6eq63uKAyXXItPtj4WR5Esbxa9rX1A1r82+cqawA+iDH8
+q5trYPjntfog8FlFT3UArFJlCGhkZVUddXLk4kKYjvswPVTP3Qi9vsPE7mo/VJsauWGArcaP5Wqs
+sUERbY3BivX8mc7hTjywtR1m6O5fwuinRsC7SwjABnd6F5aXtViuriCibu600OHzls060IKCufql
+g63Zv3Mp/t4j05foQb6spxj7zLkfX/uIVHPsB3RL7aqOIF5qnS8+en6tbzajQo/VVxLPa14fJ/Rc
+7lx3WeOhYTQz6Jip0hhMCqzc72GoPWoLu8Mb0o5f3dXGSLs4BxdoP6/eqLOVh5VO02exqHRaC0vR
++G+mirJU+fmCq5Ta1xyCRccC897nZW+WyGsxiMawF7e329Zb2621wQDo2I7tLv7jrv9/AfAaXNUU
+TOsyF6jViUG46+NBJqZXv+rRK7Evv2i81ZEw33DQ8y6YowH05r+BuxfN92SX3RbVP8bNymDOGnY7
+16PfvzG+4ecrzfzkjPZya/H/ScnXyqwX/JtSrrL5pbrryu1hPKFrZzsrJD6sUuyPwDGdKerJyxmq
+dvmdHNCrrzU/+2W0pQ6gSvPl/Mertmi+7hBlDhB80kRUqcNeJCGapHNCz1cvCFwsf0A/Ne++jGMf
+TuOJcm6+ZnP9TRR7tWjHreOhZ6huiKnPAP2zfmqpIqHHLG/emnNhyHxSs+JJYfIwj6t2AlLdVneO
+3Is9u0R33ef+Wv2pVizPfbUW0rGhps1FRRfnZ/2xsnr3oT2Slh2tvngsLXu6M0OgIen7ufrjprrD
+vzXQAgNE22ualqzbyAb97uvl6qF/2a5hcU+eBzVWzOdmVjA0PXQMQoAhsulmBv39oU13134SjSlb
+dX85nKW3umfYbtu8713Sylhb2i3v2qaoc8C7S2P3pME8uIGedi1IxXbL+adi+P2fT8Xy/m+/PrxZ
+/TrXDcpqOMjotwdo9AJmg8r1N7BySygc+Gp+XaYdJhpV8f/7Oy3Y1s330l09YBDTjnyjn5qHGF7x
+6O7hZfMXz21OyLZB6lUfOGAGMzo/bjaL7VaV7Ha76D/1yJVEqKmr+L2nCbH7+959wDtv38JZplQG
+BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
+""")
+
+##file distribute_setup.py
+DISTRIBUTE_SETUP_PY = convert("""
+eJztG2tz2zbyu34FTh4PqYSi7TT3GM+pM2nj9DzNJZnYaT8kHhoiIYk1X+XDsvrrb3cBkCAJyc61
+dzM3c7qrIxGLxWLfuwCP/lTs6k2eTabT6Xd5Xld1yQsWxfBvvGxqweKsqnmS8DoGoMnliu3yhm15
+VrM6Z00lWCXqpqjzPKkAFkdLVvDwjq+FU8lBv9h57JemqgEgTJpIsHoTV5NVnCB6+AFIeCpg1VKE
+dV7u2DauNyyuPcaziPEoogm4IMLWecHylVxJ4z8/n0wYfFZlnhrUBzTO4rTIyxqpDTpqCb7/yJ2N
+dliKXxsgi3FWFSKMV3HI7kVZATOQhm6qh98BKsq3WZLzaJLGZZmXHstL4hLPGE9qUWYceKqBuh17
+tGgIUFHOqpwtd6xqiiLZxdl6gpvmRVHmRRnj9LxAYRA/bm+HO7i99SeTa2QX8TekhRGjYGUD3yvc
+SljGBW1PSZeoLNYlj0x5+qgUE8W8vNLfql37tY5Tob+vspTX4aYdEmmBFLS/eUk/Wwk1dYwqI0eT
+fD2Z1OXuvJNiFaP2yeFPVxcfg6vL64uJeAgFkH5Jzy+QxXJKC8EW7F2eCQObJrtZAgtDUVVSVSKx
+YoFU/iBMI/cZL9fVTE7BD/4EZC5s1xcPImxqvkyEN2PPaaiFK4FfZWag90PgqEvY2GLBTid7iT4C
+RQfmg2hAihFbgRQkQeyF/80fSuQR+7XJa1AmfNykIquB9StYPgNd7MDgEWIqwNyBmBTJdwDmmxdO
+t6QmCxEK3OasP6bwOPA/MG4YHw8bbHOmx9XUYccIOIJTMMMhtenPHQXEOviiVqxuhtLJK78qOFid
+C98+BD+/urz22IBp7Jkps9cXb159ensd/HTx8ery/TtYb3rq/8V/8XLaDn36+BYfb+q6OD85KXZF
+7EtR+Xm5PlFOsDqpwFGF4iQ66fzSyXRydXH96cP1+/dvr4I3r368eD1YKDw7m05MoA8//hBcvnvz
+Hsen0y+Tf4qaR7zm85+kOzpnZ/7p5B340XPDhCft6HE1uWrSlINVsAf4TP6Rp2JeAIX0e/KqAcpL
+8/tcpDxO5JO3cSiySoG+FtKBEF58AASBBPftaDKZkBorX+OCJ1jCvzNtA+IBYk5IyknuXQ7TYJ0W
+4CJhy9qb+OldhN/BU+M4uA1/y8vMdS46JKADx5XjqckSME+iYBsBIhD/WtThNlIYWi9BUGC7G5jj
+mlMJihMR0oX5eSGydhctTKD2obbYm+yHSV4JDC+dQa5zRSxuug0ELQD4E7l1IKrg9cb/BeAVYR4+
+TECbDFo/n97MxhuRWLqBjmHv8i3b5uWdyTENbVCphIZhaIzjsh1kr1vddmamO8nyuufAHB2xYTlH
+IXcGHqRb4Ap0FEI/4N+Cy2LbMoevUVNqXTGTE99YeIBFCIIW6HlZCi4atJ7xZX4v9KRVnAEemypI
+zZlpJV42MTwQ67UL/3laWeFLHiDr/q/T/wM6TTKkWJgxkKIF0XcthKHYCNsJQsq749Q+HZ//in+X
+6PtRbejRHH/Bn9JA9EQ1lDuQUU1rVymqJqn7ygNLSWBlg5rj4gGWrmi4W6XkMaSol+8pNXGd7/Mm
+iWgWcUraznqNtqKsIAKiVQ7rqnTYa7PaYMkroTdmPI5EwndqVWTlUA0UvNOFyflxNS92x5EP/0fe
+WRMJ+ByzjgoM6uoHRJxVDjpkeXh2M3s6e5RZAMHtXoyMe8/+99E6+OzhUqdXjzgcAqScDckHfyjK
+2j31WCd/lf326x4jyV/qqk8H6IDS7wWZhpT3oMZQO14MUqQBBxZGmmTlhtzBAlW8KS1MWJz92QPh
+BCt+JxbXZSNa75pyMvGqgcJsS8kz6ShfVnmChoq8mHRLGJoGIPiva3Jvy6tAckmgN3WKu3UAJkVZ
+W0VJLPI3zaMmERVWSl/a3TgdV4aAY0/c+2GIprdeH0Aq54ZXvK5LtwcIhhJERtC1JuE4W3HQnoXT
+UL8CHoIo59DVLi3EvrKmnSlz79/jLfYzr8cMX5Xp7rRjybeL6XO12sxC1nAXfXwqbf4+z1ZJHNb9
+pQVoiawdQvIm7gz8yVBwplaNeY/TIdRBRuJvSyh03RHE9Jo8O20rMnsORm/G/XZxDAUL1PooaH4P
+6TpVMl+y6RgftlJCnjk11pvK1AHzdoNtAuqvqLYAfCubDKOLzz4kAsRjxadbB5yleYmkhpiiaUJX
+cVnVHpgmoLFOdwDxTrscNv9k7MvxLfBfsi+Z+31TlrBKspOI2XE5A+Q9/y98rOIwcxirshRaXLsv
++mMiqSz2ARrIBiZn2PfngZ+4wSkYmamxk9/tK2a/xhqeFEP2WYxVr9tsBlZ9l9dv8iaLfrfRPkqm
+jcRRqnPIXQVhKXgtht4qwM2RBbZZFIarA1H698Ys+lgCl4pXygtDPfy6a/G15kpxtW0kgu0leUil
+C7U5FePjWnbuMqjkZVJ4q2i/ZdWGMrMltiPveRL3sGvLy5p0KUqwaE6m3HoFwoXtP0p6qWPS9iFB
+C2iKYLc9ftwy7HG44CPCjV5dZJEMm9ij5cw5cWY+u5U8ucUVe7k/+BdRCp1Ctv0uvYqIfLlH4mA7
+Xe2BOqxhnkXU6yw4BvqlWKG7wbZmWDc86TqutL8aK6na12L4jyQMvVhEQm1KqIKXFIUEtrlVv7lM
+sKyaGNZojZUGihe2ufX6twDVAVs/veTYxzJs/Rs6QCV92dQue7kqCpI9b7HI/I/fC2DpnhRcg6rs
+sgwRHexLtVYNax3kzRLt7Bx5/uo+j1GrC7TcqCWny3BGIb0tXlrrIR9fTT3cUt9lS6IUl9zR8BH7
+KHh0QrGVYYCB5AxIZ0swuTsPO+xbVEKMhtK1gCaHeVmCuyDrGyCD3ZJWa3uJ8ayjFgSvVVh/sCmH
+CUIZgj7waJBRSTYS0ZJZHptul9MRkEoLEFk3NvKZShKwliXFAAJ0iT6AB/yWcAeLmvBd55QkDHtJ
+yBKUjFUlCO66Au+1zB/cVZOF6M2UE6Rhc5zaqx579uxuOzuQFcvmf1efqOnaMF5rz3Ilnx9KmIew
+mDNDIW1LlpHa+ziXraRRm938FLyqRgPDlXxcBwQ9ft4u8gQcLSxg2j+vwGMXKl2wSHpCYtNNeMMB
+4Mn5/HDefhkq3dEa0RP9o9qslhnTfZhBVhFYkzo7pKn0pt4qRSeqAvQNLpqBB+4CPEBWdyH/Z4pt
+PLxrCvIWK5lYi0zuCCK7DkjkLcG3BQqH9giIeGZ6DeDGGHahl+44dAQ+DqftNPMsPa1XfQizXap2
+3WlDN+sDQmMp4OsJkE1ibAjIGRDFMp8zNwGGtnVswVK5Nc07eya4svkh0u2JIQZYz/Quxoj2TXio
+rNlmFZp2cUPeGzxWqEZ7lggysdWRGZ9ClHX8929f+8cVHmnh6aiPf0ad3Y+ITgY3DCS57ClKEjVO
+1eTF2hZ/urZRtQH9sCU2ze8hWQbTCMwOuVskPBQbUHahO9WDMB5X2Gscg/Wp/5TdQSDsNd8h8VJ7
+MObu168V1h09/4PpqL4QYDSC7aQA1eq02Vf/ujjXM/sxz7BjOMfiYOju9eIjb7kE6d+ZbFn1y6OO
+A12HlFJ489DcXHfAgMlIC0BOqAUiEfJINm9qTHrRe2z5rrM5XecMEzaDPR6Tqq/IH0hUzTc40Tlz
+ZTlAdtCDla6qF0FGk6Q/VDM8ZjmvVJ1txdGRb++4AabAhy7KY31qrMp0BJi3LBG1UzFU/Nb5DvnZ
+KpriN+qaa7bwvEHzT7Xw8SYCfjW4pzEckoeC6R2HDfvMCmRQ7ZreZoRlHNNteglOVTbuga2aWMWJ
+PW1056q7yBMZbQJnsJO+P97na4beeR+c9tV8Bel0e0SM6yumGAEMQdobK23burWRjvdYrgAGPBUD
+/5+mQESQL39xuwNHX/e6CygJoe6Ske2xLkPPuUm6v2ZKz+Wa5IJKWoqpx9ywRdiaObqxMHZBxKnd
+PfEITE5FKvfJpyayIuw2qiKxYUXq0Kbq/CAs8KWnc+6+qwKepO0rnN6AlJH/07wcO0Cr55HgB/zO
+0Id/j/KXkXw0q0uJWgd5OC2yuk8C2J8iSVbVbU60n1WGjHyY4AyTksFW6o3B0W4r6vFjW+mRYXTK
+hvJ6fH+PmdjQ0zwCPuvl823Q63K6IxVKIAKFd6hKMf6y5dd7FVRmwBc//DBHEWIIAXHK71+hoPEo
+hT0YZ/fFhKfGVcO3d7F1T7IPxKd3Ld/6jw6yYvaIaT/Kuf+KTRms6JUdSlvslYca1Pol+5RtRBtF
+s+9kH3NvOLOczCnM1KwNilKs4gdXe/ouuLRBjkKDOpSE+vveOO839oa/1YU6DfhZf4EoGYkHI2w+
+Pzu/abMoGvT0tTuRNakoubyQZ/ZOEFTeWJX51nxewl7lPQi5iWGCDpsAHD6sWdYVtplRiRcYRiQe
+S2OmzgslGZpZJHHtOrjOwpl9ng9O5wwWaPaZiylcwyMiSRWWhpIK64FrApopbxF+K/lj7yH1yK0+
+E+RzC5VfS2lHIzC3qUTp0NFCdzlWHRViG9fasbGt0s62GIbUyJGqDpX9KuR0oGicO+rrkTbb3Xsw
+fqhDdcS2wgGLCoEES5A3sltQSONWT5QLyZRKiBTPGczj0XGXhH5u0Vz6pYK6d4RsGG/IiEOYmMLk
+beVj1tY/0/c/yvNeTLbBK5bgjHrliT1xH2gLxXzEsCA3rjyu4tz1rhAjvmGr0jhIevXh8g8mfNYV
+gUOEoJB9ZTRvc5nvFpgliSzM7aI5YpGohbo1h8EbT+LbCIiaGg1z2PYYbjEkz9dDQ30233kwih65
+NGi3bodYVlG8oEMF6QtRIckXxg9EbFHm93EkIvn6Q7xS8OaLFpXRfIjUhbvU6w41dMfRrDj6gcNG
+mV0KChsw1BsSDIjkWYjtHuhYW+WNcKBlA/XH/hqll4aBVUo5VuZ1PbUlyyZ8kUUqaNCdsT2byuby
+Nl8nvB4daN/7+2hWqerJijTAYfOwlqaKceFzP0n7MiYLKYcTKEWiuy//RJ3rdyO+Igfdm4QeaD4P
+eNOfN24/m7rRHt2hWdP5snR/dNZr+PtMDEXbz/5/rzwH9NJpZyaMhnnCmyzcdClc92QYKT+qkd6e
+MbSxDcfWFr6RJCGo4NdvtEioIi5Yyss7PMvPGacDWN5NWDat8bSp3vk3N5gufHbmoXkjm7IzvGKT
+iLlqAczFA72/BDnzPOUZxO7IuTFCnMZ4etP2A7BpZiaYn/tvXNyw5+20icZB93OsL9O03DMuJVci
+WcnG+WLqTz2WCrw4UC0wpnQnM+oiNR0EKwh5zEiXAErgtmQt/gzlFSN9j1jvr7vQgD4Z3/XKtxlW
+1Wke4Vth0v9js58AClGmcVXRa1rdkZ1GEoMSUsMLZB5VPrvFDTjtxRB8RQuQrgQRMrpGDYQqDsBX
+mKx25KAnlqkpT4iIFF+5o8siwE8imRqAGg/22JUWg8Yud2wtaoXLnfVvUKiELMyLnfkbCjHI+NWN
+QMlQeZ1cAyjGd9cGTQ6APty0eYEWyygf0AMYm5PVpK0+YCXyhxBRFEivclbDqv898EtHmrAePepC
+S8VXAqUqBsf6HaTPC6hAI1et0Xdlmq4FccvHPwcB8T4Z9m1evvwb5S5hnIL4qGgC+k7/enpqJGPJ
+ylei1zil8rc5xUeB1ipYhdw3STYN3+zpsb8z94XHXhocQhvD+aJ0AcOZh3hezKzlQpgWBONjk0AC
++t3p1JBtiNSVmO0ApaTetR09jBDdid1CK6CPx/2gvkizgwQ4M48pbPLqsGYQZG500QNwtRbcWi2q
+LokDU7kh8wZKZ4z3iKRzQGtbQwu8z6DR2TlJOdwAcZ2MFd7ZGLCh88UnAIYb2NkBQFUgmBb7b9x6
+lSqKkxPgfgJV8Nm4AqYbxYPq2nZPgZAF0XLtghJOlWvBN9nwwpPQ4SDlMdXc9x7bc8mvCwSXh153
+JRW44NVOQWnnd/j6v4rxw5fbgLiY7r9g8hRQRR4ESGoQqHcpie42ap6d38wm/wIwBuVg
+""")
+
+##file activate.sh
+ACTIVATE_SH = convert("""
+eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9
+H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq
+DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs
+cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY
+G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T
+EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs
+wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG
+5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/
+JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR
+huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx
+Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L
+Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw
+WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX
+LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2
+""")
+
+##file activate.fish
+ACTIVATE_FISH = convert("""
+eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A
+Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7
+pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ
+lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v
+g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u
+grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS
+xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV
+MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu
+H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM
+L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz
+fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV
+pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh
+MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT
+O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz
+7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi
+m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq
+djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5
+mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN
+jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk=
+""")
+
+##file activate.csh
+ACTIVATE_CSH = convert("""
+eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
+XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
+kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
+pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
+sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
+yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
+E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
+lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
+r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
+""")
+
+##file activate.bat
+ACTIVATE_BAT = convert("""
+eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
+qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
+sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
+ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
+""")
+
+##file deactivate.bat
+DEACTIVATE_BAT = convert("""
+eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
+FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
+i2dASrm4rFz9XLgAwJNbyQ==
+""")
+
+##file distutils-init.py
+DISTUTILS_INIT = convert("""
+eJytV92L4zYQf/dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313dG8odkO9d7aGBB
+luZLv/nNjFacOqUtKJMIvzK3cXlhWgp5MDBsqK5SNYftsBAGpLLA4F1oe2Ytl+9wUvW55TswCi4c
+KibhbFDSglXQCFmDPXIwtm7FawLRbwtPzg2T9gf4gupKv4GS0N262w7V0NvpbCy8cvTo3eAus6C5
+ETU3ICQZX1hFTw/dzR6V/AW1RCN4/XAtbsVXqIXmlVX6liS4lOzEYY9QFB2zx6LfoSNjz1a0pqT9
+QOIfJWQ2E888NEVZNqLlZZnvIB0NpHkimlFdKn2iRRY7yGG/CCJb6Iz280d34SFXBS2yEYPNF0Q7
+yM7oCjpWvbEDQmnhRwOs6zjThpKE8HogwRAgraqYFZgGZvzmzVh+mgz9vskT3hruwyjdFcqyENJw
+bbMPO5jdzonxK68QKT7B57CMRRG5shRSWDTX3dI8LzRndZbnSWL1zfvriUmK4TcGWSnZiEPCrxXv
+bM+sP7VW2is2WgWXCO3sAu3Rzysz3FiNCA8WPyM4gb1JAAmCiyTZbhFjWx3h9SzauuRXC9MFoVbc
+yNTCm1QXOOIfIn/g1kGMhDUBN72hI5XCBQtIXQw8UEEdma6Jaz4vJIJ51Orc15hzzmu6TdFp3ogr
+Aof0c98tsw1SiaiWotHffk3XYCkqdToxWRfTFXqgpg2khcLluOHMVC0zZhLKIomesfSreUNNgbXi
+Ky9VRzwzkBneNoGQyyvGjbsFQqOZvpWIjqH281lJ/jireFgR3cPzSyTGWzQpDNIU+03Fs4XKLkhp
+/n0uFnuF6VphB44b3uWRneSbBoMSioqE8oeF0JY+qTvYfEK+bPLYdoR4McfYQ7wMZj39q0kfP8q+
+FfsymO0GzNlPh644Jje06ulqHpOEQqdJUfoidI2O4CWx4qOglLye6RrFQirpCRXvhoRqXH3sYdVJ
+AItvc+VUsLO2v2hVAWrNIfVGtkG351cUMNncbh/WdowtSPtCdkzYFv6mwYc9o2Jt68ud6wectBr8
+hYAulPSlgzH44YbV3ikjrulEaNJxt+/H3wZ7bXSXje/YY4tfVVrVmUstaDwwOBLMg6iduDB0lMVC
+UyzYx7Ab4kjCqdViEJmDcdk/SKbgsjYXgfMznUWcrtS4z4fmJ/XOM1LPk/iIpqass5XwNbdnLb1Y
+8h3ERXSWZI6rZJxKs1LBqVH65w0Oy4ra0CBYxEeuOMbDmV5GI6E0Ha/wgVTtkX0+OXvqsD02CKLf
+XHbeft85D7tTCMYy2Njp4DJP7gWJr6paVWXZ1+/6YXLv/iE0M90FktiI7yFJD9e7SOLhEkkaMTUO
+azq9i2woBNR0/0eoF1HFMf0H8ChxH/jgcB34GZIz3Qn4/vid+VEamQrOVqAPTrOfmD4MPdVh09tb
+8dLLjvh/61lEP4yW5vJaH4vHcevG8agXvzPGoOhhXNncpTr99PTHx6e/UvffFLaxUSjuSeP286Dw
+gtEMcW1xKr/he4/6IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLn7fAY78k4aiR387bCr5XT
+5C4rFgwLGfMvJuAMew==
+""")
+
+##file distutils.cfg
+DISTUTILS_CFG = convert("""
+eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
+xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
+9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
+""")
+
+##file activate_this.py
+ACTIVATE_THIS = convert("""
+eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ
+VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a
+Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE
+qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX
+4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7
+HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n
+xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96
+1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI
+3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU=
+""")
+
+if __name__ == '__main__':
+    main()
+
+## TODO:
+## Copy python.exe.manifest
+## Monkeypatch distutils.sysconfig
diff --git a/tools/cxxtest/bin/cxxtestgen b/tools/cxxtest/bin/cxxtestgen
new file mode 100644 (file)
index 0000000..e001cfa
--- /dev/null
@@ -0,0 +1,18 @@
+#! /usr/bin/env python
+#
+# The CxxTest driver script, which uses the cxxtest Python package.
+#
+
+import sys
+import os
+from os.path import realpath, dirname
+if sys.version_info < (3,0):
+    sys.path.insert(0, dirname(dirname(realpath(__file__)))+os.sep+'python')
+else:
+    sys.path.insert(0, dirname(dirname(realpath(__file__)))+os.sep+'python'+os.sep+'python3')
+sys.path.append(".")
+
+import cxxtest
+
+cxxtest.main(sys.argv)
+
diff --git a/tools/cxxtest/build_tools/SCons/AUTHORS b/tools/cxxtest/build_tools/SCons/AUTHORS
new file mode 100644 (file)
index 0000000..1f3e7e4
--- /dev/null
@@ -0,0 +1,19 @@
+This file is meant to be a full credit of the people who helped make the CxxTest
+builder what it is today.
+
+
+Current maintainer:
+    GaÅ¡per Ažman  (gasper dot azman at gmail.com)
+
+
+Original author:
+    GaÅ¡per Ažman
+
+Additional patches and tests:
+    Diego Nieto Cid
+    Edmundo López Bobeda
+    John Darby Mitchell
+    Pavol Juhas
+
+Other helpful suggestions:
+    John Darby Mitchell
diff --git a/tools/cxxtest/build_tools/SCons/cxxtest.py b/tools/cxxtest/build_tools/SCons/cxxtest.py
new file mode 100644 (file)
index 0000000..2bcce0c
--- /dev/null
@@ -0,0 +1,348 @@
+# coding=UTF-8
+#
+# == Preamble ==
+# Authors of this script are in the Authors file in the same directory as this
+# script.
+#
+# please send bugreports/praise/comments/criticism to
+# gasper.azman at gmail.com or the cxxtest mailing list (dev at cxxtest.tigris.org)
+#
+# This file is maintained as a part of the CxxTest test suite.
+# 
+# == About ==
+#
+# This builder correctly tracks dependencies and supports just about every
+# configuration option for CxxTest that I can think of. It automatically
+# defines a target "check" (configurable), so all tests can be run with a
+#  % scons check
+# This will first compile and then run the tests.
+#
+# The default configuration assumes that cxxtest is located at the base source
+# directory (where SConstruct is), that the cxxtestgen is under
+# cxxtest/bin/cxxtestgen and headers are in cxxtest/cxxtest/. The
+# header include path is automatically added to CPPPATH. It, however, can also
+# recognise that cxxtest is installed system-wide (based on redhat's RPM).
+#
+# For a list of environment variables and their defaults, see the generate()
+# function.
+#
+# This should be in a file called cxxtest.py somewhere in the scons toolpath.
+# (default: #/site_scons/site_tools/)
+#
+# == Usage: ==
+#
+# For configuration options, check the comment of the generate() function.
+#
+# This builder has a variety of different possible usages, so bear with me.
+#
+# env.CxxTest('target')
+# The simplest of them all, it models the Program call. This sees if target.t.h
+# is around and passes it through the cxxtestgen and compiles it. Might only
+# work on unix though, because target can't have a suffix right now.
+#
+# env.CxxTest(['target.t.h'])
+# This compiles target.t.h as in the previous example, but now sees that it is a
+# source file. It need not have the same suffix as the env['CXXTEST_SUFFIX']
+# variable dictates. The only file provided is taken as the test source file.
+#
+# env.CxxTest(['test1.t.h','test1_lib.cpp','test1_lib2.cpp','test2.t.h',...])
+# You may also specify multiple source files. In this case, the 1st file that
+# ends with CXXTEST_SUFFIX (default: .t.h) will be taken as the default test
+# file. All others will be run with the --part switch and linked in. All files
+# *not* having the right suffix will be passed to the Program call verbatim.
+#
+# In the last two cases, you may also specify the desired name of the test as
+# the 1st argument to the function. This will result in the end executable
+# called that. Normal Program builder rules apply.
+#
+
+from SCons.Script import *
+from SCons.Builder import Builder
+import os
+
+# A warning class to notify users of problems
+class ToolCxxTestWarning(SCons.Warnings.Warning):
+    pass
+
+SCons.Warnings.enableWarningClass(ToolCxxTestWarning)
+
+def accumulateEnvVar(dicts, name, default = []):
+    """
+    Accumulates the values under key 'name' from the list of dictionaries dict.
+    The default value is appended to the end list if 'name' does not exist in
+    the dict.
+    """
+    final = []
+    for d in dicts:
+        final += Split(d.get(name, default))
+    return final
+
+def multiget(dictlist, key, default = None):
+    """
+    Takes a list of dictionaries as its 1st argument. Checks if the key exists
+    in each one and returns the 1st one it finds. If the key is found in no
+    dictionaries, the default is returned.
+    """
+    for dict in dictlist:
+        if dict.has_key(key):
+            return dict[key]
+    else:
+        return default
+
+def envget(env, key, default=None):
+    """Look in the env, then in os.environ. Otherwise same as multiget."""
+    return multiget([env, os.environ], key, default)
+
+def UnitTest(env, target, source = [], **kwargs):
+    """
+    Prepares the Program call arguments, calls Program and adds the result to
+    the check target.
+    """
+    # get the c and cxx flags to process.
+    ccflags   = Split( multiget([kwargs, env, os.environ], 'CCFLAGS' ))
+    cxxflags  = Split( multiget([kwargs, env, os.environ], 'CXXFLAGS'))
+    # get the removal c and cxx flags
+    cxxremove = set( Split( multiget([kwargs, env, os.environ],'CXXTEST_CXXFLAGS_REMOVE')))
+    ccremove  = set( Split( multiget([kwargs, env, os.environ],'CXXTEST_CCFLAGS_REMOVE' )))
+    # remove the required flags
+    ccflags   = [item for item in ccflags if item not in ccremove]
+    cxxflags  = [item for item in cxxflags if item not in cxxremove]
+    # fill the flags into kwargs
+    kwargs["CXXFLAGS"] = cxxflags
+    kwargs["CCFLAGS"]  = ccflags
+    test = env.Program(target, source = source, **kwargs)
+    if multiget([kwargs, env, os.environ], 'CXXTEST_SKIP_ERRORS', False):
+        runner = env.Action(test[0].abspath, exitstatfunc=lambda x:0)
+    else:
+        runner = env.Action(test[0].abspath)
+    env.Alias(env['CXXTEST_TARGET'], test, runner)
+    env.AlwaysBuild(env['CXXTEST_TARGET'])
+    return test
+
+def isValidScriptPath(cxxtestgen):
+    """check keyword arg or environment variable locating cxxtestgen script"""
+       
+    if cxxtestgen and os.path.exists(cxxtestgen):
+        return True
+    else:
+        SCons.Warnings.warn(ToolCxxTestWarning,
+                            "Invalid CXXTEST environment variable specified!")
+        return False
+    
+def defaultCxxTestGenLocation(env):
+    return os.path.join(
+                envget(env, 'CXXTEST_CXXTESTGEN_DEFAULT_LOCATION'),
+                envget(env, 'CXXTEST_CXXTESTGEN_SCRIPT_NAME')
+                )
+
+def findCxxTestGen(env):
+    """locate the cxxtestgen script by checking environment, path and project"""
+    
+    # check the SCons environment...
+    # Then, check the OS environment...
+    cxxtest = envget(env, 'CXXTEST', None)
+
+    # check for common passing errors and provide diagnostics.
+    if isinstance(cxxtest, (list, tuple, dict)):
+        SCons.Warnings.warn(
+                ToolCxxTestWarning,
+                "The CXXTEST variable was specified as a list."
+                " This is not supported. Please pass a string."
+                )
+
+    if cxxtest:
+        try:
+            #try getting the absolute path of the file first.
+            # Required to expand '#'
+            cxxtest = env.File(cxxtest).abspath
+        except TypeError:
+            try:
+                #maybe only the directory was specified?
+                cxxtest = env.File(
+                        os.path.join(cxxtest, defaultCxxTestGenLocation(env)
+                            )).abspath
+            except TypeError:
+                pass
+        # If the user specified the location in the environment,
+        # make sure it was correct
+        if isValidScriptPath(cxxtest):
+           return os.path.realpath(cxxtest)
+    
+    # No valid environment variable found, so...
+    # Next, check the path...
+    # Next, check the project
+    check_path = os.path.join(
+            envget(env, 'CXXTEST_INSTALL_DIR'),
+            envget(env, 'CXXTEST_CXXTESTGEN_DEFAULT_LOCATION'))
+
+    cxxtest = (env.WhereIs(envget(env, 'CXXTEST_CXXTESTGEN_SCRIPT_NAME')) or 
+               env.WhereIs(envget(env, 'CXXTEST_CXXTESTGEN_SCRIPT_NAME'),
+                   path=[Dir(check_path).abspath]))
+    
+    if cxxtest:
+        return cxxtest
+    else:
+        # If we weren't able to locate the cxxtestgen script, complain...
+        SCons.Warnings.warn(
+                ToolCxxTestWarning,
+                "Unable to locate cxxtestgen in environment, path or"
+                " project!\n"
+                "Please set the CXXTEST variable to the path of the"
+                " cxxtestgen script"
+                )
+        return None
+
+def findCxxTestHeaders(env):
+    searchfile = 'TestSuite.h'
+    cxxtestgen_pathlen = len(defaultCxxTestGenLocation(env))
+
+    default_path = Dir(envget(env,'CXXTEST_INSTALL_DIR')).abspath
+
+    os_cxxtestgen = os.path.realpath(File(env['CXXTEST']).abspath)
+    alt_path = os_cxxtestgen[:-cxxtestgen_pathlen]
+
+    searchpaths = [default_path, alt_path]
+    for p in searchpaths:
+        if os.path.exists(os.path.join(p, 'cxxtest', searchfile)):
+            return p
+
+def generate(env, **kwargs):
+    """
+    Keyword arguments (all can be set via environment variables as well):
+    CXXTEST         - the path to the cxxtestgen script.
+                        Default: searches SCons environment, OS environment,
+                        path and project in that order. Instead of setting this,
+                        you can also set CXXTEST_INSTALL_DIR
+    CXXTEST_RUNNER  - the runner to use.  Default: ErrorPrinter
+    CXXTEST_OPTS    - other options to pass to cxxtest.  Default: ''
+    CXXTEST_SUFFIX  - the suffix of the test files.  Default: '.t.h'
+    CXXTEST_TARGET  - the target to append the tests to.  Default: check
+    CXXTEST_CXXFLAGS_REMOVE - the flags that cxxtests can't compile with,
+                              or give lots of warnings. Will be stripped.
+                              Default: -pedantic -Weffc++
+    CXXTEST_CCFLAGS_REMOVE - the same thing as CXXTEST_CXXFLAGS_REMOVE, just for
+                            CCFLAGS. Default: same as CXXFLAGS.
+    CXXTEST_PYTHON  - the path to the python binary.
+                        Default: searches path for python
+    CXXTEST_SKIP_ERRORS - set to True to continue running the next test if one
+                          test fails. Default: False
+    CXXTEST_CPPPATH - If you do not want to clutter your global CPPPATH with the
+                        CxxTest header files and other stuff you only need for
+                        your tests, this is the variable to set. Behaves as
+                        CPPPATH does.
+    CXXTEST_INSTALL_DIR - this is where you tell the builder where CxxTest is
+                            installed. The install directory has cxxtest,
+                            python, docs and other subdirectories.
+    ... and all others that Program() accepts, like CPPPATH etc.
+    """
+
+    print "Loading CxxTest tool..."
+
+    #
+    # Expected behaviour: keyword arguments override environment variables;
+    # environment variables override default settings.
+    #          
+    env.SetDefault( CXXTEST_RUNNER  = 'ErrorPrinter'        )
+    env.SetDefault( CXXTEST_OPTS    = ''                    )
+    env.SetDefault( CXXTEST_SUFFIX  = '.t.h'                )
+    env.SetDefault( CXXTEST_TARGET  = 'check'               )
+    env.SetDefault( CXXTEST_CPPPATH = ['#']                 )
+    env.SetDefault( CXXTEST_PYTHON  = env.WhereIs('python') )
+    env.SetDefault( CXXTEST_SKIP_ERRORS = False             )
+    env.SetDefault( CXXTEST_CXXFLAGS_REMOVE =
+            ['-pedantic','-Weffc++','-pedantic-errors'] )
+    env.SetDefault( CXXTEST_CCFLAGS_REMOVE  =
+            ['-pedantic','-Weffc++','-pedantic-errors'] )
+    env.SetDefault( CXXTEST_INSTALL_DIR = '#/cxxtest/'      )
+
+    # this one's not for public use - it documents where the cxxtestgen script
+    # is located in the CxxTest tree normally.
+    env.SetDefault( CXXTEST_CXXTESTGEN_DEFAULT_LOCATION = 'bin' )
+    # the cxxtestgen script name.
+    env.SetDefault( CXXTEST_CXXTESTGEN_SCRIPT_NAME = 'cxxtestgen' )
+
+    #Here's where keyword arguments are applied
+    apply(env.Replace, (), kwargs)
+
+    #If the user specified the path to CXXTEST, make sure it is correct
+    #otherwise, search for and set the default toolpath.
+    if (not kwargs.has_key('CXXTEST') or not isValidScriptPath(kwargs['CXXTEST']) ):
+        env["CXXTEST"] = findCxxTestGen(env)
+
+    # find and add the CxxTest headers to the path.
+    env.AppendUnique( CXXTEST_CPPPATH = [findCxxTestHeaders(env)]  )
+    
+    cxxtest = env['CXXTEST']
+    if cxxtest:
+        #
+        # Create the Builder (only if we have a valid cxxtestgen!)
+        #
+        cxxtest_builder = Builder(
+            action =
+            [["$CXXTEST_PYTHON",cxxtest,"--runner=$CXXTEST_RUNNER",
+                "$CXXTEST_OPTS","$CXXTEST_ROOT_PART","-o","$TARGET","$SOURCE"]],
+            suffix = ".cpp",
+            src_suffix = '$CXXTEST_SUFFIX'
+            )
+    else:
+        cxxtest_builder = (lambda *a: sys.stderr.write("ERROR: CXXTESTGEN NOT FOUND!"))
+
+    def CxxTest(env, target, source = None, **kwargs):
+        """Usage:
+        The function is modelled to be called as the Program() call is:
+        env.CxxTest('target_name') will build the test from the source
+            target_name + env['CXXTEST_SUFFIX'],
+        env.CxxTest('target_name', source = 'test_src.t.h') will build the test
+            from test_src.t.h source,
+        env.CxxTest('target_name, source = ['test_src.t.h', other_srcs]
+            builds the test from source[0] and links in other files mentioned in
+            sources,
+        You may also add additional arguments to the function. In that case, they
+        will be passed to the actual Program builder call unmodified. Convenient
+        for passing different CPPPATHs and the sort. This function also appends
+        CXXTEST_CPPPATH to CPPPATH. It does not clutter the environment's CPPPATH.
+        """
+        if (source == None):
+            suffix = multiget([kwargs, env, os.environ], 'CXXTEST_SUFFIX', "")
+            source = [t + suffix for t in target]
+        sources = Flatten(Split(source))
+        headers = []
+        linkins = []
+        for l in sources:
+            # check whether this is a file object or a string path
+            try:
+                s = l.abspath
+            except AttributeError:
+                s = l
+
+            if s.endswith(multiget([kwargs, env, os.environ], 'CXXTEST_SUFFIX', None)):
+                headers.append(l)
+            else:
+                linkins.append(l)
+
+        deps = []
+        if len(headers) == 0:
+            if len(linkins) != 0:
+                # the 1st source specified is the test
+                deps.append(env.CxxTestCpp(linkins.pop(0), **kwargs))
+        else:
+            deps.append(env.CxxTestCpp(headers.pop(0), **kwargs))
+            deps.extend(
+                [env.CxxTestCpp(header, CXXTEST_RUNNER = 'none',
+                    CXXTEST_ROOT_PART = '--part', **kwargs)
+                    for header in headers]
+                )
+        deps.extend(linkins)
+        kwargs['CPPPATH'] = list(set(
+            Split(kwargs.get('CPPPATH', [])) +
+            Split(env.get(   'CPPPATH', [])) +
+            Split(kwargs.get('CXXTEST_CPPPATH', [])) +
+            Split(env.get(   'CXXTEST_CPPPATH', []))
+            ))
+
+        return UnitTest(env, target, source = deps, **kwargs)
+
+    env.Append( BUILDERS = { "CxxTest" : CxxTest, "CxxTestCpp" : cxxtest_builder } )
+
+def exists(env):
+    return os.path.exists(env['CXXTEST'])
diff --git a/tools/cxxtest/build_tools/SCons/test/default_env/README b/tools/cxxtest/build_tools/SCons/test/default_env/README
new file mode 100644 (file)
index 0000000..d8c8b69
--- /dev/null
@@ -0,0 +1,2 @@
+Tests if the 'default environment' defaults are sane and work out of the box.
+by: GaÅ¡per Ažman
diff --git a/tools/cxxtest/build_tools/SCons/test/default_env/SConstruct b/tools/cxxtest/build_tools/SCons/test/default_env/SConstruct
new file mode 100644 (file)
index 0000000..637992e
--- /dev/null
@@ -0,0 +1,10 @@
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest']
+    )
+
+env['CXXTEST_SKIP_ERRORS'] = True
+env.CxxTest(['src/ThrowNoStd.h'])
+env.CxxTest(['src/AborterNoThrow.h'])
+env.CxxTest(['src/Comments.h'])
+
diff --git a/tools/cxxtest/build_tools/SCons/test/default_env/TestDef.py b/tools/cxxtest/build_tools/SCons/test/default_env/TestDef.py
new file mode 100644 (file)
index 0000000..3283790
--- /dev/null
@@ -0,0 +1,9 @@
+
+expect_success = True
+type           = 'scons'
+links = {
+        'cxxtest': '../../../../',
+        'src'    : '../../../../test/'
+        }
+
+
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/README b/tools/cxxtest/build_tools/SCons/test/empty_source_list/README
new file mode 100644 (file)
index 0000000..419901b
--- /dev/null
@@ -0,0 +1,2 @@
+Tests if cxxtest behaves correctly if no sources are given.
+by: GaÅ¡per Ažman
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct b/tools/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct
new file mode 100644 (file)
index 0000000..9f1dda9
--- /dev/null
@@ -0,0 +1,4 @@
+env = Environment(toolpath=['../../'],tools=['default','cxxtest'])
+
+env.CxxTest('test_bar')
+env.CxxTest('test_foo')
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py b/tools/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py
new file mode 100644 (file)
index 0000000..4088646
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp b/tools/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp
new file mode 100644 (file)
index 0000000..3a6f757
--- /dev/null
@@ -0,0 +1,12 @@
+/**
+ * @file requirement.cpp
+ * Implementation of the requirement function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:09:42 AM
+ */
+
+bool call_a_requirement() {
+    return true;
+}
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h b/tools/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h
new file mode 100644 (file)
index 0000000..4cd1ada
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_BAR_T_H
+#define TEST_BAR_T_H
+/**
+ * @file test_bar.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:04:06 AM
+ */
+
+#include <cxxtest/TestSuite.h>
+#include "requirement.hpp"
+
+class TestBar : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h b/tools/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h
new file mode 100644 (file)
index 0000000..2850447
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_FOO_T_H
+#define TEST_FOO_T_H
+/**
+ * @file test_foo.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:02:06 AM
+ */
+
+#include "requirement.hpp"
+#include <cxxtest/TestSuite.h>
+
+class TestFoo : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/eprouvette.py b/tools/cxxtest/build_tools/SCons/test/eprouvette.py
new file mode 100644 (file)
index 0000000..9748aeb
--- /dev/null
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+# vim: fileencoding=utf-8
+
+from __future__ import print_function
+import os, sys
+from os.path import isdir, isfile, islink, join
+from optparse import OptionParser
+from subprocess import check_call, CalledProcessError, PIPE
+
+options = None
+args    = []
+available_types = set(['scons'])
+tool_stdout = PIPE
+
+def main():
+    global options
+    global args
+    global tool_stdout
+    """Parse the options and execute the program."""
+    usage = \
+    """Usage: %prog [options] [test1 [test2 [...]]]
+    
+    If you provide one or more tests, this will run the provided tests.
+    Otherwise, it will look for tests in the current directory and run them all.
+    """
+    # option parsing
+    parser = OptionParser(usage)
+
+    parser.set_defaults(
+            action='run',
+            verbose=True)
+
+    parser.add_option("-c", "--clean",
+            action='store_const', const='clean', dest='action',
+            help="deletes any generated files in the tests")
+    parser.add_option("--run",
+            action='store_const', const='run', dest='action',
+            help="sets up the environment, compiles and runs the tests")
+    parser.add_option("-v", "--verbose",
+            action='store_true', dest='verbose',
+            help="spew out more details")
+    parser.add_option("-q", "--quiet",
+            action='store_false', dest='verbose',
+            help="spew out only success/failure of tests")
+    parser.add_option("--target-dir",
+            dest='target_dir', action='store', default='./',
+            help='target directory to look for tests in. default: %default')
+    parser.add_option("--debug",
+            dest='debug', action='store_true', default=False,
+            help='turn on debug output.')
+
+    (options, args) = parser.parse_args()
+    if options.debug or options.verbose:
+        tool_stdout = None
+    # gather the tests
+    tests = []
+    if len(args) == 0:
+        tests = crawl_tests(options.target_dir)
+    else:
+        tests = args
+    tests = purge_tests(tests)
+
+    # run the tests
+    if options.action == 'run':
+        for t in tests:
+            run_test(t)
+    elif options.action == 'clean':
+        for t in tests:
+            clean_test(t)
+        
+def crawl_tests(target):
+    """Gather the directories in the test directory."""
+    files = os.listdir(target)
+    return [f for f in files if isdir(f) and f[0] != '.']
+
+def purge_tests(dirs):
+    """Look at the test candidates and purge those that aren't from the list"""
+    tests = []
+    for t in dirs:
+        if isfile(join(t, 'TestDef.py')):
+            tests.append(t)
+        else:
+            warn("{0} is not a test (missing TestDef.py file).".format(t))
+    return tests
+
+def warn(msg):
+    """A general warning function."""
+    if options.verbose:
+        print('[Warn]: ' + msg, file=sys.stderr)
+
+def notice(msg):
+    """A general print function."""
+    if options.verbose:
+        print(msg)
+
+def debug(msg):
+    """A debugging function"""
+    if options.debug:
+        print(msg)
+
+def run_test(t):
+    """Runs the test in directory t."""
+    opts = read_opts(t)
+    notice("-----------------------------------------------------")
+    notice("running test '{0}':\n".format(t))
+    readme = join(t, 'README')
+    if isfile(readme):
+        notice(open(readme).read())
+        notice("")
+    if opts['type'] not in available_types:
+        warn('{0} is not a recognised test type in {1}'.format(opts['type'], t))
+        return
+    if not opts['expect_success']:
+        warn("tests that fail intentionally are not yet supported.")
+        return
+
+    # set up the environment
+    setup_env(t, opts)
+    # run the test
+    try:
+        if opts['type'] == 'scons':
+            run_scons(t, opts)
+    except RuntimeError as e:
+        print("Test {0} failed.".format(t))
+        return
+
+    if not options.verbose:
+        print('.', end='')
+        sys.stdout.flush()
+    else:
+        print("test '{0}' successful.".format(t))
+
+def read_opts(t):
+    """Read the test options and return them."""
+    opts = {
+            'expect_success' : True,
+            'type'           : 'scons',
+            'links'          : {}
+            }
+    f = open(join(t, "TestDef.py"))
+    exec(f.read(), opts)
+    return opts
+
+def setup_env(t, opts):
+    """Set up the environment for the test."""
+    # symlinks
+    links = opts['links']
+    for link in links:
+        frm = links[link]
+        to  = join(t, link)
+        debug("Symlinking {0} to {1}".format(frm, to))
+        if islink(to):
+            os.unlink(to)
+        os.symlink(frm, to)
+
+def teardown_env(t, opts):
+    """Remove all files generated for the test."""
+    links = opts['links']
+    for link in links:
+        to  = join(t, link)
+        debug('removing link {0}'.format(to))
+        os.unlink(to)
+
+def clean_test(t):
+    """Remove all generated files."""
+    opts = read_opts(t)
+    notice("cleaning test {0}".format(t))
+    if opts['type'] == 'scons':
+        setup_env(t, opts) # scons needs the environment links to work
+        clean_scons(t, opts)
+    teardown_env(t, opts)
+
+def clean_scons(t, opts):
+    """Make scons clean after itself."""
+    cwd = os.getcwd()
+    os.chdir(t)
+    try:
+        check_call(['scons', '--clean'], stdout=tool_stdout, stderr=None)
+    except CalledProcessError as e:
+        warn("SCons failed with error {0}".format(e.returncode))
+    os.chdir(cwd)
+    sconsign = join(t, '.sconsign.dblite')
+    if isfile(sconsign):
+        os.unlink(sconsign)
+
+def run_scons(t, opts):
+    """Run scons test."""
+    cwd = os.getcwd()
+    os.chdir(t)
+    try:
+        check_call(['scons', '--clean'], stdout=tool_stdout)
+        check_call(['scons', '.'], stdout=tool_stdout)
+        check_call(['scons', 'check'], stdout=tool_stdout)
+    except CalledProcessError as e:
+        os.chdir(cwd) # clean up
+        raise e
+    os.chdir(cwd)
+    
+if __name__ == "__main__":
+    main()
+
+if not options.verbose:
+    print() # quiet doesn't output newlines.
diff --git a/tools/cxxtest/build_tools/SCons/test/expanding_#/README b/tools/cxxtest/build_tools/SCons/test/expanding_#/README
new file mode 100644 (file)
index 0000000..eac1c92
--- /dev/null
@@ -0,0 +1,3 @@
+Tests whether expanding '#' to the top-level directory works as intended in
+scons.
+by: GaÅ¡per Ažman
diff --git a/tools/cxxtest/build_tools/SCons/test/expanding_#/SConstruct b/tools/cxxtest/build_tools/SCons/test/expanding_#/SConstruct
new file mode 100644 (file)
index 0000000..bae8789
--- /dev/null
@@ -0,0 +1,10 @@
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST='./../../../../bin/cxxtestgen'
+    )
+
+env['CXXTEST_SKIP_ERRORS'] = True
+env.CxxTest(['src/ThrowNoStd.h'])
+env.CxxTest(['src/AborterNoThrow.h'])
+env.CxxTest(['src/Comments.h'])
diff --git a/tools/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py b/tools/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py
new file mode 100644 (file)
index 0000000..17997a2
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'src' : '../../../../test'}
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/README b/tools/cxxtest/build_tools/SCons/test/globbing/README
new file mode 100644 (file)
index 0000000..a83d021
--- /dev/null
@@ -0,0 +1,2 @@
+Tests whether we can swallow file nodes as sources as well as strings.
+by: GaÅ¡per Ažman
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/SConstruct b/tools/cxxtest/build_tools/SCons/test/globbing/SConstruct
new file mode 100644 (file)
index 0000000..f647182
--- /dev/null
@@ -0,0 +1,3 @@
+env = Environment(toolpath=['../../'],tools=['default','cxxtest'])
+
+env.CxxTest('joint_tests',[Glob('src/*.t.h'), 'src/requirement.cpp'])
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/TestDef.py b/tools/cxxtest/build_tools/SCons/test/globbing/TestDef.py
new file mode 100644 (file)
index 0000000..4088646
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp b/tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp
new file mode 100644 (file)
index 0000000..45d60ad
--- /dev/null
@@ -0,0 +1,14 @@
+/**
+ * @file requirement.cpp
+ * Implementation of the requirement function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:09:42 AM
+ */
+
+#include "requirement.h"
+
+bool call_a_requirement() {
+    return true;
+}
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.h b/tools/cxxtest/build_tools/SCons/test/globbing/src/requirement.h
new file mode 100644 (file)
index 0000000..9bb9437
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef REQUIREMENT_H
+#define REQUIREMENT_H
+/**
+ * @file requirement.h
+ * Prototype for the call_a_requirement() function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:08:35 AM
+ */
+
+bool call_a_requirement();
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h b/tools/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h
new file mode 100644 (file)
index 0000000..76e594d
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_BAR_T_H
+#define TEST_BAR_T_H
+/**
+ * @file test_bar.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:04:06 AM
+ */
+
+#include <cxxtest/TestSuite.h>
+#include "requirement.h"
+
+class TestBar : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h b/tools/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h
new file mode 100644 (file)
index 0000000..418a3ca
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_FOO_T_H
+#define TEST_FOO_T_H
+/**
+ * @file test_foo.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:02:06 AM
+ */
+
+#include "requirement.h"
+#include <cxxtest/TestSuite.h>
+
+class TestFoo : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/README b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/README
new file mode 100644 (file)
index 0000000..188908b
--- /dev/null
@@ -0,0 +1,2 @@
+Test for various things cxxtest failed to do, but now does.
+by: Edmundo López B.
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct
new file mode 100644 (file)
index 0000000..fdfd3bd
--- /dev/null
@@ -0,0 +1,35 @@
+# What I want to do is the following:
+# I have my class files ending with .cc and
+# the main file ending with .cpp. This way it
+# very easy to do the following line just to
+# have all sources in that variable
+
+import os
+
+mySrc = Glob("*.cc")
+myFlags = ['-I.']
+
+myEnv = Environment( ENV = os.environ, tools = ['default', \
+    'cxxtest'], toolpath=['../../'])
+
+# Here is the first problem I corrected:
+# Flags won't be correctly recognized by cxxtest
+myEnv.Replace(CXXFLAGS = myFlags)
+
+
+# Then I want to convert those sources to objects
+
+myObjs = myEnv.Object(mySrc)
+
+# Having the objects I can create my program
+# this way:
+
+myEnv.Program('hello', ['main.cpp'] + myObjs)
+
+# Now I want to do the same thing with the tests
+# target
+# With the non corrected version you'll get 2 errors:
+# The CXXFLAGS are not set correctly
+# It won't even accept this construction, which as you see
+# works perfectly with Program (and CxxTest should work like it)
+myEnv.CxxTest('helloTest', ['hellotest.t.h'] + myObjs)
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py
new file mode 100644 (file)
index 0000000..6597b0c
--- /dev/null
@@ -0,0 +1 @@
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc
new file mode 100644 (file)
index 0000000..e18191d
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * \file
+ * Implementation of class.
+ */
+/****************************************************
+ * Author: Edmundo LOPEZ
+ * email:  lopezed5@etu.unige.ch
+ *
+ * This code was written as a part of my bachelor
+ * thesis at the University of Geneva.
+ *
+ * $Id$
+ *
+ * **************************************************/
+
+#include <hello.hh>
+
+int
+Hello::foo(int x, int y)
+  {
+    return x + y;
+  }
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh
new file mode 100644 (file)
index 0000000..7229995
--- /dev/null
@@ -0,0 +1,15 @@
+/**
+ * \file
+ * File containing a class
+ */
+/****************************************************
+ * Author: Edmundo LOPEZ
+ * email:  lopezed5@etu.unige.ch
+ *
+ * **************************************************/
+
+class Hello
+  {
+    public:
+      int foo(int x, int y);
+  };
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h
new file mode 100644 (file)
index 0000000..e90f26b
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file
+ * The test file.
+ */
+/****************************************************
+ * Author: Edmundo LOPEZ
+ * email:  lopezed5@etu.unige.ch
+ *
+ * **************************************************/
+
+#include <cxxtest/TestSuite.h>
+#include <hello.hh>
+      
+
+class helloTestSuite : public CxxTest::TestSuite 
+  {
+    public:
+    void testFoo()
+      {
+        Hello h;
+        TS_ASSERT_EQUALS (h.foo(2,2), 4);
+      }
+  };
diff --git a/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp b/tools/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp
new file mode 100644 (file)
index 0000000..21f1938
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * \file
+ * Main function comes here.
+ */
+/****************************************************
+ * Author: Edmundo LOPEZ
+ * email:  lopezed5@etu.unige.ch
+ *
+ * **************************************************/
+
+#include <hello.hh>
+#include <iostream>
+
+int main (int argc, char *argv[])
+  {
+    Hello h;
+    std::cout << h.foo(2,3) << std::endl;
+  }
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/README b/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/README
new file mode 100644 (file)
index 0000000..64905b9
--- /dev/null
@@ -0,0 +1,3 @@
+Tests:
+  - if CXXTEST_CXXFLAGS_REMOVE and CXXTEST_CCFLAGS_REMOVE flags work,
+  - if CCFLAGS and CXXFLAGS vars work.
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct b/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct
new file mode 100644 (file)
index 0000000..d946c33
--- /dev/null
@@ -0,0 +1,12 @@
+flags = '-pedantic-errors -Weffc++ -Wall -Wextra -ansi'
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CCFLAGS=flags,
+    CXXFLAGS=flags,
+    CXXTEST_CXXFLAGS_REMOVE=['-pedantic-errors','-Weffc++','-Wextra','-Wall','-W'],
+    CXXTEST_CCFLAGS_REMOVE=['-pedantic-errors','-Weffc++','-Wextra','-Wall','-W']
+    )
+
+env.CxxTest(['src/not-with-pedantic.h'])
+env.CxxTest(['src/only_with_ansi.t.h'])
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py b/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py
new file mode 100644 (file)
index 0000000..6597b0c
--- /dev/null
@@ -0,0 +1 @@
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h b/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h
new file mode 100644 (file)
index 0000000..e7377bb
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * @file not-with-pedantic.h
+ * Compiles, but not with -pedantic.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-09-30 13:33:50
+ */
+
+
+#include <cxxtest/TestSuite.h>
+
+class TestPedantic : public CxxTest::TestSuite
+{
+public:
+    void testPedanticPresent() {
+        TS_ASSERT(true);
+        int f = (true)?:5;
+    }
+};
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h b/tools/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h
new file mode 100644 (file)
index 0000000..4f6615e
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * @file only_with_ansi.t.h
+ * This test only runs correctly if -ansi was supplied as a g++ switch.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2009-02-11 06:26:59 PM
+ */
+
+#include <cxxtest/TestSuite.h>
+
+class TestAnsi : public CxxTest::TestSuite
+{
+public:
+    void testAnsiPresent() {
+#ifdef __STRICT_ANSI__
+        TS_ASSERT(true);
+#else
+        TS_ASSERT(false);
+#endif
+    }
+};
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README b/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README
new file mode 100644 (file)
index 0000000..07a9947
--- /dev/null
@@ -0,0 +1,5 @@
+This test tests whether variables that are put into the environment after it has
+been initialised work as expected.
+
+If they do not, -pedantic-errors will appear in the gcc commandline and the
+compilation WILL FAIL, failing the test.
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct b/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct
new file mode 100644 (file)
index 0000000..aefb439
--- /dev/null
@@ -0,0 +1,16 @@
+flags = '-Weffc++ -Wall -Wextra -std=gnu++0x'
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CCFLAGS = Split(flags) + ['-pedantic-errors'],
+    CXXFLAGS = Split(flags) + ['-pedantic-errors']
+    )
+
+env['CXXTEST_CXXFLAGS_REMOVE']=['-Weffc++','-Wextra','-Wall','-W']
+env['CXXTEST_CCFLAGS_REMOVE']='-Weffc++ -Wextra -Wall -W'
+env['CCFLAGS'] = flags
+env['CXXFLAGS'] = flags
+env['CXXTEST_SKIP_ERRORS'] = True
+
+env.CxxTest(['src/not-with-pedantic.h'])
+
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py b/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py
new file mode 100644 (file)
index 0000000..4088646
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h b/tools/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h
new file mode 100644 (file)
index 0000000..2b92cd6
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * @file not-with-pedantic.h
+ * Compiles, but not with -pedantic.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-09-30 13:33:50
+ */
+
+
+#include <cxxtest/TestSuite.h>
+
+class TestPedantic : public CxxTest::TestSuite
+{
+public:
+    void testPedanticPresent() {
+        int f = (true)?:5;
+    }
+};
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct b/tools/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct
new file mode 100644 (file)
index 0000000..435b9cb
--- /dev/null
@@ -0,0 +1,8 @@
+env = Environment(toolpath=['../../'],tools=['default','cxxtest'])
+
+env.CxxTest('joint_tests',
+    Split('src/test_foo.t.h '
+          'src/test_bar.t.h '
+          'src/requirement.cpp'
+          )
+          )
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py b/tools/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py
new file mode 100644 (file)
index 0000000..4088646
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp b/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp
new file mode 100644 (file)
index 0000000..45d60ad
--- /dev/null
@@ -0,0 +1,14 @@
+/**
+ * @file requirement.cpp
+ * Implementation of the requirement function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:09:42 AM
+ */
+
+#include "requirement.h"
+
+bool call_a_requirement() {
+    return true;
+}
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h b/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h
new file mode 100644 (file)
index 0000000..9bb9437
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef REQUIREMENT_H
+#define REQUIREMENT_H
+/**
+ * @file requirement.h
+ * Prototype for the call_a_requirement() function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:08:35 AM
+ */
+
+bool call_a_requirement();
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h b/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h
new file mode 100644 (file)
index 0000000..76e594d
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_BAR_T_H
+#define TEST_BAR_T_H
+/**
+ * @file test_bar.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:04:06 AM
+ */
+
+#include <cxxtest/TestSuite.h>
+#include "requirement.h"
+
+class TestBar : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h b/tools/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h
new file mode 100644 (file)
index 0000000..418a3ca
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_FOO_T_H
+#define TEST_FOO_T_H
+/**
+ * @file test_foo.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:02:06 AM
+ */
+
+#include "requirement.h"
+#include <cxxtest/TestSuite.h>
+
+class TestFoo : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct b/tools/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct
new file mode 100644 (file)
index 0000000..d457e55
--- /dev/null
@@ -0,0 +1,9 @@
+
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST_INSTALL_DIR = '../../../../',
+    CPPPATH = ['src/cpppathdir/']
+    )
+
+env.CxxTest(['src/cpppath.t.h'])
diff --git a/tools/cxxtest/build_tools/SCons/test/need_cpppath/TestDef.py b/tools/cxxtest/build_tools/SCons/test/need_cpppath/TestDef.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h b/tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h
new file mode 100644 (file)
index 0000000..3c08c39
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef CPPPATH_T_H
+#define CPPPATH_T_H
+
+/**
+ * @file cpppath.t.h
+ * This file needs the include in the include dir.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:16:46 AM
+ */
+
+// actual path cpppathdir/include.h
+#include "include.h"
+#include <cxxtest/TestSuite.h>
+
+class CppPathTest : public CxxTest::TestSuite
+{
+public:
+    void test_i_need_me_exists() {
+        TS_ASSERT(i_need_me() == 0);
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h b/tools/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h
new file mode 100644 (file)
index 0000000..93d3b03
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef INCLUDE_H
+#define INCLUDE_H
+/**
+ * @file include.h
+ * Include file for this test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:15:40 AM
+ */
+
+int i_need_me() {
+    return 0;
+}
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct b/tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct
new file mode 100644 (file)
index 0000000..9b81162
--- /dev/null
@@ -0,0 +1,10 @@
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST_INSTALL_DIR = '../../../../'
+    )
+
+env['CXXTEST_SKIP_ERRORS'] = True
+env.CxxTest(['src/ThrowNoStd.h'])
+env.CxxTest(['src/AborterNoThrow.h'])
+env.CxxTest(['src/Comments.h'])
diff --git a/tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py b/tools/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py
new file mode 100644 (file)
index 0000000..811fe8d
--- /dev/null
@@ -0,0 +1,2 @@
+
+links = {'src' : '../../../../test/'}
diff --git a/tools/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct b/tools/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct
new file mode 100644 (file)
index 0000000..d87118f
--- /dev/null
@@ -0,0 +1,8 @@
+
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST_INSTALL_DIR = '../../../../',
+    )
+
+env.CxxTest(['src/failtest.t.h'], CPPPATH=['#'], CXXTEST_RUNNER="CrazyRunner")
diff --git a/tools/cxxtest/build_tools/SCons/test/printer_propagation/TestDef.py b/tools/cxxtest/build_tools/SCons/test/printer_propagation/TestDef.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h b/tools/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h
new file mode 100644 (file)
index 0000000..6ceac42
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __cxxtest_CrazyRunner_h__
+#define __cxxtest_CrazyRunner_h__
+
+
+/*
+ * This is not a proper runner. Just a simple class that looks like one.
+ */
+namespace CxxTest {
+       class CrazyRunner {
+               public:
+                       int run() { return 0; }
+            void process_commandline(int argc, char** argv) { }
+       };
+}
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h b/tools/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h
new file mode 100644 (file)
index 0000000..ac8c829
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef FAILTEST_T_H
+#define FAILTEST_T_H
+
+/**
+ * @file failtest.t.h
+ * This test will succed only with a CrazyRunner.
+ *
+ * @author
+ * @version 1.0
+ * @since jue ago 28 14:18:57 ART 2008
+ */
+
+#include <cxxtest/TestSuite.h>
+
+class CppPathTest : public CxxTest::TestSuite
+{
+public:
+    void test_i_will_fail() {
+        TS_ASSERT(false);
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/README b/tools/cxxtest/build_tools/SCons/test/recursive_sources/README
new file mode 100644 (file)
index 0000000..e1e6b74
--- /dev/null
@@ -0,0 +1,2 @@
+Tests whether we can swallow recursively supplied sources - a list of lists, for
+instance.
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct b/tools/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct
new file mode 100644 (file)
index 0000000..5ba8502
--- /dev/null
@@ -0,0 +1,3 @@
+env = Environment(toolpath=['../../'],tools=['default','cxxtest'])
+
+env.CxxTest('joint_tests',['src/test_foo.t.h',['src/test_bar.t.h','src/requirement.cpp']])
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py b/tools/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py
new file mode 100644 (file)
index 0000000..6597b0c
--- /dev/null
@@ -0,0 +1 @@
+links = {'cxxtest' : '../../../../'}
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp b/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp
new file mode 100644 (file)
index 0000000..45d60ad
--- /dev/null
@@ -0,0 +1,14 @@
+/**
+ * @file requirement.cpp
+ * Implementation of the requirement function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:09:42 AM
+ */
+
+#include "requirement.h"
+
+bool call_a_requirement() {
+    return true;
+}
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h b/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h
new file mode 100644 (file)
index 0000000..9bb9437
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef REQUIREMENT_H
+#define REQUIREMENT_H
+/**
+ * @file requirement.h
+ * Prototype for the call_a_requirement() function.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:08:35 AM
+ */
+
+bool call_a_requirement();
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h b/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h
new file mode 100644 (file)
index 0000000..76e594d
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_BAR_T_H
+#define TEST_BAR_T_H
+/**
+ * @file test_bar.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:04:06 AM
+ */
+
+#include <cxxtest/TestSuite.h>
+#include "requirement.h"
+
+class TestBar : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h b/tools/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h
new file mode 100644 (file)
index 0000000..418a3ca
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef TEST_FOO_T_H
+#define TEST_FOO_T_H
+/**
+ * @file test_foo.t.h
+ * Test one for the joint test ehm, test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-29 10:02:06 AM
+ */
+
+#include "requirement.h"
+#include <cxxtest/TestSuite.h>
+
+class TestFoo : public CxxTest::TestSuite
+{
+public:
+    void test_foo() {
+        TS_ASSERT(call_a_requirement());
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct b/tools/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct
new file mode 100644 (file)
index 0000000..4e1e8fe
--- /dev/null
@@ -0,0 +1,9 @@
+
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST_INSTALL_DIR = '../../../../',
+    CPPPATH = 'src/cpppathdir/'
+    )
+
+env.CxxTest(['src/cpppath.t.h'])
diff --git a/tools/cxxtest/build_tools/SCons/test/string_cpppath/TestDef.py b/tools/cxxtest/build_tools/SCons/test/string_cpppath/TestDef.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h b/tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h
new file mode 100644 (file)
index 0000000..3c08c39
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef CPPPATH_T_H
+#define CPPPATH_T_H
+
+/**
+ * @file cpppath.t.h
+ * This file needs the include in the include dir.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:16:46 AM
+ */
+
+// actual path cpppathdir/include.h
+#include "include.h"
+#include <cxxtest/TestSuite.h>
+
+class CppPathTest : public CxxTest::TestSuite
+{
+public:
+    void test_i_need_me_exists() {
+        TS_ASSERT(i_need_me() == 0);
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h b/tools/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h
new file mode 100644 (file)
index 0000000..93d3b03
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef INCLUDE_H
+#define INCLUDE_H
+/**
+ * @file include.h
+ * Include file for this test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:15:40 AM
+ */
+
+int i_need_me() {
+    return 0;
+}
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/target_syntax/SConstruct b/tools/cxxtest/build_tools/SCons/test/target_syntax/SConstruct
new file mode 100644 (file)
index 0000000..7a600bb
--- /dev/null
@@ -0,0 +1,9 @@
+
+env = Environment(
+    toolpath=['../../'],
+    tools=['default','cxxtest'],
+    CXXTEST_INSTALL_DIR = '../../../../',
+    CPPPATH = ['src/cpppathdir/']
+    )
+
+env.CxxTest('src/cpppath')
diff --git a/tools/cxxtest/build_tools/SCons/test/target_syntax/TestDef.py b/tools/cxxtest/build_tools/SCons/test/target_syntax/TestDef.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h b/tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h
new file mode 100644 (file)
index 0000000..3c08c39
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef CPPPATH_T_H
+#define CPPPATH_T_H
+
+/**
+ * @file cpppath.t.h
+ * This file needs the include in the include dir.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:16:46 AM
+ */
+
+// actual path cpppathdir/include.h
+#include "include.h"
+#include <cxxtest/TestSuite.h>
+
+class CppPathTest : public CxxTest::TestSuite
+{
+public:
+    void test_i_need_me_exists() {
+        TS_ASSERT(i_need_me() == 0);
+    }
+};
+
+#endif
diff --git a/tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h b/tools/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h
new file mode 100644 (file)
index 0000000..93d3b03
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef INCLUDE_H
+#define INCLUDE_H
+/**
+ * @file include.h
+ * Include file for this test.
+ *
+ * @author GaÅ¡per Ažman (GA), gasper.azman@gmail.com
+ * @version 1.0
+ * @since 2008-08-28 11:15:40 AM
+ */
+
+int i_need_me() {
+    return 0;
+}
+
+#endif
diff --git a/tools/cxxtest/cxxtest/Descriptions.cpp b/tools/cxxtest/cxxtest/Descriptions.cpp
new file mode 100644 (file)
index 0000000..dc2b88b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Descriptions_cpp__
+#define __cxxtest__Descriptions_cpp__
+
+#include <cxxtest/Descriptions.h>
+
+namespace CxxTest
+{
+    TestDescription::~TestDescription() {}
+    SuiteDescription::~SuiteDescription() {}
+    WorldDescription::~WorldDescription() {}
+    
+    //
+    // Convert total tests to string
+    //
+#ifndef _CXXTEST_FACTOR
+    char *WorldDescription::strTotalTests( char *s ) const
+    {
+        numberToString( numTotalTests(), s );
+        return s;
+    }
+#else // _CXXTEST_FACTOR
+    char *WorldDescription::strTotalTests( char *s ) const
+    {
+        char *p = numberToString( numTotalTests(), s );
+
+        if ( numTotalTests() <= 1 )
+            return s;
+
+        unsigned n = numTotalTests();
+        unsigned numFactors = 0;
+
+        for ( unsigned factor = 2; (factor * factor) <= n; factor += (factor == 2) ? 1 : 2 ) {
+            unsigned power;
+
+            for ( power = 0; (n % factor) == 0; n /= factor )
+                ++ power;
+
+            if ( !power )
+                continue;
+
+            p = numberToString( factor, copyString( p, (numFactors == 0) ? " = " : " * " ) );
+            if ( power > 1 )
+                p = numberToString( power, copyString( p, "^" ) );
+            ++ numFactors;
+        }
+
+        if ( n > 1 ) {
+            if ( !numFactors )
+                copyString( p, tracker().failedTests() ? " :(" : tracker().warnings() ? " :|" : " :)" );
+            else
+                numberToString( n, copyString( p, " * " ) );
+        }
+        return s;
+    }
+#endif // _CXXTEST_FACTOR
+}
+
+#endif // __cxxtest__Descriptions_cpp__
diff --git a/tools/cxxtest/cxxtest/Descriptions.h b/tools/cxxtest/cxxtest/Descriptions.h
new file mode 100644 (file)
index 0000000..36f3003
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Descriptions_h__
+#define __cxxtest__Descriptions_h__
+
+//
+// TestDescription, SuiteDescription and WorldDescription
+// hold information about tests so they can be run and reported.
+//
+
+#include <cxxtest/LinkedList.h>
+
+namespace CxxTest 
+{
+    class TestSuite;
+
+    class TestDescription : public Link
+    {
+    public:
+        virtual ~TestDescription();
+        
+        virtual const char *file() const = 0;
+        virtual int line() const = 0;
+        virtual const char *testName() const = 0;
+        virtual const char *suiteName() const = 0;
+        
+        virtual void run() = 0;
+        virtual bool setUp() = 0;
+        virtual bool tearDown() = 0;
+
+        virtual const TestDescription *next() const = 0;
+        virtual TestDescription *next() = 0;        
+    };
+
+    class SuiteDescription : public Link
+    {
+    public:
+        virtual ~SuiteDescription();
+        
+        virtual const char *file() const = 0;
+        virtual int line() const = 0;
+        virtual const char *suiteName() const = 0;
+        virtual TestSuite *suite() const = 0;
+        
+        virtual unsigned numTests() const = 0;
+        virtual const TestDescription &testDescription( unsigned /*i*/ ) const = 0;
+
+        virtual TestDescription *firstTest() = 0;
+        virtual const TestDescription *firstTest() const = 0;
+        virtual SuiteDescription *next() = 0;
+        virtual const SuiteDescription *next() const = 0;
+
+        virtual void activateAllTests() = 0;
+        virtual bool leaveOnly( const char * /*testName*/ ) = 0;
+
+        virtual bool setUp() = 0;
+        virtual bool tearDown() = 0;
+    };
+
+    class WorldDescription : public Link
+    {
+    public:
+        virtual ~WorldDescription();
+        
+        virtual const char *worldName() const { return "cxxtest"; }
+        virtual unsigned numSuites( void ) const = 0;
+        virtual unsigned numTotalTests( void ) const = 0;
+        virtual const SuiteDescription &suiteDescription( unsigned /*i*/ ) const = 0;
+
+        enum { MAX_STRLEN_TOTAL_TESTS = 32 };
+        char *strTotalTests( char * /*buffer*/ ) const;
+
+        virtual SuiteDescription *firstSuite() = 0;
+        virtual const SuiteDescription *firstSuite() const = 0;
+
+        virtual void activateAllTests() = 0;
+        virtual bool leaveOnly( const char * /*suiteName*/, const char * /*testName*/ = 0 ) = 0;
+    };
+}
+
+#endif // __cxxtest__Descriptions_h__
+
diff --git a/tools/cxxtest/cxxtest/DummyDescriptions.cpp b/tools/cxxtest/cxxtest/DummyDescriptions.cpp
new file mode 100644 (file)
index 0000000..0ca137d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#include <cxxtest/DummyDescriptions.h>
+
+namespace CxxTest 
+{
+    DummyTestDescription::DummyTestDescription() {}
+        
+    const char *DummyTestDescription::file() const { return "<no file>"; }
+    int DummyTestDescription::line() const { return 0; }
+    const char *DummyTestDescription::testName() const { return "<no test>"; }
+    const char *DummyTestDescription::suiteName() const { return "<no suite>"; }
+    bool DummyTestDescription::setUp() { return true;}
+    void DummyTestDescription::run() {}
+    bool DummyTestDescription::tearDown() { return true;}
+
+    TestDescription *DummyTestDescription::next() { return 0; }
+    const TestDescription *DummyTestDescription::next() const { return 0; }
+    
+    DummySuiteDescription::DummySuiteDescription() : _test() {}
+        
+    const char *DummySuiteDescription::file() const { return "<no file>"; }
+    int DummySuiteDescription::line() const { return 0; }
+    const char *DummySuiteDescription::suiteName() const { return "<no suite>"; }
+    TestSuite *DummySuiteDescription::suite() const { return 0; }
+    unsigned DummySuiteDescription::numTests() const { return 0; }
+    const TestDescription &DummySuiteDescription::testDescription( unsigned ) const { return _test; }
+    SuiteDescription *DummySuiteDescription::next() { return 0; }
+    TestDescription *DummySuiteDescription::firstTest() { return 0; }
+    const SuiteDescription *DummySuiteDescription::next() const { return 0; }
+    const TestDescription *DummySuiteDescription::firstTest() const { return 0; }
+    void DummySuiteDescription::activateAllTests() {}
+    bool DummySuiteDescription::leaveOnly( const char * /*testName*/ ) { return false; }
+        
+    bool DummySuiteDescription::setUp() { return true;}
+    bool DummySuiteDescription::tearDown() { return true;}
+
+    DummyWorldDescription::DummyWorldDescription() : _suite() {}
+        
+    unsigned DummyWorldDescription::numSuites( void ) const { return 0; }
+    unsigned DummyWorldDescription::numTotalTests( void ) const { return 0; }
+    const SuiteDescription &DummyWorldDescription::suiteDescription( unsigned ) const { return _suite; }
+    SuiteDescription *DummyWorldDescription::firstSuite() { return 0; }
+    const SuiteDescription *DummyWorldDescription::firstSuite() const { return 0; }
+    void DummyWorldDescription::activateAllTests() {}
+    bool DummyWorldDescription::leaveOnly( const char * /*suiteName*/, const char * /*testName*/ ) { return false; }
+            
+    bool DummyWorldDescription::setUp() { return true;}
+    bool DummyWorldDescription::tearDown() { return true;}
+}
+
diff --git a/tools/cxxtest/cxxtest/DummyDescriptions.h b/tools/cxxtest/cxxtest/DummyDescriptions.h
new file mode 100644 (file)
index 0000000..75623cd
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__DummyDescriptions_h__
+#define __cxxtest__DummyDescriptions_h__
+
+//
+// DummyTestDescription, DummySuiteDescription and DummyWorldDescription
+//
+
+#include <cxxtest/Descriptions.h>
+
+namespace CxxTest 
+{
+    class DummyTestDescription : public TestDescription
+    {
+    public:
+        DummyTestDescription();
+        
+        const char *file() const;
+        int line() const;
+        const char *testName() const;
+        const char *suiteName() const;
+        bool setUp();
+        void run();
+        bool tearDown();
+
+        TestDescription *next();
+        const TestDescription *next() const;
+    };
+
+    class DummySuiteDescription : public SuiteDescription
+    {      
+    public:
+        DummySuiteDescription();
+        
+        const char *file() const;
+        int line() const;
+        const char *suiteName() const;
+        TestSuite *suite() const;
+        unsigned numTests() const;
+        const TestDescription &testDescription( unsigned ) const;
+        SuiteDescription *next();
+        TestDescription *firstTest();
+        const SuiteDescription *next() const;
+        const TestDescription *firstTest() const;
+        void activateAllTests();
+        bool leaveOnly( const char * /*testName*/ );
+        
+        bool setUp();
+        bool tearDown();
+
+    private:
+        DummyTestDescription _test;
+    };
+
+    class DummyWorldDescription : public WorldDescription
+    {
+    public:
+        DummyWorldDescription();
+        
+        unsigned numSuites( void ) const;
+        unsigned numTotalTests( void ) const;
+        const SuiteDescription &suiteDescription( unsigned ) const;
+        SuiteDescription *firstSuite();
+        const SuiteDescription *firstSuite() const;
+        void activateAllTests();
+        bool leaveOnly( const char * /*suiteName*/, const char * /*testName*/ = 0 );
+            
+        bool setUp();
+        bool tearDown();
+
+    private:
+        DummySuiteDescription _suite;
+    };
+}
+
+#endif // __cxxtest__DummyDescriptions_h__
+
diff --git a/tools/cxxtest/cxxtest/ErrorFormatter.h b/tools/cxxtest/cxxtest/ErrorFormatter.h
new file mode 100644 (file)
index 0000000..715012c
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__ErrorFormatter_h__
+#define __cxxtest__ErrorFormatter_h__
+
+//
+// The ErrorFormatter is a TestListener that
+// prints reports of the errors to an output
+// stream.  Since we cannot rely on the standard
+// iostreams, this header defines a base class
+// analogout to std::ostream.
+//
+
+#include <cxxtest/TestRunner.h>
+#include <cxxtest/TestListener.h>
+#include <cxxtest/TestTracker.h>
+#include <cxxtest/ValueTraits.h>
+#include <cstdio>
+
+namespace CxxTest
+{
+    class OutputStream
+    {
+    public:
+        virtual ~OutputStream() {}
+        virtual void flush() {};
+        virtual OutputStream &operator<<( unsigned /*number*/ ) { return *this; }
+        virtual OutputStream &operator<<( const char * /*string*/ ) { return *this; }
+
+        typedef void (*Manipulator)( OutputStream & );
+        
+        virtual OutputStream &operator<<( Manipulator m ) { m( *this ); return *this; }
+        static void endl( OutputStream &o ) { (o << "\n").flush(); }
+    };
+
+    class ErrorFormatter : public TestListener
+    {
+    public:
+        ErrorFormatter( OutputStream *o, const char *preLine = ":", const char *postLine = "" ) :
+            _dotting( true ),
+            _reported( false ),
+            _o(o),
+            _preLine(preLine),
+            _postLine(postLine)
+        {
+        }
+
+        int run()
+        {
+            TestRunner::runAllTests( *this );
+            return tracker().failedTests();
+        }
+
+        void enterWorld( const WorldDescription & /*desc*/ )
+        {
+            (*_o) << "Running " << totalTests;
+            _o->flush();
+            _dotting = true;
+            _reported = false;
+        }
+
+        static void totalTests( OutputStream &o )
+        {
+            char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+            const WorldDescription &wd = tracker().world();
+            o << wd.strTotalTests( s ) << (wd.numTotalTests() == 1 ? " test" : " tests");
+        }
+
+        void enterSuite( const SuiteDescription & )
+        {
+            _reported = false;
+        }
+
+        void enterTest( const TestDescription & )
+        {
+            _reported = false;
+        }
+
+        void leaveTest( const TestDescription & )
+        {
+            if ( !tracker().testFailed() ) {
+                (*_o) << ".";
+                _o->flush();
+                fflush(stdout);
+                _dotting = true;
+            }
+        }
+
+        void leaveWorld( const WorldDescription &desc )
+        {
+            if ( !tracker().failedTests() ) {
+                (*_o) << "OK!" << endl;
+                return;
+            }
+            newLine();
+            (*_o) << "Failed " << tracker().failedTests() << " of " << totalTests << endl;
+            unsigned numPassed = desc.numTotalTests() - tracker().failedTests();
+            (*_o) << "Success rate: " << (numPassed * 100 / desc.numTotalTests()) << "%" << endl;
+        }
+
+        void trace( const char *file, int line, const char *expression )
+        {
+            stop( file, line ) << "Trace: " <<
+                expression << endl;
+        }
+
+        void warning( const char *file, int line, const char *expression )
+        {
+            stop( file, line ) << "Warning: " <<
+                expression << endl;
+        }
+
+        void failedTest( const char *file, int line, const char *expression )
+        {
+            stop( file, line ) << "Error: Test failed: " <<
+                expression << endl;
+        }
+
+        void failedAssert( const char *file, int line, const char *expression )
+        {
+            stop( file, line ) << "Error: Assertion failed: " <<
+                expression << endl;
+        }
+
+        void failedAssertEquals( const char *file, int line,
+                                 const char *xStr, const char *yStr,
+                                 const char *x, const char *y )
+        {
+            stop( file, line ) << "Error: Expected (" <<
+                xStr << " == " << yStr << "), found (" <<
+                x << " != " << y << ")" << endl;
+        }
+
+        void failedAssertSameData( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *sizeStr, const void *x,
+                                   const void *y, unsigned size )
+        {
+            stop( file, line ) << "Error: Expected " << sizeStr << " (" << size << ") bytes to be equal at (" <<
+                xStr << ") and (" << yStr << "), found:" << endl;
+            dump( x, size );
+            (*_o) << "     differs from" << endl;
+            dump( y, size );
+        }
+
+        void failedAssertSameFiles( const char* file, int line,
+                                   const char*, const char*,
+                                   const char* explanation
+                                   )
+        {
+            stop( file, line ) << "Error: " << explanation << endl;
+        }
+
+        void failedAssertDelta( const char *file, int line,
+                                const char *xStr, const char *yStr, const char *dStr,
+                                const char *x, const char *y, const char *d )
+        {
+            stop( file, line ) << "Error: Expected (" <<
+                xStr << " == " << yStr << ") up to " << dStr << " (" << d << "), found (" <<
+                x << " != " << y << ")" << endl;
+        }
+
+        void failedAssertDiffers( const char *file, int line,
+                                  const char *xStr, const char *yStr,
+                                  const char *value )
+        {
+            stop( file, line ) << "Error: Expected (" <<
+                xStr << " != " << yStr << "), found (" <<
+                value << ")" << endl;
+        }
+
+        void failedAssertLessThan( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            stop( file, line ) << "Error: Expected (" <<
+                xStr << " < " << yStr << "), found (" <<
+                x << " >= " << y << ")" << endl;
+        }
+
+        void failedAssertLessThanEquals( const char *file, int line,
+                                         const char *xStr, const char *yStr,
+                                         const char *x, const char *y )
+        {
+            stop( file, line ) << "Error: Expected (" <<
+                xStr << " <= " << yStr << "), found (" <<
+                x << " > " << y << ")" << endl;
+        }
+
+        void failedAssertRelation( const char *file, int line,
+                                   const char *relation, const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            stop( file, line ) << "Error: Expected " << relation << "( " <<
+                xStr << ", " << yStr << " ), found !" << relation << "( " << x << ", " << y << " )" << endl;
+        }
+
+        void failedAssertPredicate( const char *file, int line,
+                                    const char *predicate, const char *xStr, const char *x )
+        {
+            stop( file, line ) << "Error: Expected " << predicate << "( " <<
+                xStr << " ), found !" << predicate << "( " << x << " )" << endl;
+        }
+
+        void failedAssertThrows( const char *file, int line,
+                                 const char *expression, const char *type,
+                                 bool otherThrown )
+        {
+            stop( file, line ) << "Error: Expected (" << expression << ") to throw (" <<
+                type << ") but it " << (otherThrown ? "threw something else" : "didn't throw") <<
+                endl;
+        }
+
+        void failedAssertThrowsNot( const char *file, int line, const char *expression )
+        {
+            stop( file, line ) << "Error: Expected (" << expression << ") not to throw, but it did" <<
+                endl;
+        }
+
+    protected:
+        OutputStream *outputStream() const
+        {
+            return _o;
+        }
+
+    private:
+        ErrorFormatter( const ErrorFormatter & );
+        ErrorFormatter &operator=( const ErrorFormatter & );
+        
+        OutputStream &stop( const char *file, int line )
+        {
+            newLine();
+            reportTest();
+            return (*_o) << file << _preLine << line << _postLine << ": ";
+        }
+
+        void newLine( void )
+        {
+            if ( _dotting ) {
+                (*_o) << endl;
+                _dotting = false;
+            }
+        }
+
+        void reportTest( void )
+        {
+            if( _reported )
+                return;
+            (*_o) << "In " << tracker().suite().suiteName() << "::" << tracker().test().testName() << ":" << endl;
+            _reported = true;
+        }
+
+        void dump( const void *buffer, unsigned size )
+        {
+            if ( !buffer )
+                dumpNull();
+            else
+                dumpBuffer( buffer, size );
+        }
+
+        void dumpNull()
+        {
+            (*_o) << "   (null)" << endl;
+        }
+        
+        void dumpBuffer( const void *buffer, unsigned size )
+        {
+            unsigned dumpSize = size;
+            if ( maxDumpSize() && dumpSize > maxDumpSize() )
+                dumpSize = maxDumpSize();
+
+            const unsigned char *p = (const unsigned char *)buffer;
+            (*_o) << "   { ";
+            for ( unsigned i = 0; i < dumpSize; ++ i )
+                (*_o) << byteToHex( *p++ ) << " ";
+            if ( dumpSize < size )
+                (*_o) << "... ";
+            (*_o) << "}" << endl;
+        }
+
+        static void endl( OutputStream &o )
+        {
+            OutputStream::endl( o );
+        }
+
+        bool _dotting;
+        bool _reported;
+        OutputStream *_o;
+        const char *_preLine;
+        const char *_postLine;
+    };
+}
+
+#endif // __cxxtest__ErrorFormatter_h__
+
diff --git a/tools/cxxtest/cxxtest/ErrorPrinter.h b/tools/cxxtest/cxxtest/ErrorPrinter.h
new file mode 100644 (file)
index 0000000..130df04
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__ErrorPrinter_h__
+#define __cxxtest__ErrorPrinter_h__
+
+//
+// The ErrorPrinter is a simple TestListener that
+// just prints "OK" if everything goes well, otherwise
+// reports the error in the format of compiler messages.
+// The ErrorPrinter uses std::cout
+//
+
+#include <cxxtest/Flags.h>
+
+#ifndef _CXXTEST_HAVE_STD
+#   define _CXXTEST_HAVE_STD
+#endif // _CXXTEST_HAVE_STD
+
+#include <cxxtest/ErrorFormatter.h>
+#include <cxxtest/StdValueTraits.h>
+
+#ifdef _CXXTEST_OLD_STD
+#   include <iostream.h>
+#else // !_CXXTEST_OLD_STD
+#   include <iostream>
+#endif // _CXXTEST_OLD_STD
+
+namespace CxxTest 
+{
+    class ErrorPrinter : public ErrorFormatter
+    {
+    public:
+        ErrorPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout), const char *preLine = ":", const char *postLine = "" ) :
+            ErrorFormatter( new Adapter(o), preLine, postLine ) {}
+        virtual ~ErrorPrinter() { delete outputStream(); }
+
+    private:
+        class Adapter : public OutputStream
+        {
+            CXXTEST_STD(ostream) &_o;
+        public:
+            Adapter( CXXTEST_STD(ostream) &o ) : _o(o) {}
+            void flush() { _o.flush(); }
+            OutputStream &operator<<( const char *s ) { _o << s; return *this; }
+            OutputStream &operator<<( Manipulator m ) { return OutputStream::operator<<( m ); }
+            OutputStream &operator<<( unsigned i )
+            {
+                char s[1 + 3 * sizeof(unsigned)];
+                numberToString( i, s );
+                _o << s;
+                return *this;
+            }
+        };
+    };
+}
+
+#endif // __cxxtest__ErrorPrinter_h__
diff --git a/tools/cxxtest/cxxtest/Flags.h b/tools/cxxtest/cxxtest/Flags.h
new file mode 100644 (file)
index 0000000..7e4e06b
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Flags_h__
+#define __cxxtest__Flags_h__
+
+//
+// These are the flags that control CxxTest
+//
+
+#if !defined(CXXTEST_FLAGS)
+#   define CXXTEST_FLAGS
+#endif // !CXXTEST_FLAGS
+
+#if defined(CXXTEST_HAVE_EH) && !defined(_CXXTEST_HAVE_EH)
+#   define _CXXTEST_HAVE_EH
+#endif // CXXTEST_HAVE_EH
+
+#if defined(CXXTEST_HAVE_STD) && !defined(_CXXTEST_HAVE_STD)
+#   define _CXXTEST_HAVE_STD
+#endif // CXXTEST_HAVE_STD
+
+#if defined(CXXTEST_OLD_TEMPLATE_SYNTAX) && !defined(_CXXTEST_OLD_TEMPLATE_SYNTAX)
+#   define _CXXTEST_OLD_TEMPLATE_SYNTAX
+#endif // CXXTEST_OLD_TEMPLATE_SYNTAX
+
+#if defined(CXXTEST_OLD_STD) && !defined(_CXXTEST_OLD_STD)
+#   define _CXXTEST_OLD_STD
+#endif // CXXTEST_OLD_STD
+
+#if defined(CXXTEST_ABORT_TEST_ON_FAIL) && !defined(_CXXTEST_ABORT_TEST_ON_FAIL)
+#   define _CXXTEST_ABORT_TEST_ON_FAIL
+#endif // CXXTEST_ABORT_TEST_ON_FAIL
+
+#if defined(CXXTEST_NO_COPY_CONST) && !defined(_CXXTEST_NO_COPY_CONST)
+#   define _CXXTEST_NO_COPY_CONST
+#endif // CXXTEST_NO_COPY_CONST
+
+#if defined(CXXTEST_FACTOR) && !defined(_CXXTEST_FACTOR)
+#   define _CXXTEST_FACTOR
+#endif // CXXTEST_FACTOR
+
+#if defined(CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION) && !defined(_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION)
+#   define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#endif // CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+
+#if defined(CXXTEST_LONGLONG)
+#   if defined(_CXXTEST_LONGLONG)
+#       undef _CXXTEST_LONGLONG
+#   endif
+#   define _CXXTEST_LONGLONG CXXTEST_LONGLONG
+#endif // CXXTEST_LONGLONG
+
+#ifndef CXXTEST_MAX_DUMP_SIZE
+#   define CXXTEST_MAX_DUMP_SIZE 0
+#endif // CXXTEST_MAX_DUMP_SIZE
+
+#if defined(_CXXTEST_ABORT_TEST_ON_FAIL) && !defined(CXXTEST_DEFAULT_ABORT)
+#   define CXXTEST_DEFAULT_ABORT true
+#endif // _CXXTEST_ABORT_TEST_ON_FAIL && !CXXTEST_DEFAULT_ABORT
+
+#if !defined(CXXTEST_DEFAULT_ABORT)
+#   define CXXTEST_DEFAULT_ABORT false
+#endif // !CXXTEST_DEFAULT_ABORT
+
+#if defined(_CXXTEST_ABORT_TEST_ON_FAIL) && !defined(_CXXTEST_HAVE_EH)
+#   warning "CXXTEST_ABORT_TEST_ON_FAIL is meaningless without CXXTEST_HAVE_EH"
+#   undef _CXXTEST_ABORT_TEST_ON_FAIL
+#endif // _CXXTEST_ABORT_TEST_ON_FAIL && !_CXXTEST_HAVE_EH
+
+//
+// Some minimal per-compiler configuration to allow us to compile
+//
+
+#ifdef __BORLANDC__
+#   if __BORLANDC__ <= 0x520 // Borland C++ 5.2 or earlier
+#       ifndef _CXXTEST_OLD_STD
+#           define _CXXTEST_OLD_STD
+#       endif
+#       ifndef _CXXTEST_OLD_TEMPLATE_SYNTAX
+#           define _CXXTEST_OLD_TEMPLATE_SYNTAX
+#       endif
+#   endif
+#   if __BORLANDC__ >= 0x540 // C++ Builder 4.0 or later
+#       ifndef _CXXTEST_NO_COPY_CONST
+#           define _CXXTEST_NO_COPY_CONST
+#       endif
+#       ifndef _CXXTEST_LONGLONG
+#           define _CXXTEST_LONGLONG __int64
+#       endif
+#   endif
+#endif // __BORLANDC__
+
+#ifdef _MSC_VER // Visual C++
+#   ifndef _CXXTEST_LONGLONG
+#       define _CXXTEST_LONGLONG __int64
+#   endif
+#   if (_MSC_VER >= 0x51E)
+#       ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#           define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#       endif
+#   endif
+#   pragma warning( disable : 4127 )
+#   pragma warning( disable : 4290 )
+#   pragma warning( disable : 4511 )
+#   pragma warning( disable : 4512 )
+#   pragma warning( disable : 4514 )
+#endif // _MSC_VER
+
+#ifdef __GNUC__
+#   if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 9)
+#       ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#           define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#       endif
+#   endif
+#   if defined(__LONG_LONG_MAX__) && !defined(__cplusplus)
+#      define _CXXTEST_LONGLONG long long
+#   endif
+#endif // __GNUC__
+
+#ifdef __DMC__ // Digital Mars
+#   ifndef _CXXTEST_OLD_STD
+#       define _CXXTEST_OLD_STD
+#   endif
+#endif
+
+#ifdef __SUNPRO_CC // Sun Studio C++
+#   if __SUNPRO_CC >= 0x510
+#       ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#           define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#       endif
+#   endif
+#endif
+
+#ifdef __xlC__ // IBM XL C/C++
+// Partial specialization may be supported before 7.0.0.3, but it is
+// definitely supported after.
+#   if __xlC__ >= 0x0700
+#       ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#           define _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+#       endif
+#   endif
+#endif
+
+#endif // __cxxtest__Flags_h__
+
diff --git a/tools/cxxtest/cxxtest/GlobalFixture.cpp b/tools/cxxtest/cxxtest/GlobalFixture.cpp
new file mode 100644 (file)
index 0000000..d5bcd84
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__GlobalFixture_cpp__
+#define __cxxtest__GlobalFixture_cpp__
+
+#include <cxxtest/GlobalFixture.h>
+
+namespace CxxTest 
+{
+    bool GlobalFixture::setUpWorld() { return true; }
+    bool GlobalFixture::tearDownWorld() { return true; }
+    bool GlobalFixture::setUp() { return true; }
+    bool GlobalFixture::tearDown() { return true; }
+        
+    GlobalFixture::GlobalFixture() { attach( _list ); }
+    GlobalFixture::~GlobalFixture() { detach( _list ); }
+        
+    GlobalFixture *GlobalFixture::firstGlobalFixture() { return (GlobalFixture *)_list.head(); }
+    GlobalFixture *GlobalFixture::lastGlobalFixture() { return (GlobalFixture *)_list.tail(); }
+    GlobalFixture *GlobalFixture::nextGlobalFixture() { return (GlobalFixture *)next(); }
+    GlobalFixture *GlobalFixture::prevGlobalFixture() { return (GlobalFixture *)prev(); }
+}
+
+#endif // __cxxtest__GlobalFixture_cpp__
+
diff --git a/tools/cxxtest/cxxtest/GlobalFixture.h b/tools/cxxtest/cxxtest/GlobalFixture.h
new file mode 100644 (file)
index 0000000..ca73967
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__GlobalFixture_h__
+#define __cxxtest__GlobalFixture_h__
+
+#include <cxxtest/LinkedList.h>
+
+namespace CxxTest 
+{
+    class GlobalFixture : public Link
+    {
+    public:
+        virtual bool setUpWorld();
+        virtual bool tearDownWorld();
+        virtual bool setUp();
+        virtual bool tearDown();
+        
+        GlobalFixture();
+        ~GlobalFixture();
+        
+        static GlobalFixture *firstGlobalFixture();
+        static GlobalFixture *lastGlobalFixture();
+        GlobalFixture *nextGlobalFixture();
+        GlobalFixture *prevGlobalFixture();
+
+    private:
+        static List _list;
+    };
+}
+
+#endif // __cxxtest__GlobalFixture_h__
+
diff --git a/tools/cxxtest/cxxtest/Gui.h b/tools/cxxtest/cxxtest/Gui.h
new file mode 100644 (file)
index 0000000..cbf534b
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __CXXTEST__GUI_H
+#define __CXXTEST__GUI_H
+
+//
+// GuiListener is a simple base class for the differes GUIs
+// GuiTuiRunner<GuiT, TuiT> combines a GUI with a text-mode error formatter
+//
+
+#include <cxxtest/TeeListener.h>
+
+namespace CxxTest
+{
+    class GuiListener : public TestListener
+    {
+    public:
+        GuiListener() : _state( GREEN_BAR ) {}
+        virtual ~GuiListener() {}
+
+        virtual void runGui( int &argc, char **argv, TestListener &listener )
+        {
+            enterGui( argc, argv );
+            TestRunner::runAllTests( listener );
+            leaveGui();            
+        }
+
+        virtual void enterGui( int & /*argc*/, char ** /*argv*/ ) {}
+        virtual void leaveGui() {}
+        
+        //
+        // The easy way is to implement these functions:
+        //      
+        virtual void guiEnterWorld( unsigned /*numTotalTests*/ ) {}
+        virtual void guiEnterSuite( const char * /*suiteName*/ ) {}
+        virtual void guiEnterTest( const char * /*suiteName*/, const char * /*testName*/ ) {}
+        virtual void yellowBar() {}
+        virtual void redBar() {}
+
+        //
+        // The hard way is this:
+        //
+        void enterWorld( const WorldDescription &d ) { guiEnterWorld( d.numTotalTests() ); }
+        void enterSuite( const SuiteDescription &d ) { guiEnterSuite( d.suiteName() ); }
+        void enterTest( const TestDescription &d ) { guiEnterTest( d.suiteName(), d.testName() ); }
+        void leaveTest( const TestDescription & ) {}
+        void leaveSuite( const SuiteDescription & ) {}
+        void leaveWorld( const WorldDescription & ) {}
+        
+        void warning( const char * /*file*/, int /*line*/, const char * /*expression*/ )
+        {
+            yellowBarSafe();
+        }
+        
+        void failedTest( const char * /*file*/, int /*line*/, const char * /*expression*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssert( const char * /*file*/, int /*line*/, const char * /*expression*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertEquals( const char * /*file*/, int /*line*/,
+                                 const char * /*xStr*/, const char * /*yStr*/,
+                                 const char * /*x*/, const char * /*y*/ )
+        {
+            redBarSafe();
+        }
+
+        void failedAssertSameData( const char * /*file*/, int /*line*/,
+                                   const char * /*xStr*/, const char * /*yStr*/,
+                                   const char * /*sizeStr*/, const void * /*x*/,
+                                   const void * /*y*/, unsigned /*size*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertDelta( const char * /*file*/, int /*line*/,
+                                const char * /*xStr*/, const char * /*yStr*/, const char * /*dStr*/,
+                                const char * /*x*/, const char * /*y*/, const char * /*d*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertDiffers( const char * /*file*/, int /*line*/,
+                                  const char * /*xStr*/, const char * /*yStr*/,
+                                  const char * /*value*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertLessThan( const char * /*file*/, int /*line*/,
+                                   const char * /*xStr*/, const char * /*yStr*/,
+                                   const char * /*x*/, const char * /*y*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertLessThanEquals( const char * /*file*/, int /*line*/,
+                                         const char * /*xStr*/, const char * /*yStr*/,
+                                         const char * /*x*/, const char * /*y*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertPredicate( const char * /*file*/, int /*line*/,
+                                    const char * /*predicate*/, const char * /*xStr*/, const char * /*x*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertRelation( const char * /*file*/, int /*line*/,
+                                   const char * /*relation*/, const char * /*xStr*/, const char * /*yStr*/,
+                                   const char * /*x*/, const char * /*y*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertThrows( const char * /*file*/, int /*line*/,
+                                 const char * /*expression*/, const char * /*type*/,
+                                 bool /*otherThrown*/ )
+        {
+            redBarSafe();
+        }
+        
+        void failedAssertThrowsNot( const char * /*file*/, int /*line*/,
+                                    const char * /*expression*/ )
+        {
+            redBarSafe();
+        }
+
+    protected:
+        void yellowBarSafe()
+        {
+            if ( _state < YELLOW_BAR ) {
+                yellowBar();
+                _state = YELLOW_BAR;
+            }
+        }
+
+        void redBarSafe()
+        {
+            if ( _state < RED_BAR ) {
+                redBar();
+                _state = RED_BAR;
+            }
+        }
+        
+    private:
+        enum { GREEN_BAR, YELLOW_BAR, RED_BAR } _state;
+    };
+
+    template<class GuiT, class TuiT>
+    class GuiTuiRunner : public TeeListener
+    {
+        int* _argc;
+        char **_argv;
+        GuiT _gui;
+        TuiT _tui;
+        
+    public:
+        GuiTuiRunner() : _argc(0), _argv(0) {}
+
+        void process_commandline( int& argc, char** argv )
+        {  
+            _argc=&argc;
+            _argv=argv;
+            setFirst( _gui );
+            setSecond( _tui );
+        }
+
+        int run()
+        {
+            _gui.runGui( *_argc, _argv, *this );
+            return tracker().failedTests();
+        }
+    };
+}
+
+#endif //__CXXTEST__GUI_H
+
diff --git a/tools/cxxtest/cxxtest/LinkedList.cpp b/tools/cxxtest/cxxtest/LinkedList.cpp
new file mode 100644 (file)
index 0000000..cb8eb99
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__LinkedList_cpp__
+#define __cxxtest__LinkedList_cpp__
+
+#include <cxxtest/LinkedList.h>
+
+namespace CxxTest
+{
+    List GlobalFixture::_list = { 0, 0 };
+    List RealSuiteDescription::_suites = { 0, 0 };
+
+    void List::initialize()
+    {
+        _head = _tail = 0;
+    }
+    
+    Link *List::head()
+    {
+        Link *l = _head;
+        while ( l && !l->active() )
+            l = l->next();
+        return l;
+    }
+
+    const Link *List::head() const
+    {
+        Link *l = _head;
+        while ( l && !l->active() )
+            l = l->next();
+        return l;
+    }
+
+    Link *List::tail()
+    {
+        Link *l = _tail;
+        while ( l && !l->active() )
+            l = l->prev();
+        return l;
+    }
+
+    const Link *List::tail() const
+    {
+        Link *l = _tail;
+        while ( l && !l->active() )
+            l = l->prev();
+        return l;
+    }
+
+    bool List::empty() const
+    {
+        return (_head == 0);
+    }
+
+    unsigned List::size() const
+    {
+        unsigned count = 0;
+        for ( const Link *l = head(); l != 0; l = l->next() )
+            ++ count;
+        return count;
+    }
+
+    Link *List::nth( unsigned n )
+    {
+        Link *l = head();
+        while ( n -- )
+            l = l->next();
+        return l;
+    }
+
+    void List::activateAll()
+    {
+        for ( Link *l = _head; l != 0; l = l->justNext() )
+            l->setActive( true );
+    }
+
+    void List::leaveOnly( const Link &link )
+    {
+        for ( Link *l = head(); l != 0; l = l->next() )
+            if ( l != &link )
+                l->setActive( false );
+    }
+
+    Link::Link() :
+        _next( 0 ),
+        _prev( 0 ),
+        _active( true )
+    {
+    }
+
+    Link::~Link()
+    {
+    }
+    
+    bool Link::active() const
+    {
+        return _active;
+    }
+    
+    void Link::setActive( bool value )
+    {
+        _active = value;
+    }
+
+    Link * Link::justNext()
+    {
+        return _next;
+    }
+    
+    Link * Link::justPrev()
+    {
+        return _prev;
+    }
+        
+    Link * Link::next()
+    {
+        Link *l = _next;
+        while ( l && !l->_active )
+            l = l->_next;
+        return l;
+    }
+    
+    Link * Link::prev()
+    {
+        Link *l = _prev;
+        while ( l && !l->_active )
+            l = l->_prev;
+        return l;
+    }
+    
+    const Link * Link::next() const
+    {
+        Link *l = _next;
+        while ( l && !l->_active )
+            l = l->_next;
+        return l;
+    }
+    
+    const Link * Link::prev() const
+    {
+        Link *l = _prev;
+        while ( l && !l->_active )
+            l = l->_prev;
+        return l;
+    }
+    
+    void Link::attach( List &l )
+    {
+        if ( l._tail )
+            l._tail->_next = this;
+
+        _prev = l._tail;
+        _next = 0;
+            
+        if ( l._head == 0 )
+            l._head = this;
+        l._tail = this;
+    }
+
+    void Link::detach( List &l )
+    {
+        if ( _prev )
+            _prev->_next = _next;
+        else
+            l._head = _next;
+            
+        if ( _next )
+            _next->_prev = _prev;
+        else
+            l._tail = _prev;
+    }
+}
+
+#endif // __cxxtest__LinkedList_cpp__
diff --git a/tools/cxxtest/cxxtest/LinkedList.h b/tools/cxxtest/cxxtest/LinkedList.h
new file mode 100644 (file)
index 0000000..fbd2f38
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__LinkedList_h__
+#define __cxxtest__LinkedList_h__
+
+#include <cxxtest/Flags.h>
+
+namespace CxxTest 
+{
+    struct List;
+    class Link;
+
+    struct List
+    {
+        Link *_head;
+        Link *_tail;
+
+        void initialize();
+
+        Link *head();
+        const Link *head() const;
+        Link *tail();
+        const Link *tail() const;
+
+        bool empty() const;
+        unsigned size() const;
+        Link *nth( unsigned n );
+
+        void activateAll();
+        void leaveOnly( const Link &link );
+    };
+
+    class Link
+    {       
+    public:
+        Link();
+        virtual ~Link();
+
+        bool active() const;
+        void setActive( bool value = true );
+
+        Link *justNext();
+        Link *justPrev();
+        
+        Link *next();
+        Link *prev();
+        const Link *next() const;
+        const Link *prev() const;
+
+        void attach( List &l );
+        void detach( List &l );
+
+    private:
+        Link *_next;
+        Link *_prev;
+        bool _active;
+
+        Link( const Link & );
+        Link &operator=( const Link & );
+    };
+}
+
+#endif // __cxxtest__LinkedList_h__
+
diff --git a/tools/cxxtest/cxxtest/Mock.h b/tools/cxxtest/cxxtest/Mock.h
new file mode 100644 (file)
index 0000000..2fc85c3
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Mock_h__
+#define __cxxtest__Mock_h__
+
+namespace dummy_mock_ns {}
+
+//
+// The default namespace is T::
+//
+#ifndef CXXTEST_MOCK_NAMESPACE
+#   define CXXTEST_MOCK_NAMESPACE T
+#endif // CXXTEST_MOCK_NAMESPACE
+
+//
+// MockTraits: What to return when no mock object has been created
+//
+#define __CXXTEST_MOCK__TRAITS \
+    namespace CXXTEST_MOCK_NAMESPACE \
+    { \
+        template<class T> \
+        class MockTraits \
+        { \
+        public: \
+            static T defaultValue() { return 0; } \
+        }; \
+    }
+
+//
+// extern "C" when needed
+//
+#ifdef __cplusplus
+#   define CXXTEST_EXTERN_C extern "C"
+#else
+#   define CXXTEST_EXTERN_C
+#endif // __cplusplus
+
+//
+// Prototypes: For "normal" headers
+//
+#define __CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    namespace CXXTEST_MOCK_NAMESPACE { TYPE NAME ARGS; }
+
+#define __CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__PROTOTYPE( MOCK, void, NAME, ARGS, REAL, CALL )
+
+#define __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    TYPE REAL ARGS;
+
+#define __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__PROTOTYPE( MOCK, void, NAME, ARGS, REAL, CALL )
+
+//
+// Class declarations: For test files
+//
+#define __CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        class Base_##MOCK : public CxxTest::Link \
+        { \
+        public: \
+            Base_##MOCK(); \
+            ~Base_##MOCK(); \
+            bool setUp(); \
+            bool tearDown(); \
+         \
+            static Base_##MOCK &current(); \
+         \
+            virtual TYPE NAME ARGS = 0; \
+         \
+        private: \
+            static CxxTest::List _list; \
+        }; \
+         \
+        class Real_##MOCK  : public Base_##MOCK \
+        { \
+        public: \
+            TYPE NAME ARGS; \
+        }; \
+         \
+        class _Unimplemented_##MOCK  : public Base_##MOCK \
+        { \
+        public: \
+            TYPE NAME ARGS; \
+        }; \
+    }
+
+#define __CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__CLASS_DECLARATION( MOCK, void, NAME, ARGS, REAL, CALL )
+
+#define __CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        class Base_##MOCK : public CxxTest::Link \
+        { \
+        public: \
+            Base_##MOCK(); \
+            ~Base_##MOCK(); \
+            bool setUp(); \
+            bool tearDown(); \
+         \
+            static Base_##MOCK &current(); \
+         \
+            virtual TYPE NAME ARGS = 0; \
+         \
+        private: \
+            static CxxTest::List _list; \
+        }; \
+         \
+        class _Unimplemented_##MOCK  : public Base_##MOCK \
+        { \
+        public: \
+            TYPE NAME ARGS; \
+        }; \
+    }
+
+#define __CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, void, NAME, ARGS, REAL, CALL )
+
+//
+// Class implementation: For test source files
+//
+#define __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+         \
+        CxxTest::List Base_##MOCK::_list = { 0, 0 }; \
+         \
+        Base_##MOCK::Base_##MOCK() { attach( _list ); } \
+        Base_##MOCK::~Base_##MOCK() { detach( _list ); } \
+        bool Base_##MOCK::setUp() { return true; } \
+        bool Base_##MOCK::tearDown() { return true; } \
+         \
+        Base_##MOCK &Base_##MOCK::current() \
+        { \
+            if ( _list.empty() ) \
+                static _Unimplemented_##MOCK unimplemented; \
+            return *(Base_##MOCK *)_list.tail(); \
+        } \
+    }
+
+#define __CXXTEST_MOCK__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        TYPE Real_##MOCK::NAME ARGS \
+        { \
+            return REAL CALL; \
+        } \
+         \
+        TYPE _Unimplemented_##MOCK::NAME ARGS \
+        { \
+            while ( false ) \
+                return NAME CALL; \
+            __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
+            return MockTraits<TYPE>::defaultValue(); \
+        } \
+         \
+        TYPE NAME ARGS \
+        { \
+            return Base_##MOCK::current().NAME CALL; \
+        } \
+    }
+
+#define __CXXTEST_MOCK_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        void Real_##MOCK::NAME ARGS \
+        { \
+            REAL CALL; \
+        } \
+         \
+        void _Unimplemented_##MOCK::NAME ARGS \
+        { \
+            while ( false ) \
+                NAME CALL; \
+            __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
+        } \
+         \
+        void NAME ARGS \
+        { \
+            Base_##MOCK::current().NAME CALL; \
+        } \
+    }
+
+#define __CXXTEST_SUPPLY__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        TYPE _Unimplemented_##MOCK::NAME ARGS \
+        { \
+            while ( false ) \
+                return NAME CALL; \
+            __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
+            return MockTraits<TYPE>::defaultValue(); \
+        } \
+    } \
+     \
+    TYPE REAL ARGS \
+    { \
+        return CXXTEST_MOCK_NAMESPACE::Base_##MOCK::current().NAME CALL; \
+    }
+
+#define __CXXTEST_SUPPLY_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__COMMON_CLASS_IMPLEMENTATION( MOCK, NAME ) \
+    namespace CXXTEST_MOCK_NAMESPACE { \
+        void _Unimplemented_##MOCK::NAME ARGS \
+        { \
+            while ( false ) \
+                NAME CALL; \
+            __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ); \
+        } \
+    } \
+     \
+    void REAL ARGS \
+    { \
+        CXXTEST_MOCK_NAMESPACE::Base_##MOCK::current().NAME CALL; \
+    } \
+
+//
+// Error for calling mock function w/o object
+//
+#define __CXXTEST_MOCK_UNIMPLEMENTED( NAME, ARGS ) \
+    TS_FAIL( CXXTEST_MOCK_NAMESPACE_STR #NAME #ARGS " called with no " \
+             CXXTEST_MOCK_NAMESPACE_STR "Base_" #NAME " object" ); \
+
+#define CXXTEST_MOCK_NAMESPACE_STR __CXXTEST_STR(CXXTEST_MOCK_NAMESPACE) "::"
+#define __CXXTEST_STR(X) __CXXTEST_XSTR(X)
+#define __CXXTEST_XSTR(X) #X
+
+#if defined(CXXTEST_MOCK_TEST_SOURCE_FILE)
+//
+// Test source file: Prototypes, class declarations and implementation
+//
+#include <cxxtest/TestSuite.h>
+
+__CXXTEST_MOCK__TRAITS
+
+#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__CLASS_IMPLEMENTATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__CLASS_IMPLEMENTATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#elif defined(CXXTEST_FLAGS) || defined(CXXTEST_RUNNING)
+//
+// Test file other than source: Prototypes and class declarations
+//
+#include <cxxtest/TestSuite.h>
+
+__CXXTEST_MOCK__TRAITS;
+
+#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__CLASS_DECLARATION( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__CLASS_DECLARATION( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#elif defined(CXXTEST_MOCK_REAL_SOURCE_FILE)
+//
+// Real source file: "Real" implementations
+//
+#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    namespace CXXTEST_MOCK_NAMESPACE { TYPE NAME ARGS { return REAL CALL; } } using namespace dummy_mock_ns
+
+#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    namespace CXXTEST_MOCK_NAMESPACE { void NAME ARGS { REAL CALL; } } using namespace dummy_mock_ns
+
+#else
+//
+// Ordinary header file: Just prototypes
+//
+
+#define CXXTEST_MOCK( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_MOCK_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_MOCK_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#define CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL ) \
+    __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    using namespace dummy_mock_ns
+
+#endif // Ordinary header file
+
+//
+// How to supply extern "C" functions
+//
+#define CXXTEST_SUPPLY_C( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    CXXTEST_EXTERN_C __CXXTEST_SUPPLY__PROTOTYPE( MOCK, TYPE, NAME, ARGS, REAL, CALL ) \
+    CXXTEST_SUPPLY( MOCK, TYPE, NAME, ARGS, REAL, CALL )
+
+#define CXXTEST_SUPPLY_VOID_C( MOCK, NAME, ARGS, REAL, CALL ) \
+    CXXTEST_EXTERN_C __CXXTEST_SUPPLY_VOID__PROTOTYPE( MOCK, NAME, ARGS, REAL, CALL ) \
+    CXXTEST_SUPPLY_VOID( MOCK, NAME, ARGS, REAL, CALL )
+
+//
+// Usually we mean the global namespace
+//
+#define CXXTEST_MOCK_GLOBAL( TYPE, NAME, ARGS, CALL ) \
+    CXXTEST_MOCK( NAME, TYPE, NAME, ARGS, ::NAME, CALL )
+
+#define CXXTEST_MOCK_VOID_GLOBAL( NAME, ARGS, CALL ) \
+    CXXTEST_MOCK_VOID( NAME, NAME, ARGS, ::NAME, CALL )
+
+#define CXXTEST_SUPPLY_GLOBAL( TYPE, NAME, ARGS, CALL ) \
+    CXXTEST_SUPPLY( NAME, TYPE, NAME, ARGS, NAME, CALL )
+
+#define CXXTEST_SUPPLY_VOID_GLOBAL( NAME, ARGS, CALL ) \
+    CXXTEST_SUPPLY_VOID( NAME, NAME, ARGS, NAME, CALL )
+
+#define CXXTEST_SUPPLY_GLOBAL_C( TYPE, NAME, ARGS, CALL ) \
+    CXXTEST_SUPPLY_C( NAME, TYPE, NAME, ARGS, NAME, CALL )
+
+#define CXXTEST_SUPPLY_VOID_GLOBAL_C( NAME, ARGS, CALL ) \
+    CXXTEST_SUPPLY_VOID_C( NAME, NAME, ARGS, NAME, CALL )
+
+//
+// What to return when no mock object has been created.
+// The default value of 0 usually works, but some cases may need this.
+//
+#define CXXTEST_MOCK_DEFAULT_VALUE( TYPE, VALUE ) \
+    namespace CXXTEST_MOCK_NAMESPACE \
+    { \
+        template<> \
+        class MockTraits<TYPE> \
+        { \
+        public: \
+            static TYPE defaultValue() { return VALUE; } \
+        }; \
+    } using namespace dummy_mock_ns
+
+#endif // __cxxtest__Mock_h__
diff --git a/tools/cxxtest/cxxtest/ParenPrinter.h b/tools/cxxtest/cxxtest/ParenPrinter.h
new file mode 100644 (file)
index 0000000..21b337a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__ParenPrinter_h__
+#define __cxxtest__ParenPrinter_h__
+
+//
+// The ParenPrinter is identical to the ErrorPrinter, except it
+// prints the line number in a format expected by some compilers
+// (notably, MSVC).
+//
+
+#include <cxxtest/ErrorPrinter.h>
+
+namespace CxxTest 
+{
+    class ParenPrinter : public ErrorPrinter
+    {
+    public:
+        ParenPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout) ) : ErrorPrinter( o, "(", ")" ) {}
+    };
+}
+
+#endif // __cxxtest__ParenPrinter_h__
diff --git a/tools/cxxtest/cxxtest/QtGui.h b/tools/cxxtest/cxxtest/QtGui.h
new file mode 100644 (file)
index 0000000..9abce3d
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__QtGui_h__
+#define __cxxtest__QtGui_h__
+
+//
+// The QtGui displays a simple progress bar using the Qt Toolkit.  It
+// has been tested with versions 2.x and 3.x.
+// 
+// Apart from normal Qt command-line arguments, it accepts the following options:
+//   -minimized    Start minimized, pop up on error
+//   -keep         Don't close the window at the end
+//   -title TITLE  Set the window caption
+//
+// If both are -minimized and -keep specified, GUI will only keep the
+// window if it's in focus.
+//
+
+#include <cxxtest/Gui.h>
+
+#include <qapplication.h>
+#include <qglobal.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qpixmap.h>
+#include <qprogressbar.h>
+#include <qstatusbar.h>
+
+namespace CxxTest
+{
+    class QtGui : public GuiListener
+    {
+    public:
+        void enterGui( int &argc, char **argv )
+        {
+            parseCommandLine( argc, argv );
+            createApplication( argc, argv );
+        }
+
+        void enterWorld( const WorldDescription &wd )
+        {
+            createWindow( wd );
+            processEvents();
+        }
+
+        void guiEnterSuite( const char *suiteName )
+        {
+            showSuiteName( suiteName );
+        }
+
+        void guiEnterTest( const char *suiteName, const char *testName )
+        {
+            setCaption( suiteName, testName );
+            advanceProgressBar();
+            showTestName( testName );
+            showTestsDone( _progressBar->progress() );
+            processEvents();
+        }
+
+        void yellowBar()
+        {
+            setColor( 255, 255, 0 );
+            setIcon( QMessageBox::Warning );
+            getTotalTests();
+            processEvents();
+        }
+        
+        void redBar()
+        {
+            if ( _startMinimized && _mainWindow->isMinimized() )
+                showNormal();
+            setColor( 255, 0, 0 );
+            setIcon( QMessageBox::Critical );
+            getTotalTests();
+            processEvents();
+        }
+
+        void leaveGui()
+        {
+            if ( keep() ) {
+                showSummary();
+                _application->exec();
+            }
+            else
+                _mainWindow->close( true );
+        }
+
+    private:
+        QString _title;
+        bool _startMinimized, _keep;
+        unsigned _numTotalTests;
+        QString _strTotalTests;
+        QApplication *_application;
+        QWidget *_mainWindow;
+        QVBoxLayout *_layout;
+        QProgressBar *_progressBar;
+        QStatusBar *_statusBar;
+        QLabel *_suiteName, *_testName, *_testsDone;
+
+        void parseCommandLine( int argc, char **argv )
+        {
+            _startMinimized = _keep = false;
+            _title = argv[0];
+            
+            for ( int i = 1; i < argc; ++ i ) {
+                QString arg( argv[i] );
+                if ( arg == "-minimized" )
+                    _startMinimized = true;
+                else if ( arg == "-keep" )
+                    _keep = true;
+                else if ( arg == "-title" && (i + 1 < argc) )
+                    _title = argv[++i];
+            }
+        }
+
+        void createApplication( int &argc, char **argv )
+        {
+            _application = new QApplication( argc, argv );
+        }       
+        
+        void createWindow( const WorldDescription &wd )
+        {
+            getTotalTests( wd );            
+            createMainWindow();
+            createProgressBar();
+            createStatusBar();
+            setMainWidget();
+            if ( _startMinimized )
+                showMinimized();
+            else
+                showNormal();
+        }
+
+        void getTotalTests()
+        {
+            getTotalTests( tracker().world() );
+        }
+
+        void getTotalTests( const WorldDescription &wd )
+        {
+            _numTotalTests = wd.numTotalTests();
+            char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+            _strTotalTests = wd.strTotalTests( s );
+        }
+
+        void createMainWindow()
+        {
+            _mainWindow = new QWidget();
+            _layout = new QVBoxLayout( _mainWindow );
+        }
+
+        void createProgressBar()
+        {
+            _layout->addWidget( _progressBar = new QProgressBar( _numTotalTests, _mainWindow ) );
+            _progressBar->setProgress( 0 );
+            setColor( 0, 255, 0 );
+            setIcon( QMessageBox::Information );
+        }
+
+        void createStatusBar()
+        {
+            _layout->addWidget( _statusBar = new QStatusBar( _mainWindow ) );
+            _statusBar->addWidget( _suiteName = new QLabel( _statusBar ), 2 );
+            _statusBar->addWidget( _testName = new QLabel( _statusBar ), 4 );
+            _statusBar->addWidget( _testsDone = new QLabel( _statusBar ), 1 );
+        }
+
+        void setMainWidget()
+        {
+            _application->setMainWidget( _mainWindow );
+        }
+
+        void showMinimized()
+        {
+            _mainWindow->showMinimized();
+        }
+
+        void showNormal()
+        {
+            _mainWindow->showNormal();
+            centerWindow();
+        }
+
+        void setCaption( const QString &suiteName, const QString &testName )
+        {
+            _mainWindow->setCaption( _title + " - " + suiteName + "::" + testName + "()" );
+        }
+
+        void showSuiteName( const QString &suiteName )
+        {
+            _suiteName->setText( "class " + suiteName );
+        }
+
+        void advanceProgressBar()
+        {
+            _progressBar->setProgress( _progressBar->progress() + 1 );
+        }
+
+        void showTestName( const QString &testName )
+        {
+            _testName->setText( testName + "()" );
+        }
+
+        void showTestsDone( unsigned testsDone )
+        {
+            _testsDone->setText( asString( testsDone ) + " of " + _strTotalTests );
+        }
+
+        static QString asString( unsigned n )
+        {
+            return QString::number( n );
+        }
+
+        void setColor( int r, int g, int b )
+        {
+            QPalette palette = _progressBar->palette();
+            palette.setColor( QColorGroup::Highlight, QColor( r, g, b ) );
+            _progressBar->setPalette( palette );
+        }
+
+        void setIcon( QMessageBox::Icon icon )
+        {
+#if QT_VERSION >= 0x030000
+            _mainWindow->setIcon( QMessageBox::standardIcon( icon ) );
+#else // Qt version < 3.0.0
+            _mainWindow->setIcon( QMessageBox::standardIcon( icon, QApplication::style().guiStyle() ) );
+#endif // QT_VERSION
+        }
+
+        void processEvents()
+        {
+            _application->processEvents();
+        }
+
+        void centerWindow()
+        {
+            QWidget *desktop = QApplication::desktop();
+            int xCenter = desktop->x() + (desktop->width() / 2);
+            int yCenter = desktop->y() + (desktop->height() / 2);
+            
+            int windowWidth = (desktop->width() * 4) / 5;
+            int windowHeight = _mainWindow->height();
+            _mainWindow->setGeometry( xCenter - (windowWidth / 2), yCenter - (windowHeight / 2), windowWidth, windowHeight );
+        }
+
+        bool keep()
+        {
+            if ( !_keep )
+                return false;
+            if ( !_startMinimized )
+                return true;
+            return (_mainWindow == _application->activeWindow());
+        }
+
+        void showSummary()
+        {
+            QString summary = _strTotalTests + (_numTotalTests == 1 ? " test" : " tests");
+            if ( tracker().failedTests() )
+                summary = "Failed " + asString( tracker().failedTests() ) + " of " + summary;
+            else
+                summary = summary + " passed";
+
+            _mainWindow->setCaption( _title + " - " + summary );
+
+            _statusBar->removeWidget( _suiteName );
+            _statusBar->removeWidget( _testName );
+            _testsDone->setText( summary );
+        }
+    };
+}
+
+#endif // __cxxtest__QtGui_h__
diff --git a/tools/cxxtest/cxxtest/RealDescriptions.cpp b/tools/cxxtest/cxxtest/RealDescriptions.cpp
new file mode 100644 (file)
index 0000000..91baa9e
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__RealDescriptions_cpp__
+#define __cxxtest__RealDescriptions_cpp__
+
+//
+// NOTE: If an error occur during world construction/deletion, CxxTest cannot
+//       know where the error originated.
+//
+
+#include <cxxtest/RealDescriptions.h>
+
+namespace CxxTest 
+{
+    RealTestDescription::RealTestDescription()
+    {
+    }
+        
+    RealTestDescription::RealTestDescription( List &argList,
+                                              SuiteDescription &argSuite,
+                                              unsigned argLine,
+                                              const char *argTestName )
+    {
+        initialize( argList, argSuite, argLine, argTestName );
+    }
+
+    void RealTestDescription::initialize( List &argList,
+                                          SuiteDescription &argSuite,
+                                          unsigned argLine,
+                                          const char *argTestName )
+    {
+        _suite = &argSuite;
+        _line = argLine;
+        _testName = argTestName;
+        attach( argList );
+    }
+        
+    bool RealTestDescription::setUp()
+    {
+        if ( !suite() )
+            return false;
+
+        for ( GlobalFixture *gf = GlobalFixture::firstGlobalFixture(); gf != 0; gf = gf->nextGlobalFixture() ) {
+            bool ok;
+            _TS_TRY { ok = gf->setUp(); }
+            _TS_LAST_CATCH( { ok = false; } );
+
+            if ( !ok ) {
+                doFailTest( file(), line(), "Error in GlobalFixture::setUp()" );
+                return false;
+            }
+        }
+
+        _TS_TRY {
+            bool ok = false;
+            _TSM_ASSERT_THROWS_NOTHING( file(), line(), "Exception thrown from setUp()", suite()->setUp(); ok=true );
+            if (ok == false) return ok;
+        }
+        _TS_CATCH_ABORT( { return false; } );
+
+        return true;
+    }
+
+    bool RealTestDescription::tearDown()
+    {
+        if ( !suite() )
+            return false;
+
+        _TS_TRY {
+            _TSM_ASSERT_THROWS_NOTHING( file(), line(), "Exception thrown from tearDown()", suite()->tearDown() );
+        }
+        _TS_CATCH_ABORT( { return false; } );
+
+        for ( GlobalFixture *gf = GlobalFixture::lastGlobalFixture(); gf != 0; gf = gf->prevGlobalFixture() ) {
+            bool ok;
+            _TS_TRY { ok = gf->tearDown(); }
+            _TS_LAST_CATCH( { ok = false; } );
+
+            if ( !ok ) {
+                doFailTest( file(), line(), "Error in GlobalFixture::tearDown()" );
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    const char *RealTestDescription::file() const { return _suite->file(); }
+    int RealTestDescription::line() const { return _line; }
+    const char *RealTestDescription::testName() const { return _testName; }
+    const char *RealTestDescription::suiteName() const { return _suite->suiteName(); }
+
+    TestDescription *RealTestDescription::next() { return (RealTestDescription *)Link::next(); }
+    const TestDescription *RealTestDescription::next() const { return (const RealTestDescription *)Link::next(); }
+
+    TestSuite *RealTestDescription::suite() const { return _suite->suite(); }
+
+    void RealTestDescription::run()
+    {
+        _TS_TRY { runTest(); }
+        _TS_CATCH_ABORT( {} )
+            ___TSM_CATCH( file(), line(), "Exception thrown from test" );
+    }
+        
+    RealSuiteDescription::RealSuiteDescription() {}
+    RealSuiteDescription::RealSuiteDescription( const char *argFile,
+                                                unsigned argLine,
+                                                const char *argSuiteName,
+                                                List &argTests )
+    {
+        initialize( argFile, argLine, argSuiteName, argTests );
+    }
+
+    void RealSuiteDescription::initialize( const char *argFile,
+                                           unsigned argLine,
+                                           const char *argSuiteName,
+                                           List &argTests )
+    {
+        _file = argFile;
+        _line = argLine;
+        _suiteName = argSuiteName;
+        _tests = &argTests;
+            
+        attach( _suites );
+    }
+
+    const char *RealSuiteDescription::file() const { return _file; }
+    int RealSuiteDescription::line() const { return _line; }
+    const char *RealSuiteDescription::suiteName() const { return _suiteName; }
+
+    TestDescription *RealSuiteDescription::firstTest() { return (RealTestDescription *)_tests->head(); }
+    const TestDescription *RealSuiteDescription::firstTest() const { return (const RealTestDescription *)_tests->head(); }
+    SuiteDescription *RealSuiteDescription::next() { return (RealSuiteDescription *)Link::next(); }
+    const SuiteDescription *RealSuiteDescription::next() const { return (const RealSuiteDescription *)Link::next(); }
+        
+    unsigned RealSuiteDescription::numTests() const { return _tests->size(); }
+    
+    const TestDescription &RealSuiteDescription::testDescription( unsigned i ) const
+    {
+        return *(RealTestDescription *)_tests->nth( i );
+    }
+
+    void RealSuiteDescription::activateAllTests()
+    {
+        _tests->activateAll();
+    }
+        
+    bool RealSuiteDescription::leaveOnly( const char *testName )
+    {
+        for ( TestDescription *td = firstTest(); td != 0; td = td->next() ) {
+            if ( stringsEqual( td->testName(), testName ) ) {
+                _tests->leaveOnly( *td );
+                return true;
+            }
+        }
+        return false;        
+    }
+        
+    StaticSuiteDescription::StaticSuiteDescription() {}
+    StaticSuiteDescription::StaticSuiteDescription( const char *argFile, unsigned argLine,
+                                                    const char *argSuiteName, TestSuite &argSuite,
+                                                    List &argTests ) :
+        RealSuiteDescription( argFile, argLine, argSuiteName, argTests )
+    {
+        doInitialize( argSuite );
+    }
+
+    void StaticSuiteDescription::initialize( const char *argFile, unsigned argLine,
+                                             const char *argSuiteName, TestSuite &argSuite,
+                                             List &argTests )
+    {
+        RealSuiteDescription::initialize( argFile, argLine, argSuiteName, argTests );
+        doInitialize( argSuite );
+    }
+        
+    void StaticSuiteDescription::doInitialize( TestSuite &argSuite )
+    {
+        _suite = &argSuite;
+    }
+
+    TestSuite *StaticSuiteDescription::suite() const
+    {
+        return _suite;
+    }
+
+    bool StaticSuiteDescription::setUp() { return true; }
+    bool StaticSuiteDescription::tearDown() { return true; }
+
+    CommonDynamicSuiteDescription::CommonDynamicSuiteDescription() {}
+    CommonDynamicSuiteDescription::CommonDynamicSuiteDescription( const char *argFile, unsigned argLine,
+                                                                  const char *argSuiteName, List &argTests,
+                                                                  unsigned argCreateLine, unsigned argDestroyLine ) :
+        RealSuiteDescription( argFile, argLine, argSuiteName, argTests )
+    {
+        doInitialize( argCreateLine, argDestroyLine );
+    }
+
+    void CommonDynamicSuiteDescription::initialize( const char *argFile, unsigned argLine,
+                                                    const char *argSuiteName, List &argTests,
+                                                    unsigned argCreateLine, unsigned argDestroyLine )
+    {
+        RealSuiteDescription::initialize( argFile, argLine, argSuiteName, argTests );
+        doInitialize( argCreateLine, argDestroyLine );
+    }
+
+    void CommonDynamicSuiteDescription::doInitialize( unsigned argCreateLine, unsigned argDestroyLine )
+    {
+        _createLine = argCreateLine;
+        _destroyLine = argDestroyLine;
+    }
+        
+    List &RealWorldDescription::suites()
+    {
+        return RealSuiteDescription::_suites;
+    }
+        
+    unsigned RealWorldDescription::numSuites( void ) const
+    {
+        return suites().size();
+    }
+        
+    unsigned RealWorldDescription::numTotalTests( void ) const
+    {
+        unsigned count = 0;
+        for ( const SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() )
+            count += sd->numTests();
+        return count;
+    }
+        
+    SuiteDescription *RealWorldDescription::firstSuite()
+    {
+        return (RealSuiteDescription *)suites().head();
+    }
+
+    const SuiteDescription *RealWorldDescription::firstSuite() const
+    {
+        return (const RealSuiteDescription *)suites().head();
+    }
+
+    const SuiteDescription &RealWorldDescription::suiteDescription( unsigned i ) const
+    {
+        return *(const RealSuiteDescription *)suites().nth( i );
+    }
+
+    void RealWorldDescription::activateAllTests()
+    {
+        suites().activateAll();
+        for ( SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() )
+            sd->activateAllTests();
+    }
+
+    bool RealWorldDescription::leaveOnly( const char *suiteName, const char *testName )
+    {
+        for ( SuiteDescription *sd = firstSuite(); sd != 0; sd = sd->next() ) {
+            if ( stringsEqual( sd->suiteName(), suiteName ) ) {
+                if ( testName )
+                    if ( !sd->leaveOnly( testName ) )
+                        return false;
+                suites().leaveOnly( *sd );
+                return true;
+            }
+        }
+        return false;
+    }
+        
+    bool RealWorldDescription::setUp()
+    {
+        for ( GlobalFixture *gf = GlobalFixture::firstGlobalFixture(); gf != 0; gf = gf->nextGlobalFixture() ) {
+            bool ok;
+            _TS_TRY { 
+                ok = gf->setUpWorld(); 
+                if (tracker().testFailed()) {
+                    tracker().initialize();
+                    ok = false;
+                    }
+                }
+            _TS_LAST_CATCH( { ok = false; } );
+
+            if ( !ok ) {
+                reportError( "Error setting up world" );
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    bool RealWorldDescription::tearDown()
+    {
+        for ( GlobalFixture *gf = GlobalFixture::lastGlobalFixture(); gf != 0; gf = gf->prevGlobalFixture() ) {
+            bool ok;
+            _TS_TRY { ok = gf->tearDownWorld(); }
+            _TS_LAST_CATCH( { ok = false; } );
+
+            if ( !ok ) {
+                reportError( "Error tearing down world" );
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    void RealWorldDescription::reportError( const char *message )
+    {
+        doWarn( __FILE__, 5, message );
+    }
+
+    void activateAllTests()
+    {
+        RealWorldDescription().activateAllTests();
+    }
+
+    bool leaveOnly( const char *suiteName, const char *testName )
+    {
+        return RealWorldDescription().leaveOnly( suiteName, testName );
+    }
+}
+
+#endif // __cxxtest__RealDescriptions_cpp__
+
diff --git a/tools/cxxtest/cxxtest/RealDescriptions.h b/tools/cxxtest/cxxtest/RealDescriptions.h
new file mode 100644 (file)
index 0000000..9875175
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__RealDescriptions_h__
+#define __cxxtest__RealDescriptions_h__
+
+//
+// The "real" description classes
+//
+
+#include <cxxtest/Descriptions.h>
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+
+namespace CxxTest 
+{
+    class RealTestDescription : public TestDescription
+    {
+    public:
+        RealTestDescription();
+        RealTestDescription( List &argList, SuiteDescription &argSuite, unsigned argLine, const char *argTestName );
+        void initialize( List &argList, SuiteDescription &argSuite, unsigned argLine, const char *argTestName );
+        
+        const char *file() const;
+        int line() const;
+        const char *testName() const;
+        const char *suiteName() const;
+
+        TestDescription *next();
+        const TestDescription *next() const;
+
+        TestSuite *suite() const;
+
+        bool setUp();
+        void run();        
+        bool tearDown();
+        
+    private:
+        RealTestDescription( const RealTestDescription & );
+        RealTestDescription &operator=( const RealTestDescription & );
+
+        virtual void runTest() = 0;
+        
+        SuiteDescription *_suite;
+        int _line;
+        const char *_testName;
+    };
+
+    class RealSuiteDescription : public SuiteDescription
+    {
+    public:
+        RealSuiteDescription();
+        RealSuiteDescription( const char *argFile, unsigned argLine, const char *argSuiteName, List &argTests );
+        
+        void initialize( const char *argFile, unsigned argLine, const char *argSuiteName, List &argTests );
+
+        const char *file() const;
+        int line() const;
+        const char *suiteName() const;
+
+        TestDescription *firstTest();
+        const TestDescription *firstTest() const;
+        SuiteDescription *next();
+        const SuiteDescription *next() const;
+        
+        unsigned numTests() const;
+        const TestDescription &testDescription( unsigned i ) const;
+
+        void activateAllTests();
+        bool leaveOnly( const char *testName );
+        
+    private:
+        RealSuiteDescription( const RealSuiteDescription & );
+        RealSuiteDescription &operator=( const RealSuiteDescription & );
+        
+        const char *_file;
+        int _line;
+        const char *_suiteName;
+        List *_tests;
+
+        static List _suites;
+        friend class RealWorldDescription;
+    };
+
+    class StaticSuiteDescription : public RealSuiteDescription
+    {
+    public:
+        StaticSuiteDescription();
+        StaticSuiteDescription( const char *argFile, unsigned argLine,
+                                const char *argSuiteName, TestSuite &argSuite,
+                                List &argTests );
+
+        void initialize( const char *argFile, unsigned argLine,
+                         const char *argSuiteName, TestSuite &argSuite,
+                         List &argTests );
+        TestSuite *suite() const;
+        
+        bool setUp();
+        bool tearDown();
+        
+    private:
+        StaticSuiteDescription( const StaticSuiteDescription & );
+        StaticSuiteDescription &operator=( const StaticSuiteDescription & );
+
+        void doInitialize( TestSuite &argSuite );
+        
+        TestSuite *_suite;
+    };
+
+    class CommonDynamicSuiteDescription : public RealSuiteDescription
+    {
+    public:
+        CommonDynamicSuiteDescription();
+        CommonDynamicSuiteDescription( const char *argFile, unsigned argLine,
+                                       const char *argSuiteName, List &argTests,
+                                       unsigned argCreateLine, unsigned argDestroyLine );
+
+        void initialize( const char *argFile, unsigned argLine,
+                         const char *argSuiteName, List &argTests,
+                         unsigned argCreateLine, unsigned argDestroyLine );
+
+    protected:
+        unsigned _createLine, _destroyLine;
+
+    private:
+        void doInitialize( unsigned argCreateLine, unsigned argDestroyLine );
+    };
+    
+    template<class S>
+    class DynamicSuiteDescription : public CommonDynamicSuiteDescription
+    {
+    public:
+        DynamicSuiteDescription() {}
+        DynamicSuiteDescription( const char *argFile, unsigned argLine,
+                                 const char *argSuiteName, List &argTests,
+                                 S *&argSuite, unsigned argCreateLine,
+                                 unsigned argDestroyLine ) :
+            CommonDynamicSuiteDescription( argFile, argLine, argSuiteName, argTests, argCreateLine, argDestroyLine )
+        {
+            _suite = &argSuite;
+        }
+
+        void initialize( const char *argFile, unsigned argLine,
+                         const char *argSuiteName, List &argTests,
+                         S *&argSuite, unsigned argCreateLine,
+                         unsigned argDestroyLine )
+        {
+            CommonDynamicSuiteDescription::initialize( argFile, argLine,
+                                                       argSuiteName, argTests,
+                                                       argCreateLine, argDestroyLine );
+            _suite = &argSuite;
+        }
+
+        TestSuite *suite() const { return realSuite(); }
+
+        bool setUp();
+        bool tearDown();
+        
+    private:
+        S *realSuite() const { return *_suite; }
+        void setSuite( S *s ) { *_suite = s; }
+
+        void createSuite()
+        {
+            setSuite( S::createSuite() );
+        }
+        
+        void destroySuite()
+        {
+            S *s = realSuite();
+            setSuite( 0 );
+            S::destroySuite( s );
+        }
+
+        S **_suite;
+    };
+
+    template<class S>
+    bool DynamicSuiteDescription<S>::setUp()
+    {
+        _TS_TRY {
+            _TSM_ASSERT_THROWS_NOTHING( file(), _createLine, "Exception thrown from createSuite()", createSuite() );
+            _TSM_ASSERT( file(), _createLine, "createSuite() failed", suite() != 0 );
+        }
+        _TS_CATCH_ABORT( { return false; } );
+
+        return (suite() != 0);
+    }
+
+    template<class S>
+    bool DynamicSuiteDescription<S>::tearDown()
+    {
+        if ( !_suite )
+            return true;
+            
+        _TS_TRY {
+            _TSM_ASSERT_THROWS_NOTHING( file(), _destroyLine, "destroySuite() failed", destroySuite() );
+        }
+        _TS_CATCH_ABORT( { return false; } );
+
+        return true;
+    }
+        
+    class RealWorldDescription : public WorldDescription
+    {
+    public:
+        static List &suites();
+        const char *worldName() const { return _worldName;}
+        unsigned numSuites( void ) const;
+        unsigned numTotalTests( void ) const;
+        SuiteDescription *firstSuite();
+        const SuiteDescription *firstSuite() const;
+        const SuiteDescription &suiteDescription( unsigned i ) const;
+        void activateAllTests();
+        bool leaveOnly( const char *suiteName, const char *testName = 0 );
+        
+        bool setUp();
+        bool tearDown();
+        static void reportError( const char *message );
+
+        static const char *_worldName;
+    };
+
+    void activateAllTests();
+    bool leaveOnly( const char *suiteName, const char *testName = 0 );
+}
+
+#endif // __cxxtest__RealDescriptions_h__
+
diff --git a/tools/cxxtest/cxxtest/Root.cpp b/tools/cxxtest/cxxtest/Root.cpp
new file mode 100644 (file)
index 0000000..6faa5fd
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Root_cpp__
+#define __cxxtest__Root_cpp__
+
+//
+// This file holds the "root" of CxxTest, i.e.
+// the parts that must be in a source file file.
+//
+
+#include <cxxtest/Descriptions.cpp>
+#include <cxxtest/DummyDescriptions.cpp>
+#include <cxxtest/GlobalFixture.cpp>
+#include <cxxtest/LinkedList.cpp>
+#include <cxxtest/RealDescriptions.cpp>
+#include <cxxtest/TestSuite.cpp>
+#include <cxxtest/TestTracker.cpp>
+#include <cxxtest/ValueTraits.cpp>
+
+#endif // __cxxtest__Root_cpp__
diff --git a/tools/cxxtest/cxxtest/SelfTest.h b/tools/cxxtest/cxxtest/SelfTest.h
new file mode 100644 (file)
index 0000000..ee59fd1
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest_SelfTest_h__
+#define __cxxtest_SelfTest_h__
+
+#define CXXTEST_SUITE(name)
+#define CXXTEST_CODE(member)
+
+#endif // __cxxtest_SelfTest_h__
diff --git a/tools/cxxtest/cxxtest/StdHeaders.h b/tools/cxxtest/cxxtest/StdHeaders.h
new file mode 100644 (file)
index 0000000..991f16a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest_StdHeaders_h__
+#define __cxxtest_StdHeaders_h__
+
+//
+// This file basically #includes the STL headers.
+// It exists to support warning level 4 in Visual C++
+//
+
+#ifdef _MSC_VER
+#   pragma warning( push, 1 )
+#endif // _MSC_VER
+
+#include <complex>
+#include <deque>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#ifdef _MSC_VER
+#   pragma warning( pop )
+#endif // _MSC_VER
+
+#endif // __cxxtest_StdHeaders_h__
diff --git a/tools/cxxtest/cxxtest/StdTestSuite.h b/tools/cxxtest/cxxtest/StdTestSuite.h
new file mode 100644 (file)
index 0000000..9b77a37
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__StdTestSuite_h__
+#define __cxxtest__StdTestSuite_h__
+
+//
+// This provides explicit partial specializations for STL-based
+// TestSuite comparison functions
+//
+
+namespace CxxTest {
+
+#ifdef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+
+template<class X, class Y, class D>
+struct delta<std::vector<X>, std::vector<Y>, D>
+{
+   static bool test(std::vector<X> x, std::vector<Y> y, D d)
+   {
+      if ( x.size() != y.size() )
+         return false;
+      for(size_t i = 0; i<x.size(); ++i)
+         if ( ! delta<X,Y,D>::test(x[i], y[i], d) )
+            return false;
+      return true;
+   }
+};
+
+template<class X, class Y, class D>
+struct delta<std::list<X>, std::list<Y>, D>
+{
+   static bool test(std::list<X> x, std::list<Y> y, D d)
+   {
+      typename std::list<X>::const_iterator x_it = x.begin();
+      typename std::list<Y>::const_iterator y_it = y.begin();
+      for(; x_it != x.end(); ++x_it, ++y_it)
+      {
+         if ( y_it == y.end() )
+            return false;
+         if ( ! delta<X,Y,D>::test(*x_it, *y_it, d) )
+            return false;
+      }
+      return y_it == y.end();
+   }
+};
+
+#endif
+
+} // namespace CxxTest
+
+#endif // __cxxtest__StdTestSuite_h__
+
diff --git a/tools/cxxtest/cxxtest/StdValueTraits.h b/tools/cxxtest/cxxtest/StdValueTraits.h
new file mode 100644 (file)
index 0000000..2c9060c
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest_StdValueTraits_h__
+#define __cxxtest_StdValueTraits_h__
+
+//
+// This file defines ValueTraits for std:: stuff.
+// It is #included by <cxxtest/ValueTraits.h> if you
+// define CXXTEST_HAVE_STD
+//
+
+#include <cxxtest/ValueTraits.h>
+#include <cxxtest/StdHeaders.h>
+
+#ifdef _CXXTEST_OLD_STD
+#   define CXXTEST_STD(x) x
+#else // !_CXXTEST_OLD_STD
+#   define CXXTEST_STD(x) std::x
+#endif // _CXXTEST_OLD_STD
+
+#ifndef CXXTEST_USER_VALUE_TRAITS
+
+namespace CxxTest
+{
+    //
+    // NOTE: This should have been
+    // template<class Char, class Traits, class Allocator>
+    // class ValueTraits< std::basic_string<Char, Traits, Allocator> > {};
+    // But MSVC doesn't support it (yet).
+    //
+
+    //
+    // If we have std::string, we might as well use it
+    //
+    class StdTraitsBase
+    {
+    public:
+        StdTraitsBase &operator<<( const CXXTEST_STD(string) &s ) { _s += s; return *this; }
+        const char *asString() const { return _s.c_str(); }
+
+    private:
+        CXXTEST_STD(string) _s;
+    };
+    
+    //
+    // std::string
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const CXXTEST_STD(string)> : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(string) &s )
+        {
+            *this << "\"";
+            for ( unsigned i = 0; i < s.length(); ++ i ) {
+                char c[sizeof("\\xXX")];
+                charToString( s[i], c );
+                *this << c;
+            }
+            *this << "\"";
+        }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( CXXTEST_STD(string) );
+
+#ifndef _CXXTEST_OLD_STD
+    //
+    // std::wstring
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const CXXTEST_STD(basic_string<wchar_t>)> : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(basic_string<wchar_t>) &s )
+        {
+            *this << "L\"";
+            for ( unsigned i = 0; i < s.length(); ++ i ) {
+                char c[sizeof("\\x12345678")];
+                charToString( (unsigned long)s[i], c );
+                *this << c;
+            }
+            *this << "\"";
+        }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( CXXTEST_STD(basic_string<wchar_t>) );
+#endif // _CXXTEST_OLD_STD
+
+    //
+    // Convert a range defined by iterators to a string
+    // This is useful for almost all STL containers
+    //
+    template<class Stream, class Iterator>
+    void dumpRange( Stream &s, Iterator first, Iterator last )
+    {
+        if ( first == last ) {
+            s << "{}";
+            return;
+        }
+        
+        s << "{ ";
+        while ( first != last ) {
+            s << TS_AS_STRING(*first);
+            if ( ++ first != last )
+                s << ", ";
+        }
+        s << " }";
+    }
+
+#ifdef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+    //
+    // std::pair
+    //
+    template<class First, class Second>
+    class ValueTraits< CXXTEST_STD(pair)<First, Second> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(pair)<First, Second> &p ) 
+        {
+            *this << "<" << TS_AS_STRING( p.first ) << ", " << TS_AS_STRING( p.second ) << ">";
+        }
+    };
+
+    //
+    // std::vector
+    //
+    template<class Element>
+    class ValueTraits< CXXTEST_STD(vector)<Element> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(vector)<Element> &v )
+        {
+            dumpRange( *this, v.begin(), v.end() );
+        }
+    };
+
+    //
+    // std::list
+    //
+    template<class Element>
+    class ValueTraits< CXXTEST_STD(list)<Element> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(list)<Element> &l )
+        {
+            dumpRange( *this, l.begin(), l.end() );
+        }
+    };
+
+    //
+    // std::set
+    //
+    template<class Element>
+    class ValueTraits< CXXTEST_STD(set)<Element> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(set)<Element> &s )
+        {
+            dumpRange( *this, s.begin(), s.end() );
+        }
+    };
+
+    //
+    // std::map
+    //
+    template<class Key, class Value>
+    class ValueTraits< CXXTEST_STD(map)<Key, Value> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(map)<Key, Value> &m )
+        {
+            dumpRange( *this, m.begin(), m.end() );
+        }
+    };    
+
+    //
+    // std::deque
+    //
+    template<class Element>
+    class ValueTraits< CXXTEST_STD(deque)<Element> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(deque)<Element> &d )
+        {
+            dumpRange( *this, d.begin(), d.end() );
+        }
+    };
+
+    //
+    // std::multiset
+    //
+    template<class Element>
+    class ValueTraits< CXXTEST_STD(multiset)<Element> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(multiset)<Element> &ms )
+        {
+            dumpRange( *this, ms.begin(), ms.end() );
+        }
+    };
+
+    //
+    // std::multimap
+    //
+    template<class Key, class Value>
+    class ValueTraits< CXXTEST_STD(multimap)<Key, Value> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(multimap)<Key, Value> &mm )
+        {
+            dumpRange( *this, mm.begin(), mm.end() );
+        }
+    };
+
+    //
+    // std::complex
+    //
+    template<class Number>
+    class ValueTraits< CXXTEST_STD(complex)<Number> > : public StdTraitsBase
+    {
+    public:
+        ValueTraits( const CXXTEST_STD(complex)<Number> &c )
+        {
+            if ( !c.imag() )
+                *this << TS_AS_STRING(c.real());
+            else if ( !c.real() )
+                *this << "(" << TS_AS_STRING(c.imag()) << " * i)";
+            else
+                *this << "(" << TS_AS_STRING(c.real()) << " + " << TS_AS_STRING(c.imag()) << " * i)";
+        }
+    };
+#endif // _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+}
+
+#endif // CXXTEST_USER_VALUE_TRAITS
+
+#endif // __cxxtest_StdValueTraits_h__
diff --git a/tools/cxxtest/cxxtest/StdioFilePrinter.h b/tools/cxxtest/cxxtest/StdioFilePrinter.h
new file mode 100644 (file)
index 0000000..0d64171
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__StdioFilePrinter_h__
+#define __cxxtest__StdioFilePrinter_h__
+
+//
+// The StdioFilePrinter is a simple TestListener that
+// just prints "OK" if everything goes well, otherwise
+// reports the error in the format of compiler messages.
+// This class uses <stdio.h>, i.e. FILE * and fprintf().
+//
+
+#include <cxxtest/ErrorFormatter.h>
+#include <stdio.h>
+
+namespace CxxTest 
+{
+    class StdioFilePrinter : public ErrorFormatter
+    {
+    public:
+        StdioFilePrinter( FILE *o, const char *preLine = ":", const char *postLine = "" ) :
+            ErrorFormatter( new Adapter(o), preLine, postLine ) {}
+        virtual ~StdioFilePrinter() { delete outputStream(); }
+
+    private:
+        class Adapter : public OutputStream
+        {
+            Adapter( const Adapter & );
+            Adapter &operator=( const Adapter & );
+            
+            FILE *_o;
+            
+        public:
+            Adapter( FILE *o ) : _o(o) {}
+            void flush() { fflush( _o ); }
+            OutputStream &operator<<( unsigned i ) { fprintf( _o, "%u", i ); return *this; }
+            OutputStream &operator<<( const char *s ) { fputs( s, _o ); return *this; }
+            OutputStream &operator<<( Manipulator m ) { return OutputStream::operator<<( m ); }
+        };
+    };
+}
+
+#endif // __cxxtest__StdioFilePrinter_h__
diff --git a/tools/cxxtest/cxxtest/StdioPrinter.h b/tools/cxxtest/cxxtest/StdioPrinter.h
new file mode 100644 (file)
index 0000000..88f8551
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__StdioPrinter_h__
+#define __cxxtest__StdioPrinter_h__
+
+//
+// The StdioPrinter is an StdioFilePrinter which defaults to stdout.
+// This should have been called StdOutPrinter or something, but the name
+// has been historically used.
+//
+
+#include <cxxtest/StdioFilePrinter.h>
+
+namespace CxxTest 
+{
+    class StdioPrinter : public StdioFilePrinter
+    {
+    public:
+        StdioPrinter( FILE *o = stdout, const char *preLine = ":", const char *postLine = "" ) :
+            StdioFilePrinter( o, preLine, postLine ) {}
+    };
+}
+
+#endif // __cxxtest__StdioPrinter_h__
diff --git a/tools/cxxtest/cxxtest/TeeListener.h b/tools/cxxtest/cxxtest/TeeListener.h
new file mode 100644 (file)
index 0000000..153a625
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TeeListener_h__
+#define __cxxtest__TeeListener_h__
+
+//
+// A TeeListener notifies two "regular" TestListeners
+//
+
+#include <cxxtest/TestListener.h>
+#include <cxxtest/TestListener.h>
+
+namespace CxxTest
+{
+    class TeeListener : public TestListener
+    {
+    public:
+        TeeListener()
+        {
+            setFirst( _dummy );
+            setSecond( _dummy );
+        }
+
+        virtual ~TeeListener()
+        {
+        }
+
+        void setFirst( TestListener &first )
+        {
+            _first = &first;
+        }
+
+        void setSecond( TestListener &second )
+        {
+            _second = &second;
+        }
+
+        void enterWorld( const WorldDescription &d )
+        {
+            _first->enterWorld( d );
+            _second->enterWorld( d );
+        }
+
+        void enterSuite( const SuiteDescription &d )
+        {
+            _first->enterSuite( d );
+            _second->enterSuite( d );
+        }
+        
+        void enterTest( const TestDescription &d )
+        {
+            _first->enterTest( d );
+            _second->enterTest( d );
+        }
+        
+        void trace( const char *file, int line, const char *expression )
+        {
+            _first->trace( file, line, expression );
+            _second->trace( file, line, expression );
+        }
+        
+        void warning( const char *file, int line, const char *expression )
+        {
+            _first->warning( file, line, expression );
+            _second->warning( file, line, expression );
+        }
+        
+        void failedTest( const char *file, int line, const char *expression )
+        {
+            _first->failedTest( file, line, expression );
+            _second->failedTest( file, line, expression );
+        }
+        
+        void failedAssert( const char *file, int line, const char *expression )
+        {
+            _first->failedAssert( file, line, expression );
+            _second->failedAssert( file, line, expression );
+        }
+        
+        void failedAssertEquals( const char *file, int line,
+                                 const char *xStr, const char *yStr,
+                                 const char *x, const char *y )
+        {
+            _first->failedAssertEquals( file, line, xStr, yStr, x, y );
+            _second->failedAssertEquals( file, line, xStr, yStr, x, y );
+        }
+
+        void failedAssertSameData( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *sizeStr, const void *x,
+                                   const void *y, unsigned size )
+        {
+            _first->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
+            _second->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
+        }
+        
+        void failedAssertSameFiles( const char* file, int line, const char* file1, const char* file2, const char* explanation)
+        {
+            _first->failedAssertSameFiles( file, line, file1, file2, explanation );
+            _second->failedAssertSameFiles( file, line, file1, file2, explanation );
+        }
+
+        void failedAssertDelta( const char *file, int line,
+                                const char *xStr, const char *yStr, const char *dStr,
+                                const char *x, const char *y, const char *d )
+        {
+            _first->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
+            _second->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
+        }
+        
+        void failedAssertDiffers( const char *file, int line,
+                                  const char *xStr, const char *yStr,
+                                  const char *value )
+        {
+            _first->failedAssertDiffers( file, line, xStr, yStr, value );
+            _second->failedAssertDiffers( file, line, xStr, yStr, value );
+        }
+        
+        void failedAssertLessThan( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            _first->failedAssertLessThan( file, line, xStr, yStr, x, y );
+            _second->failedAssertLessThan( file, line, xStr, yStr, x, y );
+        }
+        
+        void failedAssertLessThanEquals( const char *file, int line,
+                                         const char *xStr, const char *yStr,
+                                         const char *x, const char *y )
+        {
+            _first->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
+            _second->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
+        }
+        
+        void failedAssertPredicate( const char *file, int line,
+                                    const char *predicate, const char *xStr, const char *x )
+        {
+            _first->failedAssertPredicate( file, line, predicate, xStr, x );
+            _second->failedAssertPredicate( file, line, predicate, xStr, x );
+        }
+        
+        void failedAssertRelation( const char *file, int line,
+                                   const char *relation, const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            _first->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
+            _second->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
+        }
+        
+        void failedAssertThrows( const char *file, int line,
+                                 const char *expression, const char *type,
+                                 bool otherThrown )
+        {
+            _first->failedAssertThrows( file, line, expression, type, otherThrown );
+            _second->failedAssertThrows( file, line, expression, type, otherThrown );
+        }
+        
+        void failedAssertThrowsNot( const char *file, int line,
+                                    const char *expression )
+        {
+            _first->failedAssertThrowsNot( file, line, expression );
+            _second->failedAssertThrowsNot( file, line, expression );
+        }
+        
+        void leaveTest( const TestDescription &d )
+        {
+            _first->leaveTest(d);
+            _second->leaveTest(d);
+        }
+        
+        void leaveSuite( const SuiteDescription &d )
+        {
+            _first->leaveSuite(d);
+            _second->leaveSuite(d);
+        }
+        
+        void leaveWorld( const WorldDescription &d )
+        {
+            _first->leaveWorld(d);
+            _second->leaveWorld(d);
+        }
+
+    private:
+        TestListener *_first, *_second;
+        TestListener _dummy;
+    };
+}
+
+
+#endif // __cxxtest__TeeListener_h__
diff --git a/tools/cxxtest/cxxtest/TestListener.h b/tools/cxxtest/cxxtest/TestListener.h
new file mode 100644 (file)
index 0000000..4881e97
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TestListener_h__
+#define __cxxtest__TestListener_h__
+
+//
+// TestListener is the base class for all "listeners",
+// i.e. classes that receive notifications of the
+// testing process.
+//
+// The names of the parameters are in comments to avoid
+// "unused parameter" warnings.
+//
+
+#include <cxxtest/Descriptions.h>
+
+namespace CxxTest
+{
+    class TestListener
+    {
+    public:
+        TestListener() {}
+        virtual ~TestListener() {}
+        virtual void process_commandline(int& /*argc*/, char** /*argv*/) {}
+        
+        virtual void enterWorld( const WorldDescription & /*desc*/ ) {}
+        virtual void enterSuite( const SuiteDescription & /*desc*/ ) {}
+        virtual void enterTest( const TestDescription & /*desc*/ ) {}
+        virtual void trace( const char * /*file*/, int /*line*/,
+                            const char * /*expression*/ ) {}
+        virtual void warning( const char * /*file*/, int /*line*/,
+                              const char * /*expression*/ ) {}
+        virtual void failedTest( const char * /*file*/, int /*line*/,
+                                 const char * /*expression*/ ) {}
+        virtual void failedAssert( const char * /*file*/, int /*line*/,
+                                   const char * /*expression*/ ) {}
+        virtual void failedAssertEquals( const char * /*file*/, int /*line*/,
+                                         const char * /*xStr*/, const char * /*yStr*/,
+                                         const char * /*x*/, const char * /*y*/ ) {}
+        virtual void failedAssertSameData( const char * /*file*/, int /*line*/,
+                                           const char * /*xStr*/, const char * /*yStr*/,
+                                           const char * /*sizeStr*/, const void * /*x*/,
+                                           const void * /*y*/, unsigned /*size*/ ) {}
+        virtual void failedAssertDelta( const char * /*file*/, int /*line*/,
+                                        const char * /*xStr*/, const char * /*yStr*/,
+                                        const char * /*dStr*/, const char * /*x*/,
+                                        const char * /*y*/, const char * /*d*/ ) {}
+        virtual void failedAssertDiffers( const char * /*file*/, int /*line*/,
+                                          const char * /*xStr*/, const char * /*yStr*/,
+                                          const char * /*value*/ ) {}
+        virtual void failedAssertLessThan( const char * /*file*/, int /*line*/,
+                                           const char * /*xStr*/, const char * /*yStr*/,
+                                           const char * /*x*/, const char * /*y*/ ) {}
+        virtual void failedAssertLessThanEquals( const char * /*file*/, int /*line*/,
+                                                 const char * /*xStr*/, const char * /*yStr*/,
+                                                 const char * /*x*/, const char * /*y*/ ) {}
+        virtual void failedAssertPredicate( const char * /*file*/, int /*line*/,
+                                            const char * /*predicate*/, const char * /*xStr*/, const char * /*x*/ ) {}
+        virtual void failedAssertRelation( const char * /*file*/, int /*line*/,
+                                           const char * /*relation*/, const char * /*xStr*/, const char * /*yStr*/,
+                                           const char * /*x*/, const char * /*y*/ ) {}
+        virtual void failedAssertThrows( const char * /*file*/, int /*line*/,
+                                         const char * /*expression*/, const char * /*type*/,
+                                         bool /*otherThrown*/ ) {}
+        virtual void failedAssertThrowsNot( const char * /*file*/, int /*line*/,
+                                            const char * /*expression*/ ) {}
+           virtual void failedAssertSameFiles( const char* /*file*/, int /*line*/, 
+                                            const char* , const char*, const char* ) {}
+        virtual void leaveTest( const TestDescription & /*desc*/ ) {}
+        virtual void leaveSuite( const SuiteDescription & /*desc*/ ) {}
+        virtual void leaveWorld( const WorldDescription & /*desc*/ ) {}
+    };
+}
+
+#endif // __cxxtest__TestListener_h__
+
diff --git a/tools/cxxtest/cxxtest/TestMain.h b/tools/cxxtest/cxxtest/TestMain.h
new file mode 100644 (file)
index 0000000..343c22b
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __CxxTestMain_h
+#define __CxxTestMain_h
+
+#include <cxxtest/TestTracker.h>
+#include <cxxtest/Flags.h>
+
+#ifndef _CXXTEST_HAVE_STD
+#   define _CXXTEST_HAVE_STD
+#endif // _CXXTEST_HAVE_STD
+
+#include <cxxtest/StdValueTraits.h>
+
+#ifdef _CXXTEST_OLD_STD
+#   include <iostream.h>
+#   include <string.h>
+#else // !_CXXTEST_OLD_STD
+#   include <iostream>
+#   include <cstring>
+#endif // _CXXTEST_OLD_STD
+
+namespace CxxTest
+{
+
+inline void print_help(const char* name)
+{
+   CXXTEST_STD(cerr) << name << " <suitename>" << CXXTEST_STD(endl);
+   CXXTEST_STD(cerr) << name << " <suitename> <testname>" << CXXTEST_STD(endl);
+   CXXTEST_STD(cerr) << name << " -h" << CXXTEST_STD(endl);
+   CXXTEST_STD(cerr) << name << " --help" << CXXTEST_STD(endl);
+   CXXTEST_STD(cerr) << name << " --help-tests" << CXXTEST_STD(endl);
+   CXXTEST_STD(cerr) << name << " -v             Enable tracing output." << CXXTEST_STD(endl);
+}
+
+
+template <class TesterT>
+int Main(TesterT& tmp, int argc, char* argv[])
+{ 
+//
+// Parse the command-line arguments. The default behavior is to run all tests
+//
+// This is a primitive parser, but I'm not sure what sort of portable
+// parser should be used in cxxtest.
+//
+
+//
+// Print command-line syntax
+//
+for (int i=1; i<argc; i++) {
+  if ((CXXTEST_STD(strcmp)(argv[i],"-h")==0) || (CXXTEST_STD(strcmp)(argv[i],"--help")==0)) {
+     print_help(argv[0]);
+     return 0;
+  } else if ((CXXTEST_STD(strcmp)(argv[1],"--help-tests")==0)) {
+    CXXTEST_STD(cout) << "Suite/Test Names" << CXXTEST_STD(endl);
+    CXXTEST_STD(cout) << "---------------------------------------------------------------------------" << CXXTEST_STD(endl);
+    for ( SuiteDescription *sd = RealWorldDescription().firstSuite(); sd; sd = sd->next() )
+        for ( TestDescription *td = sd->firstTest(); td; td = td->next() )
+            CXXTEST_STD(cout) << td->suiteName() << " " << td->testName() << CXXTEST_STD(endl);
+    return 0;
+  }
+}
+
+//
+// Process command-line options here.
+//
+while ((argc > 1) && (argv[1][0] == '-')) {
+  if (CXXTEST_STD(strcmp)(argv[1],"-v") == 0) {
+     tracker().print_tracing = true;
+     }
+  else {
+     CXXTEST_STD(cerr) << "ERROR: unknown option '" << argv[1] << "'" << CXXTEST_STD(endl);
+     return -1;
+     }
+  for (int i=1; i<(argc-1); i++)
+    argv[i] = argv[i+1];
+  argc--;
+  }
+
+//
+// Run experiments
+//
+bool status=false;
+if ((argc==2) && (argv[1][0] != '-')) {
+    status=leaveOnly(argv[1]);
+    if (!status) {
+       CXXTEST_STD(cerr) << "ERROR: unknown suite '" << argv[1] << "'" << CXXTEST_STD(endl);
+       return -1;
+       }
+    }
+if ((argc==3) && (argv[1][0] != '-')) {
+    status=leaveOnly(argv[1],argv[2]);
+    if (!status) {
+       CXXTEST_STD(cerr) << "ERROR: unknown test '" << argv[1] << "::" << argv[2] << "'" << CXXTEST_STD(endl);
+       return -1;
+       }
+    }
+
+tmp.process_commandline(argc,argv);
+return tmp.run();
+}
+
+}
+#endif
+
diff --git a/tools/cxxtest/cxxtest/TestRunner.h b/tools/cxxtest/cxxtest/TestRunner.h
new file mode 100644 (file)
index 0000000..17866a6
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest_TestRunner_h__
+#define __cxxtest_TestRunner_h__
+
+//
+// TestRunner is the class that runs all the tests.
+// To use it, create an object that implements the TestListener
+// interface and call TestRunner::runAllTests( myListener );
+// 
+
+#include <cxxtest/TestListener.h>
+#include <cxxtest/RealDescriptions.h>
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/TestTracker.h>
+
+namespace CxxTest 
+{
+    class TestRunner
+    {
+    public:
+        static void runAllTests( TestListener &listener )
+        {
+            tracker().setListener( &listener );
+            _TS_TRY { TestRunner().runWorld(); }
+            _TS_LAST_CATCH( { tracker().failedTest( __FILE__, __LINE__, "Exception thrown from world" ); } );
+            tracker().setListener( 0 );
+        }
+
+        static void runAllTests( TestListener *listener )
+        {
+            if ( listener ) {
+                listener->warning( __FILE__, __LINE__, "Deprecated; Use runAllTests( TestListener & )" );
+                runAllTests( *listener );
+            }
+        }        
+    
+    private:
+        void runWorld()
+        {
+            RealWorldDescription wd;
+            WorldGuard sg;
+            
+            tracker().enterWorld( wd );
+            if ( wd.setUp() ) {
+                for ( SuiteDescription *sd = wd.firstSuite(); sd; sd = sd->next() )
+                    if ( sd->active() )
+                        runSuite( *sd );
+            
+                wd.tearDown();
+            }
+            tracker().leaveWorld( wd );
+        }
+    
+        void runSuite( SuiteDescription &sd )
+        {
+            StateGuard sg;
+            
+            tracker().enterSuite( sd );
+            if ( sd.setUp() ) {
+                for ( TestDescription *td = sd.firstTest(); td; td = td->next() )
+                    if ( td->active() )
+                        runTest( *td );
+
+                sd.tearDown();
+            }
+            tracker().leaveSuite( sd );
+        }
+
+        void runTest( TestDescription &td )
+        {
+            StateGuard sg;
+            
+            tracker().enterTest( td );
+            if ( td.setUp() ) {
+                td.run();
+                td.tearDown();
+            }
+            tracker().leaveTest( td );
+        }
+        
+        class StateGuard
+        {
+#ifdef _CXXTEST_HAVE_EH
+            bool _abortTestOnFail;
+#endif // _CXXTEST_HAVE_EH
+            unsigned _maxDumpSize;
+            
+        public:
+            StateGuard()
+            {
+#ifdef _CXXTEST_HAVE_EH
+                _abortTestOnFail = abortTestOnFail();
+#endif // _CXXTEST_HAVE_EH
+                _maxDumpSize = maxDumpSize();
+            }
+            
+            ~StateGuard()
+            {
+#ifdef _CXXTEST_HAVE_EH
+                setAbortTestOnFail( _abortTestOnFail );
+#endif // _CXXTEST_HAVE_EH
+                setMaxDumpSize( _maxDumpSize );
+            }
+        };
+
+        class WorldGuard : public StateGuard
+        {
+        public:
+            WorldGuard() : StateGuard()
+            {
+#ifdef _CXXTEST_HAVE_EH
+                setAbortTestOnFail( CXXTEST_DEFAULT_ABORT );
+#endif // _CXXTEST_HAVE_EH
+                setMaxDumpSize( CXXTEST_MAX_DUMP_SIZE );
+            }
+        };
+    };
+
+    //
+    // For --no-static-init
+    //
+    void initialize();
+}
+
+
+#endif // __cxxtest_TestRunner_h__
diff --git a/tools/cxxtest/cxxtest/TestSuite.cpp b/tools/cxxtest/cxxtest/TestSuite.cpp
new file mode 100644 (file)
index 0000000..eef2cce
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TestSuite_cpp__
+#define __cxxtest__TestSuite_cpp__
+
+#include <cxxtest/TestSuite.h>
+#if defined(_CXXTEST_HAVE_STD)
+#include <fstream>
+#endif
+
+namespace CxxTest
+{
+    //
+    // TestSuite members
+    //
+    TestSuite::~TestSuite() {}
+    void TestSuite::setUp() {}
+    void TestSuite::tearDown() {}
+
+    //
+    // Test-aborting stuff
+    //
+    static bool currentAbortTestOnFail = false;
+
+    bool abortTestOnFail()
+    {
+        return currentAbortTestOnFail;
+    }
+
+    void setAbortTestOnFail( bool value )
+    {
+        currentAbortTestOnFail = value;
+    }
+    
+    void doAbortTest()
+    {
+#   if defined(_CXXTEST_HAVE_EH)
+        if ( currentAbortTestOnFail )
+            throw AbortTest();
+#   endif // _CXXTEST_HAVE_EH
+    }
+
+    //
+    // Max dump size
+    //
+    static unsigned currentMaxDumpSize = CXXTEST_MAX_DUMP_SIZE;
+
+    unsigned maxDumpSize()
+    {
+        return currentMaxDumpSize;
+    }
+    
+    void setMaxDumpSize( unsigned value )
+    {
+        currentMaxDumpSize = value;
+    }
+
+    //
+    // Some non-template functions
+    //
+    void doTrace( const char *file, int line, const char *message )
+    {
+        if (tracker().print_tracing) {
+           tracker().trace( file, line, message );
+           }
+    }
+
+    void doWarn( const char *file, int line, const char *message )
+    {
+        tracker().warning( file, line, message );
+    }
+
+    void doFailTest( const char *file, int line, const char *message )
+    {
+        tracker().failedTest( file, line, message );
+        TS_ABORT();
+    }
+
+    void doFailAssert( const char *file, int line,
+                       const char *expression, const char *message )
+    {
+        if ( message )
+            tracker().failedTest( file, line, message );
+        tracker().failedAssert( file, line, expression );
+        TS_ABORT();
+    }
+
+    bool sameData( const void *x, const void *y, unsigned size )
+    {
+        if ( size == 0 )
+            return true;
+        
+        if ( x == y )
+            return true;
+
+        if ( !x || !y )
+            return false;
+
+        const char *cx = (const char *)x;
+        const char *cy = (const char *)y;
+        while ( size -- )
+            if ( *cx++ != *cy++ )
+                return false;
+
+        return true;
+    }
+
+    void doAssertSameData( const char *file, int line,
+                           const char *xExpr, const void *x,
+                           const char *yExpr, const void *y,
+                           const char *sizeExpr, unsigned size,
+                           const char *message )
+    {
+        if ( !sameData( x, y, size ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertSameData( file, line, xExpr, yExpr, sizeExpr, x, y, size );
+            TS_ABORT();
+        }
+    }
+
+//#if defined(_CXXTEST_HAVE_STD)
+    bool sameFiles( const char* file1, const char* file2, std::ostringstream& explanation)
+    {
+    std::string ppprev_line;
+    std::string pprev_line;
+    std::string prev_line;
+    std::string curr_line;
+
+    std::ifstream is1;
+    is1.open(file1);
+    std::ifstream is2;
+    is2.open(file2);
+    if (!is1) {
+        explanation << "File '" << file1 << "' does not exist!";
+        return false;
+        }
+    if (!is2) {
+        explanation << "File '" << file2 << "' does not exist!";
+        return false;
+        }
+
+    int nline=1;
+    char c1, c2;
+    while (1) {
+        is1.get(c1);
+        is2.get(c2);
+        if (!is1 && !is2) return true;
+        if (!is1) {
+                explanation << "File '" << file1 << "' ended before file '" << file2 << "' (line " << nline << ")";
+                explanation << std::endl << "= " << ppprev_line << std::endl << "=  " << pprev_line << std::endl << "= " << prev_line << std::endl << "< " << curr_line;
+                is1.get(c1);
+                while (is1 && (c1 != '\n')) {
+                  explanation << c1;
+                  is1.get(c1);
+                  }
+                explanation << std::endl;
+                return false;
+                }
+        if (!is2) {
+                explanation << "File '" << file2 << "' ended before file '" << file1 << "' (line " << nline << ")";
+                explanation << std::endl << "= " << ppprev_line << std::endl << "=  " << pprev_line << std::endl << "= " << prev_line << std::endl << "> " << curr_line;
+                is2.get(c2);
+                while (is2 && (c2 != '\n')) {
+                  explanation << c2;
+                  is2.get(c2);
+                  }
+                explanation << std::endl;
+                return false;
+                }
+        if (c1 != c2) {
+                explanation << "Files '" << file1 << "' and '" << file2 << "' differ at line " << nline;
+                explanation << std::endl << "= " << ppprev_line << std::endl << "=  " << pprev_line << std::endl << "= " << prev_line;
+
+                explanation << std::endl << "< " << curr_line;
+                is2.get(c1);
+                while (is1 && (c1 != '\n')) {
+                  explanation << c1;
+                  is2.get(c1);
+                  }
+                explanation << std::endl;
+
+                explanation << std::endl << "> " << curr_line;
+                is2.get(c2);
+                while (is2 && (c2 != '\n')) {
+                  explanation << c2;
+                  is2.get(c2);
+                  }
+                explanation << std::endl;
+
+                return false;
+                }
+        if (c1 == '\n') {
+           ppprev_line = pprev_line;
+           pprev_line = prev_line;
+           prev_line = curr_line;
+           curr_line = "";
+           nline++;
+           }
+        else {
+           curr_line += c1;
+           }
+        }
+    }
+//#endif
+
+    void doAssertSameFiles( const char* file, int line,
+                            const char* file1, const char* file2,
+                            const char* message)
+    {
+#if defined(_CXXTEST_HAVE_STD)
+        std::ostringstream explanation;
+        if ( !sameFiles( file1, file2, explanation ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertSameFiles( file, line, file1, file2, explanation.str().c_str());
+            TS_ABORT();
+        }
+#else
+        tracker().failedAssertSameFiles( file, line, file1, file2, "This test is only supported when --have-std is enabled");
+        TS_ABORT();
+#endif
+    }
+
+    void doFailAssertThrows( const char *file, int line,
+                             const char *expr, const char *type,
+                             bool otherThrown,
+                             const char *message,
+                             const char *exception )
+    {
+        if ( exception )
+            tracker().failedTest( file, line, exception );
+        if ( message )
+            tracker().failedTest( file, line, message );
+        
+        tracker().failedAssertThrows( file, line, expr, type, otherThrown );
+        TS_ABORT();
+    }
+
+    void doFailAssertThrowsNot( const char *file, int line,
+                                const char *expression, const char *message,
+                                const char *exception )
+    {
+        if ( exception )
+            tracker().failedTest( file, line, exception );
+        if ( message )
+            tracker().failedTest( file, line, message );
+        
+        tracker().failedAssertThrowsNot( file, line, expression );
+        TS_ABORT();
+    }
+}
+
+#endif // __cxxtest__TestSuite_cpp__
+
diff --git a/tools/cxxtest/cxxtest/TestSuite.h b/tools/cxxtest/cxxtest/TestSuite.h
new file mode 100644 (file)
index 0000000..eeec0b3
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TestSuite_h__
+#define __cxxtest__TestSuite_h__
+
+//
+// class TestSuite is the base class for all test suites.
+// To define a test suite, derive from this class and add
+// member functions called void test*();
+//
+
+#include <cxxtest/Flags.h>
+#include <cxxtest/TestTracker.h>
+#include <cxxtest/Descriptions.h>
+#include <cxxtest/ValueTraits.h>
+#include <sstream>
+
+#if defined(_CXXTEST_HAVE_STD)
+#   include <stdexcept>
+#endif // _CXXTEST_HAVE_STD
+
+namespace CxxTest
+{
+    class TestSuite
+    {
+    public:
+        virtual ~TestSuite();
+        virtual void setUp();
+        virtual void tearDown();
+    };
+    
+    class AbortTest {};
+    void doAbortTest();
+#   define TS_ABORT() CxxTest::doAbortTest()
+    
+    bool abortTestOnFail();
+    void setAbortTestOnFail( bool value = CXXTEST_DEFAULT_ABORT );
+
+    unsigned maxDumpSize();
+    void setMaxDumpSize( unsigned value = CXXTEST_MAX_DUMP_SIZE );
+
+    void doTrace( const char *file, int line, const char *message );
+    void doWarn( const char *file, int line, const char *message );
+    void doFailTest( const char *file, int line, const char *message );
+    void doFailAssert( const char *file, int line, const char *expression, const char *message );
+
+    template<class X, class Y>
+    struct equals {
+        static bool test( X x, Y y )
+        {
+            return (x == y);
+        }
+    };
+
+    template<class X, class Y>
+    void doAssertEquals( const char *file, int line,
+                         const char *xExpr, X x,
+                         const char *yExpr, Y y,
+                         const char *message )
+    {
+        if ( !equals<X,Y>::test( x, y ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertEquals( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
+            TS_ABORT();
+        }
+    }
+
+    bool sameData( const void *x, const void *y, unsigned size );
+
+    void doAssertSameData( const char *file, int line,
+                           const char *xExpr, const void *x,
+                           const char *yExpr, const void *y,
+                           const char *sizeExpr, unsigned size,
+                           const char *message );
+
+//#if defined(_CXXTEST_HAVE_STD)
+    bool sameFiles( const char* file1, const char* file2, std::ostringstream& explanation);
+//#endif
+
+    template<class X, class Y>
+    struct differs {
+        static bool test( X x, Y y )
+        {
+            return !(x == y);
+        }
+    };
+
+    template<class X, class Y>
+    void doAssertDiffers( const char *file, int line,
+                          const char *xExpr, X x,
+                          const char *yExpr, Y y,
+                          const char *message )
+    {
+        if ( !differs<X,Y>::test( x, y ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertDiffers( file, line, xExpr, yExpr, TS_AS_STRING(x) );
+            TS_ABORT();
+        }
+    }
+
+    template<class X, class Y>
+    struct lessThan {
+        static bool test( X x, Y y )
+        {
+            return (x < y);
+        }
+    };
+
+    template<class X, class Y>
+    void doAssertLessThan( const char *file, int line,
+                           const char *xExpr, X x,
+                           const char *yExpr, Y y,
+                           const char *message )
+    {
+        if ( !lessThan<X,Y>::test(x, y) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertLessThan( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
+            TS_ABORT();
+        }
+    }
+
+    template<class X, class Y>
+    struct lessThanEquals {
+        static bool test( X x, Y y )
+        {
+            return (x <= y);
+        }
+    };
+
+    template<class X, class Y>
+    void doAssertLessThanEquals( const char *file, int line,
+                                 const char *xExpr, X x,
+                                 const char *yExpr, Y y,
+                                 const char *message )
+    {
+        if ( !lessThanEquals<X,Y>::test( x, y ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertLessThanEquals( file, line, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
+            TS_ABORT();
+        }
+    }
+
+    template<class X, class P>
+    void doAssertPredicate( const char *file, int line,
+                            const char *pExpr, const P &p,
+                            const char *xExpr, X x,
+                            const char *message )
+    {
+        if ( !p( x ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertPredicate( file, line, pExpr, xExpr, TS_AS_STRING(x) );
+            TS_ABORT();
+        }
+    }
+
+    template<class X, class Y, class R>
+    void doAssertRelation( const char *file, int line,
+                           const char *rExpr, const R &r, 
+                           const char *xExpr, X x,
+                           const char *yExpr, Y y,
+                           const char *message )
+    {
+        if ( !r( x, y ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            tracker().failedAssertRelation( file, line, rExpr, xExpr, yExpr, TS_AS_STRING(x), TS_AS_STRING(y) );
+            TS_ABORT();
+        }
+    }
+
+    // An indirection template so the compiler can determine what type 
+    // "X +/- D" should be
+    template<class X, class Y>
+    bool delta_le_helper( X x, Y y )
+    { 
+        return lessThanEquals<X,Y>::test(x,y); 
+    }
+
+    template<class X, class Y, class D>
+    struct delta {
+        static bool test( X x, Y y, D d )
+        {
+            return delta_le_helper(x-d, y) && delta_le_helper(y, x+d);
+            //(y >= x - d) && (y <= x + d));
+        }
+    };
+
+    template<class X, class Y, class D>
+    void doAssertDelta( const char *file, int line,
+                        const char *xExpr, X x,
+                        const char *yExpr, Y y,
+                        const char *dExpr, D d,
+                        const char *message )
+    {
+        if ( !delta<X,Y,D>::test( x, y, d ) ) {
+            if ( message )
+                tracker().failedTest( file, line, message );
+            
+            tracker().failedAssertDelta( file, line, xExpr, yExpr, dExpr,
+                                         TS_AS_STRING(x), TS_AS_STRING(y), TS_AS_STRING(d) );
+            TS_ABORT();
+        }
+    }
+
+    void doFailAssertThrows( const char *file, int line,
+                             const char *expr, const char *type,
+                             bool otherThrown,
+                             const char *message,
+                             const char *exception = 0 );
+    
+    void doFailAssertThrowsNot( const char *file, int line,
+                                const char *expression, const char *message,
+                                const char *exception = 0 );
+
+    void doAssertSameFiles( const char* file, int line,
+                            const char* file1, const char* file2,
+                            const char* message);
+
+#   ifdef _CXXTEST_HAVE_EH
+#       define _TS_TRY try
+#       define _TS_CATCH_TYPE(t, b) catch t b
+#       define _TS_CATCH_ABORT(b) _TS_CATCH_TYPE( (const CxxTest::AbortTest &), b )
+#       define _TS_LAST_CATCH(b) _TS_CATCH_TYPE( (...), b )
+#       define _TSM_LAST_CATCH(f,l,m) _TS_LAST_CATCH( { (CxxTest::tracker()).failedTest(f,l,m); TS_ABORT(); } )
+#       ifdef _CXXTEST_HAVE_STD
+#           define _TS_CATCH_STD(e,b) _TS_CATCH_TYPE( (const std::exception& e), b )
+#       else // !_CXXTEST_HAVE_STD
+#           define _TS_CATCH_STD(e,b)
+#       endif // _CXXTEST_HAVE_STD
+#       define ___TSM_CATCH(f,l,m) \
+            _TS_CATCH_STD(e, { (CxxTest::tracker()).failedTest(f,l,e.what()); TS_ABORT(); }) \
+            _TSM_LAST_CATCH(f,l,m)
+#       define __TSM_CATCH(f,l,m) \
+                _TS_CATCH_ABORT( { throw; } ) \
+                ___TSM_CATCH(f,l,m)
+#       define __TS_CATCH(f,l) __TSM_CATCH(f,l,"Unhandled exception")
+#       define _TS_CATCH __TS_CATCH(__FILE__,__LINE__)
+#   else // !_CXXTEST_HAVE_EH
+#       define _TS_TRY
+#       define ___TSM_CATCH(f,l,m)
+#       define __TSM_CATCH(f,l,m)
+#       define __TS_CATCH(f,l)
+#       define _TS_CATCH
+#       define _TS_CATCH_TYPE(t, b)
+#       define _TS_LAST_CATCH(b)
+#       define _TS_CATCH_STD(e,b)
+#       define _TS_CATCH_ABORT(b)
+#   endif // _CXXTEST_HAVE_EH
+
+    // TS_TRACE
+#   define _TS_TRACE(f,l,e) CxxTest::doTrace( (f), (l), TS_AS_STRING(e) )
+#   define TS_TRACE(e) _TS_TRACE( __FILE__, __LINE__, e )
+
+    // TS_WARN
+#   define _TS_WARN(f,l,e) CxxTest::doWarn( (f), (l), TS_AS_STRING(e) )
+#   define TS_WARN(e) _TS_WARN( __FILE__, __LINE__, e )
+
+    // TS_FAIL
+#   define _TS_FAIL(f,l,e) CxxTest::doFailTest( (f), (l), TS_AS_STRING(e) )
+#   define TS_FAIL(e) _TS_FAIL( __FILE__, __LINE__, e )
+
+    // TS_ASSERT
+#   define ___ETS_ASSERT(f,l,e,m) { if ( !(e) ) CxxTest::doFailAssert( (f), (l), #e, (m) ); }
+#   define ___TS_ASSERT(f,l,e,m) { _TS_TRY { ___ETS_ASSERT(f,l,e,m); } __TS_CATCH(f,l) }
+    
+#   define _ETS_ASSERT(f,l,e) ___ETS_ASSERT(f,l,e,0)
+#   define _TS_ASSERT(f,l,e) ___TS_ASSERT(f,l,e,0)
+    
+#   define ETS_ASSERT(e) _ETS_ASSERT(__FILE__,__LINE__,e)
+#   define TS_ASSERT(e) _TS_ASSERT(__FILE__,__LINE__,e)
+    
+#   define _ETSM_ASSERT(f,l,m,e) ___ETS_ASSERT(f,l,e,TS_AS_STRING(m) )
+#   define _TSM_ASSERT(f,l,m,e) ___TS_ASSERT(f,l,e,TS_AS_STRING(m) )
+
+#   define ETSM_ASSERT(m,e) _ETSM_ASSERT(__FILE__,__LINE__,m,e)
+#   define TSM_ASSERT(m,e) _TSM_ASSERT(__FILE__,__LINE__,m,e)
+    
+    // TS_ASSERT_EQUALS
+#   define ___ETS_ASSERT_EQUALS(f,l,x,y,m) CxxTest::doAssertEquals( (f), (l), #x, (x), #y, (y), (m) )
+#   define ___TS_ASSERT_EQUALS(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_EQUALS(f,l,x,y,m); } __TS_CATCH(f,l) }
+    
+#   define _ETS_ASSERT_EQUALS(f,l,x,y) ___ETS_ASSERT_EQUALS(f,l,x,y,0)
+#   define _TS_ASSERT_EQUALS(f,l,x,y) ___TS_ASSERT_EQUALS(f,l,x,y,0)
+
+#   define ETS_ASSERT_EQUALS(x,y) _ETS_ASSERT_EQUALS(__FILE__,__LINE__,x,y)
+#   define TS_ASSERT_EQUALS(x,y) _TS_ASSERT_EQUALS(__FILE__,__LINE__,x,y)
+
+#   define _ETSM_ASSERT_EQUALS(f,l,m,x,y) ___ETS_ASSERT_EQUALS(f,l,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_EQUALS(f,l,m,x,y) ___TS_ASSERT_EQUALS(f,l,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_EQUALS(m,x,y) _ETSM_ASSERT_EQUALS(__FILE__,__LINE__,m,x,y)
+#   define TSM_ASSERT_EQUALS(m,x,y) _TSM_ASSERT_EQUALS(__FILE__,__LINE__,m,x,y)
+
+    // TS_ASSERT_SAME_DATA
+#   define ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,m) CxxTest::doAssertSameData( (f), (l), #x, (x), #y, (y), #s, (s), (m) )
+#   define ___TS_ASSERT_SAME_DATA(f,l,x,y,s,m) { _TS_TRY { ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,m); } __TS_CATCH(f,l) }
+    
+#   define _ETS_ASSERT_SAME_DATA(f,l,x,y,s) ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,0)
+#   define _TS_ASSERT_SAME_DATA(f,l,x,y,s) ___TS_ASSERT_SAME_DATA(f,l,x,y,s,0)
+
+#   define ETS_ASSERT_SAME_DATA(x,y,s) _ETS_ASSERT_SAME_DATA(__FILE__,__LINE__,x,y,s)
+#   define TS_ASSERT_SAME_DATA(x,y,s) _TS_ASSERT_SAME_DATA(__FILE__,__LINE__,x,y,s)
+
+#   define _ETSM_ASSERT_SAME_DATA(f,l,m,x,y,s) ___ETS_ASSERT_SAME_DATA(f,l,x,y,s,TS_AS_STRING(m))
+#   define _TSM_ASSERT_SAME_DATA(f,l,m,x,y,s) ___TS_ASSERT_SAME_DATA(f,l,x,y,s,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_SAME_DATA(m,x,y,s) _ETSM_ASSERT_SAME_DATA(__FILE__,__LINE__,m,x,y,s)
+#   define TSM_ASSERT_SAME_DATA(m,x,y,s) _TSM_ASSERT_SAME_DATA(__FILE__,__LINE__,m,x,y,s)
+
+    // TS_ASSERT_DIFFERS
+#   define ___ETS_ASSERT_DIFFERS(f,l,x,y,m) CxxTest::doAssertDiffers( (f), (l), #x, (x), #y, (y), (m) )
+#   define ___TS_ASSERT_DIFFERS(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_DIFFERS(f,l,x,y,m); } __TS_CATCH(f,l) }
+
+#   define _ETS_ASSERT_DIFFERS(f,l,x,y) ___ETS_ASSERT_DIFFERS(f,l,x,y,0)
+#   define _TS_ASSERT_DIFFERS(f,l,x,y) ___TS_ASSERT_DIFFERS(f,l,x,y,0)
+
+#   define ETS_ASSERT_DIFFERS(x,y) _ETS_ASSERT_DIFFERS(__FILE__,__LINE__,x,y)
+#   define TS_ASSERT_DIFFERS(x,y) _TS_ASSERT_DIFFERS(__FILE__,__LINE__,x,y)
+
+#   define _ETSM_ASSERT_DIFFERS(f,l,m,x,y) ___ETS_ASSERT_DIFFERS(f,l,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_DIFFERS(f,l,m,x,y) ___TS_ASSERT_DIFFERS(f,l,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_DIFFERS(m,x,y) _ETSM_ASSERT_DIFFERS(__FILE__,__LINE__,m,x,y)
+#   define TSM_ASSERT_DIFFERS(m,x,y) _TSM_ASSERT_DIFFERS(__FILE__,__LINE__,m,x,y)
+
+    // TS_ASSERT_LESS_THAN
+#   define ___ETS_ASSERT_LESS_THAN(f,l,x,y,m) CxxTest::doAssertLessThan( (f), (l), #x, (x), #y, (y), (m) )
+#   define ___TS_ASSERT_LESS_THAN(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_LESS_THAN(f,l,x,y,m); } __TS_CATCH(f,l) }
+
+#   define _ETS_ASSERT_LESS_THAN(f,l,x,y) ___ETS_ASSERT_LESS_THAN(f,l,x,y,0)
+#   define _TS_ASSERT_LESS_THAN(f,l,x,y) ___TS_ASSERT_LESS_THAN(f,l,x,y,0)
+
+#   define ETS_ASSERT_LESS_THAN(x,y) _ETS_ASSERT_LESS_THAN(__FILE__,__LINE__,x,y)
+#   define TS_ASSERT_LESS_THAN(x,y) _TS_ASSERT_LESS_THAN(__FILE__,__LINE__,x,y)
+
+#   define _ETSM_ASSERT_LESS_THAN(f,l,m,x,y) ___ETS_ASSERT_LESS_THAN(f,l,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_LESS_THAN(f,l,m,x,y) ___TS_ASSERT_LESS_THAN(f,l,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_LESS_THAN(m,x,y) _ETSM_ASSERT_LESS_THAN(__FILE__,__LINE__,m,x,y)
+#   define TSM_ASSERT_LESS_THAN(m,x,y) _TSM_ASSERT_LESS_THAN(__FILE__,__LINE__,m,x,y)
+
+    // TS_ASSERT_LESS_THAN_EQUALS
+#   define ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m) \
+        CxxTest::doAssertLessThanEquals( (f), (l), #x, (x), #y, (y), (m) )
+#   define ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m) \
+        { _TS_TRY { ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,m); } __TS_CATCH(f,l) }
+
+#   define _ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y) ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,0)
+#   define _TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y) ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,0)
+
+#   define ETS_ASSERT_LESS_THAN_EQUALS(x,y) _ETS_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,x,y)
+#   define TS_ASSERT_LESS_THAN_EQUALS(x,y) _TS_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,x,y)
+
+#   define _ETSM_ASSERT_LESS_THAN_EQUALS(f,l,m,x,y) ___ETS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_LESS_THAN_EQUALS(f,l,m,x,y) ___TS_ASSERT_LESS_THAN_EQUALS(f,l,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_LESS_THAN_EQUALS(m,x,y) _ETSM_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,m,x,y)
+#   define TSM_ASSERT_LESS_THAN_EQUALS(m,x,y) _TSM_ASSERT_LESS_THAN_EQUALS(__FILE__,__LINE__,m,x,y)
+
+    // TS_ASSERT_PREDICATE
+#   define ___ETS_ASSERT_PREDICATE(f,l,p,x,m) \
+        CxxTest::doAssertPredicate( (f), (l), #p, p(), #x, (x), (m) )
+#   define ___TS_ASSERT_PREDICATE(f,l,p,x,m) \
+        { _TS_TRY { ___ETS_ASSERT_PREDICATE(f,l,p,x,m); } __TS_CATCH(f,l) }
+
+#   define _ETS_ASSERT_PREDICATE(f,l,p,x) ___ETS_ASSERT_PREDICATE(f,l,p,x,0)
+#   define _TS_ASSERT_PREDICATE(f,l,p,x) ___TS_ASSERT_PREDICATE(f,l,p,x,0)
+
+#   define ETS_ASSERT_PREDICATE(p,x) _ETS_ASSERT_PREDICATE(__FILE__,__LINE__,p,x)
+#   define TS_ASSERT_PREDICATE(p,x) _TS_ASSERT_PREDICATE(__FILE__,__LINE__,p,x)
+
+#   define _ETSM_ASSERT_PREDICATE(f,l,m,p,x) ___ETS_ASSERT_PREDICATE(f,l,p,x,TS_AS_STRING(m))
+#   define _TSM_ASSERT_PREDICATE(f,l,m,p,x) ___TS_ASSERT_PREDICATE(f,l,p,x,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_PREDICATE(m,p,x) _ETSM_ASSERT_PREDICATE(__FILE__,__LINE__,m,p,x)
+#   define TSM_ASSERT_PREDICATE(m,p,x) _TSM_ASSERT_PREDICATE(__FILE__,__LINE__,m,p,x)
+
+    // TS_ASSERT_RELATION
+#   define ___ETS_ASSERT_RELATION(f,l,r,x,y,m) \
+        CxxTest::doAssertRelation( (f), (l), #r, r(), #x, (x), #y, (y), (m) )
+#   define ___TS_ASSERT_RELATION(f,l,r,x,y,m) \
+        { _TS_TRY { ___ETS_ASSERT_RELATION(f,l,r,x,y,m); } __TS_CATCH(f,l) }
+
+#   define _ETS_ASSERT_RELATION(f,l,r,x,y) ___ETS_ASSERT_RELATION(f,l,r,x,y,0)
+#   define _TS_ASSERT_RELATION(f,l,r,x,y) ___TS_ASSERT_RELATION(f,l,r,x,y,0)
+
+#   define ETS_ASSERT_RELATION(r,x,y) _ETS_ASSERT_RELATION(__FILE__,__LINE__,r,x,y)
+#   define TS_ASSERT_RELATION(r,x,y) _TS_ASSERT_RELATION(__FILE__,__LINE__,r,x,y)
+
+#   define _ETSM_ASSERT_RELATION(f,l,m,r,x,y) ___ETS_ASSERT_RELATION(f,l,r,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_RELATION(f,l,m,r,x,y) ___TS_ASSERT_RELATION(f,l,r,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_RELATION(m,r,x,y) _ETSM_ASSERT_RELATION(__FILE__,__LINE__,m,r,x,y)
+#   define TSM_ASSERT_RELATION(m,r,x,y) _TSM_ASSERT_RELATION(__FILE__,__LINE__,m,r,x,y)
+
+    // TS_ASSERT_DELTA
+#   define ___ETS_ASSERT_DELTA(f,l,x,y,d,m) CxxTest::doAssertDelta( (f), (l), #x, (x), #y, (y), #d, (d), (m) )
+#   define ___TS_ASSERT_DELTA(f,l,x,y,d,m) { _TS_TRY { ___ETS_ASSERT_DELTA(f,l,x,y,d,m); } __TS_CATCH(f,l) }
+    
+#   define _ETS_ASSERT_DELTA(f,l,x,y,d) ___ETS_ASSERT_DELTA(f,l,x,y,d,0)
+#   define _TS_ASSERT_DELTA(f,l,x,y,d) ___TS_ASSERT_DELTA(f,l,x,y,d,0)
+
+#   define ETS_ASSERT_DELTA(x,y,d) _ETS_ASSERT_DELTA(__FILE__,__LINE__,x,y,d)
+#   define TS_ASSERT_DELTA(x,y,d) _TS_ASSERT_DELTA(__FILE__,__LINE__,x,y,d)
+
+#   define _ETSM_ASSERT_DELTA(f,l,m,x,y,d) ___ETS_ASSERT_DELTA(f,l,x,y,d,TS_AS_STRING(m))
+#   define _TSM_ASSERT_DELTA(f,l,m,x,y,d) ___TS_ASSERT_DELTA(f,l,x,y,d,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_DELTA(m,x,y,d) _ETSM_ASSERT_DELTA(__FILE__,__LINE__,m,x,y,d)
+#   define TSM_ASSERT_DELTA(m,x,y,d) _TSM_ASSERT_DELTA(__FILE__,__LINE__,m,x,y,d)
+
+    // TS_ASSERT_SAME_FILES
+#   define ___ETS_ASSERT_SAME_FILES(f,l,x,y,m) CxxTest::doAssertSameFiles( (f), (l), (x), (y), (m) )
+#   define ___TS_ASSERT_SAME_FILES(f,l,x,y,m) { _TS_TRY { ___ETS_ASSERT_SAME_FILES(f,l,x,y,m); } __TS_CATCH(f,l) }
+    
+#   define _ETS_ASSERT_SAME_FILES(f,l,x,y) ___ETS_ASSERT_SAME_FILES(f,l,x,y,0)
+#   define _TS_ASSERT_SAME_FILES(f,l,x,y) ___TS_ASSERT_SAME_FILES(f,l,x,y,0)
+
+#   define ETS_ASSERT_SAME_FILES(x,y) _ETS_ASSERT_SAME_FILES(__FILE__,__LINE__,x,y)
+#   define TS_ASSERT_SAME_FILES(x,y) _TS_ASSERT_SAME_FILES(__FILE__,__LINE__,x,y)
+
+#   define _ETSM_ASSERT_SAME_FILES(f,l,m,x,y) ___ETS_ASSERT_SAME_FILES(f,l,x,y,TS_AS_STRING(m))
+#   define _TSM_ASSERT_SAME_FILES(f,l,m,x,y) ___TS_ASSERT_SAME_FILES(f,l,x,y,TS_AS_STRING(m))
+
+#   define ETSM_ASSERT_SAME_FILES(m,x,y) _ETSM_ASSERT_SAME_FILES(__FILE__,__LINE__,m,x,y)
+#   define TSM_ASSERT_SAME_FILES(m,x,y) _TSM_ASSERT_SAME_FILES(__FILE__,__LINE__,m,x,y)
+
+
+    // TS_ASSERT_THROWS
+#   define ___TS_ASSERT_THROWS(f,l,e,t,m) ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,(void)0,m)
+
+#   define _TS_ASSERT_THROWS(f,l,e,t) ___TS_ASSERT_THROWS(f,l,e,t,0)
+#   define TS_ASSERT_THROWS(e,t) _TS_ASSERT_THROWS(__FILE__,__LINE__,e,t)
+
+#   define _TSM_ASSERT_THROWS(f,l,m,e,t) ___TS_ASSERT_THROWS(f,l,e,t,TS_AS_STRING(m))
+#   define TSM_ASSERT_THROWS(m,e,t) _TSM_ASSERT_THROWS(__FILE__,__LINE__,m,e,t)
+
+    // TS_ASSERT_THROWS_ASSERT
+#   define ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,m) { \
+            bool _ts_threw_expected = false, _ts_threw_else = false; \
+            _TS_TRY { e; } \
+            _TS_CATCH_TYPE( (t), { a; _ts_threw_expected = true; } ) \
+            _TS_CATCH_ABORT( { throw; } ) \
+            _TS_CATCH_STD( ex, { _ts_threw_expected = true; CxxTest::doFailAssertThrows((f), (l), #e, #t, true, (m), ex.what() ); } ) \
+            _TS_LAST_CATCH( { _ts_threw_else = true; } ) \
+            if ( !_ts_threw_expected ) { CxxTest::doFailAssertThrows( (f), (l), #e, #t, _ts_threw_else, (m), 0 ); } }
+
+#   define _TS_ASSERT_THROWS_ASSERT(f,l,e,t,a) ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,0)
+#   define TS_ASSERT_THROWS_ASSERT(e,t,a) _TS_ASSERT_THROWS_ASSERT(__FILE__,__LINE__,e,t,a)
+
+#   define _TSM_ASSERT_THROWS_ASSERT(f,l,m,e,t,a) ___TS_ASSERT_THROWS_ASSERT(f,l,e,t,a,TS_AS_STRING(m))
+#   define TSM_ASSERT_THROWS_ASSERT(m,e,t,a) _TSM_ASSERT_THROWS_ASSERT(__FILE__,__LINE__,m,e,t,a)
+
+    // TS_ASSERT_THROWS_EQUALS
+#   define TS_ASSERT_THROWS_EQUALS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_EQUALS(x,y))
+#   define TSM_ASSERT_THROWS_EQUALS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_EQUALS(m,x,y))
+
+    // TS_ASSERT_THROWS_DIFFERS
+#   define TS_ASSERT_THROWS_DIFFERS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_DIFFERS(x,y))
+#   define TSM_ASSERT_THROWS_DIFFERS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_DIFFERS(m,x,y))
+
+    // TS_ASSERT_THROWS_DELTA
+#   define TS_ASSERT_THROWS_DELTA(e,t,x,y,d) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_DELTA(x,y,d))
+#   define TSM_ASSERT_THROWS_DELTA(m,e,t,x,y,d) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_DELTA(m,x,y,d))
+
+    // TS_ASSERT_THROWS_SAME_DATA
+#   define TS_ASSERT_THROWS_SAME_DATA(e,t,x,y,s) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_SAME_DATA(x,y,s))
+#   define TSM_ASSERT_THROWS_SAME_DATA(m,e,t,x,y,s) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_SAME_DATA(m,x,y,s))
+
+    // TS_ASSERT_THROWS_LESS_THAN
+#   define TS_ASSERT_THROWS_LESS_THAN(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_LESS_THAN(x,y))
+#   define TSM_ASSERT_THROWS_LESS_THAN(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_LESS_THAN(m,x,y))
+
+    // TS_ASSERT_THROWS_LESS_THAN_EQUALS
+#   define TS_ASSERT_THROWS_LESS_THAN_EQUALS(e,t,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_LESS_THAN_EQUALS(x,y))
+#   define TSM_ASSERT_THROWS_LESS_THAN_EQUALS(m,e,t,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_LESS_THAN_EQUALS(m,x,y))
+
+    // TS_ASSERT_THROWS_PREDICATE
+#   define TS_ASSERT_THROWS_PREDICATE(e,t,p,v) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_PREDICATE(p,v))
+#   define TSM_ASSERT_THROWS_PREDICATE(m,e,t,p,v) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_PREDICATE(m,p,v))
+
+    // TS_ASSERT_THROWS_RELATION
+#   define TS_ASSERT_THROWS_RELATION(e,t,r,x,y) TS_ASSERT_THROWS_ASSERT(e,t,TS_ASSERT_RELATION(r,x,y))
+#   define TSM_ASSERT_THROWS_RELATION(m,e,t,r,x,y) TSM_ASSERT_THROWS_ASSERT(m,e,t,TSM_ASSERT_RELATION(m,r,x,y))
+
+    // TS_ASSERT_THROWS_ANYTHING
+#   define ___TS_ASSERT_THROWS_ANYTHING(f,l,e,m) { \
+            bool _ts_threw = false; \
+            _TS_TRY { e; } \
+            _TS_LAST_CATCH( { _ts_threw = true; } ) \
+            if ( !_ts_threw ) { CxxTest::doFailAssertThrows( (f), (l), #e, "...", false, (m) ); } }
+
+#   define _TS_ASSERT_THROWS_ANYTHING(f,l,e) ___TS_ASSERT_THROWS_ANYTHING(f,l,e,0)
+#   define TS_ASSERT_THROWS_ANYTHING(e) _TS_ASSERT_THROWS_ANYTHING(__FILE__, __LINE__, e)
+
+#   define _TSM_ASSERT_THROWS_ANYTHING(f,l,m,e) ___TS_ASSERT_THROWS_ANYTHING(f,l,e,TS_AS_STRING(m))
+#   define TSM_ASSERT_THROWS_ANYTHING(m,e) _TSM_ASSERT_THROWS_ANYTHING(__FILE__,__LINE__,m,e)
+
+    // TS_ASSERT_THROWS_NOTHING
+#   define ___TS_ASSERT_THROWS_NOTHING(f,l,e,m) { \
+            _TS_TRY { e; } \
+            _TS_CATCH_ABORT( { throw; } ) \
+            _TS_CATCH_STD(ex, { CxxTest::doFailAssertThrowsNot( (f), (l), #e, (m), ex.what() ); } ) \
+            _TS_LAST_CATCH( { CxxTest::doFailAssertThrowsNot( (f), (l), #e, (m), 0 ); } ) }
+
+#   define _TS_ASSERT_THROWS_NOTHING(f,l,e) ___TS_ASSERT_THROWS_NOTHING(f,l,e,0)
+#   define TS_ASSERT_THROWS_NOTHING(e) _TS_ASSERT_THROWS_NOTHING(__FILE__,__LINE__,e)
+
+#   define _TSM_ASSERT_THROWS_NOTHING(f,l,m,e) ___TS_ASSERT_THROWS_NOTHING(f,l,e,TS_AS_STRING(m))
+#   define TSM_ASSERT_THROWS_NOTHING(m,e) _TSM_ASSERT_THROWS_NOTHING(__FILE__,__LINE__,m,e)
+
+
+    //
+    // This takes care of "signed <-> unsigned" warnings
+    //
+#   define CXXTEST_COMPARISONS(CXXTEST_X, CXXTEST_Y, CXXTEST_T) \
+    template<> struct equals<CXXTEST_X,CXXTEST_Y> {                                           \
+        static bool test(CXXTEST_X x,CXXTEST_Y y) {                                           \
+            return equals<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };         \
+    template<> struct equals<CXXTEST_Y,CXXTEST_X> {                                           \
+        static bool test(CXXTEST_Y x,CXXTEST_X y) {                                           \
+            return equals<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };         \
+    template<> struct differs<CXXTEST_X,CXXTEST_Y> {                                          \
+        static bool test(CXXTEST_X x,CXXTEST_Y y) {                                           \
+            return differs<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };        \
+    template<> struct differs<CXXTEST_Y,CXXTEST_X> {                                          \
+        static bool test(CXXTEST_Y x,CXXTEST_X y) {                                           \
+            return differs<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };        \
+    template<> struct lessThan<CXXTEST_X,CXXTEST_Y> {                                         \
+        static bool test(CXXTEST_X x,CXXTEST_Y y) {                                           \
+            return lessThan<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };       \
+    template<> struct lessThan<CXXTEST_Y,CXXTEST_X> {                                         \
+        static bool test(CXXTEST_Y x,CXXTEST_X y) {                                           \
+            return lessThan<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } };       \
+    template<> struct lessThanEquals<CXXTEST_X,CXXTEST_Y> {                                   \
+        static bool test(CXXTEST_X x,CXXTEST_Y y) {                                           \
+            return lessThanEquals<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } }; \
+    template<> struct lessThanEquals<CXXTEST_Y,CXXTEST_X> {                                   \
+        static bool test(CXXTEST_Y x,CXXTEST_X y) {                                           \
+            return lessThanEquals<CXXTEST_T,CXXTEST_T>::test((CXXTEST_T)x,(CXXTEST_T)y); } }
+#if 0
+    // These specializations are not needed because delta makes use of
+    // CxxTest::lessThanEquals for the actual comparison
+    template<class D> struct delta<CXXTEST_X,CXXTEST_Y, D> {              \
+        static bool test(CXXTEST_X x,CXXTEST_Y y, D d) {              \
+            return delta<CXXTEST_T,CXXTEST_T,D>::test((CXXTEST_T)x,(CXXTEST_T)y, d); } }; \
+    template<class D> struct delta<CXXTEST_Y,CXXTEST_X, D> {              \
+        static bool test(CXXTEST_Y x,CXXTEST_X y, D d) {              \
+            return delta<CXXTEST_T,CXXTEST_T,D>::test((CXXTEST_T)x,(CXXTEST_T)y, d); } }
+#endif
+
+#   define CXXTEST_INTEGRAL(CXXTEST_T) \
+    CXXTEST_COMPARISONS( signed CXXTEST_T, unsigned CXXTEST_T, unsigned CXXTEST_T )
+
+    CXXTEST_INTEGRAL( char );
+    CXXTEST_INTEGRAL( short );
+    CXXTEST_INTEGRAL( int );
+    CXXTEST_INTEGRAL( long );
+#   ifdef _CXXTEST_LONGLONG
+    CXXTEST_INTEGRAL( _CXXTEST_LONGLONG );
+#   endif // _CXXTEST_LONGLONG
+
+#   define CXXTEST_SMALL_BIG(CXXTEST_SMALL, CXXTEST_BIG) \
+    CXXTEST_COMPARISONS( signed CXXTEST_SMALL, unsigned CXXTEST_BIG, unsigned CXXTEST_BIG ); \
+    CXXTEST_COMPARISONS( signed CXXTEST_BIG, unsigned CXXTEST_SMALL, unsigned CXXTEST_BIG )
+
+    CXXTEST_SMALL_BIG( char, short );
+    CXXTEST_SMALL_BIG( char, int );
+    CXXTEST_SMALL_BIG( short, int );
+    CXXTEST_SMALL_BIG( char, long );
+    CXXTEST_SMALL_BIG( short, long );
+    CXXTEST_SMALL_BIG( int, long );
+        
+#   ifdef _CXXTEST_LONGLONG
+    CXXTEST_SMALL_BIG( char, _CXXTEST_LONGLONG );
+    CXXTEST_SMALL_BIG( short, _CXXTEST_LONGLONG );
+    CXXTEST_SMALL_BIG( int, _CXXTEST_LONGLONG );
+    CXXTEST_SMALL_BIG( long, _CXXTEST_LONGLONG );
+#   endif // _CXXTEST_LONGLONG
+}
+
+#ifdef _CXXTEST_HAVE_STD
+#   include <cxxtest/StdTestSuite.h>
+#endif // _CXXTEST_HAVE_STD
+
+#endif // __cxxtest__TestSuite_h__
+
diff --git a/tools/cxxtest/cxxtest/TestTracker.cpp b/tools/cxxtest/cxxtest/TestTracker.cpp
new file mode 100644 (file)
index 0000000..bb051c4
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TestTracker_cpp__
+#define __cxxtest__TestTracker_cpp__
+
+#include <cxxtest/TestTracker.h>
+
+namespace CxxTest
+{
+    bool TestTracker::_created = false;
+    bool TestTracker::print_tracing = false;
+
+    TestTracker::TestTracker()
+    {
+        if ( !_created ) {
+            initialize();
+            setListener( 0 );
+            _created = true;
+        }
+    }
+
+    TestTracker::~TestTracker()
+    {
+    }
+    
+    TestTracker & TestTracker::tracker()
+    {
+        static TestTracker theTracker;
+        return theTracker;
+    }
+
+    void TestTracker::initialize()
+    {
+        _warnings = 0;
+        _failedTests = 0;
+        _testFailedAsserts = 0;
+        _suiteFailedTests = 0;
+        _failedSuites = 0;
+        _world = 0;
+        _suite = 0;
+        _test = 0;
+    }
+
+    const TestDescription *TestTracker::fixTest( const TestDescription *d ) const
+    {
+        return d ? d : &dummyTest();
+    }
+    
+    const SuiteDescription *TestTracker::fixSuite( const SuiteDescription *d ) const
+    {
+        return d ? d : &dummySuite();
+    }
+    
+    const WorldDescription *TestTracker::fixWorld( const WorldDescription *d ) const
+    {
+        return d ? d : &dummyWorld();
+    }
+    
+    const TestDescription &TestTracker::dummyTest() const
+    {
+        return dummySuite().testDescription(0);
+    }
+    
+    const SuiteDescription &TestTracker::dummySuite() const
+    {
+        return dummyWorld().suiteDescription(0);
+    }
+    
+    const WorldDescription &TestTracker::dummyWorld() const
+    {
+        return _dummyWorld;
+    }
+
+    void TestTracker::setListener( TestListener *l )
+    {
+        _l = l ? l : &_dummyListener;
+    }
+
+    void TestTracker::enterWorld( const WorldDescription &wd )
+    {
+        setWorld( &wd );
+        _warnings = _failedTests = _testFailedAsserts = _suiteFailedTests = _failedSuites = 0;
+        _l->enterWorld( wd );
+    }
+
+    void TestTracker::enterSuite( const SuiteDescription &sd )
+    {
+        setSuite( &sd );
+        _testFailedAsserts = _suiteFailedTests = 0;
+        _l->enterSuite(sd);
+    }
+        
+    void TestTracker::enterTest( const TestDescription &td )
+    {
+        setTest( &td );
+        _testFailedAsserts = false;
+        _l->enterTest(td);
+    }
+
+    void TestTracker::leaveTest( const TestDescription &td )
+    {
+        _l->leaveTest( td );
+        setTest( 0 );
+    }
+
+    void TestTracker::leaveSuite( const SuiteDescription &sd )
+    {
+        _l->leaveSuite( sd );
+        setSuite( 0 );
+    }
+
+    void TestTracker::leaveWorld( const WorldDescription &wd )
+    {
+        _l->leaveWorld( wd );
+        setWorld( 0 );
+    }
+
+    void TestTracker::trace( const char *file, int line, const char *expression )
+    {
+        _l->trace( file, line, expression );
+    }
+
+    void TestTracker::warning( const char *file, int line, const char *expression )
+    {
+        countWarning();
+        _l->warning( file, line, expression );
+    }
+
+    void TestTracker::failedTest( const char *file, int line, const char *expression )
+    {
+        countFailure();
+        _l->failedTest( file, line, expression );
+    }
+        
+    void TestTracker::failedAssert( const char *file, int line, const char *expression )
+    {
+        countFailure();
+        _l->failedAssert( file, line, expression );
+    }
+
+    void TestTracker::failedAssertEquals( const char *file, int line,
+                                          const char *xStr, const char *yStr,
+                                          const char *x, const char *y )
+    {
+        countFailure();
+        _l->failedAssertEquals( file, line, xStr, yStr, x, y );
+    }
+
+    void TestTracker::failedAssertSameData( const char *file, int line,
+                                            const char *xStr, const char *yStr,
+                                            const char *sizeStr, const void *x,
+                                            const void *y, unsigned size )
+    {
+        countFailure();
+        _l->failedAssertSameData( file, line, xStr, yStr, sizeStr, x, y, size );
+    }
+
+    void TestTracker::failedAssertDelta( const char *file, int line,
+                                         const char *xStr, const char *yStr, const char *dStr,
+                                         const char *x, const char *y, const char *d )
+    {
+        countFailure();
+        _l->failedAssertDelta( file, line, xStr, yStr, dStr, x, y, d );
+    }
+    
+    void TestTracker::failedAssertDiffers( const char *file, int line,
+                                           const char *xStr, const char *yStr,
+                                           const char *value )
+    {
+        countFailure();
+        _l->failedAssertDiffers( file, line, xStr, yStr, value );
+    }
+        
+    void TestTracker::failedAssertLessThan( const char *file, int line,
+                                            const char *xStr, const char *yStr,
+                                            const char *x, const char *y )
+    {
+        countFailure();
+        _l->failedAssertLessThan( file, line, xStr, yStr, x, y );
+    }
+
+    void TestTracker::failedAssertLessThanEquals( const char *file, int line,
+                                                  const char *xStr, const char *yStr,
+                                                  const char *x, const char *y )
+    {
+        countFailure();
+        _l->failedAssertLessThanEquals( file, line, xStr, yStr, x, y );
+    }
+
+    void TestTracker::failedAssertPredicate( const char *file, int line,
+                                             const char *predicate, const char *xStr, const char *x )
+    {
+        countFailure();
+        _l->failedAssertPredicate( file, line, predicate, xStr, x );
+    }
+        
+    void TestTracker::failedAssertRelation( const char *file, int line,
+                                            const char *relation, const char *xStr, const char *yStr,
+                                            const char *x, const char *y )
+    {
+        countFailure();
+        _l->failedAssertRelation( file, line, relation, xStr, yStr, x, y );
+    }
+        
+    void TestTracker::failedAssertThrows( const char *file, int line,
+                                          const char *expression, const char *type,
+                                          bool otherThrown )
+    {
+        countFailure();
+        _l->failedAssertThrows( file, line, expression, type, otherThrown );
+    }
+        
+    void TestTracker::failedAssertThrowsNot( const char *file, int line, const char *expression )
+    {
+        countFailure();
+        _l->failedAssertThrowsNot( file, line, expression );
+    }
+
+    void TestTracker::failedAssertSameFiles( const char *file, int line, const char *file1, const char* file2, const char* explanation )
+    {
+        countFailure();
+        _l->failedAssertSameFiles( file, line, file1, file2, explanation );
+    }
+
+    void TestTracker::setWorld( const WorldDescription *w )
+    {
+        _world = fixWorld( w );
+        setSuite( 0 );
+    }
+
+    void TestTracker::setSuite( const SuiteDescription *s )
+    {
+        _suite = fixSuite( s );
+        setTest( 0 );
+    }
+
+    void TestTracker::setTest( const TestDescription *t )
+    {
+        _test = fixTest( t );
+    }
+
+    void TestTracker::countWarning()
+    {
+        ++ _warnings;
+    }
+
+    void TestTracker::countFailure()
+    {
+        if ( ++ _testFailedAsserts == 1 ) {
+            ++ _failedTests;
+            if ( ++ _suiteFailedTests == 1 )
+                ++ _failedSuites;
+        }
+    }
+}
+
+#endif // __cxxtest__TestTracker_cpp__
+
diff --git a/tools/cxxtest/cxxtest/TestTracker.h b/tools/cxxtest/cxxtest/TestTracker.h
new file mode 100644 (file)
index 0000000..28de524
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__TestTracker_h__
+#define __cxxtest__TestTracker_h__
+
+//
+// The TestTracker tracks running tests
+// The actual work is done in CountingListenerProxy,
+// but this way avoids cyclic references TestListener<->CountingListenerProxy
+//
+
+#include <cxxtest/TestListener.h>
+#include <cxxtest/DummyDescriptions.h>
+
+namespace CxxTest
+{
+    class TestListener;
+    
+    class TestTracker : public TestListener
+    {
+    public:
+        virtual ~TestTracker();
+        
+        static TestTracker &tracker();
+        static bool print_tracing;
+
+        const TestDescription *fixTest( const TestDescription *d ) const;
+        const SuiteDescription *fixSuite( const SuiteDescription *d ) const;
+        const WorldDescription *fixWorld( const WorldDescription *d ) const;
+
+        const TestDescription &test() const { return *_test; }
+        const SuiteDescription &suite() const { return *_suite; }
+        const WorldDescription &world() const { return *_world; }
+        
+        bool testFailed() const { return (testFailedAsserts() > 0); }
+        bool suiteFailed() const { return (suiteFailedTests() > 0); }
+        bool worldFailed() const { return (failedSuites() > 0); }
+        
+        unsigned warnings() const { return _warnings; }
+        unsigned failedTests() const { return _failedTests; }
+        unsigned testFailedAsserts() const { return _testFailedAsserts; }
+        unsigned suiteFailedTests() const { return _suiteFailedTests; }
+        unsigned failedSuites() const { return _failedSuites; }
+
+        void enterWorld( const WorldDescription &wd );
+        void enterSuite( const SuiteDescription &sd );
+        void enterTest( const TestDescription &td );
+        void leaveTest( const TestDescription &td );
+        void leaveSuite( const SuiteDescription &sd );
+        void leaveWorld( const WorldDescription &wd );
+        void trace( const char *file, int line, const char *expression );
+        void warning( const char *file, int line, const char *expression );
+        void failedTest( const char *file, int line, const char *expression );
+        void failedAssert( const char *file, int line, const char *expression );
+        void failedAssertEquals( const char *file, int line,
+                                 const char *xStr, const char *yStr,
+                                 const char *x, const char *y );
+        void failedAssertSameData( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *sizeStr, const void *x,
+                                   const void *y, unsigned size );
+        void failedAssertDelta( const char *file, int line,
+                                const char *xStr, const char *yStr, const char *dStr,
+                                const char *x, const char *y, const char *d );
+        void failedAssertDiffers( const char *file, int line,
+                                  const char *xStr, const char *yStr,
+                                  const char *value );
+        void failedAssertLessThan( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *x, const char *y );
+        void failedAssertLessThanEquals( const char *file, int line,
+                                         const char *xStr, const char *yStr,
+                                         const char *x, const char *y );
+        void failedAssertPredicate( const char *file, int line,
+                                    const char *predicate, const char *xStr, const char *x );
+        void failedAssertRelation( const char *file, int line,
+                                   const char *relation, const char *xStr, const char *yStr,
+                                   const char *x, const char *y );
+        void failedAssertThrows( const char *file, int line,
+                                 const char *expression, const char *type,
+                                 bool otherThrown );
+        void failedAssertThrowsNot( const char *file, int line, const char *expression );
+        void failedAssertSameFiles( const char* file, int line, const char* file1, const char* file2, const char* explanation);
+        
+        void initialize();
+
+    private:
+        TestTracker( const TestTracker & );
+        TestTracker &operator=( const TestTracker & );
+
+        static bool _created;
+        TestListener _dummyListener;
+        DummyWorldDescription _dummyWorld;
+        unsigned _warnings, _failedTests, _testFailedAsserts, _suiteFailedTests, _failedSuites;
+        TestListener *_l;
+        const WorldDescription *_world;
+        const SuiteDescription *_suite;
+        const TestDescription *_test;
+
+        const TestDescription &dummyTest() const;
+        const SuiteDescription &dummySuite() const;
+        const WorldDescription &dummyWorld() const;
+        
+        void setWorld( const WorldDescription *w );
+        void setSuite( const SuiteDescription *s );
+        void setTest( const TestDescription *t );
+        void countWarning();
+        void countFailure();
+
+        friend class TestRunner;
+        
+        TestTracker();
+        void setListener( TestListener *l );
+    };
+
+    inline TestTracker &tracker() { return TestTracker::tracker(); }
+}
+
+#endif // __cxxtest__TestTracker_h__
+
diff --git a/tools/cxxtest/cxxtest/ValueTraits.cpp b/tools/cxxtest/cxxtest/ValueTraits.cpp
new file mode 100644 (file)
index 0000000..f19b684
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__ValueTraits_cpp__
+#define __cxxtest__ValueTraits_cpp__
+
+#include <cxxtest/ValueTraits.h>
+
+namespace CxxTest 
+{
+    //
+    // Non-inline functions from ValueTraits.h
+    //
+    
+    char digitToChar( unsigned digit )
+    {
+        if ( digit < 10 )
+            return (char)('0' + digit);
+        if ( digit <= 10 + 'Z' - 'A' )
+            return (char)('A' + digit - 10);
+        return '?';
+    }
+
+    const char *byteToHex( unsigned char byte )
+    {
+        static char asHex[3];
+        asHex[0] = digitToChar( byte >> 4 );
+        asHex[1] = digitToChar( byte & 0x0F );
+        asHex[2] = '\0';
+        return asHex;
+    }
+    
+    char *copyString( char *dst, const char *src )
+    {
+        while ( (*dst = *src) != '\0' ) {
+            ++ dst;
+            ++ src;
+        }
+        return dst;
+    }
+
+    bool stringsEqual( const char *s1, const char *s2 )
+    {
+        char c;
+        while ( (c = *s1++) == *s2++ )
+            if ( c == '\0' )
+                return true;
+        return false;
+    }
+
+    char *charToString( unsigned long c, char *s )
+    {
+        switch( c ) {
+        case '\\': return copyString( s, "\\\\" );
+        case '\"': return copyString( s, "\\\"" );
+        case '\'': return copyString( s, "\\\'" );
+        case '\0': return copyString( s, "\\0" );
+        case '\a': return copyString( s, "\\a" );
+        case '\b': return copyString( s, "\\b" );
+        case '\n': return copyString( s, "\\n" );
+        case '\r': return copyString( s, "\\r" );
+        case '\t': return copyString( s, "\\t" );
+        }
+        if ( c >= 32 && c <= 127 ) {
+            s[0] = (char)c;
+            s[1] = '\0';
+            return s + 1;
+        }
+        else {
+            s[0] = '\\';
+            s[1] = 'x';
+            if ( c < 0x10 ) {
+                s[2] = '0';
+                ++ s;
+            }
+            return numberToString( c, s + 2, 16UL );
+        }
+    }
+
+    char *charToString( char c, char *s )
+    {
+        return charToString( (unsigned long)(unsigned char)c, s );
+    }
+    
+    char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s )
+    {
+        bool truncate = (numBytes > maxBytes);
+        if ( truncate )
+            numBytes = maxBytes;
+        
+        s = copyString( s, "{ " );
+        for ( unsigned i = 0; i < numBytes; ++ i, ++ bytes )
+            s = copyString( copyString( s, byteToHex( *bytes ) ), " " );
+        if ( truncate )
+            s = copyString( s, "..." );
+        return copyString( s, " }" );
+    }
+
+#ifndef CXXTEST_USER_VALUE_TRAITS
+    unsigned ValueTraits<const double>::requiredDigitsOnLeft( double t )
+    {
+        unsigned digits = 1;
+        for ( t = (t < 0.0) ? -t : t; t > 1.0; t /= BASE )
+            ++ digits;
+        return digits;
+    }
+
+    char *ValueTraits<const double>::doNegative( double &t )
+    {
+        if ( t >= 0 )
+            return _asString;
+        _asString[0] = '-';
+        t = -t;
+        return _asString + 1;
+    }
+
+    void ValueTraits<const double>::hugeNumber( double t )
+    {
+        char *s = doNegative( t );
+        s = doubleToString( t, s, 0, 1 );
+        s = copyString( s, "." );
+        s = doubleToString( t, s, 1, DIGITS_ON_RIGHT );
+        s = copyString( s, "E" );
+        s = numberToString( requiredDigitsOnLeft( t ) - 1, s );
+    }
+        
+    void ValueTraits<const double>::normalNumber( double t )
+    {
+        char *s = doNegative( t );
+        s = doubleToString( t, s );
+        s = copyString( s, "." );
+        for ( unsigned i = 0; i < DIGITS_ON_RIGHT; ++ i )
+            s = numberToString( (unsigned)(t *= BASE) % BASE, s );
+    }
+
+    void ValueTraits<const double>::nonFiniteNumber( double t )
+    {
+        char *s = _asString;
+        if ( t != t )
+            s = copyString( s, "nan" );
+        //else if ( t == 1.0/0.0 )
+        else if ( t >= HUGE_VAL )
+            s = copyString( s, "-inf" );
+        else if ( t <= -HUGE_VAL )
+        //else if ( t == -1.0/0.0 )
+            s = copyString( s, "inf" );
+    }
+
+    char *ValueTraits<const double>::doubleToString( double t, char *s, unsigned skip, unsigned max )
+    {
+        return numberToString<double>( t, s, BASE, skip, max );
+    }
+#endif // !CXXTEST_USER_VALUE_TRAITS
+}
+
+#endif // __cxxtest__ValueTraits_cpp__
diff --git a/tools/cxxtest/cxxtest/ValueTraits.h b/tools/cxxtest/cxxtest/ValueTraits.h
new file mode 100644 (file)
index 0000000..9e24cd4
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__ValueTraits_h__
+#define __cxxtest__ValueTraits_h__
+
+//
+// ValueTraits are used by CxxTest to convert arbitrary
+// values used in TS_ASSERT_EQUALS() to a string representation.
+// 
+// This header file contains value traits for builtin integral types.
+// To declare value traits for new types you should instantiate the class
+// ValueTraits<YourClass>.
+//
+
+#include <cxxtest/Flags.h>
+
+#ifdef _CXXTEST_OLD_TEMPLATE_SYNTAX
+#   define CXXTEST_TEMPLATE_INSTANTIATION
+#else // !_CXXTEST_OLD_TEMPLATE_SYNTAX
+#   define CXXTEST_TEMPLATE_INSTANTIATION template<>
+#endif // _CXXTEST_OLD_TEMPLATE_SYNTAX
+
+#ifdef _CXXTEST_HAVE_STD
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+namespace CxxTest 
+{
+    //
+    // This is how we use the value traits
+    //
+#   define TS_AS_STRING(x) CxxTest::traits(x).asString()
+
+    //
+    // Char representation of a digit
+    //
+    char digitToChar( unsigned digit );
+
+    //
+    // Convert byte value to hex digits
+    // Returns pointer to internal buffer
+    //
+    const char *byteToHex( unsigned char byte );
+
+    //
+    // Convert byte values to string
+    // Returns one past the copied data
+    //
+    char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s );
+
+    //
+    // Copy a string.
+    // Returns one past the end of the destination string
+    // Remember -- we can't use the standard library!
+    //
+    char *copyString( char *dst, const char *src );
+
+    //
+    // Compare two strings.
+    // Remember -- we can't use the standard library!
+    //
+    bool stringsEqual( const char *s1, const char *s2 );
+
+    //
+    // Represent a character value as a string
+    // Returns one past the end of the string
+    // This will be the actual char if printable or '\xXXXX' otherwise
+    //
+    char *charToString( unsigned long c, char *s );
+
+    //
+    // Prevent problems with negative (signed char)s
+    //
+    char *charToString( char c, char *s );
+
+    //
+    // The default ValueTraits class dumps up to 8 bytes as hex values
+    //
+    template <class T>
+    class ValueTraits
+    {
+        enum { MAX_BYTES = 8 };
+        char _asString[sizeof("{ ") + sizeof("XX ") * MAX_BYTES + sizeof("... }")];
+        
+    public:
+        ValueTraits( const T &t ) { bytesToString( (const unsigned char *)&t, sizeof(T), MAX_BYTES, _asString ); }
+        const char *asString( void ) const { return _asString; }
+    };    
+
+    //
+    // traits( T t )
+    // Creates an object of type ValueTraits<T>
+    //
+    template <class T>
+    inline ValueTraits<T> traits( T t )
+    {
+        return ValueTraits<T>( t );
+    }
+
+    //
+    // You can duplicate the implementation of an existing ValueTraits
+    //
+#   define CXXTEST_COPY_TRAITS(CXXTEST_NEW_CLASS, CXXTEST_OLD_CLASS) \
+    CXXTEST_TEMPLATE_INSTANTIATION \
+    class ValueTraits< CXXTEST_NEW_CLASS > \
+    { \
+        ValueTraits< CXXTEST_OLD_CLASS > _old; \
+    public: \
+        ValueTraits( CXXTEST_NEW_CLASS n ) : _old( (CXXTEST_OLD_CLASS)n ) {} \
+        const char *asString( void ) const { return _old.asString(); } \
+    }
+
+    //
+    // Certain compilers need separate declarations for T and const T
+    //
+#   ifdef _CXXTEST_NO_COPY_CONST
+#       define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS)
+#   else // !_CXXTEST_NO_COPY_CONST
+#       define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS) CXXTEST_COPY_TRAITS(CXXTEST_CLASS, const CXXTEST_CLASS)
+#   endif // _CXXTEST_NO_COPY_CONST
+    
+    //
+    // Avoid compiler warnings about unsigned types always >= 0
+    //
+    template<class N> inline bool negative( N n ) { return n < 0; }
+    template<class N> inline N abs( N n ) { return negative(n) ? -n : n; }
+
+#   define CXXTEST_NON_NEGATIVE(Type) \
+    CXXTEST_TEMPLATE_INSTANTIATION \
+    inline bool negative<Type>( Type ) { return false; } \
+    CXXTEST_TEMPLATE_INSTANTIATION \
+    inline Type abs<Type>( Type value ) { return value; }
+
+    CXXTEST_NON_NEGATIVE( bool )
+    CXXTEST_NON_NEGATIVE( unsigned char )
+    CXXTEST_NON_NEGATIVE( unsigned short int )
+    CXXTEST_NON_NEGATIVE( unsigned int )
+    CXXTEST_NON_NEGATIVE( unsigned long int )
+#   ifdef _CXXTEST_LONGLONG
+    CXXTEST_NON_NEGATIVE( unsigned _CXXTEST_LONGLONG )
+#   endif // _CXXTEST_LONGLONG
+
+    //
+    // Represent (integral) number as a string
+    // Returns one past the end of the string
+    // Remember -- we can't use the standard library!
+    //
+    template<class N>
+    char *numberToString( N n, char *s,
+                          N base = 10,
+                          unsigned skipDigits = 0,
+                          unsigned maxDigits = (unsigned)-1 )
+    {
+        if ( negative(n) ) {
+            *s++ = '-';
+            n = abs(n);
+        }
+    
+        N digit = 1;
+        while ( digit <= (n / base) )
+            digit *= base;
+        N digitValue;
+        for ( ; digit >= 1 && skipDigits; n -= digit * digitValue, digit /= base, -- skipDigits )
+            digitValue = (unsigned)(n / digit);
+        for ( ; digit >= 1 && maxDigits; n -= digit * digitValue, digit /= base, -- maxDigits )
+            *s++ = digitToChar( (unsigned)(digitValue = (unsigned)(n / digit)) );
+
+        *s = '\0';
+        return s;
+    }
+
+    //
+    // All the specific ValueTraits follow.
+    // You can #define CXXTEST_USER_VALUE_TRAITS if you don't want them
+    //
+    
+#ifndef CXXTEST_USER_VALUE_TRAITS
+    //
+    // ValueTraits: const char * const &
+    // This is used for printing strings, as in TS_FAIL( "Message" )
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const char * const &>
+    {
+        ValueTraits &operator=( const ValueTraits & );
+        const char *_asString;
+        
+    public:
+        ValueTraits( const char * const &value ) : _asString( value ) {}
+        ValueTraits( const ValueTraits &other ) : _asString( other._asString ) {}
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_TRAITS( const char *, const char * const & );
+    CXXTEST_COPY_TRAITS( char *, const char * const & );
+
+    //
+    // ValueTraits: bool
+    //    
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const bool>
+    {
+        bool _value;
+        
+    public:
+        ValueTraits( const bool value ) : _value( value ) {}
+        const char *asString( void ) const { return _value ? "true" : "false"; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( bool );
+
+#   ifdef _CXXTEST_LONGLONG
+    //
+    // ValueTraits: signed long long
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const signed _CXXTEST_LONGLONG>
+    {
+        typedef _CXXTEST_LONGLONG T;
+        char _asString[2 + 3 * sizeof(T)];
+    public:
+        ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( signed _CXXTEST_LONGLONG );
+
+    //
+    // ValueTraits: unsigned long long
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const unsigned _CXXTEST_LONGLONG>
+    {
+        typedef unsigned _CXXTEST_LONGLONG T;
+        char _asString[1 + 3 * sizeof(T)];
+    public:
+        ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( unsigned _CXXTEST_LONGLONG );
+#   endif // _CXXTEST_LONGLONG
+
+    //
+    // ValueTraits: signed long
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const signed long int>
+    {
+        typedef signed long int T;
+        char _asString[2 + 3 * sizeof(T)];
+    public:
+        ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( signed long int );
+    
+    //
+    // ValueTraits: unsigned long
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const unsigned long int>
+    {
+        typedef unsigned long int T;
+        char _asString[1 + 3 * sizeof(T)];
+    public:
+        ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( unsigned long int );
+    
+    //
+    // All decimals are the same as the long version
+    //
+    
+    CXXTEST_COPY_TRAITS( const signed int, const signed long int );
+    CXXTEST_COPY_TRAITS( const unsigned int, const unsigned long int );
+    CXXTEST_COPY_TRAITS( const signed short int, const signed long int );
+    CXXTEST_COPY_TRAITS( const unsigned short int, const unsigned long int );
+    CXXTEST_COPY_TRAITS( const unsigned char, const unsigned long int );
+    
+    CXXTEST_COPY_CONST_TRAITS( signed int );
+    CXXTEST_COPY_CONST_TRAITS( unsigned int );
+    CXXTEST_COPY_CONST_TRAITS( signed short int );
+    CXXTEST_COPY_CONST_TRAITS( unsigned short int );
+    CXXTEST_COPY_CONST_TRAITS( unsigned char );
+
+    //
+    // ValueTraits: char
+    // Returns 'x' for printable chars, '\x??' for others
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const char>
+    {
+        char _asString[sizeof("'\\xXX'")];
+    public:
+        ValueTraits( char c ) { copyString( charToString( c, copyString( _asString, "'" ) ), "'" ); }
+        const char *asString( void ) const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( char );
+
+    //
+    // ValueTraits: signed char
+    // Same as char, some compilers need it
+    //
+    CXXTEST_COPY_TRAITS( const signed char, const char );
+    CXXTEST_COPY_CONST_TRAITS( signed char );
+
+    //
+    // ValueTraits: double
+    //
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const double>
+    {
+    public:
+        ValueTraits( double t ) 
+        {
+            //if ( ( t != t ) || ( t >= 1.0/0.0 ) || ( t == -1.0/0.0 ) )
+            if ( ( t != t ) || ( t >= HUGE_VAL ) || ( t == -HUGE_VAL ) )
+                nonFiniteNumber( t );
+            else if ( requiredDigitsOnLeft( t ) > MAX_DIGITS_ON_LEFT )
+                hugeNumber( t );
+            else
+                normalNumber( t );
+        }
+
+        const char *asString( void ) const { return _asString; }
+        
+    private:
+        enum { MAX_DIGITS_ON_LEFT = 24, DIGITS_ON_RIGHT = 4, BASE = 10 };
+        char _asString[1 + MAX_DIGITS_ON_LEFT + 1 + DIGITS_ON_RIGHT + 1];
+
+        static unsigned requiredDigitsOnLeft( double t );
+        char *doNegative( double &t );
+        void hugeNumber( double t );
+        void normalNumber( double t );
+        void nonFiniteNumber( double t );
+        char *doubleToString( double t, char *s, unsigned skip = 0, unsigned max = (unsigned)-1 );
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( double );
+
+    //
+    // ValueTraits: float
+    //
+    CXXTEST_COPY_TRAITS( const float, const double );
+    CXXTEST_COPY_CONST_TRAITS( float );
+#endif // !CXXTEST_USER_VALUE_TRAITS
+}
+
+#ifdef _CXXTEST_HAVE_STD
+#   include <cxxtest/StdValueTraits.h>
+#endif // _CXXTEST_HAVE_STD
+
+namespace dummy_enum_ns {}
+
+//
+// CXXTEST_ENUM_TRAITS
+//
+#define CXXTEST_ENUM_TRAITS( TYPE, VALUES ) \
+    namespace CxxTest \
+    { \
+        CXXTEST_TEMPLATE_INSTANTIATION \
+        class ValueTraits<TYPE> \
+        { \
+            TYPE _value; \
+            char _fallback[sizeof("(" #TYPE ")") + 3 * sizeof(TYPE)]; \
+        public: \
+            ValueTraits( TYPE value ) { \
+                _value = value; \
+                numberToString<unsigned long int>( _value, copyString( _fallback, "(" #TYPE ")" ) ); \
+            } \
+            const char *asString( void ) const \
+            { \
+                switch ( _value ) \
+                { \
+                    VALUES \
+                    default: return _fallback; \
+                } \
+            } \
+        }; \
+    } using namespace dummy_enum_ns
+
+#define CXXTEST_ENUM_MEMBER( MEMBER ) \
+    case MEMBER: return #MEMBER;
+
+#endif // __cxxtest__ValueTraits_h__
diff --git a/tools/cxxtest/cxxtest/Win32Gui.h b/tools/cxxtest/cxxtest/Win32Gui.h
new file mode 100644 (file)
index 0000000..ec47771
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__Win32Gui_h__
+#define __cxxtest__Win32Gui_h__
+
+//
+// The Win32Gui displays a simple progress bar using the Win32 API.
+//
+// It accepts the following command line options:
+//   -minimized    Start minimized, pop up on error
+//   -keep         Don't close the window at the end
+//   -title TITLE  Set the window caption
+//
+// If both -minimized and -keep are specified, GUI will only keep the
+// window if it's in focus.
+//
+// N.B. If you're wondering why this class doesn't use any standard
+// library or STL (<string> would have been nice) it's because it only
+// uses "straight" Win32 API.
+//
+
+#include <cxxtest/Gui.h>
+
+#include <windows.h>
+#include <commctrl.h>
+
+namespace CxxTest
+{
+    class Win32Gui : public GuiListener
+    {
+    public:
+        void enterGui( int &argc, char **argv )
+       {
+           parseCommandLine( argc, argv );
+       }
+       
+        void enterWorld( const WorldDescription &wd )
+        {
+            getTotalTests( wd );
+            _testsDone = 0;
+            startGuiThread();
+        }
+
+       void guiEnterSuite( const char *suiteName )
+       {
+           showSuiteName( suiteName );
+            reset( _suiteStart );
+       }
+
+        void guiEnterTest( const char *suiteName, const char *testName )
+        {
+            ++ _testsDone;
+            setTestCaption( suiteName, testName );
+            showTestName( testName );
+           showTestsDone();
+            progressBarMessage( PBM_STEPIT );
+            reset( _testStart );
+        }
+
+        void yellowBar()
+        {
+           setColor( 255, 255, 0 );
+            setIcon( IDI_WARNING );
+            getTotalTests();
+        }
+        
+        void redBar()
+        {
+            if ( _startMinimized )
+                showMainWindow( SW_SHOWNORMAL );
+           setColor( 255, 0, 0 );
+           setIcon( IDI_ERROR );
+            getTotalTests();
+        }
+
+        void leaveGui()
+        {
+            if ( keep() )
+            {
+                showSummary();
+                WaitForSingleObject( _gui, INFINITE );
+            }
+            DestroyWindow( _mainWindow );
+        }
+
+    private:
+        const char *_title;
+        bool _startMinimized, _keep;
+        HANDLE _gui;
+        WNDCLASSEX _windowClass;
+        HWND _mainWindow, _progressBar, _statusBar;
+        HANDLE _canStartTests;
+        unsigned _numTotalTests, _testsDone;
+        char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+        enum { 
+            STATUS_SUITE_NAME, STATUS_SUITE_TIME,
+            STATUS_TEST_NAME, STATUS_TEST_TIME,
+            STATUS_TESTS_DONE, STATUS_WORLD_TIME,
+            STATUS_TOTAL_PARTS 
+        };
+        int _statusWidths[STATUS_TOTAL_PARTS];
+        unsigned _statusOffsets[STATUS_TOTAL_PARTS];
+        unsigned _statusTotal;
+        char _statusTestsDone[sizeof("1000000000 of  (100%)") + WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+        DWORD _worldStart, _suiteStart, _testStart;
+        char _timeString[sizeof("00:00:00")];
+
+        void parseCommandLine( int argc, char **argv )
+        {
+            _startMinimized = _keep = false;
+           _title = argv[0];
+            
+            for ( int i = 1; i < argc; ++ i )
+            {
+                if ( !lstrcmpA( argv[i], "-minimized" ) )
+                    _startMinimized = true;
+                else if ( !lstrcmpA( argv[i], "-keep" ) )
+                    _keep = true;
+                else if ( !lstrcmpA( argv[i], "-title" ) && (i + 1 < argc) )
+                    _title = argv[++i];
+            }
+        }
+        
+        void getTotalTests()
+        {
+            getTotalTests( tracker().world() );
+        }
+
+        void getTotalTests( const WorldDescription &wd )
+        {
+            _numTotalTests = wd.numTotalTests();
+            wd.strTotalTests( _strTotalTests );
+        }
+
+        void startGuiThread()
+        {
+            _canStartTests = CreateEvent( NULL, TRUE, FALSE, NULL );
+                       DWORD threadId;
+            _gui = CreateThread( NULL, 0, &(Win32Gui::guiThread), (LPVOID)this, 0, &threadId );
+            WaitForSingleObject( _canStartTests, INFINITE );
+        }
+
+        static DWORD WINAPI guiThread( LPVOID parameter )
+        {
+            ((Win32Gui *)parameter)->gui();
+            return 0;
+        }
+
+        void gui()
+        {
+            registerWindowClass();
+            createMainWindow();
+            initCommonControls();
+            createProgressBar();
+            createStatusBar();
+            centerMainWindow();
+            showMainWindow();
+            startTimer();
+            startTests();
+
+            messageLoop();
+        }
+
+        void registerWindowClass()
+        {
+            _windowClass.cbSize = sizeof(_windowClass);
+            _windowClass.style = CS_HREDRAW | CS_VREDRAW;
+            _windowClass.lpfnWndProc = &(Win32Gui::windowProcedure);
+            _windowClass.cbClsExtra = 0;
+            _windowClass.cbWndExtra = sizeof(LONG);
+            _windowClass.hInstance = (HINSTANCE)NULL;
+            _windowClass.hIcon = (HICON)NULL;
+            _windowClass.hCursor = (HCURSOR)NULL;
+            _windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+            _windowClass.lpszMenuName = NULL;
+            _windowClass.lpszClassName = TEXT("CxxTest Window Class");
+            _windowClass.hIconSm = (HICON)NULL;
+
+            RegisterClassEx( &_windowClass );
+        }
+
+        void createMainWindow()
+        {
+            _mainWindow = createWindow( _windowClass.lpszClassName, WS_OVERLAPPEDWINDOW );
+        }
+
+        void initCommonControls()
+        {
+            HMODULE dll = LoadLibraryA( "comctl32.dll" );
+            if ( !dll )
+               return;
+               
+           typedef void (WINAPI *FUNC)( void );
+           FUNC func = (FUNC)GetProcAddress( dll, "InitCommonControls" );
+           if ( !func )
+                return;
+
+           func();
+        }
+
+        void createProgressBar()
+        {
+            _progressBar = createWindow( PROGRESS_CLASS, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, _mainWindow );
+
+#ifdef PBM_SETRANGE32
+            progressBarMessage( PBM_SETRANGE32, 0, _numTotalTests );
+#else // No PBM_SETRANGE32, use PBM_SETRANGE
+           progressBarMessage( PBM_SETRANGE, 0, MAKELPARAM( 0, (WORD)_numTotalTests ) );
+#endif // PBM_SETRANGE32
+            progressBarMessage( PBM_SETPOS, 0 );
+            progressBarMessage( PBM_SETSTEP, 1 );
+            greenBar();
+            UpdateWindow( _progressBar );
+        }
+
+        void createStatusBar()
+        {
+            _statusBar = createWindow( STATUSCLASSNAME, WS_CHILD | WS_VISIBLE, _mainWindow );
+            setRatios( 4, 1, 3, 1, 3, 1 );
+        }
+
+        void setRatios( unsigned suiteNameRatio, unsigned suiteTimeRatio,
+                        unsigned testNameRatio, unsigned testTimeRatio,
+                        unsigned testsDoneRatio, unsigned worldTimeRatio )
+        {
+            _statusTotal = 0;
+            _statusOffsets[STATUS_SUITE_NAME] = (_statusTotal += suiteNameRatio);
+            _statusOffsets[STATUS_SUITE_TIME] = (_statusTotal += suiteTimeRatio);
+            _statusOffsets[STATUS_TEST_NAME] = (_statusTotal += testNameRatio);
+            _statusOffsets[STATUS_TEST_TIME] = (_statusTotal += testTimeRatio);
+            _statusOffsets[STATUS_TESTS_DONE] = (_statusTotal += testsDoneRatio);
+            _statusOffsets[STATUS_WORLD_TIME] = (_statusTotal += worldTimeRatio);
+        }
+
+        HWND createWindow( LPCTSTR className, DWORD style, HWND parent = (HWND)NULL )
+        {
+            return CreateWindow( className, NULL, style, 0, 0, 0, 0, parent,
+                                 (HMENU)NULL, (HINSTANCE)NULL, (LPVOID)this );
+        }
+
+        void progressBarMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 )
+        {
+            SendMessage( _progressBar, message, wParam, lParam );
+        }
+
+        void centerMainWindow()
+        {
+            RECT screen;
+            getScreenArea( screen );
+
+            LONG screenWidth = screen.right - screen.left;
+            LONG screenHeight = screen.bottom - screen.top;
+
+            LONG xCenter = (screen.right + screen.left) / 2;
+            LONG yCenter = (screen.bottom + screen.top) / 2;
+
+            LONG windowWidth = (screenWidth * 4) / 5;
+            LONG windowHeight = screenHeight / 10;
+            LONG minimumHeight = 2 * (GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME ));
+            if ( windowHeight < minimumHeight )
+                windowHeight = minimumHeight;
+
+            SetWindowPos( _mainWindow, HWND_TOP,
+                          xCenter - (windowWidth / 2), yCenter - (windowHeight / 2),
+                          windowWidth, windowHeight, 0 );
+        }
+
+        void getScreenArea( RECT &area )
+        {
+            if ( !getScreenAreaWithoutTaskbar( area ) )
+                getWholeScreenArea( area );
+        }
+
+        bool getScreenAreaWithoutTaskbar( RECT &area )
+        {
+            return (SystemParametersInfo( SPI_GETWORKAREA, sizeof(RECT), &area, 0 ) != 0);
+        }
+
+        void getWholeScreenArea( RECT &area )
+        {
+            area.left = area.top = 0;
+            area.right = GetSystemMetrics( SM_CXSCREEN );
+            area.bottom = GetSystemMetrics( SM_CYSCREEN );
+        }
+
+        void showMainWindow()
+        {
+            showMainWindow( _startMinimized ? SW_MINIMIZE : SW_SHOWNORMAL );
+            UpdateWindow( _mainWindow );
+        }
+
+        void showMainWindow( int mode )
+        {
+            ShowWindow( _mainWindow, mode );
+        }
+
+        enum { TIMER_ID = 1, TIMER_DELAY = 1000 };
+
+        void startTimer()
+        {
+            reset( _worldStart );
+            reset( _suiteStart );
+            reset( _testStart );
+            SetTimer( _mainWindow, TIMER_ID, TIMER_DELAY, 0 );
+        }
+
+        void reset( DWORD &tick )
+        {
+            tick = GetTickCount();
+        }
+
+        void startTests()
+        {
+            SetEvent( _canStartTests );
+        }
+
+        void messageLoop()
+        {
+            MSG message;
+            while ( BOOL haveMessage = GetMessage( &message, NULL, 0, 0 ) )
+                if ( haveMessage != -1 )
+                    DispatchMessage( &message );
+        }
+
+        static LRESULT CALLBACK windowProcedure( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
+        {
+            if ( message == WM_CREATE )
+                setUp( window, (LPCREATESTRUCT)lParam );
+
+            Win32Gui *that = (Win32Gui *)GetWindowLong( window, GWL_USERDATA );
+            return that->handle( window, message, wParam, lParam );
+        }
+
+        static void setUp( HWND window, LPCREATESTRUCT create )
+        {
+            SetWindowLong( window, GWL_USERDATA, (LONG)create->lpCreateParams );
+        }
+
+        LRESULT handle( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
+        {
+            switch ( message )
+            {
+            case WM_SIZE: resizeControls(); break;
+
+            case WM_TIMER: updateTime(); break;
+
+            case WM_CLOSE:
+            case WM_DESTROY:
+            case WM_QUIT:
+                ExitProcess( tracker().failedTests() );
+
+            default: return DefWindowProc( window, message, wParam, lParam );
+            }
+            return 0;
+        }
+
+        void resizeControls()
+        {
+            RECT r;
+            GetClientRect( _mainWindow, &r );
+            LONG width = r.right - r.left;
+            LONG height = r.bottom - r.top;
+
+            GetClientRect( _statusBar, &r );
+            LONG statusHeight = r.bottom - r.top;
+            LONG resizeGripWidth = statusHeight;
+            LONG progressHeight = height - statusHeight;
+
+            SetWindowPos( _progressBar, HWND_TOP, 0, 0, width, progressHeight, 0 );
+            SetWindowPos( _statusBar, HWND_TOP, 0, progressHeight, width, statusHeight, 0 );
+            setStatusParts( width - resizeGripWidth );
+        }
+
+        void setStatusParts( LONG width )
+        {
+            for ( unsigned i = 0; i < STATUS_TOTAL_PARTS; ++ i )
+                _statusWidths[i] = (width * _statusOffsets[i]) / _statusTotal;
+
+            statusBarMessage( SB_SETPARTS, STATUS_TOTAL_PARTS, _statusWidths );
+        }
+
+        void statusBarMessage( UINT message, WPARAM wParam = 0, const void *lParam = 0 )
+        {
+            SendMessage( _statusBar, message, wParam, (LPARAM)lParam );
+        }
+
+        void greenBar()
+        {
+            setColor( 0, 255, 0 );
+            setIcon( IDI_INFORMATION );
+        }
+
+#ifdef PBM_SETBARCOLOR
+        void setColor( BYTE red, BYTE green, BYTE blue )
+        {
+            progressBarMessage( PBM_SETBARCOLOR, 0, RGB( red, green, blue ) );
+        }
+#else // !PBM_SETBARCOLOR
+        void setColor( BYTE, BYTE, BYTE ) 
+        {
+        }
+#endif // PBM_SETBARCOLOR
+
+        void setIcon( LPCTSTR icon )
+        {
+            SendMessage( _mainWindow, WM_SETICON, ICON_BIG, (LPARAM)loadStandardIcon( icon ) );
+        }
+
+        HICON loadStandardIcon( LPCTSTR icon )
+        {
+            return LoadIcon( (HINSTANCE)NULL, icon );
+        }
+
+        void setTestCaption( const char *suiteName, const char *testName )
+        {
+            setCaption( suiteName, "::", testName, "()" );
+        }
+
+        void setCaption( const char *a = "", const char *b = "", const char *c = "", const char *d = "" )
+        {
+            unsigned length = lstrlenA( _title ) + sizeof( " - " ) +
+                lstrlenA( a ) + lstrlenA( b ) + lstrlenA( c ) + lstrlenA( d );
+            char *name = allocate( length );
+            lstrcpyA( name, _title );
+            lstrcatA( name, " - " );
+            lstrcatA( name, a );
+            lstrcatA( name, b );
+            lstrcatA( name, c );
+            lstrcatA( name, d );
+            SetWindowTextA( _mainWindow, name );
+            deallocate( name );
+        }
+
+        void showSuiteName( const char *suiteName )
+        {
+            setStatusPart( STATUS_SUITE_NAME, suiteName );
+       }
+
+       void showTestName( const char *testName )
+       {
+            setStatusPart( STATUS_TEST_NAME, testName );
+       }
+
+       void showTestsDone()
+       {
+            wsprintfA( _statusTestsDone, "%u of %s (%u%%)",
+                       _testsDone, _strTotalTests,
+                       (_testsDone * 100) / _numTotalTests );
+            setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
+        }
+
+        void updateTime()
+        {
+            setStatusTime( STATUS_WORLD_TIME, _worldStart );
+            setStatusTime( STATUS_SUITE_TIME, _suiteStart );
+            setStatusTime( STATUS_TEST_TIME, _testStart );
+        }
+
+        void setStatusTime( unsigned part, DWORD start )
+        {
+            unsigned total = (GetTickCount() - start) / 1000;
+            unsigned hours = total / 3600;
+            unsigned minutes = (total / 60) % 60;
+            unsigned seconds = total % 60;
+
+            if ( hours )
+                wsprintfA( _timeString, "%u:%02u:%02u", hours, minutes, seconds );
+            else
+                wsprintfA( _timeString, "%02u:%02u", minutes, seconds );
+
+            setStatusPart( part, _timeString );
+        }
+
+        bool keep()
+        {
+            if ( !_keep )
+                return false;
+            if ( !_startMinimized )
+                return true;
+            return (_mainWindow == GetForegroundWindow());
+        }
+
+        void showSummary()
+        {
+            stopTimer();
+            setSummaryStatusBar();
+            setSummaryCaption();
+        }
+
+        void setStatusPart( unsigned part, const char *text )
+        {
+            statusBarMessage( SB_SETTEXTA, part, text );
+        }
+
+        void stopTimer()
+        {
+            KillTimer( _mainWindow, TIMER_ID );
+            setStatusTime( STATUS_WORLD_TIME, _worldStart );
+        }
+
+        void setSummaryStatusBar()
+        {
+            setRatios( 0, 0, 0, 0, 1, 1 );
+            resizeControls();
+        
+            const char *tests = (_numTotalTests == 1) ? "test" : "tests";
+            if ( tracker().failedTests() )
+                wsprintfA( _statusTestsDone, "Failed %u of %s %s",
+                          tracker().failedTests(), _strTotalTests, tests );
+            else
+                wsprintfA( _statusTestsDone, "%s %s passed", _strTotalTests, tests );
+
+            setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
+        }
+
+        void setSummaryCaption()
+        {
+            setCaption( _statusTestsDone );
+        }
+
+        char *allocate( unsigned length )
+        {
+            return (char *)HeapAlloc( GetProcessHeap(), 0, length );
+        }
+
+        void deallocate( char *data )
+        {
+            HeapFree( GetProcessHeap(), 0, data );
+        }
+    };
+}
+
+#endif // __cxxtest__Win32Gui_h__
diff --git a/tools/cxxtest/cxxtest/X11Gui.h b/tools/cxxtest/cxxtest/X11Gui.h
new file mode 100644 (file)
index 0000000..55e70ec
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__X11Gui_h__
+#define __cxxtest__X11Gui_h__
+
+//
+// X11Gui displays a simple progress bar using X11
+// 
+// It accepts the following command-line arguments:
+//  -title <title>              - Sets the application title
+//  -fn or -font <font>         - Sets the font
+//  -bg or -background <color>  - Sets the background color (default=Grey)
+//  -fg or -foreground <color>  - Sets the text color (default=Black)
+//  -green/-yellow/-red <color> - Sets the colors of the bar
+//
+
+#include <cxxtest/Gui.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace CxxTest
+{
+    class X11Gui : public GuiListener
+    {
+    public:
+        void enterGui( int &argc, char **argv )
+        {
+            parseCommandLine( argc, argv );
+        }
+        
+        void enterWorld( const WorldDescription &wd )
+        {
+            openDisplay();
+            if ( _display ) {
+                createColors();
+                createWindow();
+                createGc();
+                createFont();
+                centerWindow();
+                initializeEvents();
+                initializeBar( wd );
+                processEvents();
+            }
+        }
+        
+        void guiEnterTest( const char *suiteName, const char *testName )
+        {
+            if ( _display ) {
+                ++ _testsDone;
+                setWindowName( suiteName, testName );
+                redraw();
+            }
+        }
+        
+        void yellowBar()
+        {
+            if ( _display ) {
+                _barColor = getColor( _yellowName );
+                getTotalTests();
+                processEvents();
+            }
+        }
+
+        void redBar()
+        {
+            if ( _display ) {
+                _barColor = getColor( _redName );
+                getTotalTests();
+                processEvents();
+            }
+        }
+
+        void leaveGui()
+        {
+            if ( _display ) {
+                freeFontInfo();
+                destroyGc();
+                destroyWindow();
+                closeDisplay();
+            }
+        }
+
+    private:
+        const char *_programName;
+        Display *_display;
+        Window _window;
+        unsigned _numTotalTests, _testsDone;
+        char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+        const char *_foregroundName, *_backgroundName;
+        const char *_greenName, *_yellowName, *_redName;
+        unsigned long _foreground, _background, _barColor;
+        int _width, _height;
+        GC _gc;
+        const char *_fontName;
+        XID _fontId;
+        XFontStruct *_fontInfo;
+        int _textHeight, _textDescent;
+        long _eventMask;
+        Colormap _colormap;
+
+        void parseCommandLine( int &argc, char **argv )
+        {
+            _programName = argv[0];
+
+            _fontName = 0;
+            _foregroundName = "Black";
+            _backgroundName = "Grey";
+            _greenName = "Green";
+            _yellowName = "Yellow";
+            _redName = "Red";
+
+            for ( int i = 1; i + 1 < argc; ++ i ) {
+                if ( !strcmp( argv[i], "-title" ) )
+                    _programName = argv[++ i];
+                else if ( !strcmp( argv[i], "-fn" ) || !strcmp( argv[i], "-font" ) )
+                    _fontName = argv[++ i];
+                else if ( !strcmp( argv[i], "-fg" ) || !strcmp( argv[i], "-foreground" ) )
+                    _foregroundName = argv[++ i];
+                else if ( !strcmp( argv[i], "-bg" ) || !strcmp( argv[i], "-background" ) )
+                    _backgroundName = argv[++ i];
+                else if ( !strcmp( argv[i], "-green" ) )
+                    _greenName = argv[++ i];
+                else if ( !strcmp( argv[i], "-yellow" ) )
+                    _yellowName = argv[++ i];
+                else if ( !strcmp( argv[i], "-red" ) )
+                    _redName = argv[++ i];
+            }
+        }
+
+        void openDisplay()
+        {
+            _display = XOpenDisplay( NULL );
+        }
+
+        void createColors()
+        {
+            _colormap = DefaultColormap( _display, 0 );
+            _foreground = getColor( _foregroundName );
+            _background = getColor( _backgroundName );
+        }
+
+        unsigned long getColor( const char *colorName )
+        {
+            XColor color;
+            XParseColor( _display, _colormap, colorName, &color );
+            XAllocColor( _display, _colormap, &color );
+            return color.pixel;
+        }
+        
+        void createWindow()
+        {
+            _window = XCreateSimpleWindow( _display, RootWindow( _display, 0 ), 0, 0, 1, 1, 0, 0, _background );
+        }
+
+        void createGc()
+        {
+            _gc = XCreateGC( _display, _window, 0, 0 );
+        }
+
+        void createFont()
+        {
+            if ( !loadFont() )
+                useDefaultFont();
+            getFontInfo();
+            _textHeight = _fontInfo->ascent + _fontInfo->descent;
+            _textDescent = _fontInfo->descent;
+        }
+
+        bool loadFont()
+        {
+            if ( !_fontName )
+                return false;
+            _fontId = XLoadFont( _display, _fontName );
+            return (XSetFont( _display, _gc, _fontId ) == Success);
+        }
+
+        void useDefaultFont()
+        {
+            _fontId = XGContextFromGC( _gc );
+        }
+
+        void getFontInfo()
+        {
+            _fontInfo = XQueryFont( _display, _fontId );
+        }
+
+        void freeFontInfo()
+        {
+            XFreeFontInfo( NULL, _fontInfo, 1 );
+        }
+
+        void initializeEvents()
+        {
+            _eventMask = ExposureMask;
+            XSelectInput( _display, _window, _eventMask );
+        }
+
+        void initializeBar( const WorldDescription &wd )
+        {
+            getTotalTests( wd );
+            _testsDone = 0;
+            _barColor = getColor( _greenName );
+        }
+
+        void getTotalTests()
+        {
+            getTotalTests( tracker().world() );
+        }
+
+        void getTotalTests( const WorldDescription &wd )
+        {
+            _numTotalTests = wd.numTotalTests();
+            wd.strTotalTests( _strTotalTests );
+        }
+
+        void centerWindow()
+        {
+            XMapWindow( _display, _window );
+            
+            Screen *screen = XDefaultScreenOfDisplay( _display );
+            int screenWidth = WidthOfScreen( screen );
+            int screenHeight = HeightOfScreen( screen );
+            int xCenter = screenWidth / 2;
+            int yCenter = screenHeight / 2;
+
+            _width = (screenWidth * 4) / 5;
+            _height = screenHeight / 14;
+            
+            XMoveResizeWindow( _display, _window, xCenter - (_width / 2), yCenter - (_height / 2), _width, _height );
+        }
+
+        void processEvents()
+        {
+            redraw();
+            
+            XEvent event;
+            while( XCheckMaskEvent( _display, _eventMask, &event ) )
+                redraw();
+        }
+
+        void setWindowName( const char *suiteName, const char *testName )
+        {
+            unsigned length = strlen( _programName ) + strlen( suiteName ) + strlen( testName ) + sizeof( " - ::()" );
+            char *name = (char *)malloc( length );
+            sprintf( name, "%s - %s::%s()", _programName, suiteName, testName );
+            XSetStandardProperties( _display, _window, name, 0, 0, 0, 0, 0 );
+            free( name );
+        }
+
+        void redraw()
+        {
+            getWindowSize();
+            drawSolidBar();
+            drawDividers();
+            drawPercentage();
+            flush();
+        }
+
+        void getWindowSize()
+        {
+            XWindowAttributes attributes;
+            XGetWindowAttributes( _display, _window, &attributes );
+            _width = attributes.width;
+            _height = attributes.height;
+        }
+
+        void drawSolidBar()
+        {
+            unsigned barWidth = (_width * _testsDone) / _numTotalTests;
+
+            XSetForeground( _display, _gc, _barColor );
+            XFillRectangle( _display, _window, _gc, 0, 0, barWidth, _height );
+
+            XSetForeground( _display, _gc, _background );
+            XFillRectangle( _display, _window, _gc, barWidth, 0, _width + 1 - barWidth, _height );
+        }
+
+        void drawDividers()
+        {
+            if(_width / _numTotalTests < 5)
+                return;
+            for ( unsigned i = 1; i < _testsDone; ++ i ) {
+                int x = (_width * i) / _numTotalTests;
+                XDrawLine( _display, _window, _gc, x, 0, x, _height);
+            }
+        }
+
+        void drawPercentage()
+        {
+            XSetForeground( _display, _gc, _foreground );
+            
+            char str[sizeof("1000000000 of ") + sizeof(_strTotalTests) + sizeof(" (100%)")];
+            sprintf( str, "%u of %s (%u%%)", _testsDone, _strTotalTests, (_testsDone * 100) / _numTotalTests );
+            unsigned len = strlen( str );
+
+            int textWidth = XTextWidth( _fontInfo, str, len );
+
+            XDrawString( _display, _window, _gc,
+                         (_width - textWidth) / 2, ((_height + _textHeight) / 2) - _textDescent,
+                         str, len );
+        }
+
+        void flush()
+        {
+            XFlush( _display );
+        }
+
+        void destroyGc()
+        {
+            XFreeGC( _display, _gc );
+        }
+
+        void destroyWindow()
+        {
+            XDestroyWindow( _display, _window );
+        }
+
+        void closeDisplay()
+        {
+            XCloseDisplay( _display );
+        }
+    };
+}
+
+#endif //__cxxtest__X11Gui_h__
diff --git a/tools/cxxtest/cxxtest/XUnitPrinter.h b/tools/cxxtest/cxxtest/XUnitPrinter.h
new file mode 100644 (file)
index 0000000..116c37d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __CXXTEST__XUNIT_PRINTER_H
+#define __CXXTEST__XUNIT_PRINTER_H
+
+//
+// XUnitPrinter combines an ErrorPrinter with an XML formatter.
+//
+
+#include <cxxtest/TeeListener.h>
+#include <cxxtest/ErrorPrinter.h>
+#include <cxxtest/XmlPrinter.h>
+
+namespace CxxTest
+{
+    class XUnitPrinter : public TeeListener
+    {
+    public:
+
+        XmlPrinter xml_printer;
+        ErrorPrinter error_printer;
+        
+        XUnitPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout) )
+            : xml_printer(o)
+        {
+            setFirst( error_printer );
+            setSecond( xml_printer );
+        }
+
+        int run()
+        {
+            TestRunner::runAllTests( *this );
+            return tracker().failedTests();
+        }
+    };
+}
+
+#endif //__CXXTEST__XUNIT_PRINTER_H
+
diff --git a/tools/cxxtest/cxxtest/XmlFormatter.h b/tools/cxxtest/cxxtest/XmlFormatter.h
new file mode 100644 (file)
index 0000000..126b513
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+// Licensed under the LGPL, see http://www.gnu.org/licenses/lgpl.html
+
+#ifndef __CXXTEST__XMLFORMATTER_H
+#define __CXXTEST__XMLFORMATTER_H
+
+//
+// The XmlFormatter is a TestListener that
+// prints reports of the errors to an output
+// stream in the form of an XML document.
+//
+
+// The following definitions are used if stack trace support is enabled,
+// to give the traces an easily-parsable XML format.  If stack tracing is
+// not enabled, then these definitions will be ignored.
+#define CXXTEST_STACK_TRACE_ESCAPE_AS_XML
+#define CXXTEST_STACK_TRACE_NO_ESCAPE_FILELINE_AFFIXES
+
+#define CXXTEST_STACK_TRACE_INITIAL_PREFIX "<stack-frame function=\""
+#define CXXTEST_STACK_TRACE_INITIAL_SUFFIX "\"/>\n"
+#define CXXTEST_STACK_TRACE_OTHER_PREFIX CXXTEST_STACK_TRACE_INITIAL_PREFIX
+#define CXXTEST_STACK_TRACE_OTHER_SUFFIX CXXTEST_STACK_TRACE_INITIAL_SUFFIX
+#define CXXTEST_STACK_TRACE_ELLIDED_MESSAGE ""
+#define CXXTEST_STACK_TRACE_FILELINE_PREFIX "\" location=\""
+#define CXXTEST_STACK_TRACE_FILELINE_SUFFIX ""
+
+
+#include <cxxtest/TestRunner.h>
+#include <cxxtest/TestListener.h>
+#include <cxxtest/TestTracker.h>
+#include <cxxtest/ValueTraits.h>
+#include <cxxtest/ErrorFormatter.h>
+#include <cxxtest/StdHeaders.h>
+#include <iostream>
+#include <sstream>
+#include <cstring>
+#include <cstdio>
+
+namespace CxxTest
+{
+    class TeeOutputStreams
+    {
+    private:
+       class teebuffer : public std::basic_streambuf<char>
+       {
+          typedef std::basic_streambuf<char> streambuf_t;
+       public:
+          teebuffer(streambuf_t * buf1, streambuf_t * buf2)
+             : buffer1(buf1), buffer2(buf2)
+          {}
+
+          virtual int overflow(int c)
+          {
+             if (c == EOF)
+                return !EOF;
+             else
+             {
+                int const ans1 = buffer1->sputc(c);
+                int const ans2 = buffer2->sputc(c);
+                return ans1 == EOF || ans2 == EOF ? EOF : c;
+             }
+          }
+
+          virtual int sync()
+          {
+             int ans1 = buffer1->pubsync();
+             int ans2 = buffer2->pubsync();
+             return ans1 || ans2 ? -1 : 0;
+          }
+
+          streambuf_t * buffer1;
+          streambuf_t * buffer2;
+       };
+
+    public:
+       TeeOutputStreams(std::ostream& _cout, std::ostream& _cerr)
+          : out(),
+            err(),
+            orig_cout(_cout),
+            orig_cerr(_cerr),
+            tee_out(out.rdbuf(), _cout.rdbuf()),
+            tee_err(err.rdbuf(), _cerr.rdbuf())
+       {
+          orig_cout.rdbuf(&tee_out);
+          orig_cerr.rdbuf(&tee_err);
+       }
+
+       ~TeeOutputStreams()
+       {
+          orig_cout.rdbuf(tee_out.buffer2);
+          orig_cerr.rdbuf(tee_err.buffer2);
+       }
+
+       std::stringstream out;
+       std::stringstream err;
+
+    private:
+       std::ostream&  orig_cout;
+       std::ostream&  orig_cerr;
+       teebuffer      tee_out;
+       teebuffer      tee_err;
+    };
+
+    class ElementInfo
+    {
+    public:
+        std::string name;
+        std::stringstream value;
+        std::map<std::string,std::string> attribute;
+
+        ElementInfo()
+           : name(), value(), attribute()
+        {}
+
+        ElementInfo(const ElementInfo& rhs)
+           : name(rhs.name), value(rhs.value.str()), attribute(rhs.attribute)
+        {}
+
+        ElementInfo& operator=(const ElementInfo& rhs)
+        {
+           name = rhs.name;
+           value.str(rhs.value.str());
+           attribute = rhs.attribute;
+           return *this;
+        }
+
+        template <class Type>
+        void add(const std::string& name_, Type& value_)
+            {
+            std::ostringstream os;
+            os << value_;
+            attribute[name_] = os.str();
+            }
+
+        void write(OutputStream& os) {
+            os << "        <" << name.c_str() << " ";
+            std::map<std::string,std::string>::iterator curr=attribute.begin();
+            std::map<std::string,std::string>::iterator end =attribute.end();
+            while (curr != end) {
+              os << curr->first.c_str() 
+                 << "=\"" << curr->second.c_str() << "\" ";
+              curr++;
+              }
+            if (value.str().empty()) {
+                os << "/>";
+            }
+            else {
+                os << ">" << escape(value.str()).c_str() 
+                   << "</" << name.c_str() << ">";
+            }
+            os.endl(os);
+            }
+
+        std::string escape(const std::string& str)
+        {
+            std::string escStr = "";
+            for(size_t i = 0; i < str.length(); i++)
+            {
+                switch(str[i])
+                {
+                    case '"':  escStr += "&quot;"; break;
+                    case '\'': escStr += "&apos;"; break;
+                    case '<':  escStr += "&lt;"; break;
+                    case '>':  escStr += "&gt;"; break;
+                    case '&':  escStr += "&amp;"; break;
+                    default:   escStr += str[i]; break;
+                }
+            }
+            return escStr;
+        }
+
+    };
+
+    class TestCaseInfo
+    {
+    public:
+
+        TestCaseInfo() : fail(false), error(false), runtime(0.0) {}
+        std::string className;
+        std::string testName;
+        std::string line;
+        bool fail;
+        bool error;
+        double runtime;
+        std::list<ElementInfo> elements;
+        typedef std::list<ElementInfo>::iterator element_t;
+        std::string world;
+
+        element_t add_element(const std::string& name)
+            {
+            element_t elt = elements.insert(elements.end(), ElementInfo());
+            elt->name=name;
+            return elt;
+            }
+
+        element_t update_element(const std::string& name)
+            {
+            element_t elt = elements.begin();
+            while ( elt != elements.end() )
+               {
+               if ( elt->name == name )
+                  return elt;
+               }
+            return add_element(name);
+            }
+
+        void write( OutputStream &o )
+            {
+            o << "    <testcase classname=\"" << className.c_str() 
+              << "\" name=\"" << testName.c_str() 
+              << "\" line=\"" << line.c_str() << "\"";
+            bool elts=false;
+            element_t curr = elements.begin();
+            element_t end  = elements.end();
+            while (curr != end) {
+              if (!elts) {
+                 o << ">";
+                 o.endl(o);
+                 elts=true;
+              }
+              curr->write(o);
+              curr++;
+              }
+            if (elts)
+               o << "    </testcase>";
+            else
+               o << " />";
+            o.endl(o);
+            }
+
+    };
+
+    class XmlFormatter : public TestListener
+    {
+        public:
+        XmlFormatter( OutputStream *o, OutputStream *ostr, std::ostringstream *os) 
+           : _o(o), _ostr(ostr), _os(os), stream_redirect(NULL) 
+        {}
+
+        std::list<TestCaseInfo> info;
+        std::list<TestCaseInfo>::iterator testcase;
+        typedef std::list<ElementInfo>::iterator element_t;
+        std::string classname;
+        int ntests;
+        int nfail;
+        int nerror;
+        double totaltime;
+
+        int run()
+        {
+            TestRunner::runAllTests( *this );
+            return tracker().failedTests();
+        }
+
+        void enterWorld( const WorldDescription & /*desc*/ )
+        {
+            ntests=0;
+            nfail=0;
+            nerror=0;
+            totaltime=0;
+        }
+
+        static void totalTests( OutputStream &o )
+        {
+            char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
+            const WorldDescription &wd = tracker().world();
+            o << wd.strTotalTests( s ) 
+              << (wd.numTotalTests() == 1 ? " test" : " tests");
+        }
+
+        void enterSuite( const SuiteDescription& desc )
+        {
+                classname = desc.suiteName();
+                // replace "::" namespace with java-style "."
+                size_t pos = 0;
+                while( (pos = classname.find("::", pos)) !=
+                       CXXTEST_STD(string::npos) )
+                   classname.replace(pos, 2, ".");
+                while ( ! classname.empty() && classname[0] == '.' )
+                   classname.erase(0,1);
+
+                //CXXTEST_STD(cout) << "HERE " << desc.file() << " " 
+                //                  << classname << CXXTEST_STD(endl);
+
+                //classname=desc.suiteName();
+                //(*_o) << "file=\"" << desc.file() << "\" ";
+                //(*_o) << "line=\"" << desc.line() << "\"";
+                //_o->flush();
+        }
+
+        void leaveSuite( const SuiteDescription & )
+        {
+                std::list<TestCaseInfo>::iterator curr = info.begin();
+                std::list<TestCaseInfo>::iterator end  = info.end();
+                while (curr != end) {
+                    if (curr->fail) nfail++;
+                    if (curr->error) nerror++;
+                    totaltime += curr->runtime;
+                    ntests++;
+                    curr++;
+                }
+                curr = info.begin();
+                end  = info.end();
+                while (curr != end) {
+                  (*curr).write(*_ostr);
+                  curr++;
+                }
+                info.clear();
+        }
+
+        void enterTest( const TestDescription & desc )
+        {
+                testcase = info.insert(info.end(),TestCaseInfo());
+                testcase->testName = desc.testName();
+                testcase->className = classname;
+                std::ostringstream os;
+                os << desc.line();
+                testcase->line = os.str();
+
+           if ( stream_redirect )
+              CXXTEST_STD(cerr) << "ERROR: The stream_redirect != NULL" 
+                                << CXXTEST_STD(endl);
+
+           stream_redirect = 
+              new TeeOutputStreams(CXXTEST_STD(cout), CXXTEST_STD(cerr));
+        }
+
+        void leaveTest( const TestDescription & )
+        {
+           if ( stream_redirect != NULL )
+           {
+                std::string out = stream_redirect->out.str();
+                if ( ! out.empty() )
+                {
+                   // silently ignore the '.'
+                   if ( out[0] != '.' || out.size() > 1 )
+                      testcase->add_element("system-out")->value << out;
+                }
+                if ( ! stream_redirect->err.str().empty() )
+                   testcase->add_element("system-err")->value << stream_redirect->err.str();
+
+                delete stream_redirect;
+                stream_redirect = NULL;
+           }
+        }
+
+        void leaveWorld( const WorldDescription& desc )
+        {
+                std::ostringstream os;
+                os << totaltime;
+                (*_o) << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl;
+                (*_o) << "<testsuite name=\"" << desc.worldName() << "\" ";
+                (*_o) << " tests=\"" << ntests 
+                      << "\" errors=\"" << nerror 
+                      << "\" failures=\"" << nfail 
+                      << "\" time=\"" << os.str().c_str() << "\" >";
+                _o->endl(*_o);
+                (*_o) << _os->str().c_str();
+                _os->clear();
+                (*_o) << "</testsuite>" << endl;
+                _o->flush();
+        }
+
+        void trace( const char* /*file*/, int line, const char *expression )
+        {
+            element_t elt = testcase->add_element("trace");
+            elt->add("line",line);
+            elt->value << expression;
+        }
+
+        void warning( const char* /*file*/, int line, const char *expression )
+        {
+            element_t elt = testcase->add_element("warning");
+            elt->add("line",line);
+            elt->value << expression;
+        }
+
+        void failedTest( const char* file, int line, const char* expression )
+        {
+            testFailure( file, line, "failure") << "Test failed: " << expression;
+        }
+
+        void failedAssert( const char *file, int line, const char *expression )
+        {
+            testFailure( file, line, "failedAssert" ) 
+               << "Assertion failed: " << expression;
+        }
+
+        void failedAssertEquals( const char *file, int line,
+                                 const char* xStr, const char* yStr,
+                                 const char *x, const char *y )
+        {
+            testFailure( file, line, "failedAssertEquals" )
+               << "Error: Expected ("
+               << xStr << " == " << yStr << "), found ("
+               << x << " != " << y << ")";
+        }
+
+        void failedAssertSameData( const char *file, int line,
+                                   const char *xStr, const char *yStr, const char *sizeStr,
+                                   const void* /*x*/, const void* /*y*/, unsigned size )
+        {
+            testFailure( file, line, "failedAssertSameData")
+               << "Error: Expected " << sizeStr 
+               << " (" << size << ")  bytes to be equal at ("
+               << xStr << ") and (" << yStr << "), found";
+        }
+
+        void failedAssertSameFiles( const char *file, int line,
+                                   const char *, const char *,
+                                   const char* explanation
+                                   )
+        {
+            testFailure( file, line, "failedAssertSameFiles" )
+               << "Error: " << explanation;
+        }
+
+        void failedAssertDelta( const char *file, int line,
+                                const char *xStr, const char *yStr, const char *dStr,
+                                const char *x, const char *y, const char *d )
+        {
+            testFailure( file, line, "failedAssertDelta" )
+               << "Error: Expected (" 
+               << xStr << " == " << yStr << ") up to " << dStr 
+               << " (" << d << "), found (" 
+               << x << " != " << y << ")";
+        }
+
+        void failedAssertDiffers( const char *file, int line,
+                                  const char *xStr, const char *yStr,
+                                  const char *value )
+        {
+            testFailure( file, line, "failedAssertDiffers" )
+               << "Error: Expected (" 
+               << xStr << " != " << yStr << "), found (" 
+               << value << ")";
+        }
+
+        void failedAssertLessThan( const char *file, int line,
+                                   const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            testFailure( file, line, "failedAssertLessThan" )
+               << "Error: Expected (" <<
+               xStr << " < " << yStr << "), found (" <<
+               x << " >= " << y << ")";
+        }
+
+        void failedAssertLessThanEquals( const char *file, int line,
+                                         const char *xStr, const char *yStr,
+                                         const char *x, const char *y )
+        {
+            testFailure( file, line, "failedAssertLessThanEquals" )
+               << "Error: Expected (" <<
+               xStr << " <= " << yStr << "), found (" <<
+               x << " > " << y << ")";
+        }
+
+        void failedAssertRelation( const char *file, int line,
+                                   const char *relation, const char *xStr, const char *yStr,
+                                   const char *x, const char *y )
+        {
+            testFailure( file, line, "failedAssertRelation" )
+               << "Error: Expected " << relation << "( " <<
+               xStr << ", " << yStr << " ), found !" << relation 
+               << "( " << x << ", " << y << " )";
+        }
+
+        void failedAssertPredicate( const char *file, int line,
+                                    const char *predicate, const char *xStr, const char *x )
+        {
+            testFailure( file, line, "failedAssertPredicate" )
+               << "Error: Expected " << predicate << "( " <<
+               xStr << " ), found !" << predicate << "( " << x << " )";
+        }
+
+        void failedAssertThrows( const char *file, int line,
+                                 const char *expression, const char *type,
+                                 bool otherThrown )
+        {
+            testFailure( file, line, "failedAssertThrows" )
+               << "Error: Expected (" << expression << ") to throw ("  <<
+               type << ") but it " 
+               << (otherThrown ? "threw something else" : "didn't throw");
+        }
+
+        void failedAssertThrowsNot( const char *file, int line, const char *expression )
+        {
+            testFailure( file, line, "failedAssertThrowsNot" )
+               << "Error: Expected (" << expression 
+               << ") not to throw, but it did";
+        }
+
+    protected:
+
+        OutputStream *outputStream() const
+        {
+            return _o;
+        }
+
+        OutputStream *outputFileStream() const
+        {
+            return _ostr;
+        }
+
+    private:
+        XmlFormatter( const XmlFormatter & );
+        XmlFormatter &operator=( const XmlFormatter & );
+
+       std::stringstream& testFailure( const char* file, int line, const char *failureType)
+        {
+            testcase->fail=true;
+            element_t elt = testcase->update_element("failure");
+            if ( elt->value.str().empty() )
+            {
+               elt->add("type",failureType);
+               elt->add("line",line);
+               elt->add("file",file);
+            }
+            else
+               elt->value << CXXTEST_STD(endl);
+            return elt->value;
+            //failedTest(file,line,message.c_str());
+        }
+
+#if 0
+        void attributeBinary( const char* name, const void *value, unsigned size )
+        {
+            (*_o) << name;
+            (*_o) << "=\"";
+            dump(value, size);
+            (*_o) << "\" ";
+        }
+
+        void dump( const void *buffer, unsigned size )
+        {
+            if (!buffer) return;
+
+            unsigned dumpSize = size;
+            if ( maxDumpSize() && dumpSize > maxDumpSize() )
+                dumpSize = maxDumpSize();
+
+            const unsigned char *p = (const unsigned char *)buffer;
+            for ( unsigned i = 0; i < dumpSize; ++ i )
+                (*_o) << byteToHex( *p++ ) << " ";
+            if ( dumpSize < size )
+                (*_o) << "... ";
+        }
+#endif
+
+        static void endl( OutputStream &o )
+        {
+            OutputStream::endl( o );
+        }
+
+        OutputStream *_o;
+        OutputStream *_ostr;
+        std::ostringstream *_os;
+
+        TeeOutputStreams *stream_redirect;
+    };
+}
+
+#endif // __CXXTEST__XMLFORMATTER_H
+
diff --git a/tools/cxxtest/cxxtest/XmlPrinter.h b/tools/cxxtest/cxxtest/XmlPrinter.h
new file mode 100644 (file)
index 0000000..bee8010
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__XmlPrinter_h__
+#define __cxxtest__XmlPrinter_h__
+
+//
+// The XmlPrinter is a simple TestListener that
+// prints JUnit style xml to the output stream
+//
+
+
+#include <cxxtest/Flags.h>
+
+#ifndef _CXXTEST_HAVE_STD
+#   define _CXXTEST_HAVE_STD
+#endif // _CXXTEST_HAVE_STD
+
+#include <cxxtest/XmlFormatter.h>
+#include <cxxtest/StdValueTraits.h>
+
+#include <sstream>
+#ifdef _CXXTEST_OLD_STD
+#   include <iostream.h>
+#else // !_CXXTEST_OLD_STD
+#   include <iostream>
+#endif // _CXXTEST_OLD_STD
+
+namespace CxxTest
+{
+    class XmlPrinter : public XmlFormatter
+    {
+    public:
+        XmlPrinter( CXXTEST_STD(ostream) &o = CXXTEST_STD(cout), const char* /*preLine*/ = ":", const char* /*postLine*/ = "" ) :
+            XmlFormatter( new Adapter(o), new Adapter(ostr), &ostr ) {}
+
+        virtual ~XmlPrinter() 
+        {
+            delete outputStream(); 
+            delete outputFileStream(); 
+        }
+
+    private:
+
+        std::ostringstream ostr;
+
+        class Adapter : public OutputStream
+        {
+            CXXTEST_STD(ostream) &_o;
+        public:
+            Adapter( CXXTEST_STD(ostream) &o ) : _o(o) {}
+            void flush() { _o.flush(); }
+            OutputStream &operator<<( const char *s ) { _o << s; return *this; }
+            OutputStream &operator<<( Manipulator m ) { return OutputStream::operator<<( m ); }
+            OutputStream &operator<<( unsigned i )
+            {
+                char s[1 + 3 * sizeof(unsigned)];
+                numberToString( i, s );
+                _o << s;
+                return *this;
+            }
+        };
+    };
+}
+
+#endif // __cxxtest__XmlPrinter_h__
+
diff --git a/tools/cxxtest/cxxtest/YesNoRunner.h b/tools/cxxtest/cxxtest/YesNoRunner.h
new file mode 100644 (file)
index 0000000..daec671
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+-------------------------------------------------------------------------
+ CxxTest: A lightweight C++ unit testing library.
+ Copyright (c) 2008 Sandia Corporation.
+ This software is distributed under the LGPL License v2.1
+ For more information, see the COPYING file in the top CxxTest directory.
+ Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ the U.S. Government retains certain rights in this software.
+-------------------------------------------------------------------------
+*/
+
+#ifndef __cxxtest__YesNoRunner_h__
+#define __cxxtest__YesNoRunner_h__
+
+//
+// The YesNoRunner is a simple TestListener that
+// just returns true iff all tests passed.
+//
+
+#include <cxxtest/TestRunner.h>
+#include <cxxtest/TestListener.h>
+
+namespace CxxTest 
+{
+    class YesNoRunner : public TestListener
+    {
+    public:
+        YesNoRunner()
+        {
+        }
+        
+        int run()
+        {
+            TestRunner::runAllTests( *this );
+            return tracker().failedTests();
+        }
+    };
+}
+
+#endif // __cxxtest__YesNoRunner_h__
diff --git a/tools/cxxtest/doc/Makefile b/tools/cxxtest/doc/Makefile
new file mode 100644 (file)
index 0000000..ca0b7da
--- /dev/null
@@ -0,0 +1,22 @@
+
+html: guide.txt anchors outputs
+       asciidoc -v -b html -d article -n -a toc guide.txt
+
+pdf: guide.txt anchors outputs
+       a2x -a toc -L -d article -f pdf -v --dblatex-opts "-P latex.output.revhistory=0 -P doc.collab.show=1 -P toc.section.depth=2" guide.txt
+
+epub: guide.txt anchors outputs
+       export XML_CATALOG_FILES=export XML_CATALOG_FILES="catalog.xml"; a2x -L -f epub -d article --verbose --xsltproc-opts "--stringparam toc.section.depth 2 --stringparam generate.section.toc.level 1" guide.txt
+
+all: html pdf epub
+
+anchors:
+       python include_anchors.py guide.txt 
+
+outputs:
+       ../bin/cxxtestgen -h > examples/cxxtestgen.out
+
+clean:
+       - \rm -f guide.xml
+       - \rm -f examples/.*.py examples/.*.h examples/.*.cpp examples/.*.sh examples/runner examples/TEST*.xml examples/parsetab.py examples/*.orig examples/runner.cpp
+
diff --git a/tools/cxxtest/doc/README.txt b/tools/cxxtest/doc/README.txt
new file mode 100644 (file)
index 0000000..921019d
--- /dev/null
@@ -0,0 +1,34 @@
+This directory supports the creation of the CxxTest User Guide using
+asciidoc and a2x commands.
+
+HTML
+
+The command
+
+    make html
+
+creates the guide.html file.
+
+
+PDF
+
+The command
+
+    make pdf
+
+creates the guide.tex file, which generates the guide.pdf file using
+dblatex.
+
+
+
+EPUB
+
+The command
+
+    make epub
+
+creates the file make.epub.  Note that the `catalog.xml` file is
+used, which configures asciidoc to use the docbook XML data in the
+`epub` directory.  This is a bit of a hack.  It apparently works
+around a limitation of the MacPorts installation of asciidoc.
+
diff --git a/tools/cxxtest/doc/catalog.xml b/tools/cxxtest/doc/catalog.xml
new file mode 100644 (file)
index 0000000..fde98a7
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
+    "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+<nextCatalog catalog="/opt/local/etc/xml/catalog" />
+<nextCatalog catalog="/opt/local/share/xsl/docbook-xsl/catalog.xml" />
+</catalog>
diff --git a/tools/cxxtest/doc/epub/README b/tools/cxxtest/doc/epub/README
new file mode 100644 (file)
index 0000000..5e2587a
--- /dev/null
@@ -0,0 +1,88 @@
+----------------------------------------------------------------------
+              README file for the DocBook XSL Stylesheets
+----------------------------------------------------------------------
+
+These are XSL stylesheets for transforming DocBook XML document
+instances into .epub format.
+
+.epub is an open standard of the The International Digital Publishing Forum (IDPF), 
+a the trade and standards association for the digital publishing industry. 
+
+An alpha-quality reference implementation (dbtoepub) for a DocBook to .epub 
+converter (written in Ruby) is available under bin/. 
+
+From http://idpf.org
+  What is EPUB, .epub, OPS/OCF & OEB?
+
+  ".epub" is the file extension of an XML format for reflowable digital 
+  books and publications.  ".epub" is composed of three open standards, 
+  the Open Publication Structure (OPS), Open Packaging Format (OPF) and 
+  Open Container Format (OCF), produced by the IDPF. "EPUB" allows 
+  publishers to produce and send a single digital publication file 
+  through distribution and offers consumers interoperability between 
+  software/hardware for unencrypted reflowable digital books and other 
+  publications. The Open eBook Publication Structure or "OEB", 
+  originally produced in 1999, is the precursor to OPS. 
+
+----------------------------------------------------------------------
+.epub Constraints 
+----------------------------------------------------------------------
+
+.epub does not support all of the image formats that DocBook supports.
+When an image is available in an accepted format, it will be used. The
+accepted @formats are: 'GIF','GIF87a','GIF89a','JPEG','JPG','PNG','SVG'
+A mime-type for the image will be guessed from the file extension, 
+which may not work if your file extensions are non-standard.
+
+Non-supported elements:
+  * <mediaobjectco> 
+  * <inlinegraphic>, <graphic>, <textdata>, <imagedata> with text/XML 
+    @filerefs
+  * <olink>
+  * <cmdsynopsis> in lists (generic XHTML rendering inability)
+  * <footnote><para><programlisting> (just make your programlistings 
+    siblings, rather than descendents of paras)
+
+----------------------------------------------------------------------
+dbtoepub Reference Implementation
+----------------------------------------------------------------------
+
+An alpha-quality DocBook to .epub conversion program, dbtoepub, is provided
+in bin/dbtoepub. 
+
+This tool requires:
+ - 'xsltproc' in your PATH
+ - 'zip' in your PATH
+ - Ruby 1.8.4+
+
+Windows compatibility has not been extensively tested; bug reports encouraged.
+[See http://www.zlatkovic.com/libxml.en.html and http://unxutils.sourceforge.net/]
+
+$ dbtoepub --help
+  Usage: dbtoepub [OPTIONS] [DocBook Files]
+
+  dbtoepub converts DocBook <book> and <article>s into to .epub files.
+
+  .epub is defined by the IDPF at www.idpf.org and is made up of 3 standards:
+  - Open Publication Structure (OPS)
+  - Open Packaging Format (OPF) 
+  - Open Container Format (OCF)
+
+  Specific options:
+      -d, --debug                      Show debugging output.
+      -h, --help                       Display usage info
+      -v, --verbose                    Make output verbose
+
+
+----------------------------------------------------------------------
+Validation
+----------------------------------------------------------------------
+
+The epubcheck project provides limited validation for .epub documents. 
+See http://code.google.com/p/epubcheck/ for details.
+
+----------------------------------------------------------------------
+Copyright information
+----------------------------------------------------------------------
+See the accompanying file named COPYING.
+
diff --git a/tools/cxxtest/doc/epub/bin/dbtoepub b/tools/cxxtest/doc/epub/bin/dbtoepub
new file mode 100644 (file)
index 0000000..9976f81
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/env ruby
+# This program converts DocBook documents into .epub files.
+# 
+# Usage: dbtoepub [OPTIONS] [DocBook Files]
+#
+# .epub is defined by the IDPF at www.idpf.org and is made up of 3 standards:
+# - Open Publication Structure (OPS)
+# - Open Packaging Format (OPF) 
+# - Open Container Format (OCF)
+#
+# Specific options:
+#     -c, --css [FILE]                 Use FILE for CSS on generated XHTML.
+#     -d, --debug                      Show debugging output.
+#     -f, --font [OTF FILE]            Embed OTF FILE in .epub.
+#     -h, --help                       Display usage info.
+#     -s, --stylesheet [XSL FILE]      Use XSL FILE as a customization
+#                                        layer (imports epub/docbook.xsl).
+#     -v, --verbose                    Make output verbose.
+
+lib = File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
+$LOAD_PATH.unshift(lib) if File.exist?(lib)
+
+require 'fileutils'
+require 'optparse'
+require 'tmpdir'
+
+require 'docbook'
+
+verbose = false
+debug = false
+css_file = nil
+otf_files = []
+customization_layer = nil
+output_file = nil
+
+#$DEBUG=true
+
+# Set up the OptionParser
+opts = OptionParser.new
+opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [DocBook Files]
+
+#{File.basename($0)} converts DocBook <book> and <article>s into to .epub files.
+
+.epub is defined by the IDPF at www.idpf.org and is made up of 3 standards:
+- Open Publication Structure (OPS)
+- Open Packaging Format (OPF) 
+- Open Container Format (OCF)
+
+Specific options:"
+opts.on("-c", "--css [FILE]", "Use FILE for CSS on generated XHTML.") {|f| css_file = f}
+opts.on("-d", "--debug", "Show debugging output.") {debug = true; verbose = true}
+opts.on("-f", "--font [OTF FILE]", "Embed OTF FILE in .epub.") {|f| otf_files << f}
+opts.on("-h", "--help", "Display usage info.") {puts opts.to_s; exit 0}
+opts.on("-o", "--output [OUTPUT FILE]", "Output ePub file as OUTPUT FILE.") {|f| output_file = f}
+opts.on("-s", "--stylesheet [XSL FILE]", "Use XSL FILE as a customization layer (imports epub/docbook.xsl).") {|f| customization_layer = f}
+opts.on("-v", "--verbose", "Make output verbose.") {verbose = true}
+
+db_files = opts.parse(ARGV)
+if db_files.size == 0
+  puts opts.to_s
+  exit 0
+end
+
+db_files.each {|docbook_file|
+  dir = File.expand_path(File.join(Dir.tmpdir, ".epubtmp#{Time.now.to_f.to_s}"))
+  FileUtils.mkdir_p(dir)
+  e = DocBook::Epub.new(docbook_file, dir, css_file, customization_layer, otf_files)
+
+  if output_file
+    epub_file = output_file
+  else  
+    epub_file = File.basename(docbook_file, ".xml") + ".epub"
+  end  
+  puts "Rendering DocBook file #{docbook_file} to #{epub_file}" if verbose
+  e.render_to_file(epub_file)
+}  
diff --git a/tools/cxxtest/doc/epub/bin/lib/docbook.rb b/tools/cxxtest/doc/epub/bin/lib/docbook.rb
new file mode 100644 (file)
index 0000000..14110d6
--- /dev/null
@@ -0,0 +1,227 @@
+require 'fileutils'
+require 'rexml/parsers/pullparser'
+
+module DocBook
+
+  class Epub
+    CHECKER = "epubcheck"
+    STYLESHEET = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', "docbook.xsl"))
+    CALLOUT_PATH = File.join('images', 'callouts')
+    CALLOUT_FULL_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', CALLOUT_PATH))
+    CALLOUT_LIMIT = 15
+    CALLOUT_EXT = ".png"
+    XSLT_PROCESSOR = "xsltproc"
+    OUTPUT_DIR = ".epubtmp#{Time.now.to_f.to_s}"
+    MIMETYPE = "application/epub+zip"
+    META_DIR = "META-INF"
+    OEBPS_DIR = "OEBPS"
+    ZIPPER = "zip"
+
+    attr_reader :output_dir
+
+    def initialize(docbook_file, output_dir=OUTPUT_DIR, css_file=nil, customization_layer=nil, embedded_fonts=[])
+      @docbook_file = docbook_file
+      @output_dir = output_dir
+      @meta_dir  = File.join(@output_dir, META_DIR)
+      @oebps_dir = File.join(@output_dir, OEBPS_DIR)
+      @css_file = css_file ? File.expand_path(css_file) : css_file
+      @embedded_fonts = embedded_fonts
+      @to_delete = []
+      
+      if customization_layer
+        @stylesheet = File.expand_path(customization_layer)
+      else
+        @stylesheet = STYLESHEET
+      end
+
+      unless File.exist?(@docbook_file)
+        raise ArgumentError.new("File #{@docbook_file} does not exist")
+      end
+    end
+
+    def render_to_file(output_file, verbose=false)
+      render_to_epub(output_file, verbose)
+      bundle_epub(output_file, verbose)
+      cleanup_files(@to_delete)
+    end
+
+    def self.invalid?(file)
+      # Obnoxiously, we can't just check for a non-zero output...
+      cmd = %Q(#{CHECKER} "#{file}")
+      output = `#{cmd} 2>&1`
+
+      if $?.to_i == 0
+        return false
+      else  
+        STDERR.puts output if $DEBUG
+        return output
+      end  
+    end
+
+    private
+    def render_to_epub(output_file, verbose)  
+      @collapsed_docbook_file = collapse_docbook()
+
+      chunk_quietly =   "--stringparam chunk.quietly " + (verbose ? '0' : '1')
+      callout_path =    "--stringparam callout.graphics.path #{CALLOUT_PATH}/"
+      callout_limit =   "--stringparam callout.graphics.number.limit #{CALLOUT_LIMIT}"
+      callout_ext =     "--stringparam callout.graphics.extension #{CALLOUT_EXT}" 
+      html_stylesheet = "--stringparam html.stylesheet #{File.basename(@css_file)}" if @css_file
+      base =            "--stringparam base.dir #{OEBPS_DIR}/" 
+      unless @embedded_fonts.empty? 
+        embedded_fonts = @embedded_fonts.map {|f| File.basename(f)}.join(',')
+        font =            "--stringparam epub.embedded.fonts \"#{embedded_fonts}\"" 
+      end  
+      meta =            "--stringparam epub.metainf.dir #{META_DIR}/" 
+      oebps =           "--stringparam epub.oebps.dir #{OEBPS_DIR}/" 
+      options = [chunk_quietly, 
+                 callout_path, 
+                 callout_limit, 
+                 callout_ext, 
+                 base, 
+                 font, 
+                 meta, 
+                 oebps, 
+                 html_stylesheet,
+                ].join(" ")
+      # Double-quote stylesheet & file to help Windows cmd.exe
+      db2epub_cmd = %Q(cd "#{@output_dir}" && #{XSLT_PROCESSOR} #{options} "#{@stylesheet}" "#{@collapsed_docbook_file}")
+      STDERR.puts db2epub_cmd if $DEBUG
+      success = system(db2epub_cmd)
+      raise "Could not render as .epub to #{output_file} (#{db2epub_cmd})" unless success
+      @to_delete << Dir["#{@meta_dir}/*"]
+      @to_delete << Dir["#{@oebps_dir}/*"]
+    end  
+
+    def bundle_epub(output_file, verbose)  
+
+      quiet = verbose ? "" : "-q"
+      mimetype_filename = write_mimetype()
+      meta   = File.basename(@meta_dir)
+      oebps  = File.basename(@oebps_dir)
+      images = copy_images()
+      csses  = copy_csses()
+      fonts  = copy_fonts()
+      callouts = copy_callouts()
+      # zip -X -r ../book.epub mimetype META-INF OEBPS
+      # Double-quote stylesheet & file to help Windows cmd.exe
+      zip_cmd = %Q(cd "#{@output_dir}" &&  #{ZIPPER} #{quiet} -X -r  "#{File.expand_path(output_file)}" "#{mimetype_filename}" "#{meta}" "#{oebps}")
+      puts zip_cmd if $DEBUG
+      success = system(zip_cmd)
+      raise "Could not bundle into .epub file to #{output_file}" unless success
+    end
+
+    # Input must be collapsed because REXML couldn't find figures in files that
+    # were XIncluded or added by ENTITY
+    #   http://sourceforge.net/tracker/?func=detail&aid=2750442&group_id=21935&atid=373747
+    def collapse_docbook
+      # Double-quote stylesheet & file to help Windows cmd.exe
+      collapsed_file = File.join(File.expand_path(File.dirname(@docbook_file)), 
+                                 '.collapsed.' + File.basename(@docbook_file))
+      entity_collapse_command = %Q(xmllint --loaddtd --noent -o "#{collapsed_file}" "#{@docbook_file}")
+      entity_success = system(entity_collapse_command)
+      raise "Could not collapse named entites in #{@docbook_file}" unless entity_success
+
+      xinclude_collapse_command = %Q(xmllint --xinclude -o "#{collapsed_file}" "#{collapsed_file}")
+      xinclude_success = system(xinclude_collapse_command)
+      raise "Could not collapse XIncludes in #{@docbook_file}" unless xinclude_success
+
+      @to_delete << collapsed_file
+      return collapsed_file
+    end  
+
+    def copy_callouts
+      new_callout_images = []
+      if has_callouts?
+        calloutglob = "#{CALLOUT_FULL_PATH}/*#{CALLOUT_EXT}"
+        Dir.glob(calloutglob).each {|img|
+          img_new_filename = File.join(@oebps_dir, CALLOUT_PATH, File.basename(img))
+
+          # TODO: What to rescue for these two?
+          FileUtils.mkdir_p(File.dirname(img_new_filename)) 
+          FileUtils.cp(img, img_new_filename)
+          @to_delete << img_new_filename
+          new_callout_images << img
+        }  
+      end  
+      return new_callout_images
+    end
+
+    def copy_fonts
+      new_fonts = []
+      @embedded_fonts.each {|font_file|
+        font_new_filename = File.join(@oebps_dir, File.basename(font_file))
+        FileUtils.cp(font_file, font_new_filename)
+        new_fonts << font_file
+      }
+      return new_fonts
+    end
+
+    def copy_csses
+      if @css_file 
+        css_new_filename = File.join(@oebps_dir, File.basename(@css_file))
+        FileUtils.cp(@css_file, css_new_filename)
+      end
+    end
+
+    def copy_images
+      image_references = get_image_refs()
+      new_images = []
+      image_references.each {|img|
+        # TODO: It'd be cooler if we had a filetype lookup rather than just
+        # extension
+        if img =~ /\.(svg|png|gif|jpe?g|xml)/i
+          img_new_filename = File.join(@oebps_dir, img)
+          img_full = File.join(File.expand_path(File.dirname(@docbook_file)), img)
+
+          # TODO: What to rescue for these two?
+          FileUtils.mkdir_p(File.dirname(img_new_filename)) 
+          puts(img_full + ": " + img_new_filename) if $DEBUG
+          FileUtils.cp(img_full, img_new_filename)
+          @to_delete << img_new_filename
+          new_images << img_full
+        end
+      }  
+      return new_images
+    end
+
+    def write_mimetype
+      mimetype_filename = File.join(@output_dir, "mimetype")
+      File.open(mimetype_filename, "w") {|f| f.print MIMETYPE}
+      @to_delete << mimetype_filename
+      return File.basename(mimetype_filename)
+    end  
+
+    def cleanup_files(file_list)
+      file_list.flatten.each {|f|
+        # Yikes
+        FileUtils.rm_r(f, :force => true )
+      }  
+    end  
+
+    # Returns an Array of all of the (image) @filerefs in a document
+    def get_image_refs
+      parser = REXML::Parsers::PullParser.new(File.new(@collapsed_docbook_file))
+      image_refs = []
+      while parser.has_next?
+        el = parser.pull
+        if el.start_element? and (el[0] == "imagedata" or el[0] == "graphic")
+          image_refs << el[1]['fileref'] 
+        end  
+      end
+      return image_refs.uniq
+    end  
+
+    # Returns true if the document has code callouts
+    def has_callouts?
+      parser = REXML::Parsers::PullParser.new(File.new(@collapsed_docbook_file))
+      while parser.has_next?
+        el = parser.pull
+        if el.start_element? and (el[0] == "calloutlist" or el[0] == "co")
+          return true
+        end  
+      end
+      return false
+    end  
+  end
+end
diff --git a/tools/cxxtest/doc/epub/bin/xslt/obfuscate.xsl b/tools/cxxtest/doc/epub/bin/xslt/obfuscate.xsl
new file mode 100644 (file)
index 0000000..4ea4cd5
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
+  <xsl:output method="xml" omit-xml-declaration="no" doctype-public="-//OASIS//DTD DocBook XML V4.4//EN" doctype-system="http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" indent="no"/>
+  <xsl:template match="@*|*|comment()|processing-instruction()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+  <xsl:template match="text()">
+    <xsl:value-of select="replace(replace(., '[a-z]', 'x'), '[0-9]', 'd')"/>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/cxxtest/doc/epub/docbook.xsl b/tools/cxxtest/doc/epub/docbook.xsl
new file mode 100644 (file)
index 0000000..753fcd0
--- /dev/null
@@ -0,0 +1,1690 @@
+<?xml version="1.0"?>
+<xsl:stylesheet 
+  xmlns:db="http://docbook.org/ns/docbook"
+  xmlns:dc="http://purl.org/dc/elements/1.1/"  
+  xmlns:exsl="http://exslt.org/common" 
+  xmlns:h="http://www.w3.org/1999/xhtml"
+  xmlns:ncx="http://www.daisy.org/z3986/2005/ncx/"
+  xmlns:ng="http://docbook.org/docbook-ng"
+  xmlns:opf="http://www.idpf.org/2007/opf"
+  xmlns:stext="http://nwalsh.com/xslt/ext/com.nwalsh.saxon.TextFactory"
+  xmlns:str="http://exslt.org/strings"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xtext="xalan://com.nwalsh.xalan.Text"
+
+  extension-element-prefixes="stext xtext"
+  exclude-result-prefixes="exsl db dc h ncx ng opf stext str xtext"
+
+  version="1.0">
+
+  <xsl:import href="../xhtml-1_1/docbook.xsl" />
+  <xsl:import href="../xhtml-1_1/chunk-common.xsl" />
+  <xsl:include href="../xhtml-1_1/chunk-code.xsl" />
+
+
+  <!-- We want a separate TOC file, please -->
+  <xsl:param name="chunk.tocs.and.lots">1</xsl:param>
+  <xsl:param name="toc.section.depth">2</xsl:param>
+  <xsl:param name="generate.toc">
+  book   toc,title
+  </xsl:param>
+
+  <xsl:param name="ade.extensions" select="0"/>
+  <xsl:param name="epub.autolabel" select="'1'"/> 
+  <xsl:param name="epub.ncx.depth">4</xsl:param> <!-- Not functional until http://code.google.com/p/epubcheck/issues/detail?id=70 is resolved -->
+
+
+  <xsl:param name="manifest.in.base.dir" select="'1'"/> 
+  <xsl:param name="base.dir" select="$epub.oebps.dir"/>
+
+  <xsl:param name="epub.oebps.dir" select="'OEBPS/'"/> 
+  <xsl:param name="epub.ncx.filename" select="'toc.ncx'"/> 
+  <xsl:param name="epub.container.filename" select="'container.xml'"/> 
+  <xsl:param name="epub.opf.filename" select="concat($epub.oebps.dir, 'content.opf')"/> 
+  <xsl:param name="epub.cover.filename" select="concat($epub.oebps.dir, 'cover', $html.ext)"/> 
+  <xsl:param name="epub.cover.id" select="'cover'"/> 
+  <xsl:param name="epub.cover.html" select="'cover.html'" />
+  <xsl:param name="epub.cover.image.id" select="'cover-image'"/> 
+  <xsl:param name="epub.cover.linear" select="0" />
+  <xsl:param name="epub.ncx.toc.id">ncxtoc</xsl:param>
+  <xsl:param name="epub.html.toc.id">htmltoc</xsl:param>
+  <xsl:param name="epub.metainf.dir" select="'META-INF/'"/> 
+
+  <xsl:param name="epub.embedded.fonts"></xsl:param>
+
+  <!-- Turning this on crashes ADE, which is unbelievably awesome -->
+  <xsl:param name="formal.object.break.after">0</xsl:param>
+
+
+  <!-- Per Bob Stayton:
+       """Process your documents with the css.decoration parameter set to zero. 
+          That will avoid the use of style attributes in XHTML elements where they are not permitted."""
+       http://www.sagehill.net/docbookxsl/OtherOutputForms.html#StrictXhtmlValid -->
+  <xsl:param name="css.decoration" select="0"/>
+  <xsl:param name="custom.css.source"></xsl:param> <!-- FIXME: Align with current CSS parameter design -->
+
+  <xsl:param name="callout.graphics" select="1"/>
+  <xsl:param name="callout.graphics.extension">.png</xsl:param>
+  <xsl:param name="callout.graphics.number.limit" select="15"/>
+  <xsl:param name="callout.graphics.path" select="'images/callouts/'"/>
+
+  <!-- no navigation in .epub -->
+  <xsl:param name="suppress.navigation" select="'1'"/> 
+
+  <xsl:variable name="toc.params">
+    <xsl:call-template name="find.path.params">
+      <xsl:with-param name="node" select="/*"/>
+      <xsl:with-param name="table" select="normalize-space($generate.toc)"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:variable name="root.is.a.chunk">
+    <xsl:choose>
+      <xsl:when test="/*[not(self::book)][not(sect1) or not(section)]">
+        <xsl:text>1</xsl:text>
+      </xsl:when>
+      <xsl:when test="/book[*[last()][self::bookinfo]]|book[bookinfo]">
+        <xsl:text>1</xsl:text>
+      </xsl:when>
+      <xsl:when test="/book[*[last()][self::info]]|book[info]">
+        <xsl:text>1</xsl:text>
+      </xsl:when>
+      <xsl:when test="/bibliography">
+        <xsl:text>1</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:text>0</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:key name="image-filerefs" match="graphic|inlinegraphic|imagedata" use="@fileref"/>
+
+  <xsl:template match="/">
+    <!-- * Get a title for current doc so that we let the user -->
+    <!-- * know what document we are processing at this point. -->
+    <xsl:variable name="doc.title">
+      <xsl:call-template name="get.doc.title" />
+    </xsl:variable>
+    <xsl:choose>
+      <!-- Hack! If someone hands us a DocBook V5.x or DocBook NG document,
+        toss the namespace and continue.  Use the docbook5 namespaced
+        stylesheets for DocBook5 if you don't want to use this feature.-->
+      <!-- include extra test for Xalan quirk -->
+      <xsl:when test="$exsl.node.set.available != 0
+                    and (*/self::ng:* or */self::db:*)">
+        <xsl:call-template name="log.message">
+          <xsl:with-param name="level">Note</xsl:with-param>
+          <xsl:with-param name="source" select="$doc.title" />
+          <xsl:with-param name="context-desc">
+            <xsl:text>namesp. cut</xsl:text>
+          </xsl:with-param>
+          <xsl:with-param name="message">
+            <xsl:text>stripped namespace before processing</xsl:text>
+          </xsl:with-param>
+        </xsl:call-template>
+        <xsl:variable name="nons">
+          <xsl:apply-templates mode="stripNS" />
+        </xsl:variable>
+        <xsl:call-template name="log.message">
+          <xsl:with-param name="level">Note</xsl:with-param>
+          <xsl:with-param name="source" select="$doc.title" />
+          <xsl:with-param name="context-desc">
+            <xsl:text>namesp. cut</xsl:text>
+          </xsl:with-param>
+          <xsl:with-param name="message">
+            <xsl:text>processing stripped document</xsl:text>
+          </xsl:with-param>
+        </xsl:call-template>
+        <xsl:apply-templates select="exsl:node-set($nons)" />
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:choose>
+          <xsl:when test="$rootid != ''">
+            <xsl:choose>
+              <xsl:when
+                test="count(key('id',$rootid)) = 0">
+                <xsl:message terminate="yes">
+                  <xsl:text>ID '</xsl:text>
+                  <xsl:value-of select="$rootid" />
+                  <xsl:text>' not found in document.</xsl:text>
+                </xsl:message>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:if
+                  test="$collect.xref.targets = 'yes' or
+                                $collect.xref.targets = 'only'">
+                  <xsl:apply-templates
+                    select="key('id', $rootid)" mode="collect.targets" />
+                </xsl:if>
+                <xsl:if
+                  test="$collect.xref.targets != 'only'">
+                  <xsl:message>
+                    Formatting from
+                    <xsl:value-of select="$rootid" />
+                  </xsl:message>
+                  <xsl:apply-templates
+                    select="key('id',$rootid)" mode="process.root" />
+                  <xsl:call-template name="ncx" />
+                </xsl:if>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:if
+              test="$collect.xref.targets = 'yes' or
+                    $collect.xref.targets = 'only'">
+              <xsl:apply-templates select="/"
+                mode="collect.targets" />
+            </xsl:if>
+            <xsl:if
+              test="$collect.xref.targets != 'only'">
+              <xsl:apply-templates select="/"
+                mode="process.root" />
+              <xsl:call-template name="ncx" />
+              <xsl:call-template name="opf" />
+              <xsl:call-template name="cover" />
+              <xsl:call-template name="container" />
+            </xsl:if>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="package-identifier">  
+    <xsl:choose>
+      <xsl:when test="/*/*[contains(name(.), 'info')]/biblioid">
+        <xsl:if test="/*/*[contains(name(.), 'info')][1]/biblioid[1][@class = 'doi' or 
+                                                                      @class = 'isbn' or
+                                                                      @class = 'isrn' or
+                                                                      @class = 'issn']">
+          <xsl:text>urn:</xsl:text>
+          <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/biblioid[1]/@class"/>
+          <xsl:text>:</xsl:text>
+        </xsl:if>
+        <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/biblioid[1]"/>
+      </xsl:when>
+      <xsl:when test="/*/*[contains(name(.), 'info')]/isbn">
+        <xsl:text>urn:isbn:</xsl:text>
+        <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/isbn[1]"/>
+      </xsl:when>
+      <xsl:when test="/*/*[contains(name(.), 'info')]/issn">
+        <xsl:text>urn:issn:</xsl:text>
+        <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/issn[1]"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:choose>
+          <xsl:when test="/*/*[contains(name(.), 'info')]/invpartnumber"> <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/invpartnumber[1]"/> </xsl:when>
+          <xsl:when test="/*/*[contains(name(.), 'info')]/issuenum">      <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/issuenum[1]"/> </xsl:when>
+          <xsl:when test="/*/*[contains(name(.), 'info')]/productnumber"> <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/productnumber[1]"/> </xsl:when>
+          <xsl:when test="/*/*[contains(name(.), 'info')]/seriesvolnums"> <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/seriesvolnums[1]"/> </xsl:when>
+          <xsl:when test="/*/*[contains(name(.), 'info')]/volumenum">     <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/volumenum[1]"/> </xsl:when>
+          <!-- Deprecated -->
+          <xsl:when test="/*/*[contains(name(.), 'info')]/pubsnumber">    <xsl:value-of select="/*/*[contains(name(.), 'info')][1]/pubsnumber[1]"/> </xsl:when>
+        </xsl:choose>  
+        <xsl:text>_</xsl:text>
+        <xsl:choose>
+          <xsl:when test="/*/@id">
+            <xsl:value-of select="/*/@id"/>
+          </xsl:when>
+          <xsl:when test="/*/@xml:id">
+            <xsl:value-of select="/*/@xml:id"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <!-- TODO: Do UUIDs here -->
+            <xsl:value-of select="generate-id(/*)"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="opf">
+    <xsl:variable name="package-identifier-id"><xsl:value-of select="concat(name(/*), 'id')"/></xsl:variable>
+    <xsl:variable name="doc.title">
+      <xsl:call-template name="get.doc.title" />
+    </xsl:variable>
+    <xsl:call-template name="write.chunk">
+      <xsl:with-param name="filename">
+        <xsl:value-of select="$epub.opf.filename" />
+      </xsl:with-param>
+      <xsl:with-param name="method" select="'xml'" />
+      <xsl:with-param name="encoding" select="'utf-8'" />
+      <xsl:with-param name="indent" select="'no'" />
+      <xsl:with-param name="quiet" select="$chunk.quietly" />
+      <xsl:with-param name="doctype-public" select="''"/> <!-- intentionally blank -->
+      <xsl:with-param name="doctype-system" select="''"/> <!-- intentionally blank -->
+      <xsl:with-param name="content">
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="package">
+          <xsl:attribute name="version">2.0</xsl:attribute>
+          <xsl:attribute name="unique-identifier"> <xsl:value-of select="$package-identifier-id"/> </xsl:attribute>
+
+          <xsl:element namespace="http://www.idpf.org/2007/opf" name="metadata">
+            <xsl:element name="dc:identifier">
+              <xsl:attribute name="id"><xsl:value-of select="$package-identifier-id"/></xsl:attribute>
+              <xsl:call-template name="package-identifier"/>
+            </xsl:element>  
+
+            <xsl:element name="dc:title">
+              <xsl:value-of select="normalize-space($doc.title)"/>
+            </xsl:element>
+
+            <xsl:apply-templates select="/*/*[contains(name(.), 'info')]/*"
+                                 mode="opf.metadata"/>        
+            <xsl:element name="dc:language">
+              <xsl:call-template name="l10n.language">
+                <xsl:with-param name="target" select="/*"/>
+              </xsl:call-template>  
+            </xsl:element>
+
+            <xsl:if test="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+              <xsl:element namespace="http://www.idpf.org/2007/opf" name="meta">
+                <xsl:attribute name="name">cover</xsl:attribute>
+                <xsl:attribute name="content">
+                  <xsl:value-of select="$epub.cover.image.id"/>
+                </xsl:attribute>
+              </xsl:element>
+            </xsl:if>
+
+          </xsl:element>
+          <xsl:call-template name="opf.manifest"/>
+          <xsl:call-template name="opf.spine"/>
+          <xsl:call-template name="opf.guide"/>
+
+        </xsl:element>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="container">
+    <xsl:call-template name="write.chunk">
+      <xsl:with-param name="filename">
+        <xsl:value-of select="$epub.metainf.dir" />
+        <xsl:value-of select="$epub.container.filename" />
+      </xsl:with-param>
+      <xsl:with-param name="method" select="'xml'" />
+      <xsl:with-param name="encoding" select="'utf-8'" />
+      <xsl:with-param name="indent" select="'no'" />
+      <xsl:with-param name="quiet" select="$chunk.quietly" />
+      <xsl:with-param name="doctype-public" select="''"/> <!-- intentionally blank -->
+      <xsl:with-param name="doctype-system" select="''"/> <!-- intentionally blank -->
+
+      <xsl:with-param name="content">
+        <xsl:element namespace="urn:oasis:names:tc:opendocument:xmlns:container" name="container">
+          <xsl:attribute name="version">1.0</xsl:attribute>
+          <xsl:element namespace="urn:oasis:names:tc:opendocument:xmlns:container" name="rootfiles">
+            <xsl:element namespace="urn:oasis:names:tc:opendocument:xmlns:container" name="rootfile">
+              <xsl:attribute name="full-path">
+                <xsl:value-of select="$epub.opf.filename" />
+              </xsl:attribute>
+              <xsl:attribute name="media-type">
+                <xsl:text>application/oebps-package+xml</xsl:text>
+              </xsl:attribute>
+            </xsl:element>
+          </xsl:element>
+        </xsl:element>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="ncx">
+    <xsl:call-template name="write.chunk">
+      <xsl:with-param name="filename">
+        <xsl:if test="$manifest.in.base.dir != 0">
+          <xsl:value-of select="$base.dir" />
+        </xsl:if>
+        <xsl:value-of select="$epub.ncx.filename" />
+      </xsl:with-param>
+      <xsl:with-param name="method" select="'xml'" />
+      <xsl:with-param name="encoding" select="'utf-8'" />
+      <xsl:with-param name="indent" select="'no'" />
+      <xsl:with-param name="quiet" select="$chunk.quietly" />
+      <xsl:with-param name="doctype-public" select="''"/> <!-- intentionally blank -->
+      <xsl:with-param name="doctype-system" select="''"/> <!-- intentionally blank -->
+      <xsl:with-param name="content">
+        <xsl:element name="ncx" namespace="http://www.daisy.org/z3986/2005/ncx/">
+          <xsl:attribute name="version">2005-1</xsl:attribute>
+
+            <!-- Via Martin Goerner: On covers: the IDPF2.0 standard unfortunately does not have a provision for
+            covers. We had to add one and we did so in conjunction with the IDPF and
+            various publishers. The tag chosen to define the covers is:
+            <meta name="cover" content="-reference to a manifest item-">
+            Then, we also added a bit of logic to get rid cleanly of the HTML cover
+            people usually add because the logical cover is not specced by the IDPF. So,
+            if the HTML cover item is marked linear="no" AND there is a guide item of
+            type="cover" pointing to it AND there is a logical cover specified in a
+            <meta name="cover"> tag, THEN, the HTML cover is discarded. -->
+          <xsl:element name="head" namespace="http://www.daisy.org/z3986/2005/ncx/">
+            <xsl:if test="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+              <xsl:element name="meta" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                <xsl:attribute name="name">cover</xsl:attribute>
+                <xsl:attribute name="content">
+                  <xsl:value-of select="$epub.cover.id"/>
+                </xsl:attribute>
+              </xsl:element>
+            </xsl:if>
+            <xsl:element name="meta" namespace="http://www.daisy.org/z3986/2005/ncx/">
+              <xsl:attribute name="name">dtb:uid</xsl:attribute>
+              <xsl:attribute name="content"><xsl:call-template name="package-identifier"/></xsl:attribute>
+            </xsl:element>
+          </xsl:element>
+
+          <xsl:choose>
+            <xsl:when test="$rootid != ''">
+              <xsl:variable name="title">
+                <xsl:if test="$epub.autolabel != 0">
+                  <xsl:variable name="label.markup">
+                    <xsl:apply-templates select="key('id',$rootid)" mode="label.markup" />
+                  </xsl:variable>
+                  <xsl:if test="normalize-space($label.markup)">
+                    <xsl:value-of select="concat($label.markup,$autotoc.label.separator)" />
+                  </xsl:if>
+                </xsl:if>
+                <xsl:apply-templates select="key('id',$rootid)" mode="title.markup" />
+              </xsl:variable>
+              <xsl:variable name="href">
+                <xsl:call-template name="href.target.with.base.dir">
+                  <xsl:with-param name="object" select="key('id',$rootid)" />
+                </xsl:call-template>
+              </xsl:variable>
+              <xsl:element name="docTitle" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)" />  </xsl:element>
+              </xsl:element>
+              <xsl:element name="navMap" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                <xsl:apply-templates select="key('id',$rootid)/*" mode="ncx" />
+              </xsl:element>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:variable name="title">
+                <xsl:if test="$epub.autolabel != 0">
+                  <xsl:variable name="label.markup">
+                    <xsl:apply-templates select="/*" mode="label.markup" />
+                  </xsl:variable>
+                  <xsl:if test="normalize-space($label.markup)">
+                    <xsl:value-of select="concat($label.markup,$autotoc.label.separator)" />
+                  </xsl:if>
+                </xsl:if>
+                <xsl:apply-templates select="/*" mode="title.markup" />
+              </xsl:variable>
+              <xsl:variable name="href">
+                <xsl:call-template name="href.target.with.base.dir">
+                  <xsl:with-param name="object" select="/" />
+                </xsl:call-template>
+              </xsl:variable>
+              <xsl:element name="docTitle" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                  <xsl:value-of select="normalize-space($title)" />
+                </xsl:element>
+              </xsl:element>
+              <xsl:element name="navMap" namespace="http://www.daisy.org/z3986/2005/ncx/">
+                <xsl:choose>
+                  <xsl:when test="$root.is.a.chunk != '0'">
+                    <xsl:apply-templates select="/*" mode="ncx" />
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <xsl:apply-templates select="/*/*" mode="ncx" />
+                  </xsl:otherwise>
+                </xsl:choose>
+              </xsl:element>
+            </xsl:otherwise>
+
+          </xsl:choose>
+        </xsl:element>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template match="book|
+                       article|
+                       part|
+                       reference|
+                       preface|
+                       chapter|
+                       bibliography|
+                       appendix|
+                       glossary|
+                       section|
+                       sect1|
+                       sect2|
+                       sect3|
+                       sect4|
+                       sect5|
+                       refentry|
+                       colophon|
+                       bibliodiv[title]|
+                       setindex|
+                       index"
+                mode="ncx">
+    <xsl:variable name="depth" select="count(ancestor::*)"/>
+    <xsl:variable name="title">
+      <xsl:if test="$epub.autolabel != 0">
+        <xsl:variable name="label.markup">
+          <xsl:apply-templates select="." mode="label.markup" />
+        </xsl:variable>
+        <xsl:if test="normalize-space($label.markup)">
+          <xsl:value-of
+            select="concat($label.markup,$autotoc.label.separator)" />
+        </xsl:if>
+      </xsl:if>
+      <xsl:apply-templates select="." mode="title.markup" />
+    </xsl:variable>
+
+    <xsl:variable name="href">
+      <xsl:call-template name="href.target.with.base.dir">
+        <xsl:with-param name="context" select="/" />
+        <!-- Generate links relative to the location of root file/toc.xml file -->
+      </xsl:call-template>
+    </xsl:variable>
+
+    <xsl:variable name="id">
+      <xsl:value-of select="generate-id(.)"/>
+    </xsl:variable>
+    <xsl:variable name="order">
+      <xsl:value-of select="$depth +
+                                  count(preceding::part|
+                                  preceding::reference|
+                                  preceding::book[parent::set]|
+                                  preceding::preface|
+                                  preceding::chapter|
+                                  preceding::bibliography|
+                                  preceding::appendix|
+                                  preceding::article|
+                                  preceding::glossary|
+                                  preceding::section[not(parent::partintro)]|
+                                  preceding::sect1[not(parent::partintro)]|
+                                  preceding::sect2[not(ancestor::partintro)]|
+                                  preceding::sect3[not(ancestor::partintro)]|
+                                  preceding::sect4[not(ancestor::partintro)]|
+                                  preceding::sect5[not(ancestor::partintro)]|
+                                  preceding::refentry|
+                                  preceding::colophon|
+                                  preceding::bibliodiv[title]|
+                                  preceding::index)"/>
+    </xsl:variable>
+
+    <xsl:element name="navPoint" namespace="http://www.daisy.org/z3986/2005/ncx/">
+      <xsl:attribute name="id">
+        <xsl:value-of select="$id"/>
+      </xsl:attribute>
+
+      <xsl:attribute name="playOrder">
+        <xsl:choose>
+          <xsl:when test="/*[self::set]">
+            <xsl:value-of select="$order"/>
+          </xsl:when>
+          <xsl:when test="$root.is.a.chunk != '0'">
+            <xsl:value-of select="$order + 1"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="$order - 0"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+      <xsl:element name="navLabel" namespace="http://www.daisy.org/z3986/2005/ncx/">
+        <xsl:element name="text" namespace="http://www.daisy.org/z3986/2005/ncx/"><xsl:value-of select="normalize-space($title)"/> </xsl:element>
+      </xsl:element>
+      <xsl:element name="content" namespace="http://www.daisy.org/z3986/2005/ncx/">
+        <xsl:attribute name="src">
+          <xsl:value-of select="$href"/>
+        </xsl:attribute>
+      </xsl:element>
+      <xsl:apply-templates select="book[parent::set]|part|reference|preface|chapter|bibliography|appendix|article|glossary|section|sect1|sect2|sect3|sect4|sect5|refentry|colophon|bibliodiv[title]|setindex|index" mode="ncx"/>
+    </xsl:element>
+
+  </xsl:template>
+
+  <xsl:template match="*" mode="opf.metadata">
+    <!-- override if you care -->
+  </xsl:template>
+
+  <xsl:template match="authorgroup" mode="opf.metadata">
+    <xsl:apply-templates select="author|corpauthor" mode="opf.metadata"/>
+  </xsl:template>
+
+  <xsl:template match="author|corpauthor" mode="opf.metadata">
+    <xsl:variable name="n">
+      <xsl:call-template name="person.name">
+        <xsl:with-param name="node" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:element name="dc:creator">
+      <xsl:attribute name="opf:file-as">
+        <xsl:call-template name="person.name.last-first">
+          <xsl:with-param name="node" select="."/>
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:value-of select="normalize-space(string($n))"/>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="date" mode="opf.metadata">
+    <xsl:element name="dc:date">
+      <xsl:value-of select="normalize-space(string(.))"/>
+    </xsl:element>
+  </xsl:template>
+
+
+  <!-- Space separate the compontents of the abstract (dropping the inline markup, sadly) -->
+  <xsl:template match="abstract" mode="opf.metadata">
+    <xsl:element name="dc:description">
+      <xsl:for-each select="formalpara|para|simpara|title">
+        <xsl:choose>
+          <xsl:when test="self::formalpara">
+            <xsl:value-of select="normalize-space(string(title))"/>
+            <xsl:text>: </xsl:text>
+            <xsl:value-of select="normalize-space(string(para))"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="normalize-space(string(.))"/>
+          </xsl:otherwise>  
+        </xsl:choose>
+        <xsl:if test="self::title">
+          <xsl:text>:</xsl:text>
+        </xsl:if>
+        <xsl:if test="not(position() = last())">
+          <xsl:text> </xsl:text>
+        </xsl:if>
+      </xsl:for-each>  
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="subjectset" mode="opf.metadata">
+    <xsl:apply-templates select="subject/subjectterm" mode="opf.metadata"/>
+  </xsl:template>
+  
+  <xsl:template match="subjectterm" mode="opf.metadata">
+    <xsl:element name="dc:subject">
+      <xsl:value-of select="normalize-space(string(.))"/>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="publisher" mode="opf.metadata">
+    <xsl:apply-templates select="publishername" mode="opf.metadata"/>
+  </xsl:template>
+  
+  <xsl:template match="publishername" mode="opf.metadata">
+    <xsl:element name="dc:publisher">
+      <xsl:value-of select="normalize-space(string(.))"/>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="copyright" mode="opf.metadata">
+    <xsl:variable name="copyright.date">
+      <xsl:call-template name="copyright.years">
+        <xsl:with-param name="years" select="year"/>
+        <xsl:with-param name="print.ranges" select="$make.year.ranges"/>
+        <xsl:with-param name="single.year.ranges" select="$make.single.year.ranges"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:if test="not(../date)">
+      <xsl:element name="dc:date">
+        <xsl:call-template name="copyright.years">
+          <xsl:with-param name="years" select="year[last()]"/>
+          <xsl:with-param name="print.ranges" select="0"/>
+          <xsl:with-param name="single.year.ranges" select="0"/>
+        </xsl:call-template>
+      </xsl:element>
+    </xsl:if>
+    <xsl:element name="dc:rights">
+      <xsl:call-template name="gentext">
+        <xsl:with-param name="key" select="'Copyright'"/>
+      </xsl:call-template>
+      <xsl:call-template name="gentext.space"/>
+      <xsl:text>&#x00A9;</xsl:text>
+      <xsl:call-template name="gentext.space"/>
+      <xsl:value-of select="$copyright.date"/>
+      <xsl:call-template name="gentext.space"/>
+      <xsl:apply-templates select="holder" mode="titlepage.mode"/>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template name="opf.guide">
+    <xsl:if test="contains($toc.params, 'toc') or 
+                  /*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+      <xsl:element namespace="http://www.idpf.org/2007/opf" name="guide">
+        <xsl:if test="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+          <xsl:element namespace="http://www.idpf.org/2007/opf" name="reference">
+            <xsl:attribute name="href">
+              <xsl:value-of select="$epub.cover.html" />
+            </xsl:attribute>
+            <xsl:attribute name="type">cover</xsl:attribute>
+            <xsl:attribute name="title">Cover</xsl:attribute>
+          </xsl:element>
+        </xsl:if>  
+
+        <xsl:if test="contains($toc.params, 'toc')">
+          <xsl:element namespace="http://www.idpf.org/2007/opf" name="reference">
+            <xsl:attribute name="href">
+              <xsl:call-template name="toc-href">
+                <xsl:with-param name="node" select="/*"/>
+              </xsl:call-template>
+            </xsl:attribute>
+            <xsl:attribute name="type">toc</xsl:attribute>
+            <xsl:attribute name="title">Table of Contents</xsl:attribute>
+          </xsl:element>
+        </xsl:if>  
+      </xsl:element>  
+    </xsl:if>  
+  </xsl:template>
+
+  <xsl:template name="opf.spine">
+
+    <xsl:element namespace="http://www.idpf.org/2007/opf" name="spine">
+      <xsl:attribute name="toc">
+        <xsl:value-of select="$epub.ncx.toc.id"/>
+      </xsl:attribute>
+
+      <xsl:if test="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="itemref">
+          <xsl:attribute name="idref">
+            <xsl:value-of select="$epub.cover.id"/>
+          </xsl:attribute>
+          <xsl:attribute name="linear">
+          <xsl:choose>
+            <xsl:when test="$epub.cover.linear">
+              <xsl:text>yes</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>no</xsl:otherwise>
+          </xsl:choose>
+          </xsl:attribute>
+        </xsl:element>
+      </xsl:if>
+
+
+      <xsl:if test="contains($toc.params, 'toc')">
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="itemref">
+          <xsl:attribute name="idref"> <xsl:value-of select="$epub.html.toc.id"/> </xsl:attribute>
+          <xsl:attribute name="linear">yes</xsl:attribute>
+        </xsl:element>
+      </xsl:if>  
+
+      <!-- TODO: be nice to have a idref="titlepage" here -->
+      <xsl:choose>
+        <xsl:when test="$root.is.a.chunk != '0'">
+          <xsl:apply-templates select="/*" mode="opf.spine"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:apply-templates select="/*/*" mode="opf.spine"/>
+        </xsl:otherwise>
+      </xsl:choose>
+                                   
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="*" mode="opf.spine">
+    <xsl:variable name="is.chunk">
+      <xsl:call-template name="chunk">
+        <xsl:with-param name="node" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+
+    <xsl:if test="$is.chunk != 0">
+      <xsl:element namespace="http://www.idpf.org/2007/opf" name="itemref">
+        <xsl:attribute name="idref">
+          <xsl:value-of select="generate-id(.)"/>
+        </xsl:attribute>
+      </xsl:element>
+      <xsl:apply-templates select="*|.//refentry" mode="opf.spine"/>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="opf.manifest">
+    <xsl:element namespace="http://www.idpf.org/2007/opf" name="manifest">
+      <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+        <xsl:attribute name="id"> <xsl:value-of select="$epub.ncx.toc.id"/> </xsl:attribute>
+        <xsl:attribute name="media-type">application/x-dtbncx+xml</xsl:attribute>
+        <xsl:attribute name="href"><xsl:value-of select="$epub.ncx.filename"/> </xsl:attribute>
+      </xsl:element>
+
+      <xsl:if test="contains($toc.params, 'toc')">
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+          <xsl:attribute name="id"> <xsl:value-of select="$epub.html.toc.id"/> </xsl:attribute>
+          <xsl:attribute name="media-type">application/xhtml+xml</xsl:attribute>
+          <xsl:attribute name="href">
+            <xsl:call-template name="toc-href">
+              <xsl:with-param name="node" select="/*"/>
+            </xsl:call-template>
+          </xsl:attribute>
+        </xsl:element>
+      </xsl:if>  
+
+      <xsl:if test="$html.stylesheet != ''">
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+          <xsl:attribute name="media-type">text/css</xsl:attribute>
+          <xsl:attribute name="id">css</xsl:attribute>
+          <xsl:attribute name="href"><xsl:value-of select="$html.stylesheet"/></xsl:attribute>
+        </xsl:element>
+      </xsl:if>
+
+      <xsl:if test="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"> 
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+          <xsl:attribute name="id"> <xsl:value-of select="$epub.cover.id"/> </xsl:attribute>
+          <xsl:attribute name="href"> 
+            <xsl:value-of select="$epub.cover.html"/>
+          </xsl:attribute>
+          <xsl:attribute name="media-type">application/xhtml+xml</xsl:attribute>
+        </xsl:element>
+      </xsl:if>  
+
+      <xsl:choose>
+        <xsl:when test="$epub.embedded.fonts != '' and not(contains($epub.embedded.fonts, ','))">
+          <xsl:call-template name="embedded-font-item">
+            <xsl:with-param name="font.file" select="$epub.embedded.fonts"/> <!-- There is just one -->
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:when test="$epub.embedded.fonts != ''">
+          <xsl:variable name="font.file.tokens" select="str:tokenize($epub.embedded.fonts, ',')"/>
+          <xsl:for-each select="exsl:node-set($font.file.tokens)">
+            <xsl:call-template name="embedded-font-item">
+              <xsl:with-param name="font.file" select="."/>
+              <xsl:with-param name="font.order" select="position()"/>
+            </xsl:call-template>
+          </xsl:for-each>
+        </xsl:when>
+      </xsl:choose>
+
+      <!-- TODO: be nice to have a id="titlepage" here -->
+      <xsl:apply-templates select="//part|
+                                   //book[*[last()][self::bookinfo]]|
+                                   //book[bookinfo]|
+                                   /set|
+                                   /set/book|
+                                   //reference|
+                                   //preface|
+                                   //chapter|
+                                   //bibliography|
+                                   //appendix|
+                                   //article|
+                                   //glossary|
+                                   //section|
+                                   //sect1|
+                                   //sect2|
+                                   //sect3|
+                                   //sect4|
+                                   //sect5|
+                                   //refentry|
+                                   //colophon|
+                                   //bibliodiv[title]|
+                                   //index|
+                                   //setindex|
+                                   //graphic|
+                                   //inlinegraphic|
+                                   //mediaobject|
+                                   //mediaobjectco|
+                                   //inlinemediaobject" 
+                           mode="opf.manifest"/>
+      <xsl:call-template name="opf.calloutlist"/>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template name="opf.calloutlist">
+    <xsl:variable name="format">
+      <xsl:call-template name="guess-media-type">
+        <xsl:with-param name="ext" select="$callout.graphics.extension"/>
+      </xsl:call-template>
+    </xsl:variable>  
+    <xsl:if test="(//calloutlist|//co)">
+      <xsl:call-template name="opf.reference.callout">
+        <xsl:with-param name="conum" select="1"/>
+        <xsl:with-param name="format" select="$format"/>
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="opf.reference.callout">
+    <xsl:param name="conum"/>
+    <xsl:param name="format"/>
+
+    <xsl:variable name="filename" select="concat($callout.graphics.path, $conum, $callout.graphics.extension)"/>
+
+    <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+      <xsl:attribute name="id"> <xsl:value-of select="concat(generate-id(.), 'callout', $conum)"/> </xsl:attribute>
+      <xsl:attribute name="href"> <xsl:value-of select="$filename"/> </xsl:attribute>
+      <xsl:attribute name="media-type">
+        <xsl:value-of select="$format"/>
+      </xsl:attribute>
+    </xsl:element>
+    <xsl:if test="($conum &lt; $callout.graphics.number.limit)">
+      <xsl:call-template name="opf.reference.callout">
+        <xsl:with-param name="conum" select="$conum + 1"/>
+        <xsl:with-param name="format" select="$format"/>
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="guess-media-type">
+    <xsl:param name="ext"></xsl:param>
+    <xsl:choose>
+      <xsl:when test="contains($ext, '.gif')">
+        <xsl:text>image/gif</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, 'GIF')">
+        <xsl:text>image/gif</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, '.png')">
+        <xsl:text>image/png</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, 'PNG')">
+        <xsl:text>image/png</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, '.jpeg')">
+        <xsl:text>image/jpeg</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, 'JPEG')">
+        <xsl:text>image/jpeg</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, '.jpg')">
+        <xsl:text>image/jpeg</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, 'JPG')">
+        <xsl:text>image/jpeg</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, '.svg')">
+        <xsl:text>image/svg+xml</xsl:text>
+      </xsl:when>
+      <xsl:when test="contains($ext, 'SVG')">
+        <xsl:text>image/svg+xml</xsl:text>
+      </xsl:when>
+      <xsl:otherwise>
+        <!-- we failed -->
+        <xsl:text></xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="mediaobject|
+                       mediaobjectco|
+                       inlinemediaobject" 
+                mode="opf.manifest">
+
+    <xsl:variable name="olist" select="imageobject|imageobjectco                      |videoobject|audioobject                      |textobject"/>
+
+    <xsl:variable name="object.index">
+      <xsl:call-template name="select.mediaobject.index">
+        <xsl:with-param name="olist" select="$olist"/>
+        <xsl:with-param name="count" select="1"/>
+      </xsl:call-template>
+    </xsl:variable>
+
+    <xsl:variable name="object" select="$olist[position() = $object.index]"/>
+
+    <xsl:choose>
+      <xsl:when test="$object/descendant::imagedata[@format = 'GIF' or 
+                                                    @format = 'GIF87a' or 
+                                                    @format = 'GIF89a' or 
+                                                    @format = 'JPEG' or 
+                                                    @format = 'JPG' or 
+                                                    @format = 'PNG' or 
+                                                    @format = 'SVG']">
+        <xsl:apply-templates select="$object[descendant::imagedata[@format = 'GIF' or 
+                                                                   @format = 'GIF87a' or 
+                                                                   @format = 'GIF89a' or 
+                                                                   @format = 'JPEG' or 
+                                                                   @format = 'JPG' or 
+                                                                   @format = 'PNG' or 
+                                                                   @format = 'SVG']][1]/imagedata"
+                             mode="opf.manifest"/>              
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="$object/imagedata[1]"
+                             mode="opf.manifest"/>              
+      </xsl:otherwise>
+    </xsl:choose>  
+  </xsl:template>
+
+  <xsl:template match="cover/mediaobject|
+                       mediaobject[@role='cover']"
+                mode="opf.manifest">
+    <xsl:choose>
+      <xsl:when test="imageobject[@role='front-large']">
+        <xsl:apply-templates select="imageobject[@role='front-large']/imagedata"
+                             mode="opf.manifest"/>              
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="imageobject/imagedata[1]"
+                             mode="opf.manifest"/>              
+      </xsl:otherwise>
+    </xsl:choose>  
+  </xsl:template>
+
+  <xsl:template match="mediaobjectco"
+                mode="opf.manifest">
+    <xsl:message>WARNING: mediaobjectco almost certainly will not render as expected in .epub!</xsl:message>
+    <xsl:apply-templates select="imageobjectco/imageobject/imagedata" 
+                         mode="opf.manifest"/>              
+  </xsl:template>
+
+  <!-- TODO: Barf (xsl:message terminate=yes) if you find a graphic with no reasonable format or a mediaobject w/o same? [option to not die?] -->
+
+  <!-- wish I had XSLT2 ...-->
+  <!-- TODO: priority a hack -->
+  <xsl:template match="graphic[not(@format)]|
+                       inlinegraphic[not(@format)]|
+                       imagedata[not(@format)]"
+                mode="opf.manifest">        
+    <xsl:variable name="filename">
+      <xsl:choose>
+        <xsl:when test="contains(name(.), 'graphic')">
+          <xsl:choose>
+            <xsl:when test="@entityref">
+              <xsl:value-of select="unparsed-entity-uri(@entityref)"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:apply-templates select="@fileref"/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="mediaobject.filename">
+            <xsl:with-param name="object" select=".."/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>  
+    <xsl:variable name="format"> 
+      <xsl:call-template name="guess-media-type">
+        <xsl:with-param name="ext" select="@fileref"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="fr" select="@fileref"/>
+    <xsl:if test="$format != ''">
+      <!-- only do this if we're the first file to match -->
+      <!-- TODO: Why can't this be simple equality?? (I couldn't get it to work) -->
+      <xsl:if test="generate-id(.) = generate-id(key('image-filerefs', $fr)[1])">
+        <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+          <xsl:attribute name="id"> 
+            <xsl:choose>
+              <xsl:when test="ancestor::mediaobject[@role='cover'] and parent::*[@role='front-large']">
+                <xsl:value-of select="$epub.cover.image.id"/>
+              </xsl:when>
+              <xsl:when test="ancestor::mediaobject[@role='cover'] and (count(ancestor::mediaobject//imageobject) = 1)">
+                <xsl:value-of select="$epub.cover.image.id"/>
+              </xsl:when>
+              <xsl:when test="ancestor::cover">
+                <xsl:value-of select="$epub.cover.image.id"/>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="generate-id(.)"/> 
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:attribute>  
+          <xsl:attribute name="href"> <xsl:value-of select="$filename"/> </xsl:attribute>
+          <xsl:attribute name="media-type">
+            <xsl:value-of select="$format"/>
+          </xsl:attribute>
+        </xsl:element>
+      </xsl:if>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- Note: Selection of the first interesting imagedata is done in the select -->
+  <xsl:template match="graphic[@format = 'GIF' or @format = 'GIF87a' or @format = 'GIF89a' or @format = 'JPEG' or @format = 'JPG' or @format = 'PNG' or @format = 'SVG']|
+                       inlinegraphic[@format = 'GIF' or @format = 'GIF87a' or @format = 'GIF89a' or @format = 'JPEG' or @format = 'JPG' or @format = 'PNG' or @format = 'SVG']|
+                       imagedata[@format]"
+                mode="opf.manifest">
+    <xsl:variable name="filename">
+      <xsl:choose>
+        <xsl:when test="contains(name(.), 'graphic')">
+          <xsl:choose>
+            <xsl:when test="@entityref">
+              <xsl:value-of select="unparsed-entity-uri(@entityref)"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:apply-templates select="@fileref"/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="mediaobject.filename">
+            <xsl:with-param name="object" select=".."/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>  
+    <xsl:variable name="fr" select="@fileref"/>
+    <!-- only do this if we're the first file to match -->
+    <!-- TODO: Why can't this be simple equality?? (I couldn't get it to work) -->
+    <xsl:if test="generate-id(.) = generate-id(key('image-filerefs', $fr)[1])">
+      <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+        <xsl:attribute name="id"> 
+          <xsl:choose>
+            <xsl:when test="ancestor::mediaobject[@role='cover'] and parent::*[@role='front-large']">
+              <xsl:value-of select="$epub.cover.image.id"/>
+            </xsl:when>
+            <xsl:when test="ancestor::mediaobject[@role='cover'] and (count(ancestor::mediaobject//imageobject) = 1)">
+              <xsl:value-of select="$epub.cover.image.id"/>
+            </xsl:when>
+            <xsl:when test="ancestor::cover">
+              <xsl:value-of select="$epub.cover.image.id"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:value-of select="generate-id(.)"/> 
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:attribute>
+        <xsl:attribute name="href"> <xsl:value-of select="$filename"/> </xsl:attribute>
+        <xsl:attribute name="media-type">
+          <xsl:call-template name="guess-media-type">
+            <xsl:with-param name="ext" select="@format"/>
+          </xsl:call-template>
+        </xsl:attribute>
+      </xsl:element>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- Warning: While the test indicate this match list is accurate, it may 
+       need further tweaking to ensure _never_ dropping generated content (XHTML)
+       from the manifest (OPF file) -->
+  <xsl:template
+      match="set|
+            book[parent::set]|
+            book[*[last()][self::bookinfo]]|
+            book[bookinfo]|
+            article|
+            part|
+            reference|
+            preface|
+            chapter|
+            bibliography|
+            appendix|
+            glossary|
+            section|
+            sect1|
+            sect2|
+            sect3|
+            sect4|
+            sect5|
+            refentry|
+            colophon|
+            bibliodiv[title]|
+            setindex|
+            index"
+      mode="opf.manifest">
+    <xsl:variable name="href">
+      <xsl:call-template name="href.target.with.base.dir">
+        <xsl:with-param name="context" select="/" />
+        <!-- Generate links relative to the location of root file/toc.xml file -->
+      </xsl:call-template>
+    </xsl:variable>
+
+    <xsl:variable name="id">
+      <xsl:value-of select="generate-id(.)"/>
+    </xsl:variable>
+
+    <xsl:variable name="is.chunk">
+      <xsl:call-template name="chunk">
+        <xsl:with-param name="node" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+
+    <xsl:if test="$is.chunk != 0">
+      <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+        <xsl:attribute name="id"> <xsl:value-of select="$id"/> </xsl:attribute>
+        <xsl:attribute name="href"> <xsl:value-of select="$href"/> </xsl:attribute>
+        <xsl:attribute name="media-type">application/xhtml+xml</xsl:attribute>
+      </xsl:element>
+    </xsl:if>  
+  </xsl:template>  
+
+  <xsl:template match="text()" mode="ncx" />
+
+  <xsl:template name="html.head">
+    <xsl:param name="prev" select="/foo"/>
+    <xsl:param name="next" select="/foo"/>
+    <xsl:variable name="this" select="."/>
+    <xsl:variable name="home" select="/*[1]"/>
+    <xsl:variable name="up" select="parent::*"/>
+
+    <head xmlns="http://www.w3.org/1999/xhtml">
+      <xsl:call-template name="system.head.content"/>
+      <xsl:call-template name="head.content"/>
+
+      <xsl:call-template name="user.head.content"/>
+    </head>
+  </xsl:template>
+
+  <!-- OVERRIDES xhtml-1_1/graphics.xsl -->
+  <!-- we can't deal with no img/@alt, because it's required. Try grabbing a title before it instead (hopefully meaningful) -->
+  <xsl:template name="process.image.attributes">
+    <xsl:param name="alt"/>
+    <xsl:param name="html.width"/>
+    <xsl:param name="html.depth"/>
+    <xsl:param name="longdesc"/>
+    <xsl:param name="scale"/>
+    <xsl:param name="scalefit"/>
+    <xsl:param name="scaled.contentdepth"/>
+    <xsl:param name="scaled.contentwidth"/>
+    <xsl:param name="viewport"/>
+
+    <xsl:choose>
+      <xsl:when test="@contentwidth or @contentdepth">
+        <!-- ignore @width/@depth, @scale, and @scalefit if specified -->
+        <xsl:if test="@contentwidth and $scaled.contentwidth != ''">
+          <xsl:attribute name="width">
+            <xsl:value-of select="$scaled.contentwidth"/>
+          </xsl:attribute>
+        </xsl:if>
+        <xsl:if test="@contentdepth and $scaled.contentdepth != ''">
+          <xsl:attribute name="height">
+            <xsl:value-of select="$scaled.contentdepth"/>
+          </xsl:attribute>
+        </xsl:if>
+      </xsl:when>
+
+      <xsl:when test="number($scale) != 1.0">
+        <!-- scaling is always uniform, so we only have to specify one dimension -->
+        <!-- ignore @scalefit if specified -->
+        <xsl:attribute name="width">
+          <xsl:value-of select="$scaled.contentwidth"/>
+        </xsl:attribute>
+      </xsl:when>
+
+      <xsl:when test="$scalefit != 0">
+        <xsl:choose>
+          <xsl:when test="contains($html.width, '%')">
+            <xsl:choose>
+              <xsl:when test="$viewport != 0">
+                <!-- The *viewport* will be scaled, so use 100% here! -->
+                <xsl:attribute name="width">
+                  <xsl:value-of select="'100%'"/>
+                </xsl:attribute>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:attribute name="width">
+                  <xsl:value-of select="$html.width"/>
+                </xsl:attribute>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+
+          <xsl:when test="contains($html.depth, '%')">
+            <!-- HTML doesn't deal with this case very well...do nothing -->
+          </xsl:when>
+
+          <xsl:when test="$scaled.contentwidth != '' and $html.width != ''                         and $scaled.contentdepth != '' and $html.depth != ''">
+            <!-- scalefit should not be anamorphic; figure out which direction -->
+            <!-- has the limiting scale factor and scale in that direction -->
+            <xsl:choose>
+              <xsl:when test="$html.width div $scaled.contentwidth &gt;                             $html.depth div $scaled.contentdepth">
+                <xsl:attribute name="height">
+                  <xsl:value-of select="$html.depth"/>
+                </xsl:attribute>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:attribute name="width">
+                  <xsl:value-of select="$html.width"/>
+                </xsl:attribute>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+
+          <xsl:when test="$scaled.contentwidth != '' and $html.width != ''">
+            <xsl:attribute name="width">
+              <xsl:value-of select="$html.width"/>
+            </xsl:attribute>
+          </xsl:when>
+
+          <xsl:when test="$scaled.contentdepth != '' and $html.depth != ''">
+            <xsl:attribute name="height">
+              <xsl:value-of select="$html.depth"/>
+            </xsl:attribute>
+          </xsl:when>
+        </xsl:choose>
+      </xsl:when>
+    </xsl:choose>
+
+    <!-- AN OVERRIDE -->
+    <xsl:if test="not(@format ='SVG')">
+      <xsl:attribute name="alt">
+        <xsl:choose>
+          <xsl:when test="$alt != ''">
+            <xsl:value-of select="normalize-space($alt)"/>
+          </xsl:when>
+          <xsl:when test="preceding::title[1]">
+            <xsl:value-of select="normalize-space(preceding::title[1])"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:text>(missing alt)</xsl:text>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+    </xsl:if>
+    <!-- END OF OVERRIDE -->
+
+    <xsl:if test="$longdesc != ''">
+      <xsl:attribute name="longdesc">
+        <xsl:value-of select="$longdesc"/>
+      </xsl:attribute>
+    </xsl:if>
+
+    <xsl:if test="@align and $viewport = 0">
+      <xsl:attribute name="style"><xsl:text>text-align: </xsl:text>
+        <xsl:choose>
+          <xsl:when test="@align = 'center'">middle</xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="@align"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- OVERRIDES xhtml-1_1/chunk-common.xsl   -->
+  <!-- make a bibliography always a chunk -->
+  <xsl:template name="chunk"
+                priority="1">       
+    <xsl:param name="node" select="."/>
+    <!-- returns 1 if $node is a chunk -->
+
+    <!-- ==================================================================== -->
+    <!-- What's a chunk?
+
+        The root element
+        appendix
+        article
+        bibliography  ### NO LONGER TRUE in article or part or book
+        book
+        chapter
+        colophon
+        glossary      in article or part or book
+        index         in article or part or book
+        part
+        preface
+        refentry
+        reference
+        sect{1,2,3,4,5}  if position()>1 && depth < chunk.section.depth
+        section          if position()>1 && depth < chunk.section.depth
+        set
+        setindex
+                                                                              -->
+    <!-- ==================================================================== -->
+
+  <!--
+    <xsl:message>
+      <xsl:text>chunk: </xsl:text>
+      <xsl:value-of select="name($node)"/>
+      <xsl:text>(</xsl:text>
+      <xsl:value-of select="$node/@id"/>
+      <xsl:text>)</xsl:text>
+      <xsl:text> csd: </xsl:text>
+      <xsl:value-of select="$chunk.section.depth"/>
+      <xsl:text> cfs: </xsl:text>
+      <xsl:value-of select="$chunk.first.sections"/>
+      <xsl:text> ps: </xsl:text>
+      <xsl:value-of select="count($node/parent::section)"/>
+      <xsl:text> prs: </xsl:text>
+      <xsl:value-of select="count($node/preceding-sibling::section)"/>
+    </xsl:message>
+  -->
+
+    <xsl:choose>
+      <xsl:when test="not($node/parent::*)">1</xsl:when>
+
+      <xsl:when test="local-name($node) = 'sect1'                     and $chunk.section.depth &gt;= 1                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::sect1) &gt; 0)">
+        <xsl:text>1</xsl:text>
+      </xsl:when>
+      <xsl:when test="local-name($node) = 'sect2'                     and $chunk.section.depth &gt;= 2                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::sect2) &gt; 0)">
+        <xsl:call-template name="chunk">
+          <xsl:with-param name="node" select="$node/parent::*"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:when test="local-name($node) = 'sect3'                     and $chunk.section.depth &gt;= 3                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::sect3) &gt; 0)">
+        <xsl:call-template name="chunk">
+          <xsl:with-param name="node" select="$node/parent::*"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:when test="local-name($node) = 'sect4'                     and $chunk.section.depth &gt;= 4                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::sect4) &gt; 0)">
+        <xsl:call-template name="chunk">
+          <xsl:with-param name="node" select="$node/parent::*"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:when test="local-name($node) = 'sect5'                     and $chunk.section.depth &gt;= 5                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::sect5) &gt; 0)">
+        <xsl:call-template name="chunk">
+          <xsl:with-param name="node" select="$node/parent::*"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:when test="local-name($node) = 'section'                     and $chunk.section.depth &gt;= count($node/ancestor::section)+1                     and ($chunk.first.sections != 0                          or count($node/preceding-sibling::section) &gt; 0)">
+        <xsl:call-template name="chunk">
+          <xsl:with-param name="node" select="$node/parent::*"/>
+        </xsl:call-template>
+      </xsl:when>
+
+      <xsl:when test="local-name($node)='preface'">1</xsl:when>
+      <xsl:when test="local-name($node)='chapter'">1</xsl:when>
+      <xsl:when test="local-name($node)='appendix'">1</xsl:when>
+      <xsl:when test="local-name($node)='article'">1</xsl:when>
+      <xsl:when test="local-name($node)='part'">1</xsl:when>
+      <xsl:when test="local-name($node)='reference'">1</xsl:when>
+      <xsl:when test="local-name($node)='refentry'">1</xsl:when>
+      <xsl:when test="local-name($node)='index' and ($generate.index != 0 or count($node/*) &gt; 0)                     and (local-name($node/parent::*) = 'article'                     or local-name($node/parent::*) = 'book'                     or local-name($node/parent::*) = 'part'                     )">1</xsl:when>
+      <!-- AN OVERRIDE -->
+      <xsl:when test="local-name($node)='bibliography'">1</xsl:when>
+      <!-- END OF OVERRIDE -->
+      <xsl:when test="local-name($node)='glossary'                     and (local-name($node/parent::*) = 'article'                     or local-name($node/parent::*) = 'book'                     or local-name($node/parent::*) = 'part'                     )">1</xsl:when>
+      <xsl:when test="local-name($node)='colophon'">1</xsl:when>
+      <xsl:when test="local-name($node)='book'">1</xsl:when>
+      <xsl:when test="local-name($node)='set'">1</xsl:when>
+      <xsl:when test="local-name($node)='setindex'">1</xsl:when>
+      <xsl:when test="local-name($node)='legalnotice'                     and $generate.legalnotice.link != 0">1</xsl:when>
+      <xsl:otherwise>0</xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- OVERRIDES xhtml-1_1/chunk-code.xsl   -->
+  <!-- Add chunking for bibliography as root element -->
+  <!-- AN OVERRIDE --> 
+  <xsl:template match="set|
+                       book|
+                       part|
+                       preface|
+                       chapter|
+                       appendix|
+                       article|
+                       reference|
+                       refentry|
+                       book/glossary|
+                       article/glossary|
+                       part/glossary|
+                       bibliography|
+                       colophon"
+                priority="1">       
+  <!-- END OF OVERRIDE --> 
+    <xsl:choose>
+      <xsl:when test="$onechunk != 0 and parent::*">
+        <xsl:apply-imports/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="process-chunk-element"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- OVERRIDES xhtml-1_1/graphics.xsl   -->
+  <!-- Do _NOT_ output any xlink garbage, so if you don't have 
+       processor with extensions, you're screwed and we're terminating -->
+  <xsl:template match="inlinegraphic">
+    <xsl:variable name="filename">
+      <xsl:choose>
+        <xsl:when test="@entityref">
+          <xsl:value-of select="unparsed-entity-uri(@entityref)"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:apply-templates select="@fileref"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <xsl:call-template name="anchor"/>
+
+    <xsl:choose>
+      <xsl:when test="@format='linespecific'">
+        <xsl:choose>
+          <xsl:when test="$use.extensions != '0'                         and $textinsert.extension != '0'">
+            <xsl:choose>
+              <xsl:when test="element-available('stext:insertfile')">
+                <stext:insertfile href="{$filename}" encoding="{$textdata.default.encoding}"/>
+              </xsl:when>
+              <xsl:when test="element-available('xtext:insertfile')">
+                <xtext:insertfile href="{$filename}"/>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:message terminate="yes">
+                  <xsl:text>No insertfile extension available.</xsl:text>
+                </xsl:message>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <!-- AN OVERRIDE --> 
+            <xsl:message terminate="yes">
+              <xsl:text>No insertfile extension available. Use a different processor (with extensions) or turn on $use.extensions and $textinsert.extension (see docs for more).  </xsl:text>
+            </xsl:message>
+            <!-- END OF OVERRIDE --> 
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="process.image"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>  
+
+  <xsl:template name="cover">
+    <xsl:apply-templates select="/*/*[contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]"/>
+  </xsl:template>  
+
+  <xsl:template match="/*/*[cover or contains(name(.), 'info')]//mediaobject[@role='cover' or ancestor::cover]">
+    <xsl:call-template name="write.chunk">
+      <xsl:with-param name="filename">
+        <xsl:value-of select="$epub.cover.filename" />
+      </xsl:with-param>
+      <xsl:with-param name="method" select="'xml'" />
+      <xsl:with-param name="encoding" select="'utf-8'" />
+      <xsl:with-param name="indent" select="'no'" />
+      <xsl:with-param name="quiet" select="$chunk.quietly" />
+      <xsl:with-param name="content">
+        <xsl:element namespace="http://www.w3.org/1999/xhtml" name="html">
+          <xsl:element namespace="http://www.w3.org/1999/xhtml" name="head">
+            <xsl:element namespace="http://www.w3.org/1999/xhtml" name="title">Cover</xsl:element>
+            <xsl:element namespace="http://www.w3.org/1999/xhtml" name="style">
+              <xsl:attribute name="type">text/css</xsl:attribute>
+              <!-- Help the cover image scale nicely in the CSS then apply a max-width to look better in Adobe Digital Editions -->
+              <xsl:text> img { max-width: 100%; }</xsl:text>
+            </xsl:element>
+          </xsl:element>
+          <xsl:element namespace="http://www.w3.org/1999/xhtml" name="body">
+            <xsl:element namespace="http://www.w3.org/1999/xhtml" name="div">
+              <xsl:attribute name="id">
+                <xsl:value-of select="$epub.cover.image.id"/>
+              </xsl:attribute>
+              <xsl:choose>
+                <xsl:when test="imageobject[@role='front-large']">
+                  <xsl:apply-templates select="imageobject[@role='front-large']"/>
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:apply-templates select="imageobject[1]"/>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:element>
+            <!-- If this is defined as an explicit cover page, then process
+            any remaining text -->
+            <xsl:if test="ancestor::cover">
+              <xsl:apply-templates select="ancestor::cover/para"/>
+            </xsl:if>
+          </xsl:element>
+        </xsl:element>
+      </xsl:with-param>  
+    </xsl:call-template>  
+  </xsl:template>
+
+  <xsl:template name="cover-svg">
+    <xsl:param name="node"/>
+  </xsl:template>
+
+  <xsl:template name="toc-href">
+    <xsl:param name="node" select="."/>
+    <xsl:apply-templates select="$node" mode="recursive-chunk-filename">
+      <xsl:with-param name="recursive" select="true()"/>
+    </xsl:apply-templates>
+    <xsl:text>-toc</xsl:text>
+    <xsl:value-of select="$html.ext"/>
+  </xsl:template>
+
+  <xsl:template match="bibliodiv[title]" mode="label.markup">
+  </xsl:template>
+
+  <xsl:template match="token" mode="opf.manifest.font">
+    <xsl:call-template name="embedded-font-item">
+      <xsl:with-param name="font.file" select="."/>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="embedded-font-item">
+    <xsl:param name="font.file"/>
+    <xsl:param name="font.order" select="1"/>
+
+    <xsl:element namespace="http://www.idpf.org/2007/opf" name="item">
+      <xsl:attribute name="id">
+        <xsl:value-of select="concat('epub.embedded.font.', $font.order)"/>
+      </xsl:attribute>
+      <xsl:attribute name="href"><xsl:value-of select="$font.file"/></xsl:attribute>
+      <xsl:choose>
+        <xsl:when test="contains($font.file, 'otf')">
+          <xsl:attribute name="media-type">font/opentype</xsl:attribute>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:message>
+            <xsl:text>WARNING: OpenType fonts should be supplied! (</xsl:text>
+            <xsl:value-of select="$font.file"/>
+            <xsl:text>)</xsl:text>
+          </xsl:message>
+        </xsl:otherwise>  
+      </xsl:choose>
+    </xsl:element>
+  </xsl:template>
+
+<!-- Change section.heading to improve SEO on generated HTML by doing heading levels 
+     "correctly". SEO rules are sometimes silly silly, but this does actually create 
+     a semantic improvement.
+     Note: This template needs to be manually maintained outside of the html/sections.xsl 
+     code, so make sure important changes get reintegrated. -->
+<xsl:template name="section.heading">
+  <xsl:param name="section" select="."/>
+  <xsl:param name="level" select="1"/>
+  <xsl:param name="allow-anchors" select="1"/>
+  <xsl:param name="title"/>
+  <xsl:param name="class" select="'title'"/>
+
+  <xsl:variable name="id">
+    <xsl:choose>
+      <!-- Make sure the subtitle doesn't get the same id as the title -->
+      <xsl:when test="self::subtitle">
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select="."/>
+        </xsl:call-template>
+      </xsl:when>
+      <!-- if title is in an *info wrapper, get the grandparent -->
+      <xsl:when test="contains(local-name(..), 'info')">
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select="../.."/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select=".."/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <!-- For SEO, we try to actually ensure we *always* output one and only one h1,
+       so unlike the regular stylesheets, we don't add one to the section level and
+       we get the right behavior because of chunking. -->
+  <xsl:variable name="hlevel">
+    <xsl:choose>
+      <!-- highest valid HTML H level is H6; so anything nested deeper
+           than 7 levels down just becomes H6 -->
+      <xsl:when test="$level &gt; 6">6</xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$level"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+  <xsl:element name="h{$hlevel}" namespace="http://www.w3.org/1999/xhtml">
+    <xsl:attribute name="class"><xsl:value-of select="$class"/></xsl:attribute>
+    <xsl:if test="$css.decoration != '0'">
+      <xsl:if test="$hlevel&lt;3">
+        <xsl:attribute name="style">clear: both</xsl:attribute>
+      </xsl:if>
+    </xsl:if>
+    <xsl:if test="$allow-anchors != 0 and $generate.id.attributes = 0">
+      <xsl:call-template name="anchor">
+        <xsl:with-param name="node" select="$section"/>
+        <xsl:with-param name="conditional" select="0"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:if test="$generate.id.attributes != 0 and not(local-name(.) = 'appendix')">
+      <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute>
+    </xsl:if>
+    <xsl:copy-of select="$title"/>
+  </xsl:element>
+</xsl:template>
+
+<!-- ==================================================================== -->
+
+<xsl:template match="bridgehead">
+  <xsl:variable name="container" select="(ancestor::appendix                         |ancestor::article                         |ancestor::bibliography                         |ancestor::chapter                         |ancestor::glossary                         |ancestor::glossdiv                         |ancestor::index                         |ancestor::partintro                         |ancestor::preface                         |ancestor::refsect1                         |ancestor::refsect2                         |ancestor::refsect3                         |ancestor::sect1                         |ancestor::sect2                         |ancestor::sect3                         |ancestor::sect4                         |ancestor::sect5                         |ancestor::section                         |ancestor::setindex                         |ancestor::simplesect)[last()]"/>
+
+  <xsl:variable name="clevel">
+    <xsl:choose>
+      <xsl:when test="local-name($container) = 'appendix'                       or local-name($container) = 'chapter'                       or local-name($container) = 'article'                       or local-name($container) = 'bibliography'                       or local-name($container) = 'glossary'                       or local-name($container) = 'index'                       or local-name($container) = 'partintro'                       or local-name($container) = 'preface'                       or local-name($container) = 'setindex'">1</xsl:when>
+      <xsl:when test="local-name($container) = 'glossdiv'">
+        <xsl:value-of select="count(ancestor::glossdiv)+1"/>
+      </xsl:when>
+      <xsl:when test="local-name($container) = 'sect1'                       or local-name($container) = 'sect2'                       or local-name($container) = 'sect3'                       or local-name($container) = 'sect4'                       or local-name($container) = 'sect5'                       or local-name($container) = 'refsect1'                       or local-name($container) = 'refsect2'                       or local-name($container) = 'refsect3'                       or local-name($container) = 'section'                       or local-name($container) = 'simplesect'">
+        <xsl:variable name="slevel">
+          <xsl:call-template name="section.level">
+            <xsl:with-param name="node" select="$container"/>
+          </xsl:call-template>
+        </xsl:variable>
+        <xsl:value-of select="$slevel + 1"/>
+      </xsl:when>
+      <xsl:otherwise>1</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <!-- HTML H level is one higher than section level -->
+  <xsl:variable name="hlevel">
+    <xsl:choose>
+      <xsl:when test="@renderas = 'sect1'">1</xsl:when>
+      <xsl:when test="@renderas = 'sect2'">2</xsl:when>
+      <xsl:when test="@renderas = 'sect3'">3</xsl:when>
+      <xsl:when test="@renderas = 'sect4'">4</xsl:when>
+      <xsl:when test="@renderas = 'sect5'">5</xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$clevel + 1"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:element name="h{$hlevel}" namespace="http://www.w3.org/1999/xhtml">
+    <xsl:call-template name="anchor">
+      <xsl:with-param name="conditional" select="0"/>
+    </xsl:call-template>
+    <xsl:apply-templates/>
+  </xsl:element>
+</xsl:template>
+
+<!-- SEO customization #2 -->
+<xsl:template name="component.title">
+  <xsl:param name="node" select="."/>
+
+  <xsl:variable name="level">
+    <xsl:choose>
+      <xsl:when test="ancestor::section">
+        <xsl:value-of select="count(ancestor::section)+1"/>
+      </xsl:when>
+      <xsl:when test="ancestor::sect5">6</xsl:when>
+      <xsl:when test="ancestor::sect4">5</xsl:when>
+      <xsl:when test="ancestor::sect3">4</xsl:when>
+      <xsl:when test="ancestor::sect2">3</xsl:when>
+      <xsl:when test="ancestor::sect1">2</xsl:when>
+      <xsl:otherwise>1</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:element name="h{$level}" namespace="http://www.w3.org/1999/xhtml">
+    <xsl:attribute name="class">title</xsl:attribute>
+    <xsl:if test="$generate.id.attributes = 0">
+      <xsl:call-template name="anchor">
+       <xsl:with-param name="node" select="$node"/>
+       <xsl:with-param name="conditional" select="0"/>
+      </xsl:call-template>
+    </xsl:if>
+      <xsl:apply-templates select="$node" mode="object.title.markup">
+      <xsl:with-param name="allow-anchors" select="1"/>
+    </xsl:apply-templates>
+  </xsl:element>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/cxxtest/doc/examples/Assertions.h b/tools/cxxtest/doc/examples/Assertions.h
new file mode 100644 (file)
index 0000000..b8b4a25
--- /dev/null
@@ -0,0 +1,148 @@
+// Assertions.h
+#include <cxxtest/TestSuite.h>
+
+class Test : public CxxTest::TestSuite
+{
+public:
+
+// @assert:
+    void test_assert(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+    }
+// @:assert
+
+// @assertDelta:
+    void test_assert_delta(void)
+    {
+        TS_ASSERT_DELTA(sqrt(4.0), 2.0, 1e-7);
+    }
+// @:assertDelta
+
+// @assertDiffers:
+    void test_assert_differs(void)
+    {
+        TS_ASSERT_DIFFERS(1, 2);
+    }
+// @:assertDiffers
+
+// @assertEquals:
+    void test_assert_equals(void)
+    {
+        TS_ASSERT_EQUALS(21 % 5, 1);
+    }
+// @:assertEquals
+
+// @assertLessThan:
+    void test_assert_less_than(void)
+    {
+        TS_ASSERT_LESS_THAN(0, 1);
+    }
+// @:assertLessThan
+
+// @assertLessThanEquals:
+    void test_assert_less_than_equals(void)
+    {
+        TS_ASSERT_LESS_THAN_EQUALS(0, 0);
+    }
+// @:assertLessThanEquals
+
+// @assertPredicate:
+    class IsOdd
+    {
+    public:
+        bool operator()(int x) const { return x % 2 == 1; }
+    };
+
+    void test_assert_predicate(void)
+    {
+        TS_ASSERT_PREDICATE(IsOdd, 29);
+    }
+// @:assertPredicate
+
+// @assertRelation:
+    void test_assert_relation(void)
+    {
+        TS_ASSERT_RELATION(std::greater<double>, 1e6, 1000.0);
+    }
+// @:assertRelation
+
+// @assertSameData:
+    void test_assert_same_data(void)
+    {
+        char input = "The quick brown fox ran over the lazy dog";
+        char output[26];
+        memcopy(output, input, 26);
+        TS_ASSERT_SAME_DATA(input, output, 26);
+    }
+// @:assertSameData
+
+// @assertThrows:
+    void throws_runtime_error(void)
+    {
+        raise std::runtime_error, "This method simply generates an exception";
+    }
+
+    void test_assert_throws(void)
+    {
+        TS_ASSERT_THROWS(self.throws_runtime_error(), std::runtime_error);
+    }
+// @:assertThrows
+
+// @assertThrowsAnything:
+    void test_assert_throws_anything(void)
+    {
+        TS_ASSERT_THROWS_ANYTHING(self.throws_runtime_error());
+    }
+// @:assertThrowsAnything
+
+// @assertThrowsAssert:
+    void throws_value(void)
+    {
+        raise 1;
+    }
+
+    void test_assert_throws_assert(void)
+    {
+        TS_ASSERT_THROWS_ASSERT(self.throws_value(), const Error & e, TS_ASSERT_EQUALS(e, 1));
+    }
+// @:assertThrowsAssert
+
+// @assertThrowsEquals:
+    void test_assert_throws_equals(void)
+    {
+        TS_ASSERT_THROWS_EQUALS(self.throws_value(), const Error & e, e.what(), 1);
+    }
+// @:assertThrowsEquals
+
+// @assertThrowsNothing:
+    void throws_nothing(void)
+    { }
+
+    void test_assert_throws_nothing(void)
+    {
+        TS_ASSERT_THROWS_ASSERT(self.throws_nothing());
+    }
+// @:assertThrowsNothing
+
+// @fail:
+    void test_fail(void)
+    {
+        TS_FAIL("This test has failed.");
+    }
+// @:fail
+
+// @trace:
+    void test_trace(void)
+    {
+        TS_TRACE("This is a test tracing message.");
+    }
+// @:trace
+
+// @warn:
+    void test_warn(void)
+    {
+        TS_WARN("This is a warning message.");
+    }
+// @:warn
+};
diff --git a/tools/cxxtest/doc/examples/BadTestSuite1.h b/tools/cxxtest/doc/examples/BadTestSuite1.h
new file mode 100644 (file)
index 0000000..21cd8fc
--- /dev/null
@@ -0,0 +1,19 @@
+// BadTestSuite1.h
+#include <cxxtest/TestSuite.h>
+
+class BadTestSuite1 : public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+#if 0
+    void testSubtraction(void)
+    {
+        TS_ASSERT(1 - 1 < 1);
+        TS_ASSERT_EQUALS(1 - 1, 0);
+    }
+#endif
+};
diff --git a/tools/cxxtest/doc/examples/GetGlobals.sh b/tools/cxxtest/doc/examples/GetGlobals.sh
new file mode 100644 (file)
index 0000000..27d59f8
--- /dev/null
@@ -0,0 +1,4 @@
+if [[ "x$CXXTEST" -eq "x" ]]
+then
+    CXXTEST="../../"
+fi
diff --git a/tools/cxxtest/doc/examples/MockTestSuite.h b/tools/cxxtest/doc/examples/MockTestSuite.h
new file mode 100644 (file)
index 0000000..a9f4b2d
--- /dev/null
@@ -0,0 +1,26 @@
+// MockTestSuite.h
+#include <cxxtest/TestSuite.h>
+#include <time_mock.h>
+
+int generateRandomNumber();
+
+
+class MockObject : public T::Base_time
+{
+public:
+    MockObject(int initial) : counter(initial) {}
+    int counter;
+    time_t time( time_t * ) { return counter++; }
+};
+
+class TestRandom : public CxxTest::TestSuite
+{
+public:
+    void test_generateRandomNumber()
+    {
+        MockObject t(1);
+        TS_ASSERT_EQUALS( generateRandomNumber(), 3 );
+        TS_ASSERT_EQUALS( generateRandomNumber(), 6 );
+        TS_ASSERT_EQUALS( generateRandomNumber(), 9 );
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyClass.h b/tools/cxxtest/doc/examples/MyClass.h
new file mode 100644 (file)
index 0000000..706ac8b
--- /dev/null
@@ -0,0 +1,38 @@
+// MyClass.h
+
+class MyClass 
+{
+public:
+
+   int value;
+
+   MyClass(int value_) : value(value_) {}
+
+   // CxxTest requires a copy constructor
+   MyClass(const MyClass& other) : value(other.value) {}
+
+   // This is required if you want to use TS_ASSERT_EQUALS
+   bool operator==(const MyClass& other) const { return value == other.value; }
+
+   // If you want to use TS_ASSERT_LESS_THAN
+   bool operator<(const MyClass& other) const { return value < other.value; }
+};
+
+#ifdef CXXTEST_RUNNING
+// This declaration is only activated when building a CxxTest test suite
+#include <cxxtest/ValueTraits.h>
+#include <stdio.h>
+
+namespace CxxTest 
+{
+   CXXTEST_TEMPLATE_INSTANTIATION
+   class ValueTraits<MyClass> 
+   {
+      char _s[256];
+
+   public:
+      ValueTraits( const MyClass& m ) { sprintf( _s, "MyClass( %i )", m.value ); }
+      const char *asString() const { return _s; }
+   };
+};
+#endif // CXXTEST_RUNNING
diff --git a/tools/cxxtest/doc/examples/MyTestSuite1.h b/tools/cxxtest/doc/examples/MyTestSuite1.h
new file mode 100644 (file)
index 0000000..f437d11
--- /dev/null
@@ -0,0 +1,12 @@
+// MyTestSuite1.h
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite1 : public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite10.h b/tools/cxxtest/doc/examples/MyTestSuite10.h
new file mode 100644 (file)
index 0000000..dc8e488
--- /dev/null
@@ -0,0 +1,20 @@
+// MyTestSuite10.h
+#include <cxxtest/TestSuite.h>
+#include <MyClass.h>
+
+class MyTestSuite10 : public CxxTest::TestSuite
+{
+public:
+   void test_le()
+   {
+      MyClass x(1), y(2);
+      TS_ASSERT_LESS_THAN( x, y );
+   }
+
+   void test_eq()
+   {
+      MyClass x(1), y(2);
+      TS_ASSERT_EQUALS( x, y );
+   }
+};
+
diff --git a/tools/cxxtest/doc/examples/MyTestSuite11.h b/tools/cxxtest/doc/examples/MyTestSuite11.h
new file mode 100644 (file)
index 0000000..ecd7c3c
--- /dev/null
@@ -0,0 +1,20 @@
+// MyTestSuite11.h
+#include <cxxtest/TestSuite.h>
+#include <TMyClass.h>
+
+class MyTestSuite11 : public CxxTest::TestSuite
+{
+public:
+   void test_le()
+   {
+      TMyClass<int> x(1), y(2);
+      TS_ASSERT_LESS_THAN( x, y );
+   }
+
+   void test_eq()
+   {
+      TMyClass<int> x(1), y(2);
+      TS_ASSERT_EQUALS( x, y );
+   }
+};
+
diff --git a/tools/cxxtest/doc/examples/MyTestSuite2.h b/tools/cxxtest/doc/examples/MyTestSuite2.h
new file mode 100644 (file)
index 0000000..b5def59
--- /dev/null
@@ -0,0 +1,19 @@
+// MyTestSuite2.h
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite2 : public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+
+    void testMultiplication(void)
+    {
+        TS_TRACE("Starting multiplication test");
+        TS_ASSERT_EQUALS(2 * 2, 5);
+        TS_TRACE("Finishing multiplication test");
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite3.h b/tools/cxxtest/doc/examples/MyTestSuite3.h
new file mode 100644 (file)
index 0000000..cb90643
--- /dev/null
@@ -0,0 +1,32 @@
+// MyTestSuite3.h
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite3 : public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+
+//   void testMultiplication( void )
+//   {
+//      TS_ASSERT( 1 * 1 < 2 );
+//      TS_ASSERT_EQUALS( 1 * 1, 2 );
+//   }
+
+/*
+     void testSubtraction( void )
+     {
+        TS_ASSERT( 1 - 1 < 1 );
+        TS_ASSERT_EQUALS( 1 - 1, 0 );
+     }
+*/
+
+    void XtestDivision(void)
+    {
+        TS_ASSERT(1 / 1 < 2);
+        TS_ASSERT_EQUALS(1 / 1, 1);
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite4.h b/tools/cxxtest/doc/examples/MyTestSuite4.h
new file mode 100644 (file)
index 0000000..89236ee
--- /dev/null
@@ -0,0 +1,14 @@
+// MyTestSuite4.h
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite4
+    :
+public CxxTest::TestSuite
+{
+public:
+    void testAddition(void)
+    {
+        TS_ASSERT(1 + 1 > 1);
+        TS_ASSERT_EQUALS(1 + 1, 2);
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite5.h b/tools/cxxtest/doc/examples/MyTestSuite5.h
new file mode 100644 (file)
index 0000000..788c2ec
--- /dev/null
@@ -0,0 +1,35 @@
+// MyTestSuite5.h
+#include <cxxtest/TestSuite.h>
+#include <string.h>
+
+class MyTestSuite5 : public CxxTest::TestSuite
+{
+    char *_buffer;
+
+public:
+
+    void setUp()
+    {
+        _buffer = new char[1024];
+    }
+
+    void tearDown()
+    {
+        delete [] _buffer;
+    }
+
+    void test_strcpy()
+    {
+        strcpy(_buffer, "Hello, world!");
+        TS_ASSERT_EQUALS(_buffer[0], 'H');
+        TS_ASSERT_EQUALS(_buffer[1], 'e');
+    }
+
+    void test_memcpy()
+    {
+        memcpy(_buffer, "Hello, world!", sizeof(char));
+        TS_ASSERT_EQUALS(_buffer[0], 'H');
+        TS_ASSERT_EQUALS(_buffer[1], 'e');
+    }
+};
+
diff --git a/tools/cxxtest/doc/examples/MyTestSuite6.h b/tools/cxxtest/doc/examples/MyTestSuite6.h
new file mode 100644 (file)
index 0000000..3401609
--- /dev/null
@@ -0,0 +1,24 @@
+// MyTestSuite6.h
+#include <cxxtest/TestSuite.h>
+
+class MyTestSuite6 : public CxxTest::TestSuite
+{
+public:
+
+    static MyTestSuite6* createSuite() 
+    {
+    #ifdef _MSC_VER
+    return new MyTestSuite6();
+    #else
+    return 0;
+    #endif
+    }
+
+    static void destroySuite( MyTestSuite6* suite ) 
+    { delete suite; }
+
+    void test_nothing()
+    {
+        TS_FAIL( "Nothing to test" );
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite7.h b/tools/cxxtest/doc/examples/MyTestSuite7.h
new file mode 100644 (file)
index 0000000..dd0fa4a
--- /dev/null
@@ -0,0 +1,35 @@
+// MyTestSuite7.h
+#include <cxxtest/TestSuite.h>
+#include <iostream>
+
+class MyTestSuite7 : public CxxTest::TestSuite
+{
+public:
+
+   struct Data
+   {
+      char data[3];
+      bool operator==(Data o) {
+          return (memcmp(this, &o, sizeof(o)) == 0);
+      }
+   };
+
+   struct Data2
+   {
+      char data[3];
+   };
+
+   void testCompareData()
+   {
+      Data x, y;
+      memset( x.data, 0x12, sizeof(x.data) );
+      memset( y.data, 0xF6, sizeof(y.data) );
+      TS_ASSERT_EQUALS( x, y );
+
+      Data2 z, w;
+      memset( z.data, 0x12, sizeof(x.data) );
+      memset( w.data, 0xF6, sizeof(y.data) );
+      TS_ASSERT_SAME_DATA( &z, &w, sizeof(z) )
+   }
+};
+
diff --git a/tools/cxxtest/doc/examples/MyTestSuite8.h b/tools/cxxtest/doc/examples/MyTestSuite8.h
new file mode 100644 (file)
index 0000000..e1c92c5
--- /dev/null
@@ -0,0 +1,71 @@
+// MyTestSuite8.h
+#include <cstdio>
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+
+//
+// Fixture1 counts its setUp()s and tearDown()s
+//
+class Fixture1 : public CxxTest::GlobalFixture
+{
+public:
+    unsigned setUpCount;
+    unsigned tearDownCount;
+
+    Fixture1() { setUpCount = tearDownCount = 0; }
+
+    bool setUp() { ++ setUpCount; return true; }
+    bool tearDown() { ++ tearDownCount; return true; }
+
+    bool setUpWorld() { printf( "Starting a test suite\n" ); return true;}
+    bool tearDownWorld() { printf( "Finishing a test suite\n" ); return true;}
+};
+static Fixture1 fixture1;
+
+
+//
+// Fixture2 counts its setUp()s and tearDown()s and makes sure
+// its setUp() is called after Fixture1 and its tearDown() before.
+//
+class Fixture2 : public Fixture1
+{
+public:
+    bool setUp()
+    {
+        TS_ASSERT_EQUALS(setUpCount, fixture1.setUpCount - 1);
+        TS_ASSERT_EQUALS(tearDownCount, fixture1.tearDownCount);
+        return Fixture1::setUp();
+    }
+
+    bool tearDown()
+    {
+        TS_ASSERT_EQUALS(setUpCount, fixture1.setUpCount);
+        TS_ASSERT_EQUALS(tearDownCount, fixture1.tearDownCount);
+        return Fixture1::tearDown();
+    }
+};
+static Fixture2 fixture2;
+
+
+//
+// Verify the counts for the global fixtures
+//
+class MyTestSuite8 : public CxxTest::TestSuite
+{
+public:
+    void testCountsFirstTime()
+    {
+        TS_ASSERT_EQUALS(fixture1.setUpCount,    1);
+        TS_ASSERT_EQUALS(fixture1.tearDownCount, 0);
+        TS_ASSERT_EQUALS(fixture2.setUpCount,    1);
+        TS_ASSERT_EQUALS(fixture2.tearDownCount, 0);
+    }
+
+    void testCountsSecondTime()
+    {
+        TS_ASSERT_EQUALS(fixture1.setUpCount,    2);
+        TS_ASSERT_EQUALS(fixture1.tearDownCount, 1);
+        TS_ASSERT_EQUALS(fixture2.setUpCount,    2);
+        TS_ASSERT_EQUALS(fixture2.tearDownCount, 1);
+    }
+};
diff --git a/tools/cxxtest/doc/examples/MyTestSuite9.h b/tools/cxxtest/doc/examples/MyTestSuite9.h
new file mode 100644 (file)
index 0000000..300b691
--- /dev/null
@@ -0,0 +1,33 @@
+// MyTestSuite9.h
+#include <cxxtest/TestSuite.h>
+
+enum Answer {
+    Yes,
+    No,
+    Maybe,
+    DontKnow,
+    DontCare
+};
+
+// Declare value traits for the Answer enumeration
+CXXTEST_ENUM_TRAITS( Answer,
+                     CXXTEST_ENUM_MEMBER( Yes )
+                     CXXTEST_ENUM_MEMBER( No )
+                     CXXTEST_ENUM_MEMBER( Maybe )
+                     CXXTEST_ENUM_MEMBER( DontKnow )
+                     CXXTEST_ENUM_MEMBER( DontCare ) );
+
+// Test the trait values
+class EnumTraits : public CxxTest::TestSuite
+{
+public:
+    void test_Enum_traits()
+    {
+        TS_FAIL( Yes );
+        TS_FAIL( No );
+        TS_FAIL( Maybe );
+        TS_FAIL( DontKnow );
+        TS_FAIL( DontCare );
+        TS_FAIL( (Answer)1000 );
+    }
+};
diff --git a/tools/cxxtest/doc/examples/TMyClass.h b/tools/cxxtest/doc/examples/TMyClass.h
new file mode 100644 (file)
index 0000000..e60978c
--- /dev/null
@@ -0,0 +1,43 @@
+// TMyClass.h
+
+template<class T>
+class TMyClass 
+{
+public:
+
+   T value;
+
+   TMyClass(const T& value_) : value(value_) {}
+
+   // CxxTest requires a copy constructor
+   TMyClass(const TMyClass<T>& other) : value(other.value) {}
+
+   // This is required if you want to use TS_ASSERT_EQUALS
+   bool operator==(const TMyClass<T>& other) const { return value == other.value; }
+
+   // If you want to use TS_ASSERT_LESS_THAN
+   bool operator<(const TMyClass<T>& other) const { return value < other.value; }
+};
+
+#ifdef CXXTEST_RUNNING
+// This declaration is only activated when building a CxxTest test suite
+#include <cxxtest/ValueTraits.h>
+#include <typeinfo>
+#include <sstream>
+
+namespace CxxTest 
+{
+   template <class T>
+   class ValueTraits< TMyClass<T> > 
+   {
+   public:
+      std::ostringstream _s;
+
+      ValueTraits( const TMyClass<T>& t ) { _s << typeid(t).name() << "( " << t.value << " )"; }
+
+      ValueTraits( const ValueTraits< TMyClass<T> >& value ) { _s << value._s.rdbuf(); }
+
+      const char *asString() const { return _s.str().c_str(); }
+   };
+};
+#endif // CXXTEST_RUNNING
diff --git a/tools/cxxtest/doc/examples/buildRunner.sh b/tools/cxxtest/doc/examples/buildRunner.sh
new file mode 100644 (file)
index 0000000..b8153a1
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite1.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner.txt b/tools/cxxtest/doc/examples/buildRunner.txt
new file mode 100644 (file)
index 0000000..d924af7
--- /dev/null
@@ -0,0 +1 @@
+Running 1 test.OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner10.sh b/tools/cxxtest/doc/examples/buildRunner10.sh
new file mode 100644 (file)
index 0000000..eab8528
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen -o runner.cpp --template runner10.tpl MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner10.txt b/tools/cxxtest/doc/examples/buildRunner10.txt
new file mode 100644 (file)
index 0000000..e0e5efb
--- /dev/null
@@ -0,0 +1,7 @@
+Starting test runner
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
+Stopping test runner
diff --git a/tools/cxxtest/doc/examples/buildRunner11.sh b/tools/cxxtest/doc/examples/buildRunner11.sh
new file mode 100644 (file)
index 0000000..dd354f9
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen -f --error-printer -o runner.cpp MyTestSuite3.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner11.txt b/tools/cxxtest/doc/examples/buildRunner11.txt
new file mode 100644 (file)
index 0000000..62b72cc
--- /dev/null
@@ -0,0 +1,2 @@
+Parsing file MyTestSuite3.hdone.
+Running 1 test.OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner12.sh b/tools/cxxtest/doc/examples/buildRunner12.sh
new file mode 100644 (file)
index 0000000..3c4278e
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen -f --error-printer -o runner.cpp MyTestSuite4.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner12.txt b/tools/cxxtest/doc/examples/buildRunner12.txt
new file mode 100644 (file)
index 0000000..5e738c6
--- /dev/null
@@ -0,0 +1,2 @@
+Parsing file MyTestSuite4.h done.
+Running 1 test.OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner13.sh b/tools/cxxtest/doc/examples/buildRunner13.sh
new file mode 100644 (file)
index 0000000..ae3e5ba
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen -f --error-printer -o runner.cpp MyTestSuite1.h MyTestSuite2.h MyTestSuite4.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+# @help:
+./runner --help
+# @:help
+./runner --help &> runner13.help.txt
+
+# @helpTests:
+./runner --help-tests
+# @:helpTests
+./runner --help-tests &> runner13.helpTests.txt
+
+# @MyTestSuite2:
+./runner MyTestSuite2
+# @:MyTestSuite2
+./runner MyTestSuite2 &> runner13.MyTestSuite2.txt
+
+# @testMultiplication:
+./runner MyTestSuite2 testMultiplication
+# @:testMultiplication
+./runner MyTestSuite2 testMultiplication &> runner13.testMultiplication.txt
+
+# @testMultiplicationVerbose:
+./runner -v MyTestSuite2 testMultiplication
+# @:testMultiplicationVerbose
+./runner -v MyTestSuite2 testMultiplication &> runner13.testMultiplicationVerbose.txt
+
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner14.sh b/tools/cxxtest/doc/examples/buildRunner14.sh
new file mode 100644 (file)
index 0000000..215b2ce
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite5.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner14.txt b/tools/cxxtest/doc/examples/buildRunner14.txt
new file mode 100644 (file)
index 0000000..9850f82
--- /dev/null
@@ -0,0 +1 @@
+Running 2 tests..OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner15.sh b/tools/cxxtest/doc/examples/buildRunner15.sh
new file mode 100644 (file)
index 0000000..20c0ce0
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite6.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner15.txt b/tools/cxxtest/doc/examples/buildRunner15.txt
new file mode 100644 (file)
index 0000000..7132442
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In MyTestSuite6::<no test>:
+MyTestSuite6.h:8: Error: Test failed: createSuite() failed
+MyTestSuite6.h:8: Error: Assertion failed: suite() != 0
+Failed 1 of 1 test
+Success rate: 0%
diff --git a/tools/cxxtest/doc/examples/buildRunner16.sh b/tools/cxxtest/doc/examples/buildRunner16.sh
new file mode 100644 (file)
index 0000000..ba420e6
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MockTestSuite.h
+# @:main
+
+# @compile:
+g++ -o runner -I. -I$CXXTEST runner.cpp time_mock.cpp rand_example.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner16.txt b/tools/cxxtest/doc/examples/buildRunner16.txt
new file mode 100644 (file)
index 0000000..d924af7
--- /dev/null
@@ -0,0 +1 @@
+Running 1 test.OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner17.sh b/tools/cxxtest/doc/examples/buildRunner17.sh
new file mode 100644 (file)
index 0000000..649da61
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite7.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner17.txt b/tools/cxxtest/doc/examples/buildRunner17.txt
new file mode 100644 (file)
index 0000000..8bf2270
--- /dev/null
@@ -0,0 +1,9 @@
+Running 1 test
+In MyTestSuite7::testCompareData:
+MyTestSuite7.h:27: Error: Expected (x == y), found ({ 12 12 12  } != { F6 F6 F6  })
+MyTestSuite7.h:32: Error: Expected sizeof(z) (3) bytes to be equal at (&z) and (&w), found:
+   { 12 12 12 }
+     differs from
+   { F6 F6 F6 }
+Failed 1 of 1 test
+Success rate: 0%
diff --git a/tools/cxxtest/doc/examples/buildRunner18.sh b/tools/cxxtest/doc/examples/buildRunner18.sh
new file mode 100644 (file)
index 0000000..d34b913
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite8.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner18.txt b/tools/cxxtest/doc/examples/buildRunner18.txt
new file mode 100644 (file)
index 0000000..6b072d6
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 testsStarting a test suite
+Starting a test suite
+..Finishing a test suite
+Finishing a test suite
+OK!
diff --git a/tools/cxxtest/doc/examples/buildRunner19.sh b/tools/cxxtest/doc/examples/buildRunner19.sh
new file mode 100644 (file)
index 0000000..64402fc
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite9.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner19.txt b/tools/cxxtest/doc/examples/buildRunner19.txt
new file mode 100644 (file)
index 0000000..ac58c17
--- /dev/null
@@ -0,0 +1,10 @@
+Running 1 test
+In EnumTraits::test_Enum_traits:
+MyTestSuite9.h:26: Error: Test failed: Yes
+MyTestSuite9.h:27: Error: Test failed: No
+MyTestSuite9.h:28: Error: Test failed: Maybe
+MyTestSuite9.h:29: Error: Test failed: DontKnow
+MyTestSuite9.h:30: Error: Test failed: DontCare
+MyTestSuite9.h:31: Error: Test failed: (Answer)1000
+Failed 1 of 1 test
+Success rate: 0%
diff --git a/tools/cxxtest/doc/examples/buildRunner2.sh b/tools/cxxtest/doc/examples/buildRunner2.sh
new file mode 100644 (file)
index 0000000..d90b3b6
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner2.txt b/tools/cxxtest/doc/examples/buildRunner2.txt
new file mode 100644 (file)
index 0000000..677991c
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner20.sh b/tools/cxxtest/doc/examples/buildRunner20.sh
new file mode 100644 (file)
index 0000000..55c4794
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite10.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST -I. runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner20.txt b/tools/cxxtest/doc/examples/buildRunner20.txt
new file mode 100644 (file)
index 0000000..d4e03b2
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite10::test_eq:
+MyTestSuite10.h:17: Error: Expected (x == y), found (MyClass( 1 ) != MyClass( 2 ))
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner21.sh b/tools/cxxtest/doc/examples/buildRunner21.sh
new file mode 100644 (file)
index 0000000..a9f1daf
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --error-printer -o runner.cpp MyTestSuite11.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST -I. runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
+
diff --git a/tools/cxxtest/doc/examples/buildRunner21.txt b/tools/cxxtest/doc/examples/buildRunner21.txt
new file mode 100644 (file)
index 0000000..683b7bb
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite11::test_eq:
+MyTestSuite11.h:17: Error: Expected (x == y), found (8TMyClassIiE( 1 ) != 8TMyClassIiE( 1 ))
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner3.sh b/tools/cxxtest/doc/examples/buildRunner3.sh
new file mode 100644 (file)
index 0000000..f5f5c69
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --runner=ParenPrinter -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner3.txt b/tools/cxxtest/doc/examples/buildRunner3.txt
new file mode 100644 (file)
index 0000000..0c183b6
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h(16): Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner4.sh b/tools/cxxtest/doc/examples/buildRunner4.sh
new file mode 100644 (file)
index 0000000..44a6d53
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --runner=StdioPrinter -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner4.txt b/tools/cxxtest/doc/examples/buildRunner4.txt
new file mode 100644 (file)
index 0000000..677991c
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner5.sh b/tools/cxxtest/doc/examples/buildRunner5.sh
new file mode 100644 (file)
index 0000000..f3c5db0
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --runner=YesNoRunner -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+echo $?
+
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner5.txt b/tools/cxxtest/doc/examples/buildRunner5.txt
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/tools/cxxtest/doc/examples/buildRunner6.sh b/tools/cxxtest/doc/examples/buildRunner6.sh
new file mode 100644 (file)
index 0000000..3fd180c
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --runner=XmlPrinter -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner6.txt b/tools/cxxtest/doc/examples/buildRunner6.txt
new file mode 100644 (file)
index 0000000..91bf05e
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite name="cxxtest"  tests="2" errors="0" failures="1" time="0" >
+    <testcase classname="MyTestSuite2" name="testAddition" line="7" />
+    <testcase classname="MyTestSuite2" name="testMultiplication" line="13">
+        <failure file="MyTestSuite2.h" line="16" type="failedAssertEquals" >Error: Expected (2 * 2 == 5), found (4 != 5)</failure>
+    </testcase>
+</testsuite>
diff --git a/tools/cxxtest/doc/examples/buildRunner7.sh b/tools/cxxtest/doc/examples/buildRunner7.sh
new file mode 100644 (file)
index 0000000..12a25d0
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --xunit-printer -o runner.cpp MyTestSuite2.h
+# @:main
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner7.txt b/tools/cxxtest/doc/examples/buildRunner7.txt
new file mode 100644 (file)
index 0000000..677991c
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/buildRunner8.sh b/tools/cxxtest/doc/examples/buildRunner8.sh
new file mode 100644 (file)
index 0000000..6ecd796
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @main:
+cxxtestgen --gui=X11Gui -o runner.cpp MyTestSuite2.h ../../sample/gui/GreenYellowRed.h
+# @:main
+
+# @compile:
+/opt/local/bin/g++-mp-4.4 -o runner -I$CXXTEST runner.cpp -L/opt/local/lib -lX11
+# @:compile
+
+./runner
+\rm -f runner runner.cpp
diff --git a/tools/cxxtest/doc/examples/buildRunner9.sh b/tools/cxxtest/doc/examples/buildRunner9.sh
new file mode 100644 (file)
index 0000000..3c77bcc
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+. GetGlobals.sh
+export PATH=$CXXTEST/bin:$PATH
+
+# @part:
+cxxtestgen --part --error-printer -o MyTestSuite1.cpp MyTestSuite1.h
+cxxtestgen --part --error-printer -o MyTestSuite2.cpp MyTestSuite2.h
+# @:part
+
+# @root:
+cxxtestgen --root --error-printer -o runner.cpp
+# @:root
+
+# @compile:
+g++ -o runner -I$CXXTEST runner.cpp MyTestSuite1.cpp MyTestSuite2.cpp
+# @:compile
+
+./runner -v
+
+rm -f MyTestSuite1.cpp MyTestSuite2.cpp runner.cpp runner
diff --git a/tools/cxxtest/doc/examples/cxxtestgen.out b/tools/cxxtest/doc/examples/cxxtestgen.out
new file mode 100644 (file)
index 0000000..2659903
--- /dev/null
@@ -0,0 +1,43 @@
+Usage: cxxtestgen [options] [<filename> ...]
+
+Options:
+  -h, --help            show this help message and exit
+  --version             Write the CxxTest version.
+  -o NAME, --output=NAME
+                        Write output to file NAME.
+  -w WORLD, --world=WORLD
+                        The label of the tests, used to name the XML results.
+  --include=HEADER      Include file HEADER in the test runner before other
+                        headers.
+  --abort-on-fail       Abort tests on failed asserts (like xUnit).
+  --main=MAIN           Specify an alternative name for the main() function.
+  --headers=HEADER_FILENAME
+                        Specify a filename that contains a list of header
+                        files that are processed to generate a test runner.
+  --runner=CLASS        Create a test runner that processes test events using
+                        the class CxxTest::CLASS.
+  --gui=CLASS           Create a GUI test runner that processes test events
+                        using the class CxxTest::CLASS. (deprecated)
+  --error-printer       Create a test runner using the ErrorPrinter class, and
+                        allow the use of the standard library.
+  --xunit-printer       Create a test runner using the XUnitPrinter class.
+  --xunit-file=XUNIT_FILE
+                        The file to which the XML summary is written for test
+                        runners using the XUnitPrinter class.  The default XML
+                        filename is TEST-<world>.xml, where <world> is the
+                        value of the --world option.  (default: cxxtest)
+  --have-std            Use the standard library (even if not found in tests).
+  --no-std              Do not use standard library (even if found in tests).
+  --have-eh             Use exception handling (even if not found in tests).
+  --no-eh               Do not use exception handling (even if found in
+                        tests).
+  --longlong=TYPE       Use TYPE as for long long integers.  (default: not
+                        supported)
+  --no-static-init      Do not rely on static initialization in the test
+                        runner.
+  --template=TEMPLATE   Generate the test runner using file TEMPLATE to define
+                        a template.
+  --root                Write the main() function and global data for a test
+                        runner.
+  --part                Write the tester classes for a test runner.
+  -f, --fog-parser      Use new FOG C++ parser
diff --git a/tools/cxxtest/doc/examples/exeRunner.out b/tools/cxxtest/doc/examples/exeRunner.out
new file mode 100644 (file)
index 0000000..421c80d
--- /dev/null
@@ -0,0 +1,5 @@
+Running 3 tests..
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 3 tests
+Success rate: 66%
diff --git a/tools/cxxtest/doc/examples/exeRunner.sh b/tools/cxxtest/doc/examples/exeRunner.sh
new file mode 100644 (file)
index 0000000..9df4454
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# @main:
+./runner
+# @:main
diff --git a/tools/cxxtest/doc/examples/exeRunner2.out b/tools/cxxtest/doc/examples/exeRunner2.out
new file mode 100644 (file)
index 0000000..421c80d
--- /dev/null
@@ -0,0 +1,5 @@
+Running 3 tests..
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 3 tests
+Success rate: 66%
diff --git a/tools/cxxtest/doc/examples/exeRunner2.sh b/tools/cxxtest/doc/examples/exeRunner2.sh
new file mode 100644 (file)
index 0000000..9df4454
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# @main:
+./runner
+# @:main
diff --git a/tools/cxxtest/doc/examples/rand_example.cpp b/tools/cxxtest/doc/examples/rand_example.cpp
new file mode 100644 (file)
index 0000000..19ba939
--- /dev/null
@@ -0,0 +1,7 @@
+// rand_example.cpp
+#include <time_mock.h>
+
+int generateRandomNumber()
+{
+    return T::time( NULL ) * 3;
+}
diff --git a/tools/cxxtest/doc/examples/runner10.tpl b/tools/cxxtest/doc/examples/runner10.tpl
new file mode 100644 (file)
index 0000000..4d3ebb7
--- /dev/null
@@ -0,0 +1,14 @@
+#define CXXTEST_HAVE_EH
+#define CXXTEST_ABORT_TEST_ON_FAIL
+#include <cxxtest/ErrorPrinter.h>
+
+int main()
+{
+    std::cout << "Starting test runner" << std::endl;
+    int status = CxxTest::ErrorPrinter().run();
+    std::cout << "Stopping test runner" << std::endl;
+    return status;
+}
+
+// The CxxTest "world"
+<CxxTest world>
diff --git a/tools/cxxtest/doc/examples/runner13.MyTestSuite2.txt b/tools/cxxtest/doc/examples/runner13.MyTestSuite2.txt
new file mode 100644 (file)
index 0000000..677991c
--- /dev/null
@@ -0,0 +1,5 @@
+Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%
diff --git a/tools/cxxtest/doc/examples/runner13.help.txt b/tools/cxxtest/doc/examples/runner13.help.txt
new file mode 100644 (file)
index 0000000..41a6196
--- /dev/null
@@ -0,0 +1,6 @@
+./runner <suitename>
+./runner <suitename> <testname>
+./runner -h
+./runner --help
+./runner --help-tests
+./runner -v             Enable tracing output.
diff --git a/tools/cxxtest/doc/examples/runner13.helpTests.txt b/tools/cxxtest/doc/examples/runner13.helpTests.txt
new file mode 100644 (file)
index 0000000..872cce9
--- /dev/null
@@ -0,0 +1,6 @@
+Suite/Test Names
+---------------------------------------------------------------------------
+MyTestSuite1 testAddition
+MyTestSuite2 testAddition
+MyTestSuite2 testMultiplication
+MyTestSuite4 testAddition
diff --git a/tools/cxxtest/doc/examples/runner13.testMultiplication.txt b/tools/cxxtest/doc/examples/runner13.testMultiplication.txt
new file mode 100644 (file)
index 0000000..4389a91
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 1 test
+Success rate: 0%
diff --git a/tools/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt b/tools/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt
new file mode 100644 (file)
index 0000000..a705d37
--- /dev/null
@@ -0,0 +1,7 @@
+Running 1 test
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:15: Trace: Starting multiplication test
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+MyTestSuite2.h:17: Trace: Finishing multiplication test
+Failed 1 of 1 test
+Success rate: 0%
diff --git a/tools/cxxtest/doc/examples/test_examples.py b/tools/cxxtest/doc/examples/test_examples.py
new file mode 100644 (file)
index 0000000..0e01284
--- /dev/null
@@ -0,0 +1,27 @@
+# Imports
+import pyutilib.th as unittest
+import glob
+import os
+from os.path import dirname, abspath, basename
+import sys
+
+currdir = dirname(abspath(__file__))+os.sep
+datadir = currdir
+
+def filter(line):
+    return 'Running' in line or "IGNORE" in line
+
+# Declare an empty TestCase class
+class Test(unittest.TestCase): pass
+
+if not sys.platform.startswith('win'):
+    # Find all *.sh files, and use them to define baseline tests
+    for file in glob.glob(datadir+'*.sh'):
+        bname = basename(file)
+        name=bname.split('.')[0]
+        if os.path.exists(datadir+name+'.txt'):
+            Test.add_baseline_test(cwd=datadir, cmd=file, baseline=datadir+name+'.txt', name=name, filter=filter)
+
+# Execute the tests
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/cxxtest/doc/examples/time_mock.cpp b/tools/cxxtest/doc/examples/time_mock.cpp
new file mode 100644 (file)
index 0000000..38d9bd4
--- /dev/null
@@ -0,0 +1,3 @@
+// time_mock.cpp
+#define CXXTEST_MOCK_TEST_SOURCE_FILE
+#include <time_mock.h>
diff --git a/tools/cxxtest/doc/examples/time_mock.h b/tools/cxxtest/doc/examples/time_mock.h
new file mode 100644 (file)
index 0000000..263e4a8
--- /dev/null
@@ -0,0 +1,8 @@
+// time_mock.h
+#include <time.h>
+#include <cxxtest/Mock.h>
+
+CXXTEST_MOCK_GLOBAL( time_t,        /* Return type          */
+                     time,          /* Name of the function */
+                     ( time_t *t ), /* Prototype            */
+                     ( t )          /* Argument list        */ );
diff --git a/tools/cxxtest/doc/examples/time_real.cpp b/tools/cxxtest/doc/examples/time_real.cpp
new file mode 100644 (file)
index 0000000..8503f79
--- /dev/null
@@ -0,0 +1,3 @@
+// time_real.cpp
+#define CXXTEST_MOCK_REAL_SOURCE_FILE
+#include <time_mock.h>
diff --git a/tools/cxxtest/doc/guide.epub b/tools/cxxtest/doc/guide.epub
new file mode 100644 (file)
index 0000000..7956529
Binary files /dev/null and b/tools/cxxtest/doc/guide.epub differ
diff --git a/tools/cxxtest/doc/guide.html b/tools/cxxtest/doc/guide.html
new file mode 100644 (file)
index 0000000..9c0eef0
--- /dev/null
@@ -0,0 +1,3981 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.5" />
+<title>CxxTest User Guide</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+  font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+  font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+  color: navy;
+}
+
+strong {
+  font-weight: bold;
+  color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+h5 {
+  font-size: 1.0em;
+}
+
+div.sectionbody {
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+  margin-top: 0;
+}
+ul > li     { color: #aaa; }
+ul > li > * { color: black; }
+
+pre {
+  padding: 0;
+  margin: 0;
+}
+
+#author {
+  color: #527bbd;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+#preamble {
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.0em;
+  margin-bottom: 2.0em;
+  margin-right: 10%;
+  color: #606060;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  color: #527bbd;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid #dddddd;
+  border-left: 4px solid #f0f0f0;
+  padding: 0.5em;
+}
+
+div.listingblock > div.content {
+  border: 1px solid #dddddd;
+  border-left: 5px solid #f0f0f0;
+  background: #f8f8f8;
+  padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+  padding-left: 1.0em;
+  margin-left: 1.0em;
+  margin-right: 10%;
+  border-left: 5px solid #f0f0f0;
+  color: #777777;
+}
+
+div.quoteblock > div.attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock > pre.content {
+  font-family: inherit;
+  font-size: inherit;
+}
+div.verseblock > div.attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: normal;
+  color: navy;
+}
+dd > *:first-child {
+  margin-top: 0.1em;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+ol.arabic {
+  list-style-type: decimal;
+}
+ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+ol.lowerroman {
+  list-style-type: lower-roman;
+}
+ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+  margin-top: 0.1em;
+  margin-bottom: 0.1em;
+}
+
+tfoot {
+  font-weight: bold;
+}
+td > div.verse {
+  white-space: pre;
+}
+
+div.hdlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hdlist tr {
+  padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+  font-weight: bold;
+}
+td.hdlist1 {
+  vertical-align: top;
+  font-style: normal;
+  padding-right: 0.8em;
+  color: navy;
+}
+td.hdlist2 {
+  vertical-align: top;
+}
+div.hdlist.compact tr {
+  margin: 0;
+  padding-bottom: 0;
+}
+
+.comment {
+  background: yellow;
+}
+
+.footnote, .footnoteref {
+  font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+  vertical-align: super;
+}
+
+#footnotes {
+  margin: 20px 0 20px 0;
+  padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+  margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+  border: none;
+  border-top: 1px solid silver;
+  height: 1px;
+  text-align: left;
+  margin-left: 0;
+  width: 20%;
+  min-width: 100px;
+}
+
+div.colist td {
+  padding-right: 0.5em;
+  padding-bottom: 0.3em;
+  vertical-align: top;
+}
+div.colist td img {
+  margin-top: 0.3em;
+}
+
+@media print {
+  #footer-badges { display: none; }
+}
+
+#toc {
+  margin-bottom: 2.5em;
+}
+
+#toctitle {
+  color: #527bbd;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+tt {
+  font-family: monospace;
+  font-size: inherit;
+  color: navy;
+}
+
+div.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead, p.table.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.table {
+  margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+  border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+  border-left-style: none;
+  border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+  border-top-style: none;
+  border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+.monospaced {
+  font-family: monospace;
+  font-size: inherit;
+  color: navy;
+}
+
+table.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.tableblock {
+  margin-top: 0;
+}
+table.tableblock {
+  border-width: 3px;
+  border-spacing: 0px;
+  border-style: solid;
+  border-color: #527bbd;
+  border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+  border-width: 1px;
+  padding: 4px;
+  border-style: solid;
+  border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+  border-left-style: hidden;
+  border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+  border-top-style: hidden;
+  border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+  border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+  text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+  text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+  text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+  vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+  vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+  vertical-align: bottom;
+}
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = {  // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+  function getText(el) {
+    var text = "";
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+        text += i.data;
+      else if (i.firstChild != null)
+        text += getText(i);
+    }
+    return text;
+  }
+
+  function TocEntry(el, text, toclevel) {
+    this.element = el;
+    this.text = text;
+    this.toclevel = toclevel;
+  }
+
+  function tocEntries(el, toclevels) {
+    var result = new Array;
+    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+    // Function that scans the DOM tree for header elements (the DOM2
+    // nodeIterator API would be a better technique but not supported by all
+    // browsers).
+    var iterate = function (el) {
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+          var mo = re.exec(i.tagName);
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+          }
+          iterate(i);
+        }
+      }
+    }
+    iterate(el);
+    return result;
+  }
+
+  var toc = document.getElementById("toc");
+  if (!toc) {
+    return;
+  }
+
+  // Delete existing TOC entries in case we're reloading the TOC.
+  var tocEntriesToRemove = [];
+  var i;
+  for (i = 0; i < toc.childNodes.length; i++) {
+    var entry = toc.childNodes[i];
+    if (entry.nodeName == 'DIV'
+     && entry.getAttribute("class")
+     && entry.getAttribute("class").match(/^toclevel/))
+      tocEntriesToRemove.push(entry);
+  }
+  for (i = 0; i < tocEntriesToRemove.length; i++) {
+    toc.removeChild(tocEntriesToRemove[i]);
+  }
+
+  // Rebuild TOC entries.
+  var entries = tocEntries(document.getElementById("content"), toclevels);
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+    if (entry.element.id == "")
+      entry.element.id = "_toc_" + i;
+    var a = document.createElement("a");
+    a.href = "#" + entry.element.id;
+    a.appendChild(document.createTextNode(entry.text));
+    var div = document.createElement("div");
+    div.appendChild(a);
+    div.className = "toclevel" + entry.toclevel;
+    toc.appendChild(div);
+  }
+  if (entries.length == 0)
+    toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+  // Delete existing footnote entries in case we're reloading the footnodes.
+  var i;
+  var noteholder = document.getElementById("footnotes");
+  if (!noteholder) {
+    return;
+  }
+  var entriesToRemove = [];
+  for (i = 0; i < noteholder.childNodes.length; i++) {
+    var entry = noteholder.childNodes[i];
+    if (entry.nodeName == 'DIV' && entry.getAttribute("class") == "footnote")
+      entriesToRemove.push(entry);
+  }
+  for (i = 0; i < entriesToRemove.length; i++) {
+    noteholder.removeChild(entriesToRemove[i]);
+  }
+
+  // Rebuild footnote entries.
+  var cont = document.getElementById("content");
+  var spans = cont.getElementsByTagName("span");
+  var refs = {};
+  var n = 0;
+  for (i=0; i<spans.length; i++) {
+    if (spans[i].className == "footnote") {
+      n++;
+      var note = spans[i].getAttribute("data-note");
+      if (!note) {
+        // Use [\s\S] in place of . so multi-line matches work.
+        // Because JavaScript has no s (dotall) regex flag.
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+        spans[i].innerHTML =
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+        spans[i].setAttribute("data-note", note);
+      }
+      noteholder.innerHTML +=
+        "<div class='footnote' id='_footnote_" + n + "'>" +
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+        n + "</a>. " + note + "</div>";
+      var id =spans[i].getAttribute("id");
+      if (id != null) refs["#"+id] = n;
+    }
+  }
+  if (n == 0)
+    noteholder.parentNode.removeChild(noteholder);
+  else {
+    // Process footnoterefs.
+    for (i=0; i<spans.length; i++) {
+      if (spans[i].className == "footnoteref") {
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+        href = href.match(/#.*/)[0];  // Because IE return full URL.
+        n = refs[href];
+        spans[i].innerHTML =
+          "[<a href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+      }
+    }
+  }
+},
+
+install: function(toclevels) {
+  var timerId;
+
+  function reinstall() {
+    asciidoc.footnotes();
+    if (toclevels) {
+      asciidoc.toc(toclevels);
+    }
+  }
+
+  function reinstallAndRemoveTimer() {
+    clearInterval(timerId);
+    reinstall();
+  }
+
+  timerId = setInterval(reinstall, 500);
+  if (document.addEventListener)
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+  else
+    window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install(2);
+/*]]>*/
+</script>
+</head>
+<body class="article">
+<div id="header">
+<h1>CxxTest User Guide</h1>
+<div id="toc">
+  <div id="toctitle">Table of Contents</div>
+  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_abstract">Abstract</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>CxxTest is a unit testing framework for C++ that is similar in
+spirit to <a href="http://junit.org/">JUnit</a>,
+<a href="http://cppunit.sourceforge.net">CppUnit</a>, and
+<a href="http://xprogramming.com/software.html">xUnit</a>.  CxxTest is easy to
+use because it does not require precompiling a CxxTest testing
+library, it employs no advanced features of C++ (e.g. RTTI) and it
+supports a very flexible form of test discovery.  This documentation
+describes CxxTest 4.0, which includes significant enhancements to
+the test discovery process, a modern test driver, and new documentation.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_overview">1. Overview</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>CxxTest is a unit testing framework for C++ that is similar in
+spirit to <a href="http://junit.org/">JUnit</a>,
+<a href="http://cppunit.sourceforge.net">CppUnit</a>, and
+<a href="http://xprogramming.com/software.html">xUnit</a>.
+CxxTest is designed to be as portable as possible;  it does not require</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+RTTI
+</p>
+</li>
+<li>
+<p>
+Member template functions
+</p>
+</li>
+<li>
+<p>
+Exception handling
+</p>
+</li>
+<li>
+<p>
+External libraries (including memory management, file/console I/O, graphics libraries)
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>In particular, the design of CxxTest was tailored for C++ compilers
+on embedded systems, for which many of these features are not
+supported.  However, CxxTest can also leverage standard C++ features
+when they are supported by a compiler (e.g. catch unhandled
+exceptions).</p></div>
+<div class="paragraph"><p>Additionally, CxxTest supports <em>test discovery</em>.  Tests are defined
+in C++ header files, which are parsed by CxxTest to automatically
+generate a test runner.  Thus, CxxTest is somewhat easier to use
+than alternative C++ testing frameworks, since you do not need to
+<em>register</em> tests.</p></div>
+<div class="paragraph"><p>The <a href="http://cxxtest.com">CxxTest Home Page</a> is
+<a href="http://cxxtest.com">http://cxxtest.com</a>.  This webpage contains links
+for <a href="https://sourceforge.net/projects/cxxtest/files/">release downloads</a>,
+the <a href="https://groups.google.com/forum/?hl=en#!forum/cxxtest-forum">CxxTest
+discussion list</a>, and documentation in
+<a href="http://cxxtest.com/cxxtest/doc/guide.html">HTML</a>,
+<a href="http://cxxtest.com/cxxtest/doc/guide.pdf">PDF</a>, and
+<a href="http://cxxtest.comm/cxxtest/doc/guide.epub">EPUB</a> formats.  The
+<a href="http://cxxtest.com">CxxTest Home Page</a> also includes developer
+resources (e.g. <a href="https://software.sandia.gov/hudson/view/CxxTest/">automated
+test results</a>).  CxxTest is available under the
+<a href="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public</a>
+license.</p></div>
+<div class="paragraph"><p>The CxxTest User Guide provides the following documentation:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="#gettingStarted">Getting Started</a>: Some simple examples that illustrate how to use CxxTest
+</p>
+</li>
+<li>
+<p>
+<a href="#testAssertions">Test Assertions</a>: The test assertions supported by CxxTest
+</p>
+</li>
+<li>
+<p>
+<a href="#cxxtestgen">The CxxTestGen Command</a>: Documentation for the <tt>cxxtestgen</tt> command
+</p>
+</li>
+<li>
+<p>
+<a href="#runner">Test Runner Syntax</a>: Discussion of command line options for test runners
+</p>
+</li>
+<li>
+<p>
+<a href="#advanced">Advanced Testing Features</a>: Advanced features of CxxTest
+</p>
+</li>
+<li>
+<p>
+<a href="#traits">Value Traits</a>: Customizing data traits for error messages
+</p>
+</li>
+<li>
+<p>
+<a href="#mock">Testing with Mock Objects</a>: How to test with mock global functions
+</p>
+</li>
+<li>
+<p>
+<a href="#installation">Installation</a>: How to install CxxTest
+</p>
+</li>
+<li>
+<p>
+<a href="#discussion">Status and Future Plans</a>: Comments on the past, present and future of CxxTest
+</p>
+</li>
+</ul></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="gettingStarted">2. Getting Started</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Testing is performed with CxxTest in a four-step process:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Tests are defined in C++ header files
+</p>
+</li>
+<li>
+<p>
+The <tt>cxxtestgen</tt> command processes header files to generate files for the test runner.
+</p>
+</li>
+<li>
+<p>
+Compile the test runner.
+</p>
+</li>
+<li>
+<p>
+Execute the test runner to run all test suites.
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>CxxTest supports test automation, sharing of setup
+and shutdown code for tests, aggregation of tests into collections,
+and independence of the tests from the reporting framework.  To
+achieve this, CxxTest supports some important concepts that are common to xUnit frameworks (
+e.g. <a href="http://junit.org/">JUnit</a>, <a href="http://cppunit.sourceforge.net">CppUnit</a>, and
+<a href="http://xprogramming.com/software.html">xUnit</a>):</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+test fixture
+</dt>
+<dd>
+<p>
+   A <em>test fixture</em> represents the preparation needed to perform one or more
+   tests, and any associate cleanup actions.  This may involve, for example,
+   creating temporary or proxy databases, directories, or starting a server
+   process.
+</p>
+</dd>
+</dl></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+test suite
+</dt>
+<dd>
+<p>
+   A <em>test suite</em> is a collection of test cases, which represent
+   the smallest unit of testing.  A test suite is defined by a class
+   that inherits from the <tt>CxxTest::TestSuite</tt> class, and the tests
+   in a test suite are executed together.
+</p>
+</dd>
+<dt class="hdlist1">
+test
+</dt>
+<dd>
+<p>
+    A test is a public member function of a test suite whose name
+    starts with <tt>test</tt>, e.g. <tt>testDirectoryScanner()</tt>,
+    <tt>test_cool_feature()</tt> and <tt>TestImportantBugFix()</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+test runner
+</dt>
+<dd>
+<p>
+   A <em>test runner</em> is a component which orchestrates the execution
+   of tests across one or more test suites and provides the outcome
+   to the user.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>When building test fixtures using <tt>TestSuite</tt>, the <tt>TestSuite.setUp</tt>
+and <tt>TestSuite.tearDown</tt> methods can be overridden to provide
+initialization and cleanup for the fixture.  The <tt>TestSuite.setUp</tt>
+method is run before each test is executed, and the <tt>TestSuite.tearDown</tt>
+method is run after each test is executed.</p></div>
+<div class="sect2">
+<h3 id="_a_first_example">2.1. A First Example</h3>
+<div class="paragraph"><p>The following is a simple example of a
+test suite with a single test, <tt>testAddition</tt>, which perform two test assertions:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite1.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite1</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testAddition</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>You use the <tt>cxxtestgen</tt> script to generate a <em>test runner</em> for test suites in C++ header files:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --error-printer -o runner<span style="color: #990000">.</span>cpp MyTestSuite1<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>This command generates the file <tt>runner.cpp</tt>, which can be compiled.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --error-printer -o runner<span style="color: #990000">.</span>cpp MyTestSuite1<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>Note that additional compiler flags may be needed to include headers
+and libraries that are used during testing.</p></div>
+<div class="paragraph"><p>This runner can be executed to perform the specified tests:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">.</span>/runner</tt></pre></div></div>
+<div class="paragraph"><p>which generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 3 tests..
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 3 tests
+Success rate: 66%</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_a_second_example">2.2. A Second Example</h3>
+<div class="paragraph"><p>The following header file extends the previous example to
+include a test that generates an error:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite2.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite2</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testAddition</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testMultiplication</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_TRACE</span></span><span style="color: #990000">(</span><span style="color: #FF0000">"Starting multiplication test"</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">2</span> <span style="color: #990000">*</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> <span style="color: #993399">5</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_TRACE</span></span><span style="color: #990000">(</span><span style="color: #FF0000">"Finishing multiplication test"</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>The test runner generated by <tt>cxxtestgen</tt> for this test suite generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 3 tests..
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 3 tests
+Success rate: 66%</tt></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_sample_problems">2.3. Sample Problems</h3>
+<div class="paragraph"><p>CxxTest comes with example test suites in the <tt>cxxtest/sample</tt> subdirectory of
+the distribution.  If you look in that directory, you will see three
+Makefiles: <tt>Makefile.unix</tt>, <tt>Makefile.msvc</tt> and
+<tt>Makefile.bcc32</tt> which are for Linux/Unix, MS Visual C++ and Borland C++, repectively.  These files are provided as a starting point,
+and some options may need to be tweaked in them for your system.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="testAssertions">3. Test Assertions</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The following table summarizes the test assertions supported by CxxTest.
+<a href="#appendix_A">Appendix A</a> provides examples that illustrate the use of these test assertions.</p></div>
+<div class="tableblock">
+<table rules="all"
+width="100%"
+frame="border"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top"> Macro                                                                 </th>
+<th align="left" valign="top"> Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert"><tt>TS_ASSERT(expr)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify <tt>expr</tt> is true</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_delta"><tt>TS_ASSERT_DELTA(x,y,d)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>abs(x-y) &lt; d</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_differs"><tt>TS_ASSERT_DIFFERS(x,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>x != y</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_equals"><tt>TS_ASSERT_EQUALS(x,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>x == y</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_less_than"><tt>TS_ASSERT_LESS_THAN(x,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>x &lt; y</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_less_than_equals"><tt>TS_ASSERT_LESS_THAN_EQUALS(x,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>x &#8656; y</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_predicate"><tt>TS_ASSERT_PREDICATE(P,x)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify <tt>P(x)</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_relation"><tt>TS_ASSERT_RELATION(x,R,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify <tt>x R y</tt></p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_same_data"><tt>TS_ASSERT_SAME_DATA(x,y,size)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify two buffers are equal</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_throws"><tt>TS_ASSERT_THROWS(expr,type)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>expr</tt> throws the specified exception type</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_throws_anything"><tt>TS_ASSERT_THROWS_ANYTHING(expr)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>expr</tt> throws an exception</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_throws_assert"><tt>TS_ASSERT_THROWS_ASSERT(expr,arg,assertion)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify type and value of what <tt>expr</tt> throws</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_throws_equals"><tt>TS_ASSERT_THROWS_EQUALS(expr,arg,x,y)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify type and value of what <tt>expr</tt> throws</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_assert_throws_nothing"><tt>TS_ASSERT_THROWS_NOTHING(expr)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Verify that <tt>expr</tt> doesn&#8217;t throw anything</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_fail"><tt>TS_FAIL(message)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Fail unconditionally</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_trace"><tt>TS_TRACE(message)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Print <tt>message</tt> as an informational message</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><a href="#ts_warn"><tt>TS_WARN(message)</tt></a></p></td>
+<td align="left" valign="top"><p class="table">Print <tt>message</tt> as a warning</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="paragraph"><p>The test assertions supported by CxxTest are defined as macros,
+which eliminates the need for certain templates within CxxTest and
+allows tests to catch exceptions.  There are four categories of
+test assertions in CxxTest, which are distinguished by their prefixes:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+TS_
+</dt>
+<dd>
+<p>
+These test assertions perform a test. Catch exceptions generated
+during testing will cause the test to fail, except for tests that
+check for exceptions.
+</p>
+</dd>
+<dt class="hdlist1">
+TSM_
+</dt>
+<dd>
+<p>
+These test assertions perform the same tests as the corresponding
+<tt>TS</tt> assertions, but their first argument is a <tt>const char*</tt> message
+buffer that is printed when the test fails.
+</p>
+</dd>
+<dt class="hdlist1">
+ETS_
+</dt>
+<dd>
+<p>
+These test assertions perform the same tests as the corresponding
+<tt>TS</tt> assertions.  However, these test assertions do not catch
+exceptions generated during testing.
+</p>
+</dd>
+<dt class="hdlist1">
+ETSM_
+</dt>
+<dd>
+<p>
+These test assertions perform the same tests as the
+corresponding <tt>TS</tt> assertions, but (1) their first argument is a
+<tt>const char*</tt> message buffer is printed when the test fails, and
+(2) these assertions do not catch exceptions generated during
+testing.
+</p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="cxxtestgen">4. The CxxTestGen Command</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> command processes one or more C++ header files to
+generate a test runner.  The <tt>cxxtestgen</tt> command performs test
+discovery by parsing the header files to find test classes, which
+inherit from the class <tt>CxxTest::TestSuite</tt>.</p></div>
+<div class="paragraph"><p>The <tt>--help</tt> option generates the following summary of the <tt>cxxtestgen</tt> command line options:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Usage: cxxtestgen [options] [&lt;filename&gt; ...]
+
+Options:
+  -h, --help            show this help message and exit
+  --version             Write the CxxTest version.
+  -o NAME, --output=NAME
+                        Write output to file NAME.
+  -w WORLD, --world=WORLD
+                        The label of the tests, used to name the XML results.
+  --include=HEADER      Include file HEADER in the test runner before other
+                        headers.
+  --abort-on-fail       Abort tests on failed asserts (like xUnit).
+  --main=MAIN           Specify an alternative name for the main() function.
+  --headers=HEADER_FILENAME
+                        Specify a filename that contains a list of header
+                        files that are processed to generate a test runner.
+  --runner=CLASS        Create a test runner that processes test events using
+                        the class CxxTest::CLASS.
+  --gui=CLASS           Create a GUI test runner that processes test events
+                        using the class CxxTest::CLASS. (deprecated)
+  --error-printer       Create a test runner using the ErrorPrinter class, and
+                        allow the use of the standard library.
+  --xunit-printer       Create a test runner using the XUnitPrinter class.
+  --xunit-file=XUNIT_FILE
+                        The file to which the XML summary is written for test
+                        runners using the XUnitPrinter class.  The default XML
+                        filename is TEST-&lt;world&gt;.xml, where &lt;world&gt; is the
+                        value of the --world option.  (default: cxxtest)
+  --have-std            Use the standard library (even if not found in tests).
+  --no-std              Do not use standard library (even if found in tests).
+  --have-eh             Use exception handling (even if not found in tests).
+  --no-eh               Do not use exception handling (even if found in
+                        tests).
+  --longlong=TYPE       Use TYPE as for long long integers.  (default: not
+                        supported)
+  --no-static-init      Do not rely on static initialization in the test
+                        runner.
+  --template=TEMPLATE   Generate the test runner using file TEMPLATE to define
+                        a template.
+  --root                Write the main() function and global data for a test
+                        runner.
+  --part                Write the tester classes for a test runner.
+  -f, --fog-parser      Use new FOG C++ parser</tt></pre>
+</div></div>
+<div class="paragraph"><p>The following section describe illustrate the use of these command line options.</p></div>
+<div class="sect2">
+<h3 id="_general_options">4.1. General Options</h3>
+<div class="paragraph"><p>The default behavior of <tt>cxxtestgen</tt> is to send the source for the
+test runner to the standard output stream.  The <tt>--output</tt> (<tt>-o</tt>)
+option indicates a filename for the test runner.</p></div>
+<div class="paragraph"><p>The <tt>--world</tt> (<tt>-w</tt>) option specifies the value of the <tt>CxxTest::RealWorldDescription::_worldName</tt>
+variable.  This option also customizes the filename used for XML output files (see below).</p></div>
+<div class="paragraph"><p>The <tt>--include</tt> option defines a filename that is included in the runner before all other headers.</p></div>
+<div class="paragraph"><p>The <tt>--abort-on-fail</tt> option forces an abort if a test fails, rather than continuing execution
+to the next test.</p></div>
+<div class="paragraph"><p>The <tt>--main</tt> option specifies an alternate name for the <tt>main()</tt> function.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_test_listener_options">4.2. Test Listener Options</h3>
+<div class="paragraph"><p>The test runner behavior is controlled by a <em>test listener</em> class
+that is used to define to the <tt>main</tt> function.  The test listener
+class is a subclass of <tt>TestListener</tt> that receives notifications
+about the testing process, notably which assertions failed.  The
+<tt>--runner</tt> option is used to specify the test listener that is used
+in the test runner.  The following test listeners are defined in
+CxxTest:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<tt>ErrorPrinter</tt>
+</dt>
+<dd>
+<p>
+    This is the standard error printer, which formats its output to the standard output stream (<tt>std::cout</tt>).
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>StdioPrinter</tt>
+</dt>
+<dd>
+<p>
+    The same as <tt>ErrorPrinter</tt> except that it uses <tt>printf</tt> instead of <tt>std::cout</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>ParenPrinter</tt>
+</dt>
+<dd>
+<p>
+    Identical to <tt>ErrorPrinter</tt> except that it prints line numbers in parantheses. This is the way Visual Studio expects it.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>XmlPrinter</tt>
+</dt>
+<dd>
+<p>
+    Print test results to an XML file.
+</p>
+</dd>
+<dt class="hdlist1">
+<tt>XUnitPrinter</tt>
+</dt>
+<dd>
+<p>
+    This test listener generates output using both <tt>ErrorPrinter</tt> and <tt>XmlPrinter</tt>.
+</p>
+</dd>
+</dl></div>
+<div class="sect3">
+<h4 id="_errorprinter">4.2.1. ErrorPrinter</h4>
+<div class="paragraph"><p>The <tt>--error-printer</tt> option creates a runner using the <tt>ErrorPrinter</tt>
+test listener, and it indicates that the standard library is used
+in the test runner.  The <tt>ErrorPrinter</tt> test listener prints dots
+to summarize test execution, along with a summary of the test
+results.  For example, the command</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --error-printer -o runner<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 3 tests..
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 3 tests
+Success rate: 66%</tt></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_stdioprinter">4.2.2. StdioPrinter</h4>
+<div class="paragraph"><p>If your compiler does not support <tt>std::cout</tt>, then the <tt>ErrorPrinter</tt> test listener cannot be used.
+In this case, the <tt>StdioPrinter</tt> test listener can be used;  it provides the same output as <tt>ErrorPrinter</tt> but it uses the <tt>printf</tt> function. For example, the command line:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --runner<span style="color: #990000">=</span>StdioPrinter -o runner<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%</tt></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_parenprinter">4.2.3. ParenPrinter</h4>
+<div class="paragraph"><p>The <tt>--runner=ParenPrinter</tt> option creates a similar test runner:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --runner<span style="color: #990000">=</span>ParenPrinter -o runner<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>This test runner generates output that is similar to the <tt>ErrorPrinter</tt> test listener:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h(16): Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The only difference is the parentheses used in the output.  This test listener provides a format that can be recognized by Visual Studio.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_xmlprinter">4.2.4. XmlPrinter</h4>
+<div class="paragraph"><p>The <tt>--runner=XmlPrinter</tt> option creates a test runner whose output is an XML summary of the test results.  For example, the command:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --runner<span style="color: #990000">=</span>XmlPrinter -o runner<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
+&lt;testsuite name="cxxtest"  tests="2" errors="0" failures="1" time="0" &gt;
+    &lt;testcase classname="MyTestSuite2" name="testAddition" line="7" /&gt;
+    &lt;testcase classname="MyTestSuite2" name="testMultiplication" line="13"&gt;
+        &lt;failure file="MyTestSuite2.h" line="16" type="failedAssertEquals" &gt;Error: Expected (2 * 2 == 5), found (4 != 5)&lt;/failure&gt;
+    &lt;/testcase&gt;
+&lt;/testsuite&gt;</tt></pre>
+</div></div>
+<div class="paragraph"><p>This XML format is conforms to the XML standard used by other xUnit tools.  Thus, this output can be used as input in other tools, like <a href="http://jenkins-ci.org/">Jenkins</a>, to generate test summaries.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_xunitprinter">4.2.5. XUnitPrinter</h4>
+<div class="paragraph"><p>The <tt>XUnitPrinter</tt> test listener generates output using both the
+ErrorPrinter+ and <tt>XmlPrinter</tt> test listeners.  This allows the
+user to interactively view a simple test summary, while simultaneously
+generating an XML summary of the test results.  The <tt>--xunit-printer</tt>
+option specifies the use of <tt>XUnitPrinter</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --xunit-printer -o runner<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>This test runner generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The default filename for the XML results is <tt>TEST-cxxtest.xml</tt>.  The <tt>--xunit-file</tt> option can be used to specify an alternative filename.  Additionally, the value of the <tt>--world</tt> option can be used to specify the filename <tt>TEST-&lt;world&gt;.xml</tt>.</p></div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_language_options">4.3. Language Options</h3>
+<div class="paragraph"><p>When <tt>cxxtestgen</tt> performs test discovery, it also performs checks
+to detect whether (1) the standard library is used and (2) exceptions
+are used.  These checks configure CxxTest to <em>not</em> assume that these
+C++ language features are used when generating the test driver.
+Thus, CxxTest can naturally be used with compilers that do not
+support these features.</p></div>
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> command includes several options that override
+these checks and define features of C++ that are used by the test
+runner.  The <tt>--have-std</tt> option indicates that the test runner
+should use the standard library, and the <tt>--no-std</tt> option indicates
+that the test runner should not use the standard library. The
+--have-eh+ options indicates that the test runner should use
+exception handling, and the <tt>--no-eh</tt> indicates that the test runner
+should not not use exception handling.</p></div>
+<div class="paragraph"><p>The <tt>--longlong</tt> option specifies the type used for long long
+integers.  The default is for <em>no</em> long long integer type to be specified,
+which is consistent with the current C++ standard.</p></div>
+<div class="paragraph"><p>CxxTest test runners depend quite heavily on static initialization
+of objects that are used to define and execute tests. The
+--no-static-init+ option can be used to avoid static initialization
+for compilers or linkers that have trouble compiling the default test runner.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_creating_test_runners_from_parts">4.4. Creating Test Runners from Parts</h3>
+<div class="paragraph"><p>The default behavior of <tt>cxxtestgen</tt> is to generate a test runner
+that directly integrates classes that define the tests along with
+a <tt>main()</tt> function that executes all test suites.  It is often useful to
+allow test suites to be processes separately and then linked together.  The <tt>--root</tt> and <tt>--part</tt> options
+support this logic.  For example, suppose that we wish to define a test runner for tests in the headers
+MyTestSuite1.h+ and <tt>MyTestSuite2.h</tt>.  We execute <tt>cxxtestgen</tt> with the <tt>--part</tt> option to generate source files for each of the test suites:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --part --error-printer -o MyTestSuite1<span style="color: #990000">.</span>cpp MyTestSuite1<span style="color: #990000">.</span>h
+cxxtestgen --part --error-printer -o MyTestSuite2<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>Similarly, we execute <tt>cxxtestgen</tt> with the <tt>--root</tt> opiton to generate the <tt>main()</tt> routine:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --root --error-printer -o runner<span style="color: #990000">.</span>cpp</tt></pre></div></div>
+<div class="paragraph"><p>Finally, the test runner is built by compiling all of these source files together:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>g<span style="color: #990000">++</span> -o runner -I<span style="color: #009900">$CXXTEST</span> runner<span style="color: #990000">.</span>cpp MyTestSuite1<span style="color: #990000">.</span>cpp MyTestSuite2<span style="color: #990000">.</span>cpp</tt></pre></div></div>
+</div>
+<div class="sect2">
+<h3 id="_template_files">4.5. Template Files</h3>
+<div class="paragraph"><p>CxxTest supports the use of <em>template files</em> to provide a custom
+main()+ function.  This may be useful when using a custom test
+listener, or when using an existing CxxTest test listener in a
+nonstandard manner.  A template file is an ordinary source files
+with the embedded declaration <tt>&lt;CxxTest world&gt;</tt>, which tells
+cxxtestgen+ to insert the world definition at that point.</p></div>
+<div class="paragraph"><p>The <tt>--template</tt> option is used to specify the use of a template file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen -o runner<span style="color: #990000">.</span>cpp --template runner10<span style="color: #990000">.</span>tpl MyTestSuite2<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>For example, consider the following template file:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_HAVE_EH
+<span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_ABORT_TEST_ON_FAIL
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/ErrorPrinter.h&gt;</span>
+
+<span style="color: #009900">int</span> <span style="font-weight: bold"><span style="color: #000000">main</span></span><span style="color: #990000">()</span>
+<span style="color: #FF0000">{</span>
+    std<span style="color: #990000">::</span>cout <span style="color: #990000">&lt;&lt;</span> <span style="color: #FF0000">"Starting test runner"</span> <span style="color: #990000">&lt;&lt;</span> std<span style="color: #990000">::</span>endl<span style="color: #990000">;</span>
+    <span style="color: #009900">int</span> status <span style="color: #990000">=</span> CxxTest<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #000000">ErrorPrinter</span></span><span style="color: #990000">().</span><span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">();</span>
+    std<span style="color: #990000">::</span>cout <span style="color: #990000">&lt;&lt;</span> <span style="color: #FF0000">"Stopping test runner"</span> <span style="color: #990000">&lt;&lt;</span> std<span style="color: #990000">::</span>endl<span style="color: #990000">;</span>
+    <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> status<span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">// The CxxTest "world"</span></span>
+<span style="color: #990000">&lt;</span><span style="color: #008080">CxxTest</span> world<span style="color: #990000">&gt;</span></tt></pre></div></div>
+<div class="paragraph"><p>This file specifies macros that customize the test runner, and output is generated before and after the tests are run.</p></div>
+<div class="paragraph"><p>Note that CxxTest needs to insert certain definitions and <tt>#include</tt>
+directives in the runner file. It normally does that before the
+first <tt>#include &lt;cxxtest/*.h&gt;</tt> found in the template file. If this
+behavior is not what you need, use the directive <tt>&lt;CxxTest preamble&gt;</tt>
+to specify where this preamble is inserted.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_test_discovery_options">4.6. Test Discovery Options</h3>
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> command performs test discovery by searching C++
+header files for CxxTest test classes.  The default process for
+test discovery is a simple process that analyzes each line in a
+header file sequentially, looking for a sequence of lines that
+represent class definitions and test method definitions.</p></div>
+<div class="paragraph"><p>There are many limitations to this simple process for test discovery,
+and in CxxTest 4.0 a new test discovery mechanism was added based
+on the a parser for the
+<a href="http://www.computing.surrey.ac.uk/research/dsrg/fog/">Flexible Object
+Generator (FOG)</a> language, which is a superset of C+<tt>.  The grammar
+for the FOG language was adapted to parse C</tt>+ header files to
+identify class definitions and class inheritance relationships,
+class and namespace nesting of declarations, and class methods.
+This allows <tt>cxxtestgen</tt> to identify test classes that are defined
+with complex inheritance relationships.</p></div>
+<div class="paragraph"><p>The <tt>--fog</tt> option is used to specify the use of the FOG parser for
+test discovery.  Although the FOG parser is more powerful, the
+simpler <tt>cxxtestgen</tt> test discover process is the default because
+the FOG parser is slower execute.  Additionally, the FOG parser
+requires the installation of <tt>ply</tt> and, for Python version 2.6,
+ordereddict+.  If these packages are not available, then the <tt>--fog</tt>
+option is automatically disabled.</p></div>
+<div class="paragraph"><p>The following sections illustrate differences between these two test discovery mechanisms, along with
+general limitations of the test discovery process.</p></div>
+<div class="sect3">
+<h4 id="_unexpected_test_suite_format">4.6.1. Unexpected Test Suite Format</h4>
+<div class="paragraph"><p>The default test discovery mechanism does a very simple analysis
+of the input files, which can easily fail when test classes are not
+formated in a standard manner.  For example, consider the following
+test suite:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite4.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite4</span>
+    <span style="color: #990000">:</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testAddition</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>This test suite is not recognized by the default test discovery
+mechanism, but the FOG parser correctly parsers this file and
+recognizes the test suite.  A variety of similar discovery failures
+arise due to the simple process used by the test discovery mechanism.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_commenting_out_tests">4.6.2. Commenting Out Tests</h4>
+<div class="paragraph"><p>Adding and disabling tests are two common steps in test development.
+The process of test discovery makes adding tests very easy.  However,
+disabling tests is somewhat more complicated.  Consider the following
+header file, which defines four tests (three of which are disabled):</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite3.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite3</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testAddition</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">//   void testMultiplication( void )</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//   {</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//      TS_ASSERT( 1 * 1 &lt; 2 );</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//      TS_ASSERT_EQUALS( 1 * 1, 2 );</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//   }</span></span>
+
+<span style="font-style: italic"><span style="color: #9A1900">/*</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">     void testSubtraction( void )</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">     {</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">        TS_ASSERT( 1 - 1 &lt; 1 );</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">        TS_ASSERT_EQUALS( 1 - 1, 0 );</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">     }</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">*/</span></span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">XtestDivision</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">/</span> <span style="color: #993399">1</span> <span style="color: #990000">&lt;</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">/</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>The first is commented out with C++-style comments, the second
+test is commented out with C-style comments, and the third test is
+named in a manner that is not recognized through test discovery
+(i.e., it does not start with <tt>test</tt>).</p></div>
+<div class="paragraph"><p>The default test discovery mechanism only works with the first and
+third methods for disabling tests, but the FOG parser works with
+all three.  The FOG parser performs a complex, multi-line parse of
+the source file, so it can identify multi-line C-style comments.</p></div>
+<div class="paragraph"><p>Note, however, that the use of C macros will not work:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// BadTestSuite1.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">BadTestSuite1</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testAddition</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #000080">#if</span></span> <span style="color: #993399">0</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testSubtraction</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">-</span> <span style="color: #993399">1</span> <span style="color: #990000">&lt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">0</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #000080">#endif</span></span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> discovery mechanisms do not perform a C preprocessing
+step, since that would generally require using externally defined
+preprocessing variable definitions.   Additionally, preprocessor macros that act like functions will
+cause the FOG parser to fail unless they are followed by a semicolon.</p></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="runner">5. Test Runner Syntax</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The default behavior of the CxxTest test runner is to execute all
+tests in all of the test suites that are linked into the runner.
+However, CxxTest test runners process command line options that
+allow individual tests and test suites to be selected.</p></div>
+<div class="paragraph"><p>For example, consider a test runner defined as follows:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen -f --error-printer -o runner<span style="color: #990000">.</span>cpp MyTestSuite1<span style="color: #990000">.</span>h MyTestSuite2<span style="color: #990000">.</span>h MyTestSuite4<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>The <tt>--help</tt> (<tt>-h</tt>) option can be used to print the command line options for a test runner.  The command</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>./runner --help</tt></pre>
+</div></div>
+<div class="paragraph"><p>generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>./runner &lt;suitename&gt;
+./runner &lt;suitename&gt; &lt;testname&gt;
+./runner -h
+./runner --help
+./runner --help-tests
+./runner -v             Enable tracing output.</tt></pre>
+</div></div>
+<div class="paragraph"><p>The <tt>--help-tests</tt> option is used to list all test suites that are defined in a test runner.  The command</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">.</span>/runner --help-tests</tt></pre></div></div>
+<div class="paragraph"><p>generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Suite/Test Names
+---------------------------------------------------------------------------
+MyTestSuite1 testAddition
+MyTestSuite2 testAddition
+MyTestSuite2 testMultiplication
+MyTestSuite4 testAddition</tt></pre>
+</div></div>
+<div class="paragraph"><p>The first column is the test suite name, and the second column is the test name.</p></div>
+<div class="paragraph"><p>All tests in a test suite can be executed by simply specifying the test suite name.  For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">.</span>/runner MyTestSuite2</tt></pre></div></div>
+<div class="paragraph"><p>executes the tests in test suite <tt>MyTestSuite2</tt>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 tests.
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 2 tests
+Success rate: 50%</tt></pre>
+</div></div>
+<div class="paragraph"><p>Similarly, a single test can be executed by specifying the test suite followed by the test name.  For example</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">.</span>/runner MyTestSuite2 testMultiplication</tt></pre></div></div>
+<div class="paragraph"><p>executes the <tt>testMultiplication</tt> test in test suite <tt>MyTestSuite2</tt>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 1 test
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+Failed 1 of 1 test
+Success rate: 0%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The <tt>-v</tt> option enables the printing of trace information generated
+by the <tt>TS_TRACE</tt> function.  For example, the <tt>testMultiplication</tt> test contains trace declarations
+before and after the multiplication test.  Thus, the command</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">.</span>/runner -v MyTestSuite2 testMultiplication</tt></pre></div></div>
+<div class="paragraph"><p>generates this trace output before and after the test:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 1 test
+In MyTestSuite2::testMultiplication:
+MyTestSuite2.h:15: Trace: Starting multiplication test
+MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5)
+MyTestSuite2.h:17: Trace: Finishing multiplication test
+Failed 1 of 1 test
+Success rate: 0%</tt></pre>
+</div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="advanced">6. Advanced Testing Features</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_preprocessor_macros">6.1. Preprocessor Macros</h3>
+<div class="paragraph"><p>CxxTest recognizes a variety of preprocessor macros that can be used to modify the behavior of a test runner.  Many of these mimic the options of the <tt>cxxtestgen</tt> command.</p></div>
+<div class="tableblock">
+<table rules="all"
+width="100%"
+frame="border"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top"> Preprocessor Macro  </th>
+<th align="left" valign="top"> Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_HAVE_STD</tt></p></td>
+<td align="left" valign="top"><p class="table">Use the standard library.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_HAVE_EH</tt></p></td>
+<td align="left" valign="top"><p class="table">Use exception handling.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_ABORT_TEST_ON_FAIL</tt></p></td>
+<td align="left" valign="top"><p class="table">Abort tests on failed asserts.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_USER_VALUE_TRAITS</tt></p></td>
+<td align="left" valign="top"><p class="table">Enable user-defined value traits.  The default traits dump up to 8 bytes of the data as hex values.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_OLD_TEMPLATE_SYNTAX</tt></p></td>
+<td align="left" valign="top"><p class="table">Use old template syntax that is used by some compilers (e.g. Borland C++ 5).</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_OLD_STD</tt></p></td>
+<td align="left" valign="top"><p class="table">Use old syntax for libraries where <tt>std::</tt> is not recognized.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_MAX_DUMP_SIZE</tt></p></td>
+<td align="left" valign="top"><p class="table">The value of this macro defines the maximum number of bytes to dump if <tt>TS_ASSERT_SAME_DATA()</tt> fails. The default is 0, which indicates no limit.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_DEFAULT_ABORT</tt></p></td>
+<td align="left" valign="top"><p class="table">The value of this macro is the default value of the dynamic <em>abort on fail</em> flag.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>CXXTEST_LONGLONG</tt></p></td>
+<td align="left" valign="top"><p class="table">The value of this macro is used to define long long integers.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="paragraph"><p>These preprocessor macros must be defined before the CxxTest header
+files are included in the test runner.  For example, the following
+template file defines <tt>CXXTEST_HAVE_EH</tt> and <tt>CXXTEST_ABORT_TEST_ON_FAIL</tt>
+before other headers are included:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_HAVE_EH
+<span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_ABORT_TEST_ON_FAIL
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/ErrorPrinter.h&gt;</span>
+
+<span style="color: #009900">int</span> <span style="font-weight: bold"><span style="color: #000000">main</span></span><span style="color: #990000">()</span>
+<span style="color: #FF0000">{</span>
+    std<span style="color: #990000">::</span>cout <span style="color: #990000">&lt;&lt;</span> <span style="color: #FF0000">"Starting test runner"</span> <span style="color: #990000">&lt;&lt;</span> std<span style="color: #990000">::</span>endl<span style="color: #990000">;</span>
+    <span style="color: #009900">int</span> status <span style="color: #990000">=</span> CxxTest<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #000000">ErrorPrinter</span></span><span style="color: #990000">().</span><span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">();</span>
+    std<span style="color: #990000">::</span>cout <span style="color: #990000">&lt;&lt;</span> <span style="color: #FF0000">"Stopping test runner"</span> <span style="color: #990000">&lt;&lt;</span> std<span style="color: #990000">::</span>endl<span style="color: #990000">;</span>
+    <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> status<span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">// The CxxTest "world"</span></span>
+<span style="color: #990000">&lt;</span><span style="color: #008080">CxxTest</span> world<span style="color: #990000">&gt;</span></tt></pre></div></div>
+<div class="paragraph"><p>Several of these macros concern whether modern C++ conventions are
+supported by the compiler.  If tests need to be ported to multiple
+compilers, then one important convention is whether the namespace
+<tt>std::</tt> is supported.  For example, switching between <tt>cout</tt> and
+<tt>std::cout</tt> typically needs to be done throughout a code.  CxxTest
+supports this with the <tt>CXXTEST_STD()</tt> macro.  For example,
+<tt>CXXTEST_STD(cout)</tt> can be used within a test suite, and CxxTest
+handles the mapping of this to <tt>cout</tt> or <tt>std::cout</tt> depending on
+options provided to <tt>cxxtestgen</tt>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_customizing_test_fixtures">6.2. Customizing Test Fixtures</h3>
+<div class="sect3">
+<h4 id="_setup_and_teardown">6.2.1. Setup and Teardown</h4>
+<div class="paragraph"><p>CxxTest test fixtures can be customized in several ways to manage
+the environment for test suites and individual tests.  A common
+feature of test suites is that they share a common logic for setting
+up data used in the tests.  Thus, there may be duplicate code for
+creating objects, files, inputs, etc.  Similarly, the tests may
+share common logic for cleaning up after the test is finished (e.g. deleting temporary objects).</p></div>
+<div class="paragraph"><p>You can put this shared code in a common place by overriding the
+virtual functions <tt>TestSuite::setUp()</tt> and <tt>TestSuite::tearDown()</tt>.
+The <tt>setUp()</tt> function is called before each test, and <tt>tearDown()</tt>
+is called after each test.</p></div>
+<div class="paragraph"><p>For example, the following test suite employs <tt>setUp()</tt> and <tt>tearDown()</tt> methods to
+allocate and deallocate memory for a string buffer:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite5.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;string.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite5</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+    <span style="color: #009900">char</span> <span style="color: #990000">*</span>_buffer<span style="color: #990000">;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">setUp</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        _buffer <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">new</span></span> <span style="color: #009900">char</span><span style="color: #990000">[</span><span style="color: #993399">1024</span><span style="color: #990000">];</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">tearDown</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #0000FF">delete</span></span> <span style="color: #990000">[]</span> _buffer<span style="color: #990000">;</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_strcpy</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">strcpy</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">,</span> <span style="color: #FF0000">"Hello, world!"</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">[</span><span style="color: #993399">0</span><span style="color: #990000">],</span> <span style="color: #FF0000">'H'</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">[</span><span style="color: #993399">1</span><span style="color: #990000">],</span> <span style="color: #FF0000">'e'</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_memcpy</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">memcpy</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">,</span> <span style="color: #FF0000">"Hello, world!"</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span><span style="color: #009900">char</span><span style="color: #990000">));</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">[</span><span style="color: #993399">0</span><span style="color: #990000">],</span> <span style="color: #FF0000">'H'</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>_buffer<span style="color: #990000">[</span><span style="color: #993399">1</span><span style="color: #990000">],</span> <span style="color: #FF0000">'e'</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+</tt></pre></div></div>
+</div>
+<div class="sect3">
+<h4 id="_dynamically_created_test_suites">6.2.2. Dynamically Created Test Suites</h4>
+<div class="paragraph"><p>CxxTest test fixtures can also be customized during the construction
+and deconstruction of test suites.  By default, CxxTest test suites
+are instantiated statically in the test runner.  However, dynamically
+created test suites can be used to perform suite-level setup and
+teardown operations, verify the environment needed to execute a
+test suite, and construct test suites that require a nontrivial
+constructor.</p></div>
+<div class="paragraph"><p>CxxTest instantiates a test suite dynamically if the <tt>createSuite()</tt>
+or <tt>destroySuite()</tt> methods are defined.  For example, the following
+test suite checks to see if it is being compiled with Microsoft
+Visual Studio.  If not, the <tt>createSuite()</tt> returns a null pointer,
+indicating that the test suite was not created.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite6.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite6</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+
+    <span style="font-weight: bold"><span style="color: #0000FF">static</span></span> MyTestSuite6<span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #000000">createSuite</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #000080">    #ifdef</span></span> _MSC_VER
+    <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="font-weight: bold"><span style="color: #0000FF">new</span></span> <span style="font-weight: bold"><span style="color: #000000">MyTestSuite6</span></span><span style="color: #990000">();</span>
+<span style="font-weight: bold"><span style="color: #000080">    #else</span></span>
+    <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="color: #993399">0</span><span style="color: #990000">;</span>
+<span style="font-weight: bold"><span style="color: #000080">    #endif</span></span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="font-weight: bold"><span style="color: #0000FF">static</span></span> <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">destroySuite</span></span><span style="color: #990000">(</span> MyTestSuite6<span style="color: #990000">*</span> suite <span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">delete</span></span> suite<span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_nothing</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> <span style="color: #FF0000">"Nothing to test"</span> <span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+</div>
+<div class="sect3">
+<h4 id="_global_and_world_fixtures">6.2.3. Global and World Fixtures</h4>
+<div class="paragraph"><p>CxxTest supports two related mechanisms for performing <em>global</em>
+setup and teardown operations.  <em>Global fixtures</em> are classes that
+inherit from <tt>CxxTest::GlobalFixture</tt>, and they define <tt>setUp</tt> and
+<tt>tearDown</tt> methods.  The <tt>setUp</tt> method for all global fixtures is
+called before each test is executed, and the <tt>tearDown</tt> method for
+all global fixtures is called after each test is completed.  Thus,
+this mechanism provides a convenient way of defining setup and
+teardown operations that apply to all test suites.</p></div>
+<div class="paragraph"><p>For example, consider the following test suite:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite8.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cstdio&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/GlobalFixture.h&gt;</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">// Fixture1 counts its setUp()s and tearDown()s</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">Fixture1</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>GlobalFixture
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">unsigned</span> setUpCount<span style="color: #990000">;</span>
+    <span style="color: #009900">unsigned</span> tearDownCount<span style="color: #990000">;</span>
+
+    <span style="font-weight: bold"><span style="color: #000000">Fixture1</span></span><span style="color: #990000">()</span> <span style="color: #FF0000">{</span> setUpCount <span style="color: #990000">=</span> tearDownCount <span style="color: #990000">=</span> <span style="color: #993399">0</span><span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">setUp</span></span><span style="color: #990000">()</span> <span style="color: #FF0000">{</span> <span style="color: #990000">++</span> setUpCount<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">tearDown</span></span><span style="color: #990000">()</span> <span style="color: #FF0000">{</span> <span style="color: #990000">++</span> tearDownCount<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">setUpWorld</span></span><span style="color: #990000">()</span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #000000">printf</span></span><span style="color: #990000">(</span> <span style="color: #FF0000">"Starting a test suite</span><span style="color: #CC33CC">\n</span><span style="color: #FF0000">"</span> <span style="color: #990000">);</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">;</span><span style="color: #FF0000">}</span>
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">tearDownWorld</span></span><span style="color: #990000">()</span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #000000">printf</span></span><span style="color: #990000">(</span> <span style="color: #FF0000">"Finishing a test suite</span><span style="color: #CC33CC">\n</span><span style="color: #FF0000">"</span> <span style="color: #990000">);</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">;</span><span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+<span style="font-weight: bold"><span style="color: #0000FF">static</span></span> <span style="color: #008080">Fixture1</span> fixture1<span style="color: #990000">;</span>
+
+
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">// Fixture2 counts its setUp()s and tearDown()s and makes sure</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">// its setUp() is called after Fixture1 and its tearDown() before.</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">Fixture2</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> Fixture1
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">setUp</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>setUpCount<span style="color: #990000">,</span> fixture1<span style="color: #990000">.</span>setUpCount <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>tearDownCount<span style="color: #990000">,</span> fixture1<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> Fixture1<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #000000">setUp</span></span><span style="color: #990000">();</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #000000">tearDown</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>setUpCount<span style="color: #990000">,</span> fixture1<span style="color: #990000">.</span>setUpCount<span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>tearDownCount<span style="color: #990000">,</span> fixture1<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> Fixture1<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #000000">tearDown</span></span><span style="color: #990000">();</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+<span style="font-weight: bold"><span style="color: #0000FF">static</span></span> <span style="color: #008080">Fixture2</span> fixture2<span style="color: #990000">;</span>
+
+
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">// Verify the counts for the global fixtures</span></span>
+<span style="font-style: italic"><span style="color: #9A1900">//</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite8</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testCountsFirstTime</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture1<span style="color: #990000">.</span>setUpCount<span style="color: #990000">,</span>    <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture1<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">,</span> <span style="color: #993399">0</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture2<span style="color: #990000">.</span>setUpCount<span style="color: #990000">,</span>    <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture2<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">,</span> <span style="color: #993399">0</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testCountsSecondTime</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture1<span style="color: #990000">.</span>setUpCount<span style="color: #990000">,</span>    <span style="color: #993399">2</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture1<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture2<span style="color: #990000">.</span>setUpCount<span style="color: #990000">,</span>    <span style="color: #993399">2</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>fixture2<span style="color: #990000">.</span>tearDownCount<span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>This test suite defines a runner that generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 testsStarting a test suite
+Starting a test suite
+..Finishing a test suite
+Finishing a test suite
+OK!</tt></pre>
+</div></div>
+<div class="paragraph"><p>Note that the global fixtures are instantiated with static global
+values.  This ensures that these fixtures are created before the
+runner is initialized.  Also, note that the <tt>setUp</tt> methods are
+called in the same sequence that the global fixtures are instantiated,
+and the <tt>tearDown</tt> methods are called in the reverse sequence.
+Finally, note that the <tt>setUp</tt> and <tt>tearDown</tt> methods in global
+fixtures return a boolean value, which indicates success or failure
+of that operation.</p></div>
+<div class="paragraph"><p>This example also illustrates the use of <em>world fixtures</em>, which
+perform setup and teardown operations that are executed once each
+when beginning and finishing tests in each test suite.  World
+fixtures are defined with the <tt>setUpWorld</tt> and <tt>tearDownWorld</tt>
+methods in a global fixture.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_runtime_test_customization">6.2.4. Runtime Test Customization</h4>
+<div class="paragraph"><p>CxxTest defines several functions that can be called in a test suite to modify the default behavior of CxxTest.</p></div>
+<div class="tableblock">
+<table rules="all"
+width="100%"
+frame="border"
+cellspacing="0" cellpadding="4">
+<col width="50%" />
+<col width="50%" />
+<thead>
+<tr>
+<th align="left" valign="top"> Test Suite Method </th>
+<th align="left" valign="top"> Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>setAbortTestOnFail(bool)</tt></p></td>
+<td align="left" valign="top"><p class="table">This function specifies whether tests abort after a failure.  The default value of the flag is <tt>false</tt>.  This function only has an effect if exception handling is enabled.</p></td>
+</tr>
+<tr>
+<td align="left" valign="top"><p class="table"><tt>setMaxDumpSize(unsigned)</tt></p></td>
+<td align="left" valign="top"><p class="table">This function sets the maximum number of bytes that are dumped when
+<tt>TS_ASSERT_SAME_DATA()</tt> fails. The default is 0, which indicates no limit.</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="paragraph"><p>Note that the the configuration parameters are reset to their default
+values after each test is executed (more precisely, after <tt>tearDown()</tt>
+is called).  Consequently, calling these functions in the <tt>setUp()</tt>
+function has the effect of setting that value for the entire test
+suite.</p></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="traits">7. Value Traits</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>CxxTest&#8217;s test assertions like <a href="#ts_assert_equals">TS_ASSERT_EQUALS</a>
+work for built-in types, but they will not likely work for user-defined
+data types.  This is because CxxTest needs a way to compare objects
+and to convert them to strings when printing test failure summaries.
+Thus, user-defined data types need to have the <tt>operator=</tt> method
+defined to ensure that test assertions can be applied.</p></div>
+<div class="paragraph"><p>For example, the following code</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite7.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;iostream&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite7</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+
+   <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #008080">Data</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #009900">char</span> data<span style="color: #990000">[</span><span style="color: #993399">3</span><span style="color: #990000">];</span>
+      <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #0000FF">operator</span></span><span style="color: #990000">==(</span><span style="color: #008080">Data</span> o<span style="color: #990000">)</span> <span style="color: #FF0000">{</span>
+          <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> <span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #000000">memcmp</span></span><span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">this</span></span><span style="color: #990000">,</span> <span style="color: #990000">&amp;</span>o<span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>o<span style="color: #990000">))</span> <span style="color: #990000">==</span> <span style="color: #993399">0</span><span style="color: #990000">);</span>
+      <span style="color: #FF0000">}</span>
+   <span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+   <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #008080">Data2</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #009900">char</span> data<span style="color: #990000">[</span><span style="color: #993399">3</span><span style="color: #990000">];</span>
+   <span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+   <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">testCompareData</span></span><span style="color: #990000">()</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #008080">Data</span> x<span style="color: #990000">,</span> y<span style="color: #990000">;</span>
+      <span style="font-weight: bold"><span style="color: #000000">memset</span></span><span style="color: #990000">(</span> x<span style="color: #990000">.</span>data<span style="color: #990000">,</span> <span style="color: #993399">0x12</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>x<span style="color: #990000">.</span>data<span style="color: #990000">)</span> <span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">memset</span></span><span style="color: #990000">(</span> y<span style="color: #990000">.</span>data<span style="color: #990000">,</span> <span style="color: #993399">0xF6</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>y<span style="color: #990000">.</span>data<span style="color: #990000">)</span> <span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> x<span style="color: #990000">,</span> y <span style="color: #990000">);</span>
+
+      <span style="color: #008080">Data2</span> z<span style="color: #990000">,</span> w<span style="color: #990000">;</span>
+      <span style="font-weight: bold"><span style="color: #000000">memset</span></span><span style="color: #990000">(</span> z<span style="color: #990000">.</span>data<span style="color: #990000">,</span> <span style="color: #993399">0x12</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>x<span style="color: #990000">.</span>data<span style="color: #990000">)</span> <span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">memset</span></span><span style="color: #990000">(</span> w<span style="color: #990000">.</span>data<span style="color: #990000">,</span> <span style="color: #993399">0xF6</span><span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>y<span style="color: #990000">.</span>data<span style="color: #990000">)</span> <span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_SAME_DATA</span></span><span style="color: #990000">(</span> <span style="color: #990000">&amp;</span>z<span style="color: #990000">,</span> <span style="color: #990000">&amp;</span>w<span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #0000FF">sizeof</span></span><span style="color: #990000">(</span>z<span style="color: #990000">)</span> <span style="color: #990000">)</span>
+   <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+</tt></pre></div></div>
+<div class="paragraph"><p>defines a test runner that generates the following output</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 1 test
+In MyTestSuite7::testCompareData:
+MyTestSuite7.h:27: Error: Expected (x == y), found ({ 12 12 12  } != { F6 F6 F6  })
+MyTestSuite7.h:32: Error: Expected sizeof(z) (3) bytes to be equal at (&amp;z) and (&amp;w), found:
+   { 12 12 12 }
+     differs from
+   { F6 F6 F6 }
+Failed 1 of 1 test
+Success rate: 0%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The <tt>operator=</tt> method is required to apply
+<a href="#ts_assert_equals">TS_ASSERT_EQUALS</a> to <tt>Data</tt> objects.  However,
+the <a href="#ts_assert_same_data">TS_ASSERT_SAME_DATA</a> assertion can be
+applied to <tt>Data2</tt> objects that do not have <tt>operator=</tt> defined.</p></div>
+<div class="paragraph"><p>Since CxxTest does not rely on any external library, conversion
+from arbitrary data types to strings is done using <em>value traits</em>.
+For example, to convert an integer to a string, CxxTest does the following:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #009900">int</span> i <span style="color: #990000">=</span> <span style="color: #993399">10</span><span style="color: #990000">;</span>
+CxxTest<span style="color: #990000">::</span><span style="color: #008080">ValueTraits&lt;int&gt;</span> <span style="font-weight: bold"><span style="color: #000000">converter</span></span><span style="color: #990000">(</span>i<span style="color: #990000">);</span>
+<span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">char</span><span style="color: #990000">*</span> string <span style="color: #990000">=</span> converter<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">asString</span></span><span style="color: #990000">();</span></tt></pre></div></div>
+<div class="paragraph"><p>The CxxTest header file <tt>cxxtest/ValueTraits.h</tt> defines value traits
+for standard types like <tt>int</tt>, <tt>char</tt>, <tt>double</tt>, etc.  The default
+<tt>ValueTraits</tt> class for unknown types dumps up to 8 bytes of the value
+in hex format.</p></div>
+<div class="paragraph"><p>If the macro <tt>CXXTEST_USER_VALUE_TRAITS</tt> is defined, then CxxTest will
+omit the default definitions for <tt>ValueTraits</tt>.  This allows a user to define their own trait specifications to customize the display of trait information.</p></div>
+<div class="sect2">
+<h3 id="_enumeration_traits">7.1. Enumeration Traits</h3>
+<div class="paragraph"><p>CxxTest provides a simple way to define value traits for enumeration
+types.  The <tt>CXXTEST_ENUM_TRAITS</tt> macro is used to define value
+traits for all members of an enumeration set.</p></div>
+<div class="paragraph"><p>For example, the following code</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite9.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">enum</span></span> Answer <span style="color: #FF0000">{</span>
+    Yes<span style="color: #990000">,</span>
+    No<span style="color: #990000">,</span>
+    Maybe<span style="color: #990000">,</span>
+    DontKnow<span style="color: #990000">,</span>
+    DontCare
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">// Declare value traits for the Answer enumeration</span></span>
+<span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_TRAITS</span></span><span style="color: #990000">(</span> Answer<span style="color: #990000">,</span>
+                     <span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_MEMBER</span></span><span style="color: #990000">(</span> Yes <span style="color: #990000">)</span>
+                     <span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_MEMBER</span></span><span style="color: #990000">(</span> No <span style="color: #990000">)</span>
+                     <span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_MEMBER</span></span><span style="color: #990000">(</span> Maybe <span style="color: #990000">)</span>
+                     <span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_MEMBER</span></span><span style="color: #990000">(</span> DontKnow <span style="color: #990000">)</span>
+                     <span style="font-weight: bold"><span style="color: #000000">CXXTEST_ENUM_MEMBER</span></span><span style="color: #990000">(</span> DontCare <span style="color: #990000">)</span> <span style="color: #990000">);</span>
+
+<span style="font-style: italic"><span style="color: #9A1900">// Test the trait values</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">EnumTraits</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_Enum_traits</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> Yes <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> No <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> Maybe <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> DontKnow <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> DontCare <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span> <span style="color: #990000">(</span>Answer<span style="color: #990000">)</span><span style="color: #993399">1000</span> <span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>defines a test runner that generates the following output</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 1 test
+In EnumTraits::test_Enum_traits:
+MyTestSuite9.h:26: Error: Test failed: Yes
+MyTestSuite9.h:27: Error: Test failed: No
+MyTestSuite9.h:28: Error: Test failed: Maybe
+MyTestSuite9.h:29: Error: Test failed: DontKnow
+MyTestSuite9.h:30: Error: Test failed: DontCare
+MyTestSuite9.h:31: Error: Test failed: (Answer)1000
+Failed 1 of 1 test
+Success rate: 0%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The enumeration value traits print strings that represent the elements of the enumeration, except where a numeric value is provided.</p></div>
+<div class="paragraph"><p>Note that the <tt>CXXTEST_ENUM_TRAITS</tt> macros has two arguments;  the list of <tt>CXXTEST_ENUM_MEMBER</tt> macros is not separated by commas!</p></div>
+</div>
+<div class="sect2">
+<h3 id="_defining_new_value_traits">7.2. Defining New Value Traits</h3>
+<div class="paragraph"><p>Defining value traits for a new class is done by providing a class
+specialization of <tt>ValueTraits</tt> that converts an object of the new
+class to a string.  For example, consider the definition of the
+<tt>MyClass</tt> class:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyClass.h</span></span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyClass</span>
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+
+   <span style="color: #009900">int</span> value<span style="color: #990000">;</span>
+
+   <span style="font-weight: bold"><span style="color: #000000">MyClass</span></span><span style="color: #990000">(</span><span style="color: #009900">int</span> value_<span style="color: #990000">)</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #000000">value</span></span><span style="color: #990000">(</span>value_<span style="color: #990000">)</span> <span style="color: #FF0000">{}</span>
+
+   <span style="font-style: italic"><span style="color: #9A1900">// CxxTest requires a copy constructor</span></span>
+   <span style="font-weight: bold"><span style="color: #000000">MyClass</span></span><span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">const</span></span> MyClass<span style="color: #990000">&amp;</span> other<span style="color: #990000">)</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #000000">value</span></span><span style="color: #990000">(</span>other<span style="color: #990000">.</span>value<span style="color: #990000">)</span> <span style="color: #FF0000">{}</span>
+
+   <span style="font-style: italic"><span style="color: #9A1900">// This is required if you want to use TS_ASSERT_EQUALS</span></span>
+   <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #0000FF">operator</span></span><span style="color: #990000">==(</span><span style="font-weight: bold"><span style="color: #0000FF">const</span></span> MyClass<span style="color: #990000">&amp;</span> other<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> value <span style="color: #990000">==</span> other<span style="color: #990000">.</span>value<span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+
+   <span style="font-style: italic"><span style="color: #9A1900">// If you want to use TS_ASSERT_LESS_THAN</span></span>
+   <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #0000FF">operator</span></span><span style="color: #990000">&lt;(</span><span style="font-weight: bold"><span style="color: #0000FF">const</span></span> MyClass<span style="color: #990000">&amp;</span> other<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> value <span style="color: #990000">&lt;</span> other<span style="color: #990000">.</span>value<span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+<span style="font-weight: bold"><span style="color: #000080">#ifdef</span></span> CXXTEST_RUNNING
+<span style="font-style: italic"><span style="color: #9A1900">// This declaration is only activated when building a CxxTest test suite</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/ValueTraits.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;stdio.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">namespace</span></span> CxxTest
+<span style="color: #FF0000">{</span>
+   CXXTEST_TEMPLATE_INSTANTIATION
+   <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">ValueTraits</span><span style="color: #990000">&lt;</span>MyClass<span style="color: #990000">&gt;</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #009900">char</span> _s<span style="color: #990000">[</span><span style="color: #993399">256</span><span style="color: #990000">];</span>
+
+   <span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+      <span style="font-weight: bold"><span style="color: #000000">ValueTraits</span></span><span style="color: #990000">(</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> MyClass<span style="color: #990000">&amp;</span> m <span style="color: #990000">)</span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #000000">sprintf</span></span><span style="color: #990000">(</span> _s<span style="color: #990000">,</span> <span style="color: #FF0000">"MyClass( %i )"</span><span style="color: #990000">,</span> m<span style="color: #990000">.</span>value <span style="color: #990000">);</span> <span style="color: #FF0000">}</span>
+      <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">char</span> <span style="color: #990000">*</span><span style="font-weight: bold"><span style="color: #000000">asString</span></span><span style="color: #990000">()</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> _s<span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+   <span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+<span style="font-weight: bold"><span style="color: #000080">#endif</span></span> <span style="font-style: italic"><span style="color: #9A1900">// CXXTEST_RUNNING</span></span></tt></pre></div></div>
+<div class="paragraph"><p>This class includes definitions of <tt>operator==</tt> and <tt>operator&lt;</tt>
+that support comparisons with <a href="#ts_assert_equals">TS_ASSERT_EQUALS</a>
+and <a href="#ts_assert_less_than">TS_ASSERT_LESS_THAN</a>.  Additionally,
+this header contains a specialization of <tt>ValueTraits</tt> (in the
+<tt>CxxTest</tt> namespace) that generates a string description of a <tt>MyClass</tt>
+instance.</p></div>
+<div class="paragraph"><p>The following test suite illustrates how these definitions can be
+used to define a test runner:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite10.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;MyClass.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite10</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+   <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_le</span></span><span style="color: #990000">()</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #008080">MyClass</span> <span style="font-weight: bold"><span style="color: #000000">x</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">),</span> <span style="font-weight: bold"><span style="color: #000000">y</span></span><span style="color: #990000">(</span><span style="color: #993399">2</span><span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_LESS_THAN</span></span><span style="color: #990000">(</span> x<span style="color: #990000">,</span> y <span style="color: #990000">);</span>
+   <span style="color: #FF0000">}</span>
+
+   <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_eq</span></span><span style="color: #990000">()</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #008080">MyClass</span> <span style="font-weight: bold"><span style="color: #000000">x</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">),</span> <span style="font-weight: bold"><span style="color: #000000">y</span></span><span style="color: #990000">(</span><span style="color: #993399">2</span><span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> x<span style="color: #990000">,</span> y <span style="color: #990000">);</span>
+   <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+</tt></pre></div></div>
+<div class="paragraph"><p>This runner for this test suite generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 2 tests.
+In MyTestSuite10::test_eq:
+MyTestSuite10.h:17: Error: Expected (x == y), found (MyClass( 1 ) != MyClass( 2 ))
+Failed 1 of 2 tests
+Success rate: 50%</tt></pre>
+</div></div>
+<div class="paragraph"><p>The test failure print logic uses the specialization of <tt>ValueTraits</tt> to create
+the string description of <tt>MyClass</tt> that appears in the output.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_defining_value_traits_for_template_classes">7.3. Defining Value Traits for Template Classes</h3>
+<div class="paragraph"><p>A simple modification to the above example illustrates how a trait can be defined for a
+template class:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MyTestSuite11.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;TMyClass.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MyTestSuite11</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+   <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_le</span></span><span style="color: #990000">()</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #008080">TMyClass&lt;int&gt;</span> <span style="font-weight: bold"><span style="color: #000000">x</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">),</span> <span style="font-weight: bold"><span style="color: #000000">y</span></span><span style="color: #990000">(</span><span style="color: #993399">2</span><span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_LESS_THAN</span></span><span style="color: #990000">(</span> x<span style="color: #990000">,</span> y <span style="color: #990000">);</span>
+   <span style="color: #FF0000">}</span>
+
+   <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_eq</span></span><span style="color: #990000">()</span>
+   <span style="color: #FF0000">{</span>
+      <span style="color: #008080">TMyClass&lt;int&gt;</span> <span style="font-weight: bold"><span style="color: #000000">x</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">),</span> <span style="font-weight: bold"><span style="color: #000000">y</span></span><span style="color: #990000">(</span><span style="color: #993399">2</span><span style="color: #990000">);</span>
+      <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> x<span style="color: #990000">,</span> y <span style="color: #990000">);</span>
+   <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+</tt></pre></div></div>
+<div class="paragraph"><p>Unfortunately, this example employs partial template specialization, which  is not supported by all C++ compilers.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="mock">8. Testing with Mock Objects</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Mock Objects are a very useful concept for testing complex software.
+The key idea is to pass special objects to tested code that facilitates
+the testing process.  For instance, a class that implements a
+protocol over TCP might rely on an abstract <tt>ISocket</tt> interface.
+Then a mock testing strategy could pass a <tt>MockSocket</tt> object that
+does anything that is useful for testing (e.g., keep a log of all
+data &#8220;sent&#8221; to verify later).</p></div>
+<div class="paragraph"><p>However, when a challenge for C/C++ developers is that you may need
+to call <em>global</em> functions which you cannot override.  Consider any
+code that uses <tt>fopen()</tt>, <tt>fwrite()</tt> and <tt>fclose()</tt>.  It is not
+very elegant to have this code actually create files while being
+tested.  Even more importantly, you need to test how the code behaves
+when &#8220;bad&#8221; things happen (e.g., when <tt>fopen()</tt> fails).  Handling
+these types of exceptional conditions is often a very challenging
+issue for software testing.</p></div>
+<div class="paragraph"><p>CxxTest addresses this challenge by providing a generic mechanism for
+defining mock global functions.  The next section illustrates this mechanism for a single
+global function.  The following section provides more detail about specific features of CxxTest&#8217;s
+support for mock testing.</p></div>
+<div class="sect2">
+<h3 id="_example_a_mock_tt_time_tt_function">8.1. Example: A Mock <tt>time()</tt> Function</h3>
+<div class="paragraph"><p>Suppose that we want to perform mock testing using the well known
+standard library function <tt>time()</tt>.  Setting up a test suite with
+a mock global function for <tt>time()</tt> can be broken down into the
+following steps.</p></div>
+<div class="sect3">
+<h4 id="_declare_mock_functions">8.1.1. Declare Mock Functions</h4>
+<div class="paragraph"><p>The <tt>CXXTEST_MOCK_GLOBAL</tt> macro is used to declare mock global functions.  It is often convenient to include
+these declarations in a header file, which is used in both the test suite as well as the code that is being tested:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// time_mock.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;time.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/Mock.h&gt;</span>
+
+<span style="font-weight: bold"><span style="color: #000000">CXXTEST_MOCK_GLOBAL</span></span><span style="color: #990000">(</span> time_t<span style="color: #990000">,</span>        <span style="font-style: italic"><span style="color: #9A1900">/* Return type          */</span></span>
+                     time<span style="color: #990000">,</span>          <span style="font-style: italic"><span style="color: #9A1900">/* Name of the function */</span></span>
+                     <span style="color: #990000">(</span> <span style="color: #008080">time_t</span> <span style="color: #990000">*</span>t <span style="color: #990000">),</span> <span style="font-style: italic"><span style="color: #9A1900">/* Prototype            */</span></span>
+                     <span style="color: #990000">(</span> t <span style="color: #990000">)</span>          <span style="font-style: italic"><span style="color: #9A1900">/* Argument list        */</span></span> <span style="color: #990000">);</span></tt></pre></div></div>
+</div>
+<div class="sect3">
+<h4 id="_mock_functions_in_tested_code">8.1.2. Mock Functions in Tested Code</h4>
+<div class="paragraph"><p>The tested code uses mock global functions, rather than using the global functions directly.
+You access mock functions in the <tt>T</tt> (for <em>Test</em>) namespace, so the tested code calls <tt>T::time()</tt> instead of
+<tt>time()</tt>. This is the equivalent of using abstract interfaces
+instead of concrete classes.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// rand_example.cpp</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;time_mock.h&gt;</span>
+
+<span style="color: #009900">int</span> <span style="font-weight: bold"><span style="color: #000000">generateRandomNumber</span></span><span style="color: #990000">()</span>
+<span style="color: #FF0000">{</span>
+    <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> T<span style="color: #990000">::</span><span style="font-weight: bold"><span style="color: #000000">time</span></span><span style="color: #990000">(</span> NULL <span style="color: #990000">)</span> <span style="color: #990000">*</span> <span style="color: #993399">3</span><span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span></tt></pre></div></div>
+</div>
+<div class="sect3">
+<h4 id="_mock_source_files">8.1.3. Mock Source Files</h4>
+<div class="paragraph"><p>A source file needs to be defined that implements <tt>T::time()</tt> by
+calling the real global function.  This definition is performed automatically by
+defining <tt>CXXTEST_MOCK_REAL_SOURCE_FILE</tt> before the header file is defined:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// time_real.cpp</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_MOCK_REAL_SOURCE_FILE
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;time_mock.h&gt;</span></tt></pre></div></div>
+<div class="paragraph"><p>This source file is not used for testing, but instead it supports normal use of the tested code.</p></div>
+<div class="paragraph"><p>Similarly, a source file needs to be defined that implements <tt>T::time()</tt> by calling the mock
+global function.  This definition is performed automatically by defining <tt>CXXTEST_MOCK_TEST_SOURCE_FILE</tt> before the header file is defined:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// time_mock.cpp</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#define</span></span> CXXTEST_MOCK_TEST_SOURCE_FILE
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;time_mock.h&gt;</span></tt></pre></div></div>
+</div>
+<div class="sect3">
+<h4 id="_test_suites_using_mock_functions">8.1.4. Test Suites using Mock Functions</h4>
+<div class="paragraph"><p>A mock object for the <tt>time()</tt> function is created using the <tt>T::Base_time</tt> class,
+which is automatically created by CxxTest.  This class includes a <tt>time()</tt> method whose
+API is the same as the global <tt>time()</tt> function.  Thus, this method can be defined to have
+whatever behavior is desired during testing.  For example, the following example defines a
+mock object that increments a counter to define an incremental value for <tt>time()</tt>.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900">// MockTestSuite.h</span></span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;cxxtest/TestSuite.h&gt;</span>
+<span style="font-weight: bold"><span style="color: #000080">#include</span></span> <span style="color: #FF0000">&lt;time_mock.h&gt;</span>
+
+<span style="color: #009900">int</span> <span style="font-weight: bold"><span style="color: #000000">generateRandomNumber</span></span><span style="color: #990000">();</span>
+
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">MockObject</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> T<span style="color: #990000">::</span>Base_time
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="font-weight: bold"><span style="color: #000000">MockObject</span></span><span style="color: #990000">(</span><span style="color: #009900">int</span> initial<span style="color: #990000">)</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #000000">counter</span></span><span style="color: #990000">(</span>initial<span style="color: #990000">)</span> <span style="color: #FF0000">{}</span>
+    <span style="color: #009900">int</span> counter<span style="color: #990000">;</span>
+    <span style="color: #008080">time_t</span> <span style="font-weight: bold"><span style="color: #000000">time</span></span><span style="color: #990000">(</span> time_t <span style="color: #990000">*</span> <span style="color: #990000">)</span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> counter<span style="color: #990000">++;</span> <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">TestRandom</span> <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">public</span></span> CxxTest<span style="color: #990000">::</span>TestSuite
+<span style="color: #FF0000">{</span>
+<span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_generateRandomNumber</span></span><span style="color: #990000">()</span>
+    <span style="color: #FF0000">{</span>
+        <span style="color: #008080">MockObject</span> <span style="font-weight: bold"><span style="color: #000000">t</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> <span style="font-weight: bold"><span style="color: #000000">generateRandomNumber</span></span><span style="color: #990000">(),</span> <span style="color: #993399">3</span> <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> <span style="font-weight: bold"><span style="color: #000000">generateRandomNumber</span></span><span style="color: #990000">(),</span> <span style="color: #993399">6</span> <span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span> <span style="font-weight: bold"><span style="color: #000000">generateRandomNumber</span></span><span style="color: #990000">(),</span> <span style="color: #993399">9</span> <span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span>
+<span style="color: #FF0000">}</span><span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>Note that CxxTest uses global data to associate calls made with <tt>T::time()</tt>
+to calls to <tt>MockObject::time()</tt>.  The <tt>MockObject</tt> class simply
+needs to be instantiated prior to the call to <tt>T::time()</tt>.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_building_the_test_runner">8.1.5. Building the Test Runner</h4>
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> command is used to create a test runner with mock functions in a normal manner:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>cxxtestgen --error-printer -o runner<span style="color: #990000">.</span>cpp MockTestSuite<span style="color: #990000">.</span>h</tt></pre></div></div>
+<div class="paragraph"><p>The test runner source file, <tt>runner.cpp</tt>, needs to be compiled an linked to the mock function definition, <tt>time_mock.cpp</tt>, as well as the code being tested, <tt>rand_example.cpp</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>g<span style="color: #990000">++</span> -o runner -I<span style="color: #990000">.</span> -I<span style="color: #009900">$CXXTEST</span> runner<span style="color: #990000">.</span>cpp time_mock<span style="color: #990000">.</span>cpp rand_example<span style="color: #990000">.</span>cpp</tt></pre></div></div>
+<div class="paragraph"><p>This generates a test runner that generates the following output:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>Running 1 test.OK!</tt></pre>
+</div></div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_advanced_topics">8.2. Advanced Topics</h3>
+<div class="sect3">
+<h4 id="_void_functions">8.2.1. Void Functions</h4>
+<div class="paragraph"><p>The <tt>CXXTEST_MOCK_VOID_GLOBAL</tt> is used to define mock global functions that return <tt>void</tt>.
+This is identical to
+<tt>CXXTEST_MOCK_GLOBAL</tt> except that it does not specify the return
+type.  Take a look in <tt>sample/mock/T/stdlib.h</tt> for a demonstation.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_calling_the_real_functions_while_testing">8.2.2. Calling the Real Functions While Testing</h4>
+<div class="paragraph"><p>During testing it is sometimes necessary to call the real global
+function instead of the mock global function.  CxxTest allows a
+user to do this by creating a special mock object.  For a global
+mock function of <tt>time()</tt>, the object <tt>T::Real_time</tt> represents the
+real function.  If this class is created, then <tt>T::time()</tt> will be
+redirected to the real function.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_mocking_nonexistent_functions">8.2.3. Mocking Nonexistent Functions</h4>
+<div class="paragraph"><p>Sometimes the tested code calls functions that are not available
+when testing.  For example, this can happen when testing driver
+code that calls kernel functions that are not available to a user-mode
+test runner.  CxxTest can provide mock global function definitions
+for the test code while using the original functions in the tested code.</p></div>
+<div class="paragraph"><p>The <tt>CXXTEST_SUPPLY_GLOBAL</tt> and <tt>CXXTEST_SUPPLY_VOID_GLOBAL</tt> macros are used to provide mock global function definitions.  For example, the following declaration creates a mock global function for the Win32 kernel function <tt>IoCallDriver</tt>:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">CXXTEST_SUPPLY_GLOBAL</span></span><span style="color: #990000">(</span> NTSTATUS<span style="color: #990000">,</span>                <span style="font-style: italic"><span style="color: #9A1900">/* Return type */</span></span>
+                       IoCallDriver<span style="color: #990000">,</span>            <span style="font-style: italic"><span style="color: #9A1900">/* Name        */</span></span>
+                       <span style="color: #990000">(</span> <span style="color: #008080">PDEVICE_OBJECT</span> Device<span style="color: #990000">,</span> <span style="font-style: italic"><span style="color: #9A1900">/* Prototype   */</span></span>
+                         <span style="color: #008080">PIRP</span> Irp <span style="color: #990000">),</span>
+                       <span style="color: #990000">(</span> Device<span style="color: #990000">,</span> Irp <span style="color: #990000">)</span>          <span style="font-style: italic"><span style="color: #9A1900">/* How to call */</span></span> <span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>The tested driver code calls <tt>IoCallDriver()</tt> normally;  there is no need for the <tt>T::</tt> syntax.
+The test suite is defined using the <tt>T::Base_IoCallDriver</tt> as with normal mock objects.</p></div>
+<div class="paragraph"><p>CxxTest also provides the macros <tt>CXXTEST_SUPPLY_GLOBAL_C</tt> and
+<tt>CXXTEST_SUPPLY_GLOBAL_VOID_C</tt> that declare the functions with <tt>C</tt>
+linkage (i.e., using <tt>extern "C"</tt>).  These macros are used to declare
+function prototypes, since you may not be able to include the header
+files in the test suite that are associated with the mock global function.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_functions_in_namespaces">8.2.4. Functions in Namespaces</h4>
+<div class="paragraph"><p>The <tt>CXXTEST_MOCK</tt> macro is used to declare a mock global function that is associated
+with a function in a namespace, including static class member functions.
+For example, consider the function <tt>bool Files::FileExists( const
+String &amp;name )</tt>;  the namespace <tt>Files</tt> contains the function
+<tt>FileExists</tt>.  The mock class will be called <tt>T::Base_Files_FileExists</tt>
+and the function to implemented would be <tt>fileExists</tt>.  The <tt>CXXTEST_MOCK</tt> macro declares this mock global function as follows:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">CXXTEST_MOCK</span></span><span style="color: #990000">(</span> Files_FileExists<span style="color: #990000">,</span>       <span style="font-style: italic"><span style="color: #9A1900">/* Suffix of mock class  */</span></span>
+              <span style="color: #009900">bool</span><span style="color: #990000">,</span>                   <span style="font-style: italic"><span style="color: #9A1900">/* Return type           */</span></span>
+              fileExists<span style="color: #990000">,</span>             <span style="font-style: italic"><span style="color: #9A1900">/* Name of mock member   */</span></span>
+              <span style="color: #990000">(</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #008080">String</span> <span style="color: #990000">&amp;</span>name <span style="color: #990000">),</span> <span style="font-style: italic"><span style="color: #9A1900">/* Prototype             */</span></span>
+              Files<span style="color: #990000">::</span>FileExists<span style="color: #990000">,</span>      <span style="font-style: italic"><span style="color: #9A1900">/* Name of real function */</span></span>
+              <span style="color: #990000">(</span> name <span style="color: #990000">)</span>                <span style="font-style: italic"><span style="color: #9A1900">/* Parameter list        */</span></span> <span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>Similarly, the <tt>CXXTEST_MOCK_VOID</tt> macro is used to declare a mock global function that returns <tt>void</tt>.</p></div>
+<div class="paragraph"><p>The <tt>CXXTEST_SUPPLY</tt> and <tt>CXXTEST_SUPPLY_VOID</tt> macros are used to provide mock global function definitions for nonexistent functions.  For example:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">CXXTEST_SUPPLY</span></span><span style="color: #990000">(</span> AllocateIrp<span style="color: #990000">,</span>         <span style="font-style: italic"><span style="color: #9A1900">/* =&gt; T::Base_AllocateIrp */</span></span>
+                PIRP<span style="color: #990000">,</span>                <span style="font-style: italic"><span style="color: #9A1900">/* Return type            */</span></span>
+                allocateIrp<span style="color: #990000">,</span>         <span style="font-style: italic"><span style="color: #9A1900">/* Name of mock member    */</span></span>
+                <span style="color: #990000">(</span> <span style="color: #008080">CCHAR</span> StackSize <span style="color: #990000">),</span> <span style="font-style: italic"><span style="color: #9A1900">/* Prototype              */</span></span>
+                IoAllocateIrp<span style="color: #990000">,</span>       <span style="font-style: italic"><span style="color: #9A1900">/* Name of real function  */</span></span>
+                <span style="color: #990000">(</span> StackSize <span style="color: #990000">)</span>        <span style="font-style: italic"><span style="color: #9A1900">/* Parameter list         */</span></span> <span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>Similarly, the <tt>CXXTEST_SUPPLY_C</tt> and <tt>CXXTEST_SUPPLY_VOID_C</tt> macros declare the functions with <tt>C</tt> linkage.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_overloaded_functions">8.2.5. Overloaded Functions</h4>
+<div class="paragraph"><p>The <tt>CXXTEST_MOCK</tt> and <tt>CXXTEST_MOCK_VOID</tt> macros have a flexible
+interface that can provide mock global function definitions for
+overloaded functions.  The arguments simply need to specify different
+mock class names, mock member names and different prototype definitions.
+These different mock declarations will generate different mock objects that can be explicitly
+referenced in a test suite.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_the_mock_namespace">8.2.6. The Mock Namespace</h4>
+<div class="paragraph"><p>The default namespace for mock functions is <tt>T::</tt>.  This namespace can be changed by defining the
+<tt>CXXTEST_MOCK_NAMESPACE</tt> macro.</p></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="installation">9. Installation</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>A key feature of CxxTest is that it does has virtually no installation
+process.  The <tt>cxxtestgen</tt> script can be directly executed from the
+<tt>cxxtest/bin</tt> directory.  Simply adding this directory to the PATH
+environment of a command shell is sufficient for many applications.
+Beyond that, the build process for test runners simply needs to
+reference the <tt>cxxtest</tt> root directory to enable proper includes
+during compilation.</p></div>
+<div class="paragraph"><p>The FOG parser requires two Python packages:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt>ply</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>ordereddict</tt> (This is needed when running Python 2.4, 2.5 or 2.6)
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>If these packages are not available, then <tt>cxxtestgen</tt> will generate an error when the
+FOG parser option is selected.
+If you have
+<a href="http://pypi.python.org/pypi/setuptools">setuptools</a> or
+<a href="http://pypi.python.org/pypi/distribute">distribute</a>
+installed, then
+you can install these packages from PyPI by executing</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>easy_install ply
+easy_install ordereddict</tt></pre></div></div>
+<div class="paragraph"><p>The <tt>cxxtestgen</tt> script has been tested with many different versions
+of Python:  2.4 - 3.2.  Note that this script has only been tested
+with the CPython implementation.  CxxTest 4.0 has been tested on
+Linux and Mac platforms using the G<tt> and CLang</tt> compilers.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="discussion">10. Status and Future Plans</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The CxxTest 4.0 release reflects major changes in the management
+and focus of CxxTest.  The 4.0 release is the first release of
+CxxTest in over seven years, and virtually all of the initial
+developers have moved on to other projects.  CxxTest is heavily
+used at Sandia National Laboratories, and Sandia&#8217;s ongoing use of
+CxxTest is a major driver for the 4.0 release.</p></div>
+<div class="paragraph"><p>Similarly, major
+changes in CxxTest reflect the focus of the developer team:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Perl is no longer used to support CxxTest scripts.  Python is now the only scripting language used by CxxTest.
+</p>
+</li>
+<li>
+<p>
+The testing scripts have been rewritten using the PyUnit framework.
+</p>
+</li>
+<li>
+<p>
+The installation process for CxxTest now leverages and integrates with the system Python installation.
+</p>
+</li>
+<li>
+<p>
+A more comprehensive C++ parser is now available, which supports testing of templates.
+</p>
+</li>
+<li>
+<p>
+The CxxTest GUI is no longer supported, and the <a href="#ts_warn">TS_WARN</a> is deprecated.
+</p>
+</li>
+<li>
+<p>
+CxxTest runners now have a command-line interface that facilitates interative use of the test runner.
+</p>
+</li>
+<li>
+<p>
+A new user guide is now available in PDF, HTML and Ebook formats.
+</p>
+</li>
+<li>
+<p>
+Updated the <tt>cxxtestgen</tt> script to work with Python 2.6 through 3.2
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>Additionally, CxxTest is now validated with continuous integration
+tests.  Yes, the CxxTest developers eat their own dog food!</p></div>
+<div class="paragraph"><p>Although the GUI option for <tt>cxxtestgen</tt> appears to work fine, this
+GUI is rather primitive.  It simply provides a visual summary of
+the test results, and not the interactive test execution that a
+user would expect.  This capability is deprecated since none of the
+current developers use this feature.  CxxTest users should consider
+using CxxTest with <a href="http://jenkins-ci.org/">Jenkins</a>.  The <tt>XUnitPrinter</tt>
+test listener generates XML files that can be easily integrated by
+<a href="http://jenkins-ci.org/">Jenkins</a>, which creates a visual summary of
+test results with links to drill-down into test outputs.</p></div>
+<div class="paragraph"><p>This documentation has highlighted the commonly used test listeners.
+There are a variety of other test listeners provided by CxxTest
+that support advanced Cxxtest applications.  For example, the
+<tt>YesNoRunner</tt> is perhaps the simplest test listener;  it simply
+returns the number of test failures.  The <tt>StdioFilePrinter</tt> is
+used by <tt>StdioPrinter</tt>, but it does not assume that <tt>stdio</tt> is the
+default output stream.  This test listener can be used in contexts
+where a custom output stream must be specified.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="acknowledgements">Acknowledgements</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>CxxTest was originally developed by Erez Volk.  The following
+developers actively contributed to the CxxTest 4.0 release:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+GaÅ¡per Ažman
+</p>
+</li>
+<li>
+<p>
+Kevin Fitch
+</p>
+</li>
+<li>
+<p>
+William Hart
+</p>
+</li>
+<li>
+<p>
+John Siirola
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>The CxxTest documentation is generated using
+<a href="http://www.methods.co.nz/asciidoc/">AsciiDoc</a>.  The following people
+have contributed to the CxxTest User Manual:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+William Hart
+</p>
+</li>
+<li>
+<p>
+Lionel Orry
+</p>
+</li>
+<li>
+<p>
+Erez Volk
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>A major advancement in CxxTest&#8217;s capability is the new test discovery
+mechanism that is based on a parser of the Flexible Object Language
+(FOG).  FOG generalizes the C++ syntax, which enables CxxTest to
+extract high-level class structure for test discovery.  FOG was
+developed by Edward Willink:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Edward D. Willink.  <em>Meta-Compilation for C++</em>, PhD Thesis, Computer Science Research Group, University of Surrey, January 2000.
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>The FOG parser in CxxTest critically relies on the excellent LALR
+parser provided by Dave Beazley&#8217;s <tt>ply</tt> Python package.  The scalable
+performance of <tt>ply</tt> is critical for CxxTest.</p></div>
+<div class="paragraph"><p>CxxTest has greatly benefited from the support of the open source
+community.  We would like to thank the following organizations for
+providing web hosting and computing resources: GitHub, SourceForge,
+Tigris.org, Sandia National Laboratories, Google and COIN-OR.  The development
+of CxxTest has been partially supported by Sandia National Laboratories.
+Sandia National Laboratories is a multi-program laboratory managed
+and operated by Sandia Corporation, a wholly owned subsidiary of
+Lockheed Martin Corporation, for the U.S.  Department of Energy&#8217;s
+National Nuclear Security Administration under contract DE-AC04-94AL85000.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="appendix_A">Appendix A: Test Assertion Examples</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert"></a> TS_ASSERT
+</dt>
+<dd>
+<p>
+This is the most basic test assertion, which simply verifies that the <tt>expr</tt> argument is true:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span> <span style="color: #990000">+</span> <span style="color: #993399">1</span> <span style="color: #990000">&gt;</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_delta"></a> TS_ASSERT_DELTA
+</dt>
+<dd>
+<p>
+This test assertion verifies two floating point values are within a specified absolute difference:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_delta</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_DELTA</span></span><span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #000000">sqrt</span></span><span style="color: #990000">(</span><span style="color: #993399">4.0</span><span style="color: #990000">),</span> <span style="color: #993399">2.0</span><span style="color: #990000">,</span> <span style="color: #993399">1e-7</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_differs"></a> TS_ASSERT_DIFFERS
+</dt>
+<dd>
+<p>
+This test assertion verifies that the two arguments are not equal:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_differs</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_DIFFERS</span></span><span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_equals"></a> TS_ASSERT_EQUALS
+</dt>
+<dd>
+<p>
+  This test assertion verifies that the two arguments are equal:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_equals</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">21</span> <span style="color: #990000">%</span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>Note that this test is performed using the C++ <tt>==</tt> operator, whose behavior may be redefined for the two argument types.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_less_than"></a> TS_ASSERT_LESS_THAN
+</dt>
+<dd>
+<p>
+This test assertion verifies that the first argument is strictly less than the second argument:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_less_than</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_LESS_THAN</span></span><span style="color: #990000">(</span><span style="color: #993399">0</span><span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_less_than_equals"></a> TS_ASSERT_LESS_THAN_EQUALS
+</dt>
+<dd>
+<p>
+This test assertion verifies that the first argument is less than or equal to the second argument:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_less_than_equals</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_LESS_THAN_EQUALS</span></span><span style="color: #990000">(</span><span style="color: #993399">0</span><span style="color: #990000">,</span> <span style="color: #993399">0</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_predicate"></a> TS_ASSERT_PREDICATE
+</dt>
+<dd>
+<p>
+This test assertion takes as an argument the name of a class, similar to a STL <tt>unary_function</tt>, and evaluates the <tt>operator()</tt> method:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="font-weight: bold"><span style="color: #0000FF">class</span></span> <span style="color: #008080">IsOdd</span>
+    <span style="color: #FF0000">{</span>
+    <span style="font-weight: bold"><span style="color: #0000FF">public</span></span><span style="color: #990000">:</span>
+        <span style="color: #009900">bool</span> <span style="font-weight: bold"><span style="color: #0000FF">operator</span></span><span style="color: #990000">()(</span><span style="color: #009900">int</span> x<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #FF0000">{</span> <span style="font-weight: bold"><span style="color: #0000FF">return</span></span> x <span style="color: #990000">%</span> <span style="color: #993399">2</span> <span style="color: #990000">==</span> <span style="color: #993399">1</span><span style="color: #990000">;</span> <span style="color: #FF0000">}</span>
+    <span style="color: #FF0000">}</span><span style="color: #990000">;</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_predicate</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_PREDICATE</span></span><span style="color: #990000">(</span>IsOdd<span style="color: #990000">,</span> <span style="color: #993399">29</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>This test assertion can be seen as a generalization of <a href="#ts_assert">TS_ASSERT</a>, but it
+allows the tester to see the failed value.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_relation"></a> TS_ASSERT_RELATION
+</dt>
+<dd>
+<p>
+It takes as an argument the name of a class, similar to a STL <tt>binary_function</tt>, and evaluates the <tt>operator()</tt> method:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_relation</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_RELATION</span></span><span style="color: #990000">(</span>std<span style="color: #990000">::</span>greater<span style="color: #990000">&lt;</span><span style="color: #009900">double</span><span style="color: #990000">&gt;,</span> <span style="color: #993399">1e6</span><span style="color: #990000">,</span> <span style="color: #993399">1000.0</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>This test assertion can be seen as a generalization of <a href="#ts_assert_equals">TS_ASSERT_EQUALS</a>, <a href="#ts_assert_differs">TS_ASSERT_DIFFERS</a>, <a href="#ts_assert_less_than">TS_ASSERT_LESS_THAN</a> and <a href="#ts_assert_less_than_equals">TS_ASSERT_LESS_THAN_EQUALS</a>.
+This can be used to assert comparisons which are not covered by the builtin test assertions.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_same_data"></a> TS_ASSERT_SAME_DATA
+</dt>
+<dd>
+<p>
+This test assertion is similar to <a href="#ts_assert_equals">TS_ASSERT_EQUALS</a>,
+except that it compares the contents of two buffers in memory:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_same_data</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="color: #009900">char</span> input <span style="color: #990000">=</span> <span style="color: #FF0000">"The quick brown fox ran over the lazy dog"</span><span style="color: #990000">;</span>
+        <span style="color: #009900">char</span> output<span style="color: #990000">[</span><span style="color: #993399">26</span><span style="color: #990000">];</span>
+        <span style="font-weight: bold"><span style="color: #000000">memcopy</span></span><span style="color: #990000">(</span>output<span style="color: #990000">,</span> input<span style="color: #990000">,</span> <span style="color: #993399">26</span><span style="color: #990000">);</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_SAME_DATA</span></span><span style="color: #990000">(</span>input<span style="color: #990000">,</span> output<span style="color: #990000">,</span> <span style="color: #993399">26</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>The standard runner dumps the contents of both buffers as hex values when this test fails.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_throws"></a> TS_ASSERT_THROWS
+</dt>
+<dd>
+<p>
+This test assertion verifies that the specified exception is thrown when the first argument is executed:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">throws_runtime_error</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="color: #008080">raise</span> std<span style="color: #990000">::</span>runtime_error<span style="color: #990000">,</span> <span style="color: #FF0000">"This method simply generates an exception"</span><span style="color: #990000">;</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_throws</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_THROWS</span></span><span style="color: #990000">(</span>self<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">throws_runtime_error</span></span><span style="color: #990000">(),</span> std<span style="color: #990000">::</span>runtime_error<span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_throws_anything"></a> TS_ASSERT_THROWS_ANYTHING
+</dt>
+<dd>
+<p>
+This test assertion verifies that <em>some</em> exception is thrown when the first argument is executed:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_throws_anything</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_THROWS_ANYTHING</span></span><span style="color: #990000">(</span>self<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">throws_runtime_error</span></span><span style="color: #990000">());</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_throws_assert"></a> TS_ASSERT_THROWS_ASSERT
+</dt>
+<dd>
+<p>
+This test assertion verifies that an exception is thrown when executing the first argument.  The second argument specifies a variable declaration for the exception, and the third argument is executed to test that
+exception value:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">throws_value</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        raise <span style="color: #993399">1</span><span style="color: #990000">;</span>
+    <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_throws_assert</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_THROWS_ASSERT</span></span><span style="color: #990000">(</span>self<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">throws_value</span></span><span style="color: #990000">(),</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> Error <span style="color: #990000">&amp;</span> e<span style="color: #990000">,</span> <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_EQUALS</span></span><span style="color: #990000">(</span>e<span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">));</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>Note that this can be viewed as a generalization of <a href="#ts_assert_throws_equals">TS_ASSERT_THROWS_EQUALS</a>.</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_throws_equals"></a> TS_ASSERT_THROWS_EQUALS
+</dt>
+<dd>
+<p>
+This test assertion verifies that an exception is thrown when executing the first argument.  The second argument specifies a variable declaration for the exception, and the third and fourth arguments are values that are asserted equal after the exception is thrown:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_throws_equals</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_THROWS_EQUALS</span></span><span style="color: #990000">(</span>self<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">throws_value</span></span><span style="color: #990000">(),</span> <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> Error <span style="color: #990000">&amp;</span> e<span style="color: #990000">,</span> e<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">what</span></span><span style="color: #990000">(),</span> <span style="color: #993399">1</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_assert_throws_nothing"></a> TS_ASSERT_THROWS_NOTHING
+</dt>
+<dd>
+<p>
+This test assertion verifies that an exception is <em>not</em> thrown when executing the first argument:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">throws_nothing</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span> <span style="color: #FF0000">}</span>
+
+    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_assert_throws_nothing</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_ASSERT_THROWS_ASSERT</span></span><span style="color: #990000">(</span>self<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">throws_nothing</span></span><span style="color: #990000">());</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_fail"></a> TS_FAIL
+</dt>
+<dd>
+<p>
+This function triggers a test failure with an associated message:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_fail</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_FAIL</span></span><span style="color: #990000">(</span><span style="color: #FF0000">"This test has failed."</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_trace"></a> TS_TRACE
+</dt>
+<dd>
+<p>
+This function prints an informational message:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_trace</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_TRACE</span></span><span style="color: #990000">(</span><span style="color: #FF0000">"This is a test tracing message."</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<a id="ts_warn"></a> TS_WARN
+</dt>
+<dd>
+<p>
+This function prints a message as a warning:
+</p>
+</dd>
+</dl></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>    <span style="color: #009900">void</span> <span style="font-weight: bold"><span style="color: #000000">test_warn</span></span><span style="color: #990000">(</span><span style="color: #009900">void</span><span style="color: #990000">)</span>
+    <span style="color: #FF0000">{</span>
+        <span style="font-weight: bold"><span style="color: #000000">TS_WARN</span></span><span style="color: #990000">(</span><span style="color: #FF0000">"This is a warning message."</span><span style="color: #990000">);</span>
+    <span style="color: #FF0000">}</span></tt></pre></div></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="appendix_B">Appendix B: Integrating with Your Build Environment</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>CxxTest can be integrated into a variety of build environments to
+automate the generation, compilation and execution of test runners.
+Here is a rough breakdown of this process:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Split the application into a library and a main module that just
+  calls the library classes.  This way, the test runner will be
+  able to access all your classes through the library.
+</p>
+</li>
+<li>
+<p>
+Create another application (or target, or project, or whatever)
+  for the test runner.  Make the build tool generate it automatically.
+</p>
+</li>
+<li>
+<p>
+Configure the build tool to run the tests automatically.
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>Unfortunately, different build tools and IDEs need to setup this
+process in different ways.  The following sections provide rough
+guidance for doing this for some come use cases.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">These examples are not actively maintained and tested.  Please send
+suggestions to the CxxTest developers for updating this documentation.</td>
+</tr></table>
+</div>
+<div class="sect2">
+<h3 id="_using_makefiles">Using Makefiles</h3>
+<div class="paragraph"><p>Generating the tests with a makefile is pretty straightforward.
+Simply add rules to generate, compile and run the test runner.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #990000">all:</span> lib run_tests app
+
+<span style="font-style: italic"><span style="color: #9A1900"># Rules to build your targets</span></span>
+<span style="color: #990000">lib:</span> <span style="color: #990000">...</span>
+
+<span style="color: #990000">app:</span> <span style="color: #990000">...</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># A rule that runs the unit tests</span></span>
+<span style="color: #990000">run_tests:</span> runner
+        <span style="color: #990000">.</span>/runner
+
+<span style="font-style: italic"><span style="color: #9A1900"># How to build the test runner</span></span>
+<span style="color: #990000">runner:</span> runner.cpp lib
+        g<span style="color: #990000">++</span> -o <span style="color: #009900">$@</span> <span style="color: #009900">$^</span>
+
+<span style="font-style: italic"><span style="color: #9A1900"># How to generate the test runner</span></span>
+<span style="color: #990000">runner.cpp:</span> SimpleTest.h ComplicatedTest.h
+         cxxtestgen -o <span style="color: #009900">$@</span> --error-printer <span style="color: #009900">$^</span></tt></pre></div></div>
+</div>
+<div class="sect2">
+<h3 id="_using_cons">Using Cons</h3>
+<div class="paragraph"><p><a href="http://dsmit.com/cons/">Cons</a> is a powerful and
+versatile make replacement which uses Perl scripts instead of Makefiles.</p></div>
+<div class="paragraph"><p>See <tt>cxxtest/sample/Construct</tt> in the CxxTest distribution for an
+example of building CxxTest test runners with Cons.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_using_microsoft_visual_studio">Using Microsoft Visual Studio</h3>
+<div class="paragraph"><p>See <tt>cxxtest/sample/msvc</tt> in the distribution
+to see a reasonable integration of CxxTest with Microsoft Visual Studio&#8217;s IDE.
+Basically, the workspace has three
+projects:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+The project <tt>CxxTest_3_Generate</tt> runs <tt>cxxtestgen</tt>.
+</p>
+</li>
+<li>
+<p>
+The project <tt>CxxTest_2_Build</tt> compiles the generated file.
+</p>
+</li>
+<li>
+<p>
+The project <tt>CxxTest_1_Run</tt> runs the tests.
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>This method certainly works, and the test results are conveniently
+displayed as compilation errors and warnings (for <a href="#ts_warn">TS_WARN</a>.
+However, there are still a few things missing; to integrate this
+approach with your own project, you usually need to work a little
+bit and tweak some makefiles and project options.  The script
+<tt>sample/msvc/FixFiles.bat</tt> can automate some of this process.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_using_microsoft_windows_ddk">Using Microsoft Windows DDK</h3>
+<div class="paragraph"><p>To use CxxTest with the <tt>build</tt> utility for device drivers, you add
+the generated tests file as an extra dependency using the
+<tt>NTBUILDTARGET0</tt> macro and the <tt>Makefile.inc</tt> file.  An example of
+how to do this is in the CxxTest distribution under <tt>sample/winddk</tt>.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="appendix_C">Appendix C: Testing CxxTest</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>In the <tt>cxxtest/test</tt> directory, you can execute</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>python test_cxxtest<span style="color: #990000">.</span>py</tt></pre></div></div>
+<div class="paragraph"><p>to launch all tests.  By default, this script executes test suites
+for a variety of compilers if they are found on the user&#8217;s path:
+<tt>g++</tt>, <tt>clang++</tt>, <tt>cl</tt> (the Microsoft Visual Studio compiler).
+Additionally, this test script includes separate test suites for
+the default test discovery mechanism as well as test discovery using
+the new FOG parser.</p></div>
+<div class="paragraph"><p>You can execute a specific test suite by giving its name as an
+argument to this test script.  For example, the command</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>python test_cxxtest<span style="color: #990000">.</span>py TestGpp</tt></pre></div></div>
+<div class="paragraph"><p>executes the <tt>TestGpp</tt> test suite, which tests CxxTest with the
+<tt>g++</tt> compiler.  Similarly, the command</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>python test_cxxtest<span style="color: #990000">.</span>py TestGppFOG</tt></pre></div></div>
+<div class="paragraph"><p>executes the test suite that tests CxxTest using the <tt>g++</tt> compiler
+and the FOG parser.</p></div>
+<div class="paragraph"><p>The <tt>test_cxxtest.py</tt> script should work with versions Python 2.7
+or newer.  If you are running Python 2.6, you will need to install
+the <tt>unittest2</tt> package.  If you have
+<a href="http://pypi.python.org/pypi/setuptools">setuptools</a> or
+<a href="http://pypi.python.org/pypi/distribute">distribute</a>
+installed, then
+you can install this package from PyPI by executing</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.4
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>easy_install unittest2</tt></pre></div></div>
+<div class="paragraph"><p>Similarly, the tests for this document rely on the <tt>PyUtilib</tt> Python package.</p></div>
+<div class="paragraph"><p>The FOG parser requires two Python packages:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt>ply</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>ordereddict</tt> (This is only needed when running Python 2.6)
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>If these packages are not available, then <tt>test_cxxtest.py</tt> will skip the FOG tests.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="appendix_D">Appendix D: CxxTest Releases</h2>
+<div class="sectionbody">
+<div class="ulist"><ul>
+<li>
+<p>
+Version 4.0.3 (TODO)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Adding support for Python 2.4, 2.5, 2.6, 2.7 and 3.2
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 4.0.2 (2012-01-02)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Bug fix to enable installation of cxxtestgen without the <em>setuptools</em> package
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 4.0.1 (2012-01-01)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Documentation updates
+</p>
+</li>
+<li>
+<p>
+Bug fix for installation of cxxtestgen script
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 4.0 (2011-12-28)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Perl is no longer used to support CxxTest scripts.  Python is now the only scripting language used by      CxxTest.
+</p>
+</li>
+<li>
+<p>
+The testing scripts have been rewritten using the PyUnit framework.
+</p>
+</li>
+<li>
+<p>
+The installation process for CxxTest now leverages and integrates with the system Python installation.
+</p>
+</li>
+<li>
+<p>
+A more comprehensive C++ parser is now available, which supports testing of templates.
+</p>
+</li>
+<li>
+<p>
+The CxxTest GUI is no longer supported, and the <a href="#ts_warn">TS_WARN</a> is deprecated.
+</p>
+</li>
+<li>
+<p>
+CxxTest runners now have a command-line interface that facilitates interative use of the test runner.
+</p>
+</li>
+<li>
+<p>
+A new user guide is now available in PDF, HTML and Ebook formats.
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.10.1 (2004-12-01)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Improved support for VC7
+</p>
+</li>
+<li>
+<p>
+Fixed clash with some versions of STL
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.10.0 (2004-11-20)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added mock framework for global functions
+</p>
+</li>
+<li>
+<p>
+Added TS_ASSERT_THROWS_ASSERT and TS_ASSERT_THROWS_EQUALS
+</p>
+</li>
+<li>
+<p>
+Added CXXTEST_ENUM_TRAITS
+</p>
+</li>
+<li>
+<p>
+Improved support for STL classes (vector, map etc.)
+</p>
+</li>
+<li>
+<p>
+Added support for Digital Mars compiler
+</p>
+</li>
+<li>
+<p>
+Reduced root/part compilation time and binary size
+</p>
+</li>
+<li>
+<p>
+Support C++-style commenting of tests
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.9.1 (2004-01-19)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed small bug with runner exit code
+</p>
+</li>
+<li>
+<p>
+Embedded test suites are now deprecated
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.9.0 (2004-01-17)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added TS_TRACE
+</p>
+</li>
+<li>
+<p>
+Added --no-static-init
+</p>
+</li>
+<li>
+<p>
+CxxTest::setAbortTestOnFail() works even without --abort-on-fail
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.8.5 (2004-01-08)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added --no-eh
+</p>
+</li>
+<li>
+<p>
+Added CxxTest::setAbortTestOnFail() and CXXTEST_DEFAULT_ABORT
+</p>
+</li>
+<li>
+<p>
+Added CxxTest::setMaxDumpSize()
+</p>
+</li>
+<li>
+<p>
+Added StdioFilePrinter
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.8.4 (2003-12-31)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Split distribution into cxxtest and cxxtest-selftest
+</p>
+</li>
+<li>
+<p>
+Added &#8216;sample/msvc/FixFiles.bat&#8217;
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.8.3 (2003-12-24)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added TS_ASSERT_PREDICATE
+</p>
+</li>
+<li>
+<p>
+Template files can now specify where to insert the preamble
+</p>
+</li>
+<li>
+<p>
+Added a sample Visual Studio workspace in &#8216;sample/msvc&#8217;
+</p>
+</li>
+<li>
+<p>
+Can compile in MSVC with warning level 4
+</p>
+</li>
+<li>
+<p>
+Changed output format slightly
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.8.1 (2003-12-21)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed small bug when using multiple --part files.
+</p>
+</li>
+<li>
+<p>
+Fixed X11 GUI crash when there&#8217;s no X server.
+</p>
+</li>
+<li>
+<p>
+Added GlobalFixture::setUpWorld()/tearDownWorld()
+</p>
+</li>
+<li>
+<p>
+Added leaveOnly(), activateAllTests() and &#8216;sample/only.tpl&#8217;
+</p>
+</li>
+<li>
+<p>
+Should now run without warnings on Sun compiler.
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.8.0 (2003-12-13)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed bug where &#8216;Root.cpp&#8217; needed exception handling
+</p>
+</li>
+<li>
+<p>
+Added TS_ASSERT_RELATION
+</p>
+</li>
+<li>
+<p>
+TSM_ macros now also tell you what went wrong
+</p>
+</li>
+<li>
+<p>
+Renamed Win32Gui::free() to avoid clashes
+</p>
+</li>
+<li>
+<p>
+Now compatible with more versions of Borland compiler
+</p>
+</li>
+<li>
+<p>
+Improved the documentation
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.7.1 (2003-09-29)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added --version
+</p>
+</li>
+<li>
+<p>
+Compiles with even more exotic g++ warnings
+</p>
+</li>
+<li>
+<p>
+Win32 Gui compiles with UNICODE
+</p>
+</li>
+<li>
+<p>
+Should compile on some more platforms (Sun Forte, HP aCC)
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.7.0 (2003-09-20)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added TS_ASSERT_LESS_THAN_EQUALS
+</p>
+</li>
+<li>
+<p>
+Minor cleanups
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.6.1 (2003-09-15)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Improved QT GUI
+</p>
+</li>
+<li>
+<p>
+Improved portability some more
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.6.0 (2003-09-04)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added --longlong
+</p>
+</li>
+<li>
+<p>
+Some portability improvements
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.5.1 (2003-09-03)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Major internal rewrite of macros
+</p>
+</li>
+<li>
+<p>
+Added TS_ASSERT_SAME_DATA
+</p>
+</li>
+<li>
+<p>
+Added --include option
+</p>
+</li>
+<li>
+<p>
+Added --part and --root to enable splitting the test runner
+</p>
+</li>
+<li>
+<p>
+Added global fixtures
+</p>
+</li>
+<li>
+<p>
+Enhanced Win32 GUI with timers, -keep and -title
+</p>
+</li>
+<li>
+<p>
+Now compiles with strict warnings
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.1.1 (2003-08-27)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed small bug in TS_ASSERT_THROWS_*()
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.1.0 (2003-08-23)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Default ValueTraits now dumps value as hex bytes
+</p>
+</li>
+<li>
+<p>
+Fixed double invocation bug (e.g. TS_FAIL(functionWithSideEffects()))
+</p>
+</li>
+<li>
+<p>
+TS_ASSERT_THROWS*() are now "abort on fail"-friendly
+</p>
+</li>
+<li>
+<p>
+Win32 GUI now supports Windows 98 and doesn&#8217;t need comctl32.lib
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 3.0.1 (2003-08-07)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added simple GUI for X11, Win32 and Qt
+</p>
+</li>
+<li>
+<p>
+Added TS_WARN() macro
+</p>
+</li>
+<li>
+<p>
+Removed --exit-code
+</p>
+</li>
+<li>
+<p>
+Improved samples
+</p>
+</li>
+<li>
+<p>
+Improved support for older (pre-std::) compilers
+</p>
+</li>
+<li>
+<p>
+Made a PDF version of the User&#8217;s Guide
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.8.4 (2003-07-21)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Now supports g++-3.3
+</p>
+</li>
+<li>
+<p>
+Added --have-eh
+</p>
+</li>
+<li>
+<p>
+Fixed bug in numberToString()
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.8.3 (2003-06-30)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed bugs in cxxtestgen.pl
+</p>
+</li>
+<li>
+<p>
+Fixed warning for some compilers in ErrorPrinter/StdioPrinter
+</p>
+</li>
+<li>
+<p>
+Thanks Martin Jost for pointing out these problems!
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.8.2 (2003-06-10)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed bug when using CXXTEST_ABORT_TEST_ON_FAIL without standard library
+</p>
+</li>
+<li>
+<p>
+Added CXXTEST_USER_TRAITS
+</p>
+</li>
+<li>
+<p>
+Added --abort-on-fail
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.8.1 (2003-01-16)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Fixed charToString() for negative chars
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.8.0 (2003-01-13)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added CXXTEST_ABORT_TEST_ON_FAIL for xUnit-like behaviour
+</p>
+</li>
+<li>
+<p>
+Added &#8216;sample/winddk&#8217;
+</p>
+</li>
+<li>
+<p>
+Improved ValueTraits
+</p>
+</li>
+<li>
+<p>
+Improved output formatter
+</p>
+</li>
+<li>
+<p>
+Started version history
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+Version 2.7.0 (2002-09-29)
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added embedded test suites
+</p>
+</li>
+<li>
+<p>
+Major internal improvements
+</p>
+</li>
+</ul></div>
+</li>
+</ul></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2012-01-07 08:51:08 MST
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/cxxtest/doc/guide.pdf b/tools/cxxtest/doc/guide.pdf
new file mode 100644 (file)
index 0000000..3bd721f
Binary files /dev/null and b/tools/cxxtest/doc/guide.pdf differ
diff --git a/tools/cxxtest/doc/guide.txt b/tools/cxxtest/doc/guide.txt
new file mode 100644 (file)
index 0000000..f4fe68e
--- /dev/null
@@ -0,0 +1,1559 @@
+CxxTest User Guide
+==================
+:doctype: article
+
+:cpp: {basebackend@docbook:c++:cpp}
+:makefile: {basebackend@docbook:make:makefile}
+
+:numbered!:
+[abstract]
+Abstract
+--------
+CxxTest is a unit testing framework for C\++ that is similar in
+spirit to http://junit.org/[JUnit],
+http://cppunit.sourceforge.net[CppUnit], and
+http://xprogramming.com/software.html[xUnit].  CxxTest is easy to
+use because it does not require precompiling a CxxTest testing
+library, it employs no advanced features of C++ (e.g. RTTI) and it
+supports a very flexible form of test discovery.  This documentation
+describes CxxTest 4.0, which includes significant enhancements to
+the test discovery process, a modern test driver, and new documentation.
+
+:numbered:
+
+Overview
+--------
+
+CxxTest is a unit testing framework for C++ that is similar in
+spirit to http://junit.org/[JUnit],
+http://cppunit.sourceforge.net[CppUnit], and
+http://xprogramming.com/software.html[xUnit].  
+CxxTest is designed to be as portable as possible;  it does not require
+
+ - RTTI
+ - Member template functions
+ - Exception handling
+ - External libraries (including memory management, file/console I/O, graphics libraries)
+
+In particular, the design of CxxTest was tailored for C\++ compilers
+on embedded systems, for which many of these features are not
+supported.  However, CxxTest can also leverage standard C++ features
+when they are supported by a compiler (e.g. catch unhandled
+exceptions).
+
+Additionally, CxxTest supports _test discovery_.  Tests are defined
+in C\++ header files, which are parsed by CxxTest to automatically
+generate a test runner.  Thus, CxxTest is somewhat easier to use
+than alternative C++ testing frameworks, since you do not need to
+_register_ tests.
+
+The http://cxxtest.com[CxxTest Home Page] is
+http://cxxtest.com[http://cxxtest.com].  This webpage contains links
+for https://sourceforge.net/projects/cxxtest/files/[release downloads],
+the https://groups.google.com/forum/?hl=en#!forum/cxxtest-forum[CxxTest
+discussion list], and documentation in
+http://cxxtest.com/cxxtest/doc/guide.html[HTML],
+http://cxxtest.com/cxxtest/doc/guide.pdf[PDF], and
+http://cxxtest.comm/cxxtest/doc/guide.epub[EPUB] formats.  The
+http://cxxtest.com[CxxTest Home Page] also includes developer
+resources (e.g. https://software.sandia.gov/hudson/view/CxxTest/[automated
+test results]).  CxxTest is available under the
+http://www.gnu.org/copyleft/lesser.html[GNU Lesser General Public]
+license.
+
+The CxxTest User Guide provides the following documentation:
+
+ - <<gettingStarted,Getting Started>>: Some simple examples that illustrate how to use CxxTest
+ - <<testAssertions,Test Assertions>>: The test assertions supported by CxxTest
+ - <<cxxtestgen,The CxxTestGen Command>>: Documentation for the +cxxtestgen+ command
+ - <<runner,Test Runner Syntax>>: Discussion of command line options for test runners
+ - <<advanced,Advanced Testing Features>>: Advanced features of CxxTest
+ - <<traits,Value Traits>>: Customizing data traits for error messages
+ - <<mock,Testing with Mock Objects>>: How to test with mock global functions
+ - <<installation,Installation>>: How to install CxxTest
+ - <<discussion,Status and Future Plans>>: Comments on the past, present and future of CxxTest
+
+
+
+[[gettingStarted]]
+Getting Started
+---------------
+
+Testing is performed with CxxTest in a four-step process:
+
+ 1. Tests are defined in C++ header files
+ 2. The +cxxtestgen+ command processes header files to generate files for the test runner.
+ 3. Compile the test runner.
+ 4. Execute the test runner to run all test suites.
+
+CxxTest supports test automation, sharing of setup
+and shutdown code for tests, aggregation of tests into collections,
+and independence of the tests from the reporting framework.  To
+achieve this, CxxTest supports some important concepts that are common to xUnit frameworks (
+e.g. http://junit.org/[JUnit], http://cppunit.sourceforge.net[CppUnit], and
+http://xprogramming.com/software.html[xUnit]):
+
+test fixture::
+   A 'test fixture' represents the preparation needed to perform one or more
+   tests, and any associate cleanup actions.  This may involve, for example,
+   creating temporary or proxy databases, directories, or starting a server
+   process.
+
+/////
+test case::
+   A 'test case' is the smallest unit of testing.  It checks for a specific
+   response to a particular set of inputs.  CxxTest provides a base class,
+   +TestCase+, which may be used to create new test cases.
+/////
+
+test suite::
+   A 'test suite' is a collection of test cases, which represent
+   the smallest unit of testing.  A test suite is defined by a class
+   that inherits from the +CxxTest::TestSuite+ class, and the tests
+   in a test suite are executed together.
+
+test::
+    A test is a public member function of a test suite whose name
+    starts with +test+, e.g. +testDirectoryScanner()+,
+    +test_cool_feature()+ and +TestImportantBugFix()+.
+
+test runner::
+   A 'test runner' is a component which orchestrates the execution
+   of tests across one or more test suites and provides the outcome
+   to the user.
+
+When building test fixtures using +TestSuite+, the +TestSuite.setUp+
+and +TestSuite.tearDown+ methods can be overridden to provide
+initialization and cleanup for the fixture.  The +TestSuite.setUp+
+method is run before each test is executed, and the +TestSuite.tearDown+
+method is run after each test is executed.
+
+
+A First Example
+~~~~~~~~~~~~~~~
+
+The following is a simple example of a
+test suite with a single test, +testAddition+, which perform two test assertions:
+[source,{cpp}]
+----
+include::examples/MyTestSuite1.h[]
+----
+
+You use the +cxxtestgen+ script to generate a _test runner_ for test suites in C++ header files:
+[source,bash]
+----
+include::examples/.buildRunner_main.sh[]
+----
+This command generates the file +runner.cpp+, which can be compiled.
+[source,bash]
+----
+include::examples/.buildRunner_main.sh[]
+----
+Note that additional compiler flags may be needed to include headers
+and libraries that are used during testing.
+
+
+This runner can be executed to perform the specified tests:
+[source,bash]
+----
+include::examples/.exeRunner_main.sh[]
+----
+which generates the following output:
+----
+include::examples/exeRunner.out[]
+----
+
+
+A Second Example
+~~~~~~~~~~~~~~~~
+
+The following header file extends the previous example to
+include a test that generates an error:
+[source,{cpp}]
+----
+include::examples/.MyTestSuite2_.h[]
+----
+
+The test runner generated by +cxxtestgen+ for this test suite generates the following output:
+----
+include::examples/exeRunner2.out[]
+----
+
+
+Sample Problems
+~~~~~~~~~~~~~~~
+
+CxxTest comes with example test suites in the `cxxtest/sample` subdirectory of
+the distribution.  If you look in that directory, you will see three
+Makefiles: `Makefile.unix`, `Makefile.msvc` and
+`Makefile.bcc32` which are for Linux/Unix, MS Visual C\++ and Borland C++, repectively.  These files are provided as a starting point,
+and some options may need to be tweaked in them for your system.
+
+////
+WEH - I think we should omit these command line unless they are tested...
+
+If you are running under Windows, a good guess would be to run
+`nmake -fMakefile.msvc run_win32` (you may need to run
+`VCVARS32.BAT` first).
+Under Linux, `make -fMakefile.unix run_x11` should probably work.
+////
+
+
+[[testAssertions]]
+Test Assertions
+---------------
+
+The following table summarizes the test assertions supported by CxxTest.
+<<appendix_A,Appendix A>> provides examples that illustrate the use of these test assertions.
+
+[options="header"]
+|====================================================================================
+| Macro                                                                 | Description
+| <<ts_assert,+TS_ASSERT(expr)+>>                                   | Verify +expr+ is true
+| xref:ts_assert_delta[+TS_ASSERT_DELTA(x,y,d)+]                        | Verify that +abs(x-y) < d+
+| xref:ts_assert_differs[+TS_ASSERT_DIFFERS(x,y)+]                      | Verify that +x != y+
+| xref:ts_assert_equals[+TS_ASSERT_EQUALS(x,y)+]                        | Verify that +x == y+
+| xref:ts_assert_less_than[+TS_ASSERT_LESS_THAN(x,y)+]                  | Verify that +x < y+
+| xref:ts_assert_less_than_equals[+TS_ASSERT_LESS_THAN_EQUALS(x,y)+]    | Verify that +x <= y+
+| xref:ts_assert_predicate[+TS_ASSERT_PREDICATE(P,x)+]                  | Verify +P(x)+
+| xref:ts_assert_relation[+TS_ASSERT_RELATION(x,R,y)+]                  | Verify +x R y+
+| xref:ts_assert_same_data[+TS_ASSERT_SAME_DATA(x,y,size)+]             | Verify two buffers are equal
+| xref:ts_assert_throws[+TS_ASSERT_THROWS(expr,type)+]                  | Verify that +expr+ throws the specified exception type
+| <<ts_assert_throws_anything,+TS_ASSERT_THROWS_ANYTHING(expr)+>>     | Verify that +expr+ throws an exception
+| xref:ts_assert_throws_assert[+TS_ASSERT_THROWS_ASSERT(expr,arg,assertion)+] | Verify type and value of what +expr+ throws
+| xref:ts_assert_throws_equals[+TS_ASSERT_THROWS_EQUALS(expr,arg,x,y)+] | Verify type and value of what +expr+ throws
+| <<ts_assert_throws_nothing,+TS_ASSERT_THROWS_NOTHING(expr)+>>       | Verify that +expr+ doesn't throw anything
+| <<ts_fail,+TS_FAIL(message)+>>                                   | Fail unconditionally
+| <<ts_trace,+TS_TRACE(message)+>>                                 | Print +message+ as an informational message
+| <<ts_warn,+TS_WARN(message)+>>                                    | Print +message+ as a warning
+|====================================================================================
+
+The test assertions supported by CxxTest are defined as macros,
+which eliminates the need for certain templates within CxxTest and
+allows tests to catch exceptions.  There are four categories of
+test assertions in CxxTest, which are distinguished by their prefixes:
+
+TS_:: These test assertions perform a test. Catch exceptions generated
+during testing will cause the test to fail, except for tests that
+check for exceptions.
+
+TSM_:: These test assertions perform the same tests as the corresponding
++TS+ assertions, but their first argument is a +const char*+ message
+buffer that is printed when the test fails.
+
+ETS_:: These test assertions perform the same tests as the corresponding
++TS+ assertions.  However, these test assertions do not catch
+exceptions generated during testing.
+
+ETSM_:: These test assertions perform the same tests as the
+corresponding +TS+ assertions, but (1) their first argument is a
++const char*+ message buffer is printed when the test fails, and
+(2) these assertions do not catch exceptions generated during
+testing.
+
+
+[[cxxtestgen]]
+The CxxTestGen Command
+----------------------
+
+The +cxxtestgen+ command processes one or more C++ header files to
+generate a test runner.  The +cxxtestgen+ command performs test
+discovery by parsing the header files to find test classes, which
+inherit from the class +CxxTest::TestSuite+.
+
+The +--help+ option generates the following summary of the +cxxtestgen+ command line options:
+
+----
+include::examples/cxxtestgen.out[]
+----
+The following section describe illustrate the use of these command line options.
+
+
+General Options
+~~~~~~~~~~~~~~~
+
+The default behavior of +cxxtestgen+ is to send the source for the
+test runner to the standard output stream.  The +--output+ (+-o+)
+option indicates a filename for the test runner.
+
+The +--world+ (+-w+) option specifies the value of the +CxxTest::RealWorldDescription::_worldName+
+variable.  This option also customizes the filename used for XML output files (see below).
+
+The +--include+ option defines a filename that is included in the runner before all other headers.
+
+The +--abort-on-fail+ option forces an abort if a test fails, rather than continuing execution
+to the next test.
+
+The +--main+ option specifies an alternate name for the +main()+ function.
+
+Test Listener Options
+~~~~~~~~~~~~~~~~~~~~~
+
+The test runner behavior is controlled by a _test listener_ class
+that is used to define to the +main+ function.  The test listener
+class is a subclass of +TestListener+ that receives notifications
+about the testing process, notably which assertions failed.  The
++--runner+ option is used to specify the test listener that is used
+in the test runner.  The following test listeners are defined in
+CxxTest:
+
+ +ErrorPrinter+::
+    This is the standard error printer, which formats its output to the standard output stream (+std::cout+).
+ +StdioPrinter+::
+    The same as +ErrorPrinter+ except that it uses +printf+ instead of +std::cout+.
+ +ParenPrinter+::
+    Identical to +ErrorPrinter+ except that it prints line numbers in parantheses. This is the way Visual Studio expects it.
+ +XmlPrinter+::
+    Print test results to an XML file.
+ +XUnitPrinter+::
+    This test listener generates output using both +ErrorPrinter+ and +XmlPrinter+.
+
+ErrorPrinter
+^^^^^^^^^^^^
+
+The +--error-printer+ option creates a runner using the +ErrorPrinter+
+test listener, and it indicates that the standard library is used
+in the test runner.  The +ErrorPrinter+ test listener prints dots
+to summarize test execution, along with a summary of the test
+results.  For example, the command
+[source,bash]
+----
+include::examples/.buildRunner2_main.sh[]
+----
+generates the following output:
+
+----
+include::examples/exeRunner2.out[]
+----
+
+StdioPrinter
+^^^^^^^^^^^^
+
+If your compiler does not support +std::cout+, then the +ErrorPrinter+ test listener cannot be used.
+In this case, the +StdioPrinter+ test listener can be used;  it provides the same output as +ErrorPrinter+ but it uses the +printf+ function. For example, the command line:
+[source,bash]
+----
+include::examples/.buildRunner4_main.sh[]
+----
+generates the following output:
+
+----
+include::examples/buildRunner4.txt[]
+----
+
+ParenPrinter
+^^^^^^^^^^^^
+
+The +--runner=ParenPrinter+ option creates a similar test runner:
+[source,bash]
+----
+include::examples/.buildRunner3_main.sh[]
+----
+This test runner generates output that is similar to the +ErrorPrinter+ test listener:
+
+----
+include::examples/buildRunner3.txt[]
+----
+The only difference is the parentheses used in the output.  This test listener provides a format that can be recognized by Visual Studio.
+
+////
+The +StdioPrinter+ makes reference to +stdout+ as the default output
+stream. In some environments, the +stdio.h+ header may be defined
+but not +stdout+.  The +StdioFilePrinter+ test listener can be used
+in this case, though the main() function needs to be adapted to specify the 
+stream that is used in output.
+////
+
+XmlPrinter
+^^^^^^^^^^
+
+The +--runner=XmlPrinter+ option creates a test runner whose output is an XML summary of the test results.  For example, the command:
+[source,bash]
+----
+include::examples/.buildRunner6_main.sh[]
+----
+generates the following output:
+
+----
+include::examples/buildRunner6.txt[]
+----
+This XML format is conforms to the XML standard used by other xUnit tools.  Thus, this output can be used as input in other tools, like http://jenkins-ci.org/[Jenkins], to generate test summaries.
+
+
+XUnitPrinter
+^^^^^^^^^^^^
+
+The +XUnitPrinter+ test listener generates output using both the
+ErrorPrinter+ and +XmlPrinter+ test listeners.  This allows the
+user to interactively view a simple test summary, while simultaneously
+generating an XML summary of the test results.  The +--xunit-printer+
+option specifies the use of +XUnitPrinter+:
+[source,bash]
+----
+include::examples/.buildRunner7_main.sh[]
+----
+This test runner generates the following output:
+
+----
+include::examples/buildRunner7.txt[]
+----
+The default filename for the XML results is +TEST-cxxtest.xml+.  The +--xunit-file+ option can be used to specify an alternative filename.  Additionally, the value of the +--world+ option can be used to specify the filename +TEST-<world>.xml+.
+
+
+Language Options
+~~~~~~~~~~~~~~~~
+
+When +cxxtestgen+ performs test discovery, it also performs checks
+to detect whether (1) the standard library is used and (2) exceptions
+are used.  These checks configure CxxTest to _not_ assume that these
+C++ language features are used when generating the test driver.
+Thus, CxxTest can naturally be used with compilers that do not
+support these features.
+
+The +cxxtestgen+ command includes several options that override
+these checks and define features of C++ that are used by the test
+runner.  The +--have-std+ option indicates that the test runner
+should use the standard library, and the +--no-std+ option indicates
+that the test runner should not use the standard library. The
+--have-eh+ options indicates that the test runner should use
+exception handling, and the +--no-eh+ indicates that the test runner
+should not not use exception handling.  
+
+The +--longlong+ option specifies the type used for long long
+integers.  The default is for _no_ long long integer type to be specified,
+which is consistent with the current C++ standard.
+
+CxxTest test runners depend quite heavily on static initialization
+of objects that are used to define and execute tests. The
+--no-static-init+ option can be used to avoid static initialization
+for compilers or linkers that have trouble compiling the default test runner.
+
+
+Creating Test Runners from Parts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The default behavior of +cxxtestgen+ is to generate a test runner
+that directly integrates classes that define the tests along with
+a +main()+ function that executes all test suites.  It is often useful to 
+allow test suites to be processes separately and then linked together.  The +--root+ and +--part+ options
+support this logic.  For example, suppose that we wish to define a test runner for tests in the headers
+MyTestSuite1.h+ and +MyTestSuite2.h+.  We execute +cxxtestgen+ with the +--part+ option to generate source files for each of the test suites:
+[source,bash]
+----
+include::examples/.buildRunner9_part.sh[]
+----
+Similarly, we execute +cxxtestgen+ with the +--root+ opiton to generate the +main()+ routine:
+[source,bash]
+----
+include::examples/.buildRunner9_root.sh[]
+----
+Finally, the test runner is built by compiling all of these source files together:
+[source,bash]
+----
+include::examples/.buildRunner9_compile.sh[]
+----
+
+
+Template Files
+~~~~~~~~~~~~~~
+
+CxxTest supports the use of _template files_ to provide a custom
+main()+ function.  This may be useful when using a custom test
+listener, or when using an existing CxxTest test listener in a
+nonstandard manner.  A template file is an ordinary source files
+with the embedded declaration +<CxxTest world>+, which tells
+cxxtestgen+ to insert the world definition at that point.
+
+The +--template+ option is used to specify the use of a template file:
+[source,bash]
+----
+include::examples/.buildRunner10_main.sh[]
+----
+For example, consider the following template file:
+[source,{cpp}]
+----
+include::examples/runner10.tpl[]
+----
+This file specifies macros that customize the test runner, and output is generated before and after the tests are run.
+
+Note that CxxTest needs to insert certain definitions and +#include+
+directives in the runner file. It normally does that before the
+first +#include <cxxtest/*.h>+ found in the template file. If this
+behavior is not what you need, use the directive +<CxxTest preamble>+
+to specify where this preamble is inserted.
+
+
+Test Discovery Options
+~~~~~~~~~~~~~~~~~~~~~~
+
+The +cxxtestgen+ command performs test discovery by searching C++
+header files for CxxTest test classes.  The default process for
+test discovery is a simple process that analyzes each line in a
+header file sequentially, looking for a sequence of lines that
+represent class definitions and test method definitions.
+
+There are many limitations to this simple process for test discovery,
+and in CxxTest 4.0 a new test discovery mechanism was added based
+on the a parser for the
+http://www.computing.surrey.ac.uk/research/dsrg/fog/[Flexible Object
+Generator (FOG)] language, which is a superset of C\++.  The grammar
+for the FOG language was adapted to parse C++ header files to
+identify class definitions and class inheritance relationships,
+class and namespace nesting of declarations, and class methods.
+This allows +cxxtestgen+ to identify test classes that are defined
+with complex inheritance relationships.
+
+The +--fog+ option is used to specify the use of the FOG parser for
+test discovery.  Although the FOG parser is more powerful, the
+simpler +cxxtestgen+ test discover process is the default because
+the FOG parser is slower execute.  Additionally, the FOG parser
+requires the installation of +ply+ and, for Python version 2.6,
+ordereddict+.  If these packages are not available, then the +--fog+
+option is automatically disabled.
+
+The following sections illustrate differences between these two test discovery mechanisms, along with
+general limitations of the test discovery process.
+
+Unexpected Test Suite Format
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The default test discovery mechanism does a very simple analysis
+of the input files, which can easily fail when test classes are not
+formated in a standard manner.  For example, consider the following
+test suite:
+[source,{cpp}]
+-----
+include::examples/MyTestSuite4.h[]
+----
+This test suite is not recognized by the default test discovery
+mechanism, but the FOG parser correctly parsers this file and
+recognizes the test suite.  A variety of similar discovery failures
+arise due to the simple process used by the test discovery mechanism.
+
+
+Commenting Out Tests
+^^^^^^^^^^^^^^^^^^^^
+
+Adding and disabling tests are two common steps in test development.
+The process of test discovery makes adding tests very easy.  However,
+disabling tests is somewhat more complicated.  Consider the following
+header file, which defines four tests (three of which are disabled):
+[source,{cpp}]
+-----
+include::examples/MyTestSuite3.h[]
+----
+
+The first is commented out with C\++-style comments, the second
+test is commented out with C-style comments, and the third test is
+named in a manner that is not recognized through test discovery
+(i.e., it does not start with +test+).
+
+The default test discovery mechanism only works with the first and
+third methods for disabling tests, but the FOG parser works with
+all three.  The FOG parser performs a complex, multi-line parse of
+the source file, so it can identify multi-line C-style comments.
+
+Note, however, that the use of C macros will not work:
+[source,{cpp}]
+-----
+include::examples/BadTestSuite1.h[]
+----
+The +cxxtestgen+ discovery mechanisms do not perform a C preprocessing
+step, since that would generally require using externally defined
+preprocessing variable definitions.   Additionally, preprocessor macros that act like functions will
+cause the FOG parser to fail unless they are followed by a semicolon.
+
+
+[[runner]]
+Test Runner Syntax
+------------------
+
+The default behavior of the CxxTest test runner is to execute all
+tests in all of the test suites that are linked into the runner.
+However, CxxTest test runners process command line options that
+allow individual tests and test suites to be selected.
+
+For example, consider a test runner defined as follows:
+[source,bash]
+----
+include::examples/.buildRunner13_main.sh[]
+----
+The +--help+ (+-h+) option can be used to print the command line options for a test runner.  The command
+
+----
+include::examples/.buildRunner13_help.sh[]
+----
+generates the following output:
+
+----
+include::examples/runner13.help.txt[]
+----
+
+The +--help-tests+ option is used to list all test suites that are defined in a test runner.  The command
+[source,bash]
+----
+include::examples/.buildRunner13_helpTests.sh[]
+----
+generates the following output:
+
+----
+include::examples/runner13.helpTests.txt[]
+----
+The first column is the test suite name, and the second column is the test name.
+
+All tests in a test suite can be executed by simply specifying the test suite name.  For example
+[source,bash]
+----
+include::examples/.buildRunner13_MyTestSuite2.sh[]
+----
+executes the tests in test suite +MyTestSuite2+:
+
+----
+include::examples/runner13.MyTestSuite2.txt[]
+----
+
+Similarly, a single test can be executed by specifying the test suite followed by the test name.  For example
+[source,bash]
+----
+include::examples/.buildRunner13_testMultiplication.sh[]
+----
+executes the +testMultiplication+ test in test suite +MyTestSuite2+:
+
+----
+include::examples/runner13.testMultiplication.txt[]
+----
+
+The +-v+ option enables the printing of trace information generated
+by the +TS_TRACE+ function.  For example, the +testMultiplication+ test contains trace declarations
+before and after the multiplication test.  Thus, the command
+[source,bash]
+----
+include::examples/.buildRunner13_testMultiplicationVerbose.sh[]
+----
+generates this trace output before and after the test:
+
+----
+include::examples/runner13.testMultiplicationVerbose.txt[]
+----
+
+
+[[advanced]]
+Advanced Testing Features
+-------------------------
+
+Preprocessor Macros
+~~~~~~~~~~~~~~~~~~~
+
+CxxTest recognizes a variety of preprocessor macros that can be used to modify the behavior of a test runner.  Many of these mimic the options of the +cxxtestgen+ command.
+
+[options="header"]
+|====================================================================================
+| Preprocessor Macro  | Description 
+| +CXXTEST_HAVE_STD+              | Use the standard library. 
+| +CXXTEST_HAVE_EH+               | Use exception handling.   
+| +CXXTEST_ABORT_TEST_ON_FAIL+    | Abort tests on failed asserts. 
+| +CXXTEST_USER_VALUE_TRAITS+     | Enable user-defined value traits.  The default traits dump up to 8 bytes of the data as hex values. 
+| +CXXTEST_OLD_TEMPLATE_SYNTAX+   | Use old template syntax that is used by some compilers (e.g. Borland C++ 5). 
+| +CXXTEST_OLD_STD+               | Use old syntax for libraries where +std::+ is not recognized. 
+| +CXXTEST_MAX_DUMP_SIZE+         | The value of this macro defines the maximum number of bytes to dump if +TS_ASSERT_SAME_DATA()+ fails. The default is 0, which indicates no limit. 
+| +CXXTEST_DEFAULT_ABORT+         | The value of this macro is the default value of the dynamic _abort on fail_ flag. 
+| +CXXTEST_LONGLONG+              | The value of this macro is used to define long long integers.
+|=====================================
+
+These preprocessor macros must be defined before the CxxTest header
+files are included in the test runner.  For example, the following
+template file defines +CXXTEST_HAVE_EH+ and +CXXTEST_ABORT_TEST_ON_FAIL+
+before other headers are included:
+[source,{cpp}]
+----
+include::examples/runner10.tpl[]
+----
+
+Several of these macros concern whether modern C++ conventions are
+supported by the compiler.  If tests need to be ported to multiple
+compilers, then one important convention is whether the namespace
++std::+ is supported.  For example, switching between +cout+ and
++std::cout+ typically needs to be done throughout a code.  CxxTest
+supports this with the +CXXTEST_STD()+ macro.  For example,
++CXXTEST_STD(cout)+ can be used within a test suite, and CxxTest
+handles the mapping of this to +cout+ or +std::cout+ depending on
+options provided to +cxxtestgen+.
+
+
+
+Customizing Test Fixtures
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Setup and Teardown
+^^^^^^^^^^^^^^^^^^
+
+CxxTest test fixtures can be customized in several ways to manage
+the environment for test suites and individual tests.  A common
+feature of test suites is that they share a common logic for setting
+up data used in the tests.  Thus, there may be duplicate code for
+creating objects, files, inputs, etc.  Similarly, the tests may
+share common logic for cleaning up after the test is finished (e.g. deleting temporary objects).
+
+You can put this shared code in a common place by overriding the
+virtual functions `TestSuite::setUp()` and `TestSuite::tearDown()`.
+The `setUp()` function is called before each test, and `tearDown()`
+is called after each test.
+
+For example, the following test suite employs +setUp()+ and +tearDown()+ methods to 
+allocate and deallocate memory for a string buffer:
+[source,{cpp}]
+-----
+include::examples/MyTestSuite5.h[]
+-----
+
+Dynamically Created Test Suites
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CxxTest test fixtures can also be customized during the construction
+and deconstruction of test suites.  By default, CxxTest test suites
+are instantiated statically in the test runner.  However, dynamically
+created test suites can be used to perform suite-level setup and
+teardown operations, verify the environment needed to execute a
+test suite, and construct test suites that require a nontrivial
+constructor.
+
+CxxTest instantiates a test suite dynamically if the +createSuite()+
+or +destroySuite()+ methods are defined.  For example, the following
+test suite checks to see if it is being compiled with Microsoft
+Visual Studio.  If not, the +createSuite()+ returns a null pointer,
+indicating that the test suite was not created.
+[source,{cpp}]
+-----
+include::examples/MyTestSuite6.h[]
+-----
+
+Global and World Fixtures
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CxxTest supports two related mechanisms for performing _global_
+setup and teardown operations.  _Global fixtures_ are classes that
+inherit from `CxxTest::GlobalFixture`, and they define `setUp` and
+`tearDown` methods.  The `setUp` method for all global fixtures is
+called before each test is executed, and the `tearDown` method for
+all global fixtures is called after each test is completed.  Thus,
+this mechanism provides a convenient way of defining setup and
+teardown operations that apply to all test suites.
+
+For example, consider the following test suite:
+[source,{cpp}]
+-----
+include::examples/MyTestSuite8.h[]
+-----
+This test suite defines a runner that generates the following output:
+
+-----
+include::examples/buildRunner18.txt[]
+-----
+
+Note that the global fixtures are instantiated with static global
+values.  This ensures that these fixtures are created before the
+runner is initialized.  Also, note that the `setUp` methods are
+called in the same sequence that the global fixtures are instantiated,
+and the `tearDown` methods are called in the reverse sequence.
+Finally, note that the `setUp` and `tearDown` methods in global
+fixtures return a boolean value, which indicates success or failure
+of that operation.
+
+This example also illustrates the use of _world fixtures_, which
+perform setup and teardown operations that are executed once each
+when beginning and finishing tests in each test suite.  World
+fixtures are defined with the `setUpWorld` and `tearDownWorld`
+methods in a global fixture.
+
+
+Runtime Test Customization
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CxxTest defines several functions that can be called in a test suite to modify the default behavior of CxxTest.
+
+[options="header"]
+|==================================
+| Test Suite Method | Description
+| +setAbortTestOnFail(bool)+ |  This function specifies whether tests abort after a failure.  The default value of the flag is +false+.  This function only has an effect if exception handling is enabled.
+| +setMaxDumpSize(unsigned)+ | This function sets the maximum number of bytes that are dumped when 
++TS_ASSERT_SAME_DATA()+ fails. The default is 0, which indicates no limit.
+|=============
+
+Note that the the configuration parameters are reset to their default
+values after each test is executed (more precisely, after +tearDown()+
+is called).  Consequently, calling these functions in the +setUp()+
+function has the effect of setting that value for the entire test
+suite.
+
+
+
+[[traits]]
+Value Traits
+------------
+
+CxxTest's test assertions like <<ts_assert_equals,TS_ASSERT_EQUALS>>
+work for built-in types, but they will not likely work for user-defined
+data types.  This is because CxxTest needs a way to compare objects
+and to convert them to strings when printing test failure summaries.
+Thus, user-defined data types need to have the `operator=` method
+defined to ensure that test assertions can be applied.
+
+For example, the following code
+[source,{cpp}]
+-----
+include::examples/MyTestSuite7.h[]
+-----
+defines a test runner that generates the following output
+
+-----
+include::examples/buildRunner17.txt[]
+-----
+The `operator=` method is required to apply
+<<ts_assert_equals,TS_ASSERT_EQUALS>> to `Data` objects.  However,
+the <<ts_assert_same_data,TS_ASSERT_SAME_DATA>> assertion can be
+applied to `Data2` objects that do not have `operator=` defined.
+
+Since CxxTest does not rely on any external library, conversion
+from arbitrary data types to strings is done using _value traits_.
+For example, to convert an integer to a string, CxxTest does the following:
+[source,{cpp}]
+----
+int i = 10;
+CxxTest::ValueTraits<int> converter(i);
+const char* string = converter.asString();
+----
+The CxxTest header file `cxxtest/ValueTraits.h` defines value traits
+for standard types like `int`, `char`, `double`, etc.  The default
+`ValueTraits` class for unknown types dumps up to 8 bytes of the value
+in hex format.
+
+If the macro `CXXTEST_USER_VALUE_TRAITS` is defined, then CxxTest will
+omit the default definitions for `ValueTraits`.  This allows a user to define their own trait specifications to customize the display of trait information.
+
+
+
+Enumeration Traits
+~~~~~~~~~~~~~~~~~~
+
+CxxTest provides a simple way to define value traits for enumeration
+types.  The `CXXTEST_ENUM_TRAITS` macro is used to define value
+traits for all members of an enumeration set.
+
+For example, the following code
+[source,{cpp}]
+-----
+include::examples/MyTestSuite9.h[]
+-----
+defines a test runner that generates the following output
+
+-----
+include::examples/buildRunner19.txt[]
+-----
+The enumeration value traits print strings that represent the elements of the enumeration, except where a numeric value is provided.
+
+Note that the `CXXTEST_ENUM_TRAITS` macros has two arguments;  the list of `CXXTEST_ENUM_MEMBER` macros is not separated by commas!  
+
+
+Defining New Value Traits
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Defining value traits for a new class is done by providing a class
+specialization of `ValueTraits` that converts an object of the new
+class to a string.  For example, consider the definition of the
+`MyClass` class:
+[source,{cpp}]
+-----
+include::examples/MyClass.h[]
+-----
+This class includes definitions of `operator==` and `operator<`
+that support comparisons with <<ts_assert_equals,TS_ASSERT_EQUALS>>
+and <<ts_assert_less_than,TS_ASSERT_LESS_THAN>>.  Additionally,
+this header contains a specialization of `ValueTraits` (in the
+`CxxTest` namespace) that generates a string description of a `MyClass`
+instance.
+
+The following test suite illustrates how these definitions can be
+used to define a test runner:
+[source,{cpp}]
+-----
+include::examples/MyTestSuite10.h[]
+-----
+This runner for this test suite generates the following output:
+
+-----
+include::examples/buildRunner20.txt[]
+-----
+The test failure print logic uses the specialization of `ValueTraits` to create
+the string description of `MyClass` that appears in the output.
+
+
+Defining Value Traits for Template Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A simple modification to the above example illustrates how a trait can be defined for a
+template class:
+[source,{cpp}]
+-----
+include::examples/MyTestSuite11.h[]
+-----
+Unfortunately, this example employs partial template specialization, which  is not supported by all C++ compilers.
+
+
+[[mock]]
+Testing with Mock Objects
+-------------------------
+
+Mock Objects are a very useful concept for testing complex software.
+The key idea is to pass special objects to tested code that facilitates
+the testing process.  For instance, a class that implements a
+protocol over TCP might rely on an abstract `ISocket` interface.
+Then a mock testing strategy could pass a `MockSocket` object that
+does anything that is useful for testing (e.g., keep a log of all
+data ``sent'' to verify later).
+
+However, when a challenge for C/C++ developers is that you may need
+to call _global_ functions which you cannot override.  Consider any
+code that uses `fopen()`, `fwrite()` and `fclose()`.  It is not
+very elegant to have this code actually create files while being
+tested.  Even more importantly, you need to test how the code behaves
+when ``bad'' things happen (e.g., when `fopen()` fails).  Handling
+these types of exceptional conditions is often a very challenging
+issue for software testing.
+
+CxxTest addresses this challenge by providing a generic mechanism for 
+defining mock global functions.  The next section illustrates this mechanism for a single 
+global function.  The following section provides more detail about specific features of CxxTest's 
+support for mock testing.
+
+
+Example: A Mock +time()+ Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Suppose that we want to perform mock testing using the well known
+standard library function `time()`.  Setting up a test suite with
+a mock global function for `time()` can be broken down into the
+following steps.
+
+Declare Mock Functions
+^^^^^^^^^^^^^^^^^^^^^^
+
+The `CXXTEST_MOCK_GLOBAL` macro is used to declare mock global functions.  It is often convenient to include
+these declarations in a header file, which is used in both the test suite as well as the code that is being tested:
+[source,{cpp}]
+-----
+include::examples/time_mock.h[]
+-----
+
+Mock Functions in Tested Code
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The tested code uses mock global functions, rather than using the global functions directly.
+You access mock functions in the `T` (for _Test_) namespace, so the tested code calls `T::time()` instead of
+`time()`. This is the equivalent of using abstract interfaces
+instead of concrete classes.
+[source,{cpp}]
+-----
+include::examples/rand_example.cpp[]
+-----
+
+
+Mock Source Files
+^^^^^^^^^^^^^^^^^
+
+A source file needs to be defined that implements `T::time()` by
+calling the real global function.  This definition is performed automatically by
+defining `CXXTEST_MOCK_REAL_SOURCE_FILE` before the header file is defined:
+[source,{cpp}]
+-----
+include::examples/time_real.cpp[]
+-----
+This source file is not used for testing, but instead it supports normal use of the tested code.
+
+Similarly, a source file needs to be defined that implements `T::time()` by calling the mock
+global function.  This definition is performed automatically by defining `CXXTEST_MOCK_TEST_SOURCE_FILE` before the header file is defined:
+[source,{cpp}]
+-----
+include::examples/time_mock.cpp[]
+-----
+
+
+Test Suites using Mock Functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A mock object for the `time()` function is created using the `T::Base_time` class,
+which is automatically created by CxxTest.  This class includes a `time()` method whose
+API is the same as the global `time()` function.  Thus, this method can be defined to have
+whatever behavior is desired during testing.  For example, the following example defines a 
+mock object that increments a counter to define an incremental value for `time()`.
+[source,{cpp}]
+-----
+include::examples/MockTestSuite.h[]
+-----
+Note that CxxTest uses global data to associate calls made with `T::time()`
+to calls to `MockObject::time()`.  The `MockObject` class simply
+needs to be instantiated prior to the call to `T::time()`.
+
+
+Building the Test Runner
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The +cxxtestgen+ command is used to create a test runner with mock functions in a normal manner:
+[source,bash]
+-----
+include::examples/.buildRunner16_main.sh[]
+-----
+The test runner source file, `runner.cpp`, needs to be compiled an linked to the mock function definition, `time_mock.cpp`, as well as the code being tested, `rand_example.cpp`:
+[source,bash]
+-----
+include::examples/.buildRunner16_compile.sh[]
+-----
+This generates a test runner that generates the following output:
+
+-----
+include::examples/buildRunner16.txt[]
+-----
+
+
+Advanced Topics
+~~~~~~~~~~~~~~~
+
+Void Functions
+^^^^^^^^^^^^^^
+
+The `CXXTEST_MOCK_VOID_GLOBAL` is used to define mock global functions that return `void`.  
+This is identical to
+`CXXTEST_MOCK_GLOBAL` except that it does not specify the return
+type.  Take a look in `sample/mock/T/stdlib.h` for a demonstation.
+
+Calling the Real Functions While Testing
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+During testing it is sometimes necessary to call the real global
+function instead of the mock global function.  CxxTest allows a
+user to do this by creating a special mock object.  For a global
+mock function of `time()`, the object `T::Real_time` represents the
+real function.  If this class is created, then `T::time()` will be
+redirected to the real function.
+
+Mocking Nonexistent Functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes the tested code calls functions that are not available
+when testing.  For example, this can happen when testing driver
+code that calls kernel functions that are not available to a user-mode
+test runner.  CxxTest can provide mock global function definitions
+for the test code while using the original functions in the tested code.
+
+
+The `CXXTEST_SUPPLY_GLOBAL` and `CXXTEST_SUPPLY_VOID_GLOBAL` macros are used to provide mock global function definitions.  For example, the following declaration creates a mock global function for the Win32 kernel function `IoCallDriver`:
+[source,{cpp}]
+-----
+CXXTEST_SUPPLY_GLOBAL( NTSTATUS,                /* Return type */
+                       IoCallDriver,            /* Name        */
+                       ( PDEVICE_OBJECT Device, /* Prototype   */
+                         PIRP Irp ),
+                       ( Device, Irp )          /* How to call */ );
+-----
+The tested driver code calls `IoCallDriver()` normally;  there is no need for the `T::` syntax.
+The test suite is defined using the `T::Base_IoCallDriver` as with normal mock objects.
+
+CxxTest also provides the macros `CXXTEST_SUPPLY_GLOBAL_C` and
+`CXXTEST_SUPPLY_GLOBAL_VOID_C` that declare the functions with `C`
+linkage (i.e., using `extern "C"`).  These macros are used to declare
+function prototypes, since you may not be able to include the header
+files in the test suite that are associated with the mock global function.
+
+
+Functions in Namespaces
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The `CXXTEST_MOCK` macro is used to declare a mock global function that is associated
+with a function in a namespace, including static class member functions.  
+For example, consider the function `bool Files::FileExists( const
+String &name )`;  the namespace `Files` contains the function
+`FileExists`.  The mock class will be called `T::Base_Files_FileExists`
+and the function to implemented would be `fileExists`.  The `CXXTEST_MOCK` macro declares this mock global function as follows:
+[source,{cpp}]
+-----
+CXXTEST_MOCK( Files_FileExists,       /* Suffix of mock class  */
+              bool,                   /* Return type           */
+              fileExists,             /* Name of mock member   */
+              ( const String &name ), /* Prototype             */
+              Files::FileExists,      /* Name of real function */
+              ( name )                /* Parameter list        */ );
+-----
+Similarly, the `CXXTEST_MOCK_VOID` macro is used to declare a mock global function that returns `void`.
+
+The `CXXTEST_SUPPLY` and `CXXTEST_SUPPLY_VOID` macros are used to provide mock global function definitions for nonexistent functions.  For example:
+[source,{cpp}]
+-----
+CXXTEST_SUPPLY( AllocateIrp,         /* => T::Base_AllocateIrp */
+                PIRP,                /* Return type            */
+                allocateIrp,         /* Name of mock member    */
+                ( CCHAR StackSize ), /* Prototype              */
+                IoAllocateIrp,       /* Name of real function  */
+                ( StackSize )        /* Parameter list         */ );
+-----
+Similarly, the `CXXTEST_SUPPLY_C` and `CXXTEST_SUPPLY_VOID_C` macros declare the functions with `C` linkage.
+
+Overloaded Functions
+^^^^^^^^^^^^^^^^^^^^
+
+The `CXXTEST_MOCK` and `CXXTEST_MOCK_VOID` macros have a flexible
+interface that can provide mock global function definitions for
+overloaded functions.  The arguments simply need to specify different
+mock class names, mock member names and different prototype definitions.  
+These different mock declarations will generate different mock objects that can be explicitly
+referenced in a test suite.
+
+The Mock Namespace
+^^^^^^^^^^^^^^^^^^
+
+The default namespace for mock functions is `T::`.  This namespace can be changed by defining the 
+`CXXTEST_MOCK_NAMESPACE` macro.
+
+
+[[installation]]
+Installation
+------------
+
+A key feature of CxxTest is that it does has virtually no installation
+process.  The +cxxtestgen+ script can be directly executed from the
++cxxtest/bin+ directory.  Simply adding this directory to the PATH
+environment of a command shell is sufficient for many applications.
+Beyond that, the build process for test runners simply needs to
+reference the +cxxtest+ root directory to enable proper includes
+during compilation.
+
+The FOG parser requires two Python packages:
+
+ - +ply+
+ - +ordereddict+ (This is needed when running Python 2.4, 2.5 or 2.6)
+
+If these packages are not available, then +cxxtestgen+ will generate an error when the 
+FOG parser option is selected.
+If you have
+http://pypi.python.org/pypi/setuptools[setuptools] or
+http://pypi.python.org/pypi/distribute[distribute]
+installed, then
+you can install these packages from PyPI by executing
+[source,bash]
+----
+easy_install ply
+easy_install ordereddict
+----
+
+The +cxxtestgen+ script has been tested with many different versions
+of Python:  2.4 - 3.2.  Note that this script has only been tested
+with the CPython implementation.  CxxTest 4.0 has been tested on
+Linux and Mac platforms using the G++ and CLang++ compilers.
+
+
+////
+
+WEH - I thought about moving this section into the Getting Started
+section.  However, it makes sense to leave this here to reference
+future installations in Debian, Mac Ports, etc.  I think that that
+distribution model is very strategic for cxxtest.
+
+////
+
+
+[[discussion]]
+Status and Future Plans
+-----------------------
+
+The CxxTest 4.0 release reflects major changes in the management
+and focus of CxxTest.  The 4.0 release is the first release of
+CxxTest in over seven years, and virtually all of the initial
+developers have moved on to other projects.  CxxTest is heavily
+used at Sandia National Laboratories, and Sandia's ongoing use of
+CxxTest is a major driver for the 4.0 release.
+
+Similarly, major
+changes in CxxTest reflect the focus of the developer team:
+
+ - Perl is no longer used to support CxxTest scripts.  Python is now the only scripting language used by CxxTest.
+ - The testing scripts have been rewritten using the PyUnit framework.
+ - The installation process for CxxTest now leverages and integrates with the system Python installation.
+ - A more comprehensive C++ parser is now available, which supports testing of templates.
+ - The CxxTest GUI is no longer supported, and the <<ts_warn,TS_WARN>> is deprecated.
+ - CxxTest runners now have a command-line interface that facilitates interative use of the test runner.
+ - A new user guide is now available in PDF, HTML and Ebook formats.
+ - Updated the +cxxtestgen+ script to work with Python 2.6 through 3.2
+
+Additionally, CxxTest is now validated with continuous integration
+tests.  Yes, the CxxTest developers eat their own dog food!
+
+Although the GUI option for +cxxtestgen+ appears to work fine, this
+GUI is rather primitive.  It simply provides a visual summary of
+the test results, and not the interactive test execution that a
+user would expect.  This capability is deprecated since none of the
+current developers use this feature.  CxxTest users should consider
+using CxxTest with http://jenkins-ci.org/[Jenkins].  The +XUnitPrinter+
+test listener generates XML files that can be easily integrated by
+http://jenkins-ci.org/[Jenkins], which creates a visual summary of
+test results with links to drill-down into test outputs.
+
+This documentation has highlighted the commonly used test listeners.
+There are a variety of other test listeners provided by CxxTest
+that support advanced Cxxtest applications.  For example, the
++YesNoRunner+ is perhaps the simplest test listener;  it simply
+returns the number of test failures.  The +StdioFilePrinter+ is
+used by +StdioPrinter+, but it does not assume that +stdio+ is the
+default output stream.  This test listener can be used in contexts
+where a custom output stream must be specified.
+
+////
+WEH - I'd like to say more about future support for CxxTest, but I don't know more basic things like how we should plan to host CxxTest in the future.
+
+Discuss support for ...
+
+ - embedded compilers...  (Macros vs templates)
+ - SCONS
+
+Future work:
+
+ - ply cpp
+ - ignore template test classes using the FOG parser
+
+////
+
+////
+NOTE: we do not have test coverage for the following macros:
+CXXTEST_OLD_TEMPLATE_SYNTAX
+CXXTEST_OLD_STD
+CXXTEST_LONGLONG
+////
+
+
+:numbered!:
+
+[[acknowledgements]] 
+Acknowledgements
+----------------
+
+CxxTest was originally developed by Erez Volk.  The following
+developers actively contributed to the CxxTest 4.0 release:
+
+* GaÅ¡per Ažman
+* Kevin Fitch 
+* William Hart
+* John Siirola
+
+The CxxTest documentation is generated using
+http://www.methods.co.nz/asciidoc/[AsciiDoc].  The following people
+have contributed to the CxxTest User Manual:
+
+* William Hart
+* Lionel Orry
+* Erez Volk
+
+A major advancement in CxxTest's capability is the new test discovery
+mechanism that is based on a parser of the Flexible Object Language
+(FOG).  FOG generalizes the C++ syntax, which enables CxxTest to
+extract high-level class structure for test discovery.  FOG was
+developed by Edward Willink:
+
+* Edward D. Willink.  'Meta-Compilation for C++', PhD Thesis, Computer Science Research Group, University of Surrey, January 2000. 
+
+The FOG parser in CxxTest critically relies on the excellent LALR
+parser provided by Dave Beazley's `ply` Python package.  The scalable
+performance of `ply` is critical for CxxTest.
+
+CxxTest has greatly benefited from the support of the open source
+community.  We would like to thank the following organizations for
+providing web hosting and computing resources: GitHub, SourceForge,
+Tigris.org, Sandia National Laboratories, Google and COIN-OR.  The development
+of CxxTest has been partially supported by Sandia National Laboratories.
+Sandia National Laboratories is a multi-program laboratory managed
+and operated by Sandia Corporation, a wholly owned subsidiary of
+Lockheed Martin Corporation, for the U.S.  Department of Energy's
+National Nuclear Security Administration under contract DE-AC04-94AL85000.
+
+
+[appendix]
+[[appendix_A]] 
+Test Assertion Examples
+-----------------------
+
+[[ts_assert]] TS_ASSERT::
+This is the most basic test assertion, which simply verifies that the +expr+ argument is true:
+[source,{cpp}]
+----
+include::examples/.Assertions_assert.h[]
+----
+[[ts_assert_delta]] TS_ASSERT_DELTA::
+This test assertion verifies two floating point values are within a specified absolute difference:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertDelta.h[]
+----
+
+[[ts_assert_differs]] TS_ASSERT_DIFFERS::
+This test assertion verifies that the two arguments are not equal:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertDiffers.h[]
+----
+
+[[ts_assert_equals]] TS_ASSERT_EQUALS::
+  This test assertion verifies that the two arguments are equal:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertEquals.h[]
+----
+Note that this test is performed using the C++ +==+ operator, whose behavior may be redefined for the two argument types.
+
+[[ts_assert_less_than]] TS_ASSERT_LESS_THAN::
+This test assertion verifies that the first argument is strictly less than the second argument:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertLessThan.h[]
+----
+
+[[ts_assert_less_than_equals]] TS_ASSERT_LESS_THAN_EQUALS::
+This test assertion verifies that the first argument is less than or equal to the second argument:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertLessThanEquals.h[]
+----
+
+[[ts_assert_predicate]] TS_ASSERT_PREDICATE::
+This test assertion takes as an argument the name of a class, similar to a STL +unary_function+, and evaluates the +operator()+ method:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertPredicate.h[]
+----
+This test assertion can be seen as a generalization of <<ts_assert,TS_ASSERT>>, but it 
+allows the tester to see the failed value. 
+
+[[ts_assert_relation]] TS_ASSERT_RELATION::
+It takes as an argument the name of a class, similar to a STL +binary_function+, and evaluates the +operator()+ method:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertRelation.h[]
+----
+This test assertion can be seen as a generalization of <<ts_assert_equals,TS_ASSERT_EQUALS>>, <<ts_assert_differs,TS_ASSERT_DIFFERS>>, <<ts_assert_less_than,TS_ASSERT_LESS_THAN>> and <<ts_assert_less_than_equals,TS_ASSERT_LESS_THAN_EQUALS>>. 
+This can be used to assert comparisons which are not covered by the builtin test assertions. 
+
+[[ts_assert_same_data]] TS_ASSERT_SAME_DATA::
+This test assertion is similar to <<ts_assert_equals,TS_ASSERT_EQUALS>>,
+except that it compares the contents of two buffers in memory:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertSameData.h[]
+----
+The standard runner dumps the contents of both buffers as hex values when this test fails.
+
+[[ts_assert_throws]] TS_ASSERT_THROWS::
+This test assertion verifies that the specified exception is thrown when the first argument is executed:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertThrows.h[]
+----
+
+[[ts_assert_throws_anything]] TS_ASSERT_THROWS_ANYTHING::
+This test assertion verifies that _some_ exception is thrown when the first argument is executed:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertThrowsAnything.h[]
+----
+
+[[ts_assert_throws_assert]] TS_ASSERT_THROWS_ASSERT::
+This test assertion verifies that an exception is thrown when executing the first argument.  The second argument specifies a variable declaration for the exception, and the third argument is executed to test that 
+exception value:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertThrowsAssert.h[]
+----
+Note that this can be viewed as a generalization of <<ts_assert_throws_equals,TS_ASSERT_THROWS_EQUALS>>.
+
+[[ts_assert_throws_equals]] TS_ASSERT_THROWS_EQUALS::
+This test assertion verifies that an exception is thrown when executing the first argument.  The second argument specifies a variable declaration for the exception, and the third and fourth arguments are values that are asserted equal after the exception is thrown:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertThrowsEquals.h[]
+----
+
+[[ts_assert_throws_nothing]] TS_ASSERT_THROWS_NOTHING::
+This test assertion verifies that an exception is _not_ thrown when executing the first argument:
+[source,{cpp}]
+----
+include::examples/.Assertions_assertThrowsNothing.h[]
+----
+
+[[ts_fail]] TS_FAIL::
+This function triggers a test failure with an associated message:
+[source,{cpp}]
+----
+include::examples/.Assertions_fail.h[]
+----
+
+[[ts_trace]] TS_TRACE::
+This function prints an informational message:
+[source,{cpp}]
+----
+include::examples/.Assertions_trace.h[]
+----
+
+[[ts_warn]] TS_WARN::
+This function prints a message as a warning:
+[source,{cpp}]
+----
+include::examples/.Assertions_warn.h[]
+----
+
+
+[appendix]
+[[appendix_B]] 
+Integrating with Your Build Environment
+---------------------------------------
+
+CxxTest can be integrated into a variety of build environments to
+automate the generation, compilation and execution of test runners.
+Here is a rough breakdown of this process:
+
+* Split the application into a library and a main module that just
+  calls the library classes.  This way, the test runner will be
+  able to access all your classes through the library.
+* Create another application (or target, or project, or whatever)
+  for the test runner.  Make the build tool generate it automatically.
+* Configure the build tool to run the tests automatically.
+
+Unfortunately, different build tools and IDEs need to setup this
+process in different ways.  The following sections provide rough
+guidance for doing this for some come use cases.
+
+[NOTE]
+These examples are not actively maintained and tested.  Please send
+suggestions to the CxxTest developers for updating this documentation.
+
+
+Using Makefiles
+~~~~~~~~~~~~~~~
+
+Generating the tests with a makefile is pretty straightforward.
+Simply add rules to generate, compile and run the test runner.
+
+[source,{makefile}]
+-----
+all: lib run_tests app
+
+# Rules to build your targets
+lib: ...
+
+app: ...
+
+# A rule that runs the unit tests
+run_tests: runner
+        ./runner
+
+# How to build the test runner
+runner: runner.cpp lib
+        g++ -o $@ $^
+
+# How to generate the test runner
+runner.cpp: SimpleTest.h ComplicatedTest.h
+         cxxtestgen -o $@ --error-printer $^
+-----
+
+
+Using Cons
+~~~~~~~~~~
+
+http://dsmit.com/cons/[Cons] is a powerful and 
+versatile make replacement which uses Perl scripts instead of Makefiles.
+
+See `cxxtest/sample/Construct` in the CxxTest distribution for an
+example of building CxxTest test runners with Cons.
+
+
+Using Microsoft Visual Studio
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+See `cxxtest/sample/msvc` in the distribution
+to see a reasonable integration of CxxTest with Microsoft Visual Studio's IDE.
+Basically, the workspace has three
+projects:
+
+* The project `CxxTest_3_Generate` runs `cxxtestgen`.
+* The project `CxxTest_2_Build` compiles the generated file.
+* The project `CxxTest_1_Run` runs the tests.
+
+This method certainly works, and the test results are conveniently
+displayed as compilation errors and warnings (for <<ts_warn,TS_WARN>>.
+However, there are still a few things missing; to integrate this
+approach with your own project, you usually need to work a little
+bit and tweak some makefiles and project options.  The script
+`sample/msvc/FixFiles.bat` can automate some of this process.
+
+
+Using Microsoft Windows DDK
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To use CxxTest with the `build` utility for device drivers, you add
+the generated tests file as an extra dependency using the
+`NTBUILDTARGET0` macro and the `Makefile.inc` file.  An example of
+how to do this is in the CxxTest distribution under `sample/winddk`.
+
+
+[appendix]
+[[appendix_C]] 
+Testing CxxTest
+---------------
+
+In the +cxxtest/test+ directory, you can execute
+[source,bash]
+----
+python test_cxxtest.py 
+----
+to launch all tests.  By default, this script executes test suites
+for a variety of compilers if they are found on the user's path:
+`g++`, `clang++`, +cl+ (the Microsoft Visual Studio compiler).
+Additionally, this test script includes separate test suites for
+the default test discovery mechanism as well as test discovery using
+the new FOG parser.
+
+You can execute a specific test suite by giving its name as an
+argument to this test script.  For example, the command
+[source,bash]
+----
+python test_cxxtest.py TestGpp
+----
+executes the +TestGpp+ test suite, which tests CxxTest with the
+`g++` compiler.  Similarly, the command
+[source,bash]
+----
+python test_cxxtest.py TestGppFOG
+----
+executes the test suite that tests CxxTest using the `g++` compiler
+and the FOG parser.
+
+The +test_cxxtest.py+ script should work with versions Python 2.7
+or newer.  If you are running Python 2.6, you will need to install
+the +unittest2+ package.  If you have
+http://pypi.python.org/pypi/setuptools[setuptools] or
+http://pypi.python.org/pypi/distribute[distribute]
+installed, then
+you can install this package from PyPI by executing
+[source,bash]
+----
+easy_install unittest2
+----
+Similarly, the tests for this document rely on the `PyUtilib` Python package.
+
+The FOG parser requires two Python packages:
+
+ - +ply+
+ - +ordereddict+ (This is only needed when running Python 2.6)
+
+If these packages are not available, then +test_cxxtest.py+ will skip the FOG tests.
+
+
+[appendix]
+[[appendix_D]] 
+include::../Versions[]
+
+// vim: set syntax=asciidoc:
+
diff --git a/tools/cxxtest/doc/include_anchors.py b/tools/cxxtest/doc/include_anchors.py
new file mode 100644 (file)
index 0000000..a3537a4
--- /dev/null
@@ -0,0 +1,81 @@
+import re
+import sys
+import os.path
+import os
+
+
+pat1a = re.compile('include::([a-zA-Z0-9_\.\-/\/]+\/)\.([^\_]+)\_[a-zA-Z0-9]*\.py\[\]')
+pat1b = re.compile('include::([a-zA-Z0-9_\.\-/\/]+\/)\.([^\_]+)\_[a-zA-Z0-9]*\.sh\[\]')
+pat1c = re.compile('include::([a-zA-Z0-9_\.\-/\/]+\/)\.([^\_]+)\_[a-zA-Z0-9]*\.h\[\]')
+pat1d = re.compile('include::([a-zA-Z0-9_\.\-/\/]+\/)\.([^\_]+)\_[a-zA-Z0-9]*\.cpp\[\]')
+pat2 = re.compile('([^@]+)@([a-zA-Z0-9]+):')
+pat3 = re.compile('([^@]+)@:([a-zA-Z0-9]+)')
+
+processed = set()
+
+def process(dir, root, suffix):
+    #print "PROCESS ",root, suffix
+    bname = "%s%s" % (dir, root)
+    global processed
+    if bname in processed:
+        return
+    #
+    anchors = {}
+    anchors[''] = open('%s.%s_.%s' % (dir, root, suffix), 'w')
+    INPUT = open('%s%s.%s' % (dir, root, suffix), 'r')
+    for line in INPUT:
+        m2 = pat2.match(line)
+        m3 = pat3.match(line)
+        if m2:
+            anchor = m2.group(2)
+            anchors[anchor] = open('%s.%s_%s.%s' % (dir, root, anchor, suffix), 'w')
+        elif m3:
+            anchor = m3.group(2)
+            anchors[anchor].close()
+            del anchors[anchor]
+        else:
+            for anchor in anchors:
+                os.write(anchors[anchor].fileno(), line)
+    INPUT.close()
+    for anchor in anchors:
+        if anchor != '':
+            print "ERROR: anchor '%s' did not terminate" % anchor
+        anchors[anchor].close()
+    #
+    processed.add(bname)
+
+
+for file in sys.argv[1:]:
+    print "Processing file '%s' ..." % file
+    INPUT = open(file, 'r')
+    for line in INPUT:
+        suffix = None
+        m = pat1a.match(line)
+        if m:
+            suffix = 'py'
+        #
+        if suffix is None:
+            m = pat1b.match(line)
+            if m:
+                suffix = 'sh'
+        #
+        if suffix is None:
+            m = pat1c.match(line)
+            if m:
+                suffix = 'h'
+        #
+        if suffix is None:
+            m = pat1d.match(line)
+            if m:
+                suffix = 'cpp'
+        #
+        if not suffix is None:
+            #print "HERE", line, suffix
+            fname = m.group(1)+m.group(2)+'.'+suffix
+            if not os.path.exists(fname):
+                print line
+                print "ERROR: file '%s' does not exist!" % fname
+                sys.exit(1)
+            process(m.group(1), m.group(2), suffix)
+    INPUT.close()
+
diff --git a/tools/cxxtest/python/README.txt b/tools/cxxtest/python/README.txt
new file mode 100644 (file)
index 0000000..1cd84b9
--- /dev/null
@@ -0,0 +1,8 @@
+CxxTest Python Package
+======================
+
+The CxxTest Python package includes utilities that are used by the
+CxxTest unit testing framework.  Specifically, this Python package
+supports C++ parsing and code generation done in the cxxtestgen 
+script.
+
diff --git a/tools/cxxtest/python/convert.py b/tools/cxxtest/python/convert.py
new file mode 100644 (file)
index 0000000..ec5cdb5
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Execute this script to copy the cxxtest/*.py files
+# and run 2to3 to convert them to Python 3.
+#
+
+import glob
+import subprocess
+import os
+import shutil
+
+os.chdir('cxxtest')
+for file in glob.glob('*.py'):
+    shutil.copyfile(file, '../python3/cxxtest/'+file)
+#
+os.chdir('../python3/cxxtest')
+#
+for file in glob.glob('*.py'):
+    subprocess.call('2to3 -w '+file, shell=True)
+
diff --git a/tools/cxxtest/python/cxxtest/__init__.py b/tools/cxxtest/python/cxxtest/__init__.py
new file mode 100644 (file)
index 0000000..e9f6d13
--- /dev/null
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+"""cxxtest: A Python package that supports the CxxTest test framework for C/C++.
+
+.. _CxxTest: http://cxxtest.tigris.org/
+
+CxxTest is a unit testing framework for C++ that is similar in
+spirit to JUnit, CppUnit, and xUnit. CxxTest is easy to use because
+it does not require precompiling a CxxTest testing library, it
+employs no advanced features of C++ (e.g. RTTI) and it supports a
+very flexible form of test discovery.
+
+The cxxtest Python package includes capabilities for parsing C/C++ source files and generating
+CxxTest drivers.
+"""
+
+from cxxtest.__release__ import __version__, __date__
+__date__
+__version__
+
+__maintainer__ = "William E. Hart"
+__maintainer_email__ = "whart222@gmail.com"
+__license__ = "LGPL"
+__url__ = "http://cxxtest.tigris.org/"
+
+from cxxtest.cxxtestgen import *
diff --git a/tools/cxxtest/python/cxxtest/__init__.pyc b/tools/cxxtest/python/cxxtest/__init__.pyc
new file mode 100644 (file)
index 0000000..35a2237
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/__init__.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/__release__.py b/tools/cxxtest/python/cxxtest/__release__.py
new file mode 100644 (file)
index 0000000..a949226
--- /dev/null
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+""" Release Information for cxxtest """
+
+__version__ = '4.0.2'
+__date__ = "2012-01-02"
diff --git a/tools/cxxtest/python/cxxtest/__release__.pyc b/tools/cxxtest/python/cxxtest/__release__.pyc
new file mode 100644 (file)
index 0000000..16fc56c
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/__release__.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/cxx_parser.py b/tools/cxxtest/python/cxxtest/cxx_parser.py
new file mode 100644 (file)
index 0000000..70051cb
--- /dev/null
@@ -0,0 +1,2189 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+# vim: fileencoding=utf-8
+
+#
+# This is a PLY parser for the entire ANSI C++ grammar.  This grammar was 
+# adapted from the FOG grammar developed by E. D. Willink.  See
+#
+#    http://www.computing.surrey.ac.uk/research/dsrg/fog/
+#
+# for further details.
+#
+# The goal of this grammar is to extract information about class, function and
+# class method declarations, along with their associated scope.  Thus, this 
+# grammar can be used to analyze classes in an inheritance heirarchy, and then
+# enumerate the methods in a derived class.
+#
+# This grammar parses blocks of <>, (), [] and {} in a generic manner.  Thus,
+# There are several capabilities that this grammar does not support:
+#
+# 1. Ambiguous template specification.  This grammar cannot parse template
+#       specifications that do not have paired <>'s in their declaration.  In
+#       particular, ambiguous declarations like
+#
+#           foo<A, c<3 >();
+#
+#       cannot be correctly parsed.
+#
+# 2. Template class specialization.  Although the goal of this grammar is to
+#       extract class information, specialization of templated classes is
+#       not supported.  When a template class definition is parsed, it's 
+#       declaration is archived without information about the template
+#       parameters.  Class specializations will be stored separately, and 
+#       thus they can be processed after the fact.  However, this grammar
+#       does not attempt to correctly process properties of class inheritence
+#       when template class specialization is employed.
+#
+
+#
+# TODO: document usage of this file
+#
+
+from __future__ import division
+
+import os
+import ply.lex as lex
+import ply.yacc as yacc
+import re
+try:
+    from collections import OrderedDict
+except ImportError:
+    from ordereddict import OrderedDict
+
+lexer = None
+scope_lineno = 0
+identifier_lineno = {}
+_parse_info=None
+_parsedata=None
+noExceptionLogic = True
+
+def ply_init(data):
+    global _parsedata
+    _parsedata=data
+
+
+class Scope(object):
+
+    def __init__(self,name,abs_name,scope_t,base_classes,lineno):
+        self.function=[]
+        self.name=name
+        self.scope_t=scope_t
+        self.sub_scopes=[]
+        self.base_classes=base_classes
+        self.abs_name=abs_name
+        self.lineno=lineno
+   
+    def insert(self,scope):
+        self.sub_scopes.append(scope)
+
+
+class CppInfo(object):
+
+    def __init__(self, filter=None):
+        self.verbose=0
+        if filter is None:
+            self.filter=re.compile("[Tt][Ee][Ss][Tt]|createSuite|destroySuite")
+        else:
+            self.filter=filter
+        self.scopes=[""]
+        self.index=OrderedDict()
+        self.index[""]=Scope("","::","namespace",[],1)
+        self.function=[]
+
+    def push_scope(self,ns,scope_t,base_classes=[]):
+        name = self.scopes[-1]+"::"+ns
+        if self.verbose>=2:
+            print "-- Starting "+scope_t+" "+name
+        self.scopes.append(name)
+        self.index[name] = Scope(ns,name,scope_t,base_classes,scope_lineno-1)
+
+    def pop_scope(self):
+        scope = self.scopes.pop()
+        if self.verbose>=2:
+            print "-- Stopping "+scope
+        return scope
+
+    def add_function(self, fn):
+        fn = str(fn)
+        if self.filter.search(fn):
+            self.index[self.scopes[-1]].function.append((fn, identifier_lineno.get(fn,lexer.lineno-1)))
+            tmp = self.scopes[-1]+"::"+fn
+            if self.verbose==2:
+                print "-- Function declaration "+fn+"  "+tmp
+            elif self.verbose==1:
+                print "-- Function declaration "+tmp
+
+    def get_functions(self,name,quiet=False):
+        if name == "::":
+            name = ""
+        scope = self.index[name]
+        fns=scope.function
+        for key in scope.base_classes:
+            cname = self.find_class(key,scope)
+            if cname is None:
+                if not quiet:
+                    print "Defined classes: ",list(self.index.keys())
+                    print "WARNING: Unknown class "+key
+            else:
+                fns += self.get_functions(cname,quiet)
+        return fns
+        
+    def find_class(self,name,scope):
+        if ':' in name:
+            if name in self.index:
+                return name
+            else:
+                return None           
+        tmp = scope.abs_name.split(':')
+        name1 = ":".join(tmp[:-1] + [name])
+        if name1 in self.index:
+            return name1
+        name2 = "::"+name
+        if name2 in self.index:
+            return name2
+        return None
+
+    def __repr__(self):
+        return str(self)
+
+    def is_baseclass(self,cls,base):
+        '''Returns true if base is a base-class of cls'''
+        if cls in self.index:
+            bases = self.index[cls]
+        elif "::"+cls in self.index:
+            bases = self.index["::"+cls]
+        else:
+            return False
+            #raise IOError, "Unknown class "+cls
+        if base in bases.base_classes:
+            return True
+        for name in bases.base_classes:
+            if self.is_baseclass(name,base):
+                return True
+        return False
+
+    def __str__(self):
+        ans=""
+        keys = list(self.index.keys())
+        keys.sort()
+        for key in keys:
+            scope = self.index[key]
+            ans += scope.scope_t+" "+scope.abs_name+"\n"
+            if scope.scope_t == "class":
+                ans += "  Base Classes: "+str(scope.base_classes)+"\n"
+                for fn in self.get_functions(scope.abs_name):
+                    ans += "  "+fn+"\n"
+            else:
+                for fn in scope.function:
+                    ans += "  "+fn+"\n"
+        return ans
+
+
+def flatten(x):
+    """Flatten nested list"""
+    try:
+        strtypes = basestring
+    except: # for python3 etc
+        strtypes = (str, bytes)
+
+    result = []
+    for el in x:
+        if hasattr(el, "__iter__") and not isinstance(el, strtypes):
+            result.extend(flatten(el))
+        else:
+            result.append(el)
+    return result
+
+#
+# The lexer (and/or a preprocessor) is expected to identify the following
+#
+#  Punctuation:
+#
+#
+literals = "+-*/%^&|~!<>=:()?.\'\"\\@$;,"
+
+#
+reserved = {
+    'private' : 'PRIVATE',
+    'protected' : 'PROTECTED',
+    'public' : 'PUBLIC',
+
+    'bool' : 'BOOL',
+    'char' : 'CHAR',
+    'double' : 'DOUBLE',
+    'float' : 'FLOAT',
+    'int' : 'INT',
+    'long' : 'LONG',
+    'short' : 'SHORT',
+    'signed' : 'SIGNED',
+    'unsigned' : 'UNSIGNED',
+    'void' : 'VOID',
+    'wchar_t' : 'WCHAR_T',
+
+    'class' : 'CLASS',
+    'enum' : 'ENUM',
+    'namespace' : 'NAMESPACE',
+    'struct' : 'STRUCT',
+    'typename' : 'TYPENAME',
+    'union' : 'UNION',
+
+    'const' : 'CONST',
+    'volatile' : 'VOLATILE',
+
+    'auto' : 'AUTO',
+    'explicit' : 'EXPLICIT',
+    'export' : 'EXPORT',
+    'extern' : 'EXTERN',
+    '__extension__' : 'EXTENSION',
+    'friend' : 'FRIEND',
+    'inline' : 'INLINE',
+    'mutable' : 'MUTABLE',
+    'register' : 'REGISTER',
+    'static' : 'STATIC',
+    'template' : 'TEMPLATE',
+    'typedef' : 'TYPEDEF',
+    'using' : 'USING',
+    'virtual' : 'VIRTUAL',
+
+    'asm' : 'ASM',
+    'break' : 'BREAK',
+    'case' : 'CASE',
+    'catch' : 'CATCH',
+    'const_cast' : 'CONST_CAST',
+    'continue' : 'CONTINUE',
+    'default' : 'DEFAULT',
+    'delete' : 'DELETE',
+    'do' : 'DO',
+    'dynamic_cast' : 'DYNAMIC_CAST',
+    'else' : 'ELSE',
+    'false' : 'FALSE',
+    'for' : 'FOR',
+    'goto' : 'GOTO',
+    'if' : 'IF',
+    'new' : 'NEW',
+    'operator' : 'OPERATOR',
+    'reinterpret_cast' : 'REINTERPRET_CAST',
+    'return' : 'RETURN',
+    'sizeof' : 'SIZEOF',
+    'static_cast' : 'STATIC_CAST',
+    'switch' : 'SWITCH',
+    'this' : 'THIS',
+    'throw' : 'THROW',
+    'true' : 'TRUE',
+    'try' : 'TRY',
+    'typeid' : 'TYPEID',
+    'while' : 'WHILE',
+    '"C"' : 'CLiteral',
+    '"C++"' : 'CppLiteral',
+
+    '__attribute__' : 'ATTRIBUTE',
+    '__cdecl__' : 'CDECL',
+    '__typeof' : 'uTYPEOF',
+    'typeof' : 'TYPEOF', 
+
+    'CXXTEST_STD' : 'CXXTEST_STD'
+}
+   
+tokens = [
+    "CharacterLiteral",
+    "FloatingLiteral",
+    "Identifier",
+    "IntegerLiteral",
+    "StringLiteral",
+ "RBRACE",
+ "LBRACE",
+ "RBRACKET",
+ "LBRACKET",
+ "ARROW",
+ "ARROW_STAR",
+ "DEC",
+ "EQ",
+ "GE",
+ "INC",
+ "LE",
+ "LOG_AND",
+ "LOG_OR",
+ "NE",
+ "SHL",
+ "SHR",
+ "ASS_ADD",
+ "ASS_AND",
+ "ASS_DIV",
+ "ASS_MOD",
+ "ASS_MUL",
+ "ASS_OR",
+ "ASS_SHL",
+ "ASS_SHR",
+ "ASS_SUB",
+ "ASS_XOR",
+ "DOT_STAR",
+ "ELLIPSIS",
+ "SCOPE",
+] + list(reserved.values())
+
+t_ignore = " \t\r"
+
+t_LBRACE = r"(\{)|(<%)"
+t_RBRACE = r"(\})|(%>)"
+t_LBRACKET = r"(\[)|(<:)"
+t_RBRACKET = r"(\])|(:>)"
+t_ARROW = r"->"
+t_ARROW_STAR = r"->\*"
+t_DEC = r"--"
+t_EQ = r"=="
+t_GE = r">="
+t_INC = r"\+\+"
+t_LE = r"<="
+t_LOG_AND = r"&&"
+t_LOG_OR = r"\|\|"
+t_NE = r"!="
+t_SHL = r"<<"
+t_SHR = r">>"
+t_ASS_ADD = r"\+="
+t_ASS_AND = r"&="
+t_ASS_DIV = r"/="
+t_ASS_MOD = r"%="
+t_ASS_MUL = r"\*="
+t_ASS_OR  = r"\|="
+t_ASS_SHL = r"<<="
+t_ASS_SHR = r">>="
+t_ASS_SUB = r"-="
+t_ASS_XOR = r"^="
+t_DOT_STAR = r"\.\*"
+t_ELLIPSIS = r"\.\.\."
+t_SCOPE = r"::"
+
+# Discard comments
+def t_COMMENT(t):
+    r'(/\*(.|\n)*?\*/)|(//.*?\n)|(\#.*?\n)'
+    t.lexer.lineno += t.value.count("\n")
+
+t_IntegerLiteral = r'(0x[0-9A-F]+)|([0-9]+(L){0,1})'
+t_FloatingLiteral = r"[0-9]+[eE\.\+-]+[eE\.\+\-0-9]+"
+t_CharacterLiteral = r'\'([^\'\\]|\\.)*\''
+#t_StringLiteral = r'"([^"\\]|\\.)*"'
+def t_StringLiteral(t):
+    r'"([^"\\]|\\.)*"'
+    t.type = reserved.get(t.value,'StringLiteral')
+    return t
+
+def t_Identifier(t):
+    r"[a-zA-Z_][a-zA-Z_0-9\.]*"
+    t.type = reserved.get(t.value,'Identifier')
+    return t
+
+
+def t_error(t):
+    print "Illegal character '%s'" % t.value[0]
+    #raise IOError, "Parse error"
+    #t.lexer.skip()
+
+def t_newline(t):
+    r'[\n]+'
+    t.lexer.lineno += len(t.value)
+
+precedence = (
+    ( 'right', 'SHIFT_THERE', 'REDUCE_HERE_MOSTLY', 'SCOPE'),
+    ( 'nonassoc', 'ELSE', 'INC', 'DEC', '+', '-', '*', '&', 'LBRACKET', 'LBRACE', '<', ':', ')')
+    )
+
+start = 'translation_unit'
+
+#
+#  The %prec resolves the 14.2-3 ambiguity:
+#  Identifier '<' is forced to go through the is-it-a-template-name test
+#  All names absorb TEMPLATE with the name, so that no template_test is 
+#  performed for them.  This requires all potential declarations within an 
+#  expression to perpetuate this policy and thereby guarantee the ultimate 
+#  coverage of explicit_instantiation.
+#
+#  The %prec also resolves a conflict in identifier : which is forced to be a 
+#  shift of a label for a labeled-statement rather than a reduction for the 
+#  name of a bit-field or generalised constructor.  This is pretty dubious 
+#  syntactically but correct for all semantic possibilities.  The shift is 
+#  only activated when the ambiguity exists at the start of a statement. 
+#  In this context a bit-field declaration or constructor definition are not 
+#  allowed.
+#
+
+def p_identifier(p):
+    '''identifier : Identifier
+    |               CXXTEST_STD '(' Identifier ')'
+    '''
+    if p[1][0] in ('t','T','c','d'):
+        identifier_lineno[p[1]] = p.lineno(1)
+    p[0] = p[1]
+
+def p_id(p):
+    '''id :                         identifier %prec SHIFT_THERE
+    |                               template_decl
+    |                               TEMPLATE id
+    '''
+    p[0] = get_rest(p)
+
+def p_global_scope(p):
+    '''global_scope :               SCOPE
+    '''
+    p[0] = get_rest(p)
+
+def p_id_scope(p):
+    '''id_scope : id SCOPE'''
+    p[0] = get_rest(p)
+
+def p_id_scope_seq(p):
+    '''id_scope_seq :                id_scope
+    |                                id_scope id_scope_seq
+    '''
+    p[0] = get_rest(p)
+
+#
+#  A :: B :: C; is ambiguous How much is type and how much name ?
+#  The %prec maximises the (type) length which is the 7.1-2 semantic constraint.
+#
+def p_nested_id(p):
+    '''nested_id :                  id %prec SHIFT_THERE
+    |                               id_scope nested_id
+    '''
+    p[0] = get_rest(p)
+
+def p_scoped_id(p):
+    '''scoped_id :                  nested_id
+    |                               global_scope nested_id
+    |                               id_scope_seq
+    |                               global_scope id_scope_seq
+    '''
+    global scope_lineno
+    scope_lineno = lexer.lineno
+    data = flatten(get_rest(p))
+    if data[0] != None:
+        p[0] = "".join(data)
+
+#
+#  destructor_id has to be held back to avoid a conflict with a one's 
+#  complement as per 5.3.1-9, It gets put back only when scoped or in a 
+#  declarator_id, which is only used as an explicit member name.
+#  Declarations of an unscoped destructor are always parsed as a one's 
+#  complement.
+#
+def p_destructor_id(p):
+    '''destructor_id :              '~' id
+    |                               TEMPLATE destructor_id
+    '''
+    p[0]=get_rest(p)
+
+#def p_template_id(p):
+#    '''template_id :                empty
+#    |                               TEMPLATE
+#    '''
+#    pass
+
+def p_template_decl(p):
+    '''template_decl :              identifier '<' nonlgt_seq_opt '>'
+    '''
+    #
+    # WEH: should we include the lt/gt symbols to indicate that this is a
+    # template class?  How is that going to be used later???
+    #
+    #p[0] = [p[1] ,"<",">"]
+    p[0] = p[1]
+
+def p_special_function_id(p):
+    '''special_function_id :        conversion_function_id
+    |                               operator_function_id
+    |                               TEMPLATE special_function_id
+    '''
+    p[0]=get_rest(p)
+
+def p_nested_special_function_id(p):
+    '''nested_special_function_id : special_function_id
+    |                               id_scope destructor_id
+    |                               id_scope nested_special_function_id
+    '''
+    p[0]=get_rest(p)
+
+def p_scoped_special_function_id(p):
+    '''scoped_special_function_id : nested_special_function_id
+    |                               global_scope nested_special_function_id
+    '''
+    p[0]=get_rest(p)
+
+# declarator-id is all names in all scopes, except reserved words
+def p_declarator_id(p):
+    '''declarator_id :              scoped_id
+    |                               scoped_special_function_id
+    |                               destructor_id
+    '''
+    p[0]=p[1]
+
+#
+# The standard defines pseudo-destructors in terms of type-name, which is 
+# class/enum/typedef, of which class-name is covered by a normal destructor. 
+# pseudo-destructors are supposed to support ~int() in templates, so the 
+# grammar here covers built-in names. Other names are covered by the lack 
+# of identifier/type discrimination.
+#
+def p_built_in_type_id(p):
+    '''built_in_type_id :           built_in_type_specifier
+    |                               built_in_type_id built_in_type_specifier
+    '''
+    pass
+
+def p_pseudo_destructor_id(p):
+    '''pseudo_destructor_id :       built_in_type_id SCOPE '~' built_in_type_id
+    |                               '~' built_in_type_id
+    |                               TEMPLATE pseudo_destructor_id
+    '''
+    pass
+
+def p_nested_pseudo_destructor_id(p):
+    '''nested_pseudo_destructor_id : pseudo_destructor_id
+    |                               id_scope nested_pseudo_destructor_id
+    '''
+    pass
+
+def p_scoped_pseudo_destructor_id(p):
+    '''scoped_pseudo_destructor_id : nested_pseudo_destructor_id
+    |                               global_scope scoped_pseudo_destructor_id
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.2 Lexical conventions
+#-------------------------------------------------------------------------------
+#
+
+def p_literal(p):
+    '''literal :                    IntegerLiteral
+    |                               CharacterLiteral
+    |                               FloatingLiteral
+    |                               StringLiteral
+    |                               TRUE
+    |                               FALSE
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.3 Basic concepts
+#-------------------------------------------------------------------------------
+def p_translation_unit(p):
+    '''translation_unit :           declaration_seq_opt
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.4 Expressions
+#-------------------------------------------------------------------------------
+#
+#  primary_expression covers an arbitrary sequence of all names with the 
+#  exception of an unscoped destructor, which is parsed as its unary expression 
+#  which is the correct disambiguation (when ambiguous).  This eliminates the 
+#  traditional A(B) meaning A B ambiguity, since we never have to tack an A 
+#  onto the front of something that might start with (. The name length got 
+#  maximised ab initio. The downside is that semantic interpretation must split 
+#  the names up again.
+#
+#  Unification of the declaration and expression syntax means that unary and 
+#  binary pointer declarator operators:
+#      int * * name
+#  are parsed as binary and unary arithmetic operators (int) * (*name). Since 
+#  type information is not used
+#  ambiguities resulting from a cast
+#      (cast)*(value)
+#  are resolved to favour the binary rather than the cast unary to ease AST 
+#  clean-up. The cast-call ambiguity must be resolved to the cast to ensure 
+#  that (a)(b)c can be parsed.
+#
+#  The problem of the functional cast ambiguity
+#      name(arg)
+#  as call or declaration is avoided by maximising the name within the parsing 
+#  kernel. So  primary_id_expression picks up 
+#      extern long int const var = 5;
+#  as an assignment to the syntax parsed as "extern long int const var". The 
+#  presence of two names is parsed so that "extern long into const" is 
+#  distinguished from "var" considerably simplifying subsequent 
+#  semantic resolution.
+#
+#  The generalised name is a concatenation of potential type-names (scoped 
+#  identifiers or built-in sequences) plus optionally one of the special names 
+#  such as an operator-function-id, conversion-function-id or destructor as the 
+#  final name. 
+#
+
+def get_rest(p):
+    return [p[i] for i in range(1, len(p))]
+
+def p_primary_expression(p):
+    '''primary_expression :         literal
+    |                               THIS
+    |                               suffix_decl_specified_ids
+    |                               abstract_expression %prec REDUCE_HERE_MOSTLY
+    '''
+    p[0] = get_rest(p)
+
+#
+#  Abstract-expression covers the () and [] of abstract-declarators.
+#
+def p_abstract_expression(p):
+    '''abstract_expression :        parenthesis_clause
+    |                               LBRACKET bexpression_opt RBRACKET
+    |                               TEMPLATE abstract_expression
+    '''
+    pass
+
+def p_postfix_expression(p):
+    '''postfix_expression :         primary_expression
+    |                               postfix_expression parenthesis_clause
+    |                               postfix_expression LBRACKET bexpression_opt RBRACKET
+    |                               postfix_expression LBRACKET bexpression_opt RBRACKET attributes
+    |                               postfix_expression '.' declarator_id
+    |                               postfix_expression '.' scoped_pseudo_destructor_id
+    |                               postfix_expression ARROW declarator_id
+    |                               postfix_expression ARROW scoped_pseudo_destructor_id   
+    |                               postfix_expression INC
+    |                               postfix_expression DEC
+    |                               DYNAMIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               STATIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               REINTERPRET_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               CONST_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               TYPEID parameters_clause
+    '''
+    #print "HERE",str(p[1])
+    p[0] = get_rest(p)
+
+def p_bexpression_opt(p):
+    '''bexpression_opt :            empty
+    |                               bexpression
+    '''
+    pass
+
+def p_bexpression(p):
+    '''bexpression :                nonbracket_seq
+    |                               nonbracket_seq bexpression_seq bexpression_clause nonbracket_seq_opt
+    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
+    '''
+    pass
+
+def p_bexpression_seq(p):
+    '''bexpression_seq :            empty
+    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
+    '''
+    pass
+
+def p_bexpression_clause(p):
+    '''bexpression_clause :          LBRACKET bexpression_opt RBRACKET
+    '''
+    pass
+
+
+
+def p_expression_list_opt(p):
+    '''expression_list_opt :        empty
+    |                               expression_list
+    '''
+    pass
+
+def p_expression_list(p):
+    '''expression_list :            assignment_expression
+    |                               expression_list ',' assignment_expression
+    '''
+    pass
+
+def p_unary_expression(p):
+    '''unary_expression :           postfix_expression
+    |                               INC cast_expression
+    |                               DEC cast_expression
+    |                               ptr_operator cast_expression
+    |                               suffix_decl_specified_scope star_ptr_operator cast_expression
+    |                               '+' cast_expression
+    |                               '-' cast_expression
+    |                               '!' cast_expression
+    |                               '~' cast_expression
+    |                               SIZEOF unary_expression
+    |                               new_expression
+    |                               global_scope new_expression
+    |                               delete_expression
+    |                               global_scope delete_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_delete_expression(p):
+    '''delete_expression :          DELETE cast_expression
+    '''
+    pass
+
+def p_new_expression(p):
+    '''new_expression :             NEW new_type_id new_initializer_opt
+    |                               NEW parameters_clause new_type_id new_initializer_opt
+    |                               NEW parameters_clause
+    |                               NEW parameters_clause parameters_clause new_initializer_opt
+    '''
+    pass
+
+def p_new_type_id(p):
+    '''new_type_id :                type_specifier ptr_operator_seq_opt
+    |                               type_specifier new_declarator
+    |                               type_specifier new_type_id
+    '''
+    pass
+
+def p_new_declarator(p):
+    '''new_declarator :             ptr_operator new_declarator
+    |                               direct_new_declarator
+    '''
+    pass
+
+def p_direct_new_declarator(p):
+    '''direct_new_declarator :      LBRACKET bexpression_opt RBRACKET
+    |                               direct_new_declarator LBRACKET bexpression RBRACKET
+    '''
+    pass
+
+def p_new_initializer_opt(p):
+    '''new_initializer_opt :        empty
+    |                               '(' expression_list_opt ')'
+    '''
+    pass
+
+#
+# cast-expression is generalised to support a [] as well as a () prefix. This covers the omission of 
+# DELETE[] which when followed by a parenthesised expression was ambiguous. It also covers the gcc 
+# indexed array initialisation for free.
+#
+def p_cast_expression(p):
+    '''cast_expression :            unary_expression
+    |                               abstract_expression cast_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_pm_expression(p):
+    '''pm_expression :              cast_expression
+    |                               pm_expression DOT_STAR cast_expression
+    |                               pm_expression ARROW_STAR cast_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_multiplicative_expression(p):
+    '''multiplicative_expression :  pm_expression
+    |                               multiplicative_expression star_ptr_operator pm_expression
+    |                               multiplicative_expression '/' pm_expression
+    |                               multiplicative_expression '%' pm_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_additive_expression(p):
+    '''additive_expression :        multiplicative_expression
+    |                               additive_expression '+' multiplicative_expression
+    |                               additive_expression '-' multiplicative_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_shift_expression(p):
+    '''shift_expression :           additive_expression
+    |                               shift_expression SHL additive_expression
+    |                               shift_expression SHR additive_expression
+    '''
+    p[0] = get_rest(p)
+
+#    |                               relational_expression '<' shift_expression
+#    |                               relational_expression '>' shift_expression
+#    |                               relational_expression LE shift_expression
+#    |                               relational_expression GE shift_expression
+def p_relational_expression(p):
+    '''relational_expression :      shift_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_equality_expression(p):
+    '''equality_expression :        relational_expression
+    |                               equality_expression EQ relational_expression
+    |                               equality_expression NE relational_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_and_expression(p):
+    '''and_expression :             equality_expression
+    |                               and_expression '&' equality_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_exclusive_or_expression(p):
+    '''exclusive_or_expression :    and_expression
+    |                               exclusive_or_expression '^' and_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_inclusive_or_expression(p):
+    '''inclusive_or_expression :    exclusive_or_expression
+    |                               inclusive_or_expression '|' exclusive_or_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_logical_and_expression(p):
+    '''logical_and_expression :     inclusive_or_expression
+    |                               logical_and_expression LOG_AND inclusive_or_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_logical_or_expression(p):
+    '''logical_or_expression :      logical_and_expression
+    |                               logical_or_expression LOG_OR logical_and_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_conditional_expression(p):
+    '''conditional_expression :     logical_or_expression
+    |                               logical_or_expression '?' expression ':' assignment_expression
+    '''
+    p[0] = get_rest(p)
+
+
+#
+# assignment-expression is generalised to cover the simple assignment of a braced initializer in order to 
+# contribute to the coverage of parameter-declaration and init-declaration.
+#
+#    |                               logical_or_expression assignment_operator assignment_expression
+def p_assignment_expression(p):
+    '''assignment_expression :      conditional_expression
+    |                               logical_or_expression assignment_operator nonsemicolon_seq
+    |                               logical_or_expression '=' braced_initializer
+    |                               throw_expression
+    '''
+    p[0]=get_rest(p)
+
+def p_assignment_operator(p):
+    '''assignment_operator :        '=' 
+                           | ASS_ADD
+                           | ASS_AND
+                           | ASS_DIV
+                           | ASS_MOD
+                           | ASS_MUL
+                           | ASS_OR
+                           | ASS_SHL
+                           | ASS_SHR
+                           | ASS_SUB
+                           | ASS_XOR
+    '''
+    pass
+
+#
+# expression is widely used and usually single-element, so the reductions are arranged so that a
+# single-element expression is returned as is. Multi-element expressions are parsed as a list that
+# may then behave polymorphically as an element or be compacted to an element.
+#
+
+def p_expression(p):
+    '''expression :                 assignment_expression
+    |                               expression_list ',' assignment_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_constant_expression(p):
+    '''constant_expression :        conditional_expression
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.5 Statements
+#---------------------------------------------------------------------------------------------------
+# Parsing statements is easy once simple_declaration has been generalised to cover expression_statement.
+#
+#
+# The use of extern here is a hack.  The 'extern "C" {}' block gets parsed
+# as a function, so when nested 'extern "C"' declarations exist, they don't
+# work because the block is viewed as a list of statements... :(
+#
+def p_statement(p):
+    '''statement :                  compound_statement
+    |                               declaration_statement
+    |                               try_block
+    |                               labeled_statement
+    |                               selection_statement
+    |                               iteration_statement
+    |                               jump_statement
+    '''
+    pass
+
+def p_compound_statement(p):
+    '''compound_statement :         LBRACE statement_seq_opt RBRACE
+    '''
+    pass
+
+def p_statement_seq_opt(p):
+    '''statement_seq_opt :          empty
+    |                               statement_seq_opt statement
+    '''
+    pass
+
+#
+#  The dangling else conflict is resolved to the innermost if.
+#
+def p_selection_statement(p):
+    '''selection_statement :        IF '(' condition ')' statement    %prec SHIFT_THERE
+    |                               IF '(' condition ')' statement ELSE statement
+    |                               SWITCH '(' condition ')' statement
+    '''
+    pass
+
+def p_condition_opt(p):
+    '''condition_opt :              empty
+    |                               condition
+    '''
+    pass
+
+def p_condition(p):
+    '''condition :                  nonparen_seq
+    |                               nonparen_seq condition_seq parameters_clause nonparen_seq_opt
+    |                               condition_seq parameters_clause nonparen_seq_opt
+    '''
+    pass
+
+def p_condition_seq(p):
+    '''condition_seq :              empty
+    |                               condition_seq parameters_clause nonparen_seq_opt
+    '''
+    pass
+
+def p_labeled_statement(p):
+    '''labeled_statement :          identifier ':' statement
+    |                               CASE constant_expression ':' statement
+    |                               DEFAULT ':' statement
+    '''
+    pass
+
+def p_try_block(p):
+    '''try_block :                  TRY compound_statement handler_seq
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_jump_statement(p):
+    '''jump_statement :             BREAK ';'
+    |                               CONTINUE ';'
+    |                               RETURN nonsemicolon_seq ';'
+    |                               GOTO identifier ';'
+    '''
+    pass
+
+def p_iteration_statement(p):
+    '''iteration_statement :        WHILE '(' condition ')' statement
+    |                               DO statement WHILE '(' expression ')' ';'
+    |                               FOR '(' nonparen_seq_opt ')' statement
+    '''
+    pass
+
+def p_declaration_statement(p):
+    '''declaration_statement :      block_declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.6 Declarations
+#---------------------------------------------------------------------------------------------------
+def p_compound_declaration(p):
+    '''compound_declaration :       LBRACE declaration_seq_opt RBRACE                            
+    '''
+    pass
+
+def p_declaration_seq_opt(p):
+    '''declaration_seq_opt :        empty
+    |                               declaration_seq_opt declaration
+    '''
+    pass
+
+def p_declaration(p):
+    '''declaration :                block_declaration
+    |                               function_definition
+    |                               template_declaration
+    |                               explicit_specialization
+    |                               specialised_declaration
+    '''
+    pass
+
+def p_specialised_declaration(p):
+    '''specialised_declaration :    linkage_specification
+    |                               namespace_definition
+    |                               TEMPLATE specialised_declaration
+    '''
+    pass
+
+def p_block_declaration(p):
+    '''block_declaration :          simple_declaration
+    |                               specialised_block_declaration
+    '''
+    pass
+
+def p_specialised_block_declaration(p):
+    '''specialised_block_declaration :      asm_definition
+    |                               namespace_alias_definition
+    |                               using_declaration
+    |                               using_directive
+    |                               TEMPLATE specialised_block_declaration
+    '''
+    pass
+
+def p_simple_declaration(p):
+    '''simple_declaration :         ';'
+    |                               init_declaration ';'
+    |                               init_declarations ';'
+    |                               decl_specifier_prefix simple_declaration
+    '''
+    global _parse_info
+    if len(p) == 3:
+        if p[2] == ";":
+            decl = p[1]
+        else:
+            decl = p[2]
+        if decl is not None:
+            fp = flatten(decl)
+            if len(fp) >= 2 and fp[0] is not None and fp[0]!="operator" and fp[1] == '(':
+                p[0] = fp[0]
+                _parse_info.add_function(fp[0])
+
+#
+#  A decl-specifier following a ptr_operator provokes a shift-reduce conflict for * const name which is resolved in favour of the pointer, and implemented by providing versions of decl-specifier guaranteed not to start with a cv_qualifier.  decl-specifiers are implemented type-centrically. That is the semantic constraint that there must be a type is exploited to impose structure, but actually eliminate very little syntax. built-in types are multi-name and so need a different policy.
+#
+#  non-type decl-specifiers are bound to the left-most type in a decl-specifier-seq, by parsing from the right and attaching suffixes to the right-hand type. Finally residual prefixes attach to the left.                
+#
+def p_suffix_built_in_decl_specifier_raw(p):
+    '''suffix_built_in_decl_specifier_raw : built_in_type_specifier
+    |                               suffix_built_in_decl_specifier_raw built_in_type_specifier
+    |                               suffix_built_in_decl_specifier_raw decl_specifier_suffix
+    '''
+    pass
+
+def p_suffix_built_in_decl_specifier(p):
+    '''suffix_built_in_decl_specifier :     suffix_built_in_decl_specifier_raw
+    |                               TEMPLATE suffix_built_in_decl_specifier
+    '''
+    pass
+
+#    |                                       id_scope_seq
+#    |                                       SCOPE id_scope_seq
+def p_suffix_named_decl_specifier(p):
+    '''suffix_named_decl_specifier :        scoped_id 
+    |                               elaborate_type_specifier 
+    |                               suffix_named_decl_specifier decl_specifier_suffix
+    '''
+    p[0]=get_rest(p)
+
+def p_suffix_named_decl_specifier_bi(p):
+    '''suffix_named_decl_specifier_bi :     suffix_named_decl_specifier
+    |                               suffix_named_decl_specifier suffix_built_in_decl_specifier_raw
+    '''
+    p[0] = get_rest(p)
+    #print "HERE",get_rest(p)
+
+def p_suffix_named_decl_specifiers(p):
+    '''suffix_named_decl_specifiers :       suffix_named_decl_specifier_bi
+    |                               suffix_named_decl_specifiers suffix_named_decl_specifier_bi
+    '''
+    p[0] = get_rest(p)
+
+def p_suffix_named_decl_specifiers_sf(p):
+    '''suffix_named_decl_specifiers_sf :    scoped_special_function_id
+    |                               suffix_named_decl_specifiers
+    |                               suffix_named_decl_specifiers scoped_special_function_id
+    '''
+    #print "HERE",get_rest(p)
+    p[0] = get_rest(p)
+
+def p_suffix_decl_specified_ids(p):
+    '''suffix_decl_specified_ids :          suffix_built_in_decl_specifier
+    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers_sf
+    |                               suffix_named_decl_specifiers_sf
+    '''
+    if len(p) == 3:
+        p[0] = p[2]
+    else:
+        p[0] = p[1]
+
+def p_suffix_decl_specified_scope(p):
+    '''suffix_decl_specified_scope : suffix_named_decl_specifiers SCOPE
+    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers SCOPE
+    |                               suffix_built_in_decl_specifier SCOPE
+    '''
+    p[0] = get_rest(p)
+
+def p_decl_specifier_affix(p):
+    '''decl_specifier_affix :       storage_class_specifier
+    |                               function_specifier
+    |                               FRIEND
+    |                               TYPEDEF
+    |                               cv_qualifier
+    '''
+    pass
+
+def p_decl_specifier_suffix(p):
+    '''decl_specifier_suffix :      decl_specifier_affix
+    '''
+    pass
+
+def p_decl_specifier_prefix(p):
+    '''decl_specifier_prefix :      decl_specifier_affix
+    |                               TEMPLATE decl_specifier_prefix
+    '''
+    pass
+
+def p_storage_class_specifier(p):
+    '''storage_class_specifier :    REGISTER 
+    |                               STATIC 
+    |                               MUTABLE
+    |                               EXTERN                  %prec SHIFT_THERE
+    |                               EXTENSION
+    |                               AUTO
+    '''
+    pass
+
+def p_function_specifier(p):
+    '''function_specifier :         EXPLICIT
+    |                               INLINE
+    |                               VIRTUAL
+    '''
+    pass
+
+def p_type_specifier(p):
+    '''type_specifier :             simple_type_specifier
+    |                               elaborate_type_specifier
+    |                               cv_qualifier
+    '''
+    pass
+
+def p_elaborate_type_specifier(p):
+    '''elaborate_type_specifier :   class_specifier
+    |                               enum_specifier
+    |                               elaborated_type_specifier
+    |                               TEMPLATE elaborate_type_specifier
+    '''
+    pass
+
+def p_simple_type_specifier(p):
+    '''simple_type_specifier :      scoped_id
+    |                               scoped_id attributes
+    |                               built_in_type_specifier
+    '''
+    p[0] = p[1]
+
+def p_built_in_type_specifier(p):
+    '''built_in_type_specifier : Xbuilt_in_type_specifier
+    |                            Xbuilt_in_type_specifier attributes
+    '''
+    pass
+
+def p_attributes(p):
+    '''attributes :                 attribute
+    |                               attributes attribute
+    '''
+    pass
+
+def p_attribute(p):
+    '''attribute :                  ATTRIBUTE '(' parameters_clause ')'
+    '''
+
+def p_Xbuilt_in_type_specifier(p):
+    '''Xbuilt_in_type_specifier :    CHAR 
+    | WCHAR_T 
+    | BOOL 
+    | SHORT 
+    | INT 
+    | LONG 
+    | SIGNED 
+    | UNSIGNED 
+    | FLOAT 
+    | DOUBLE 
+    | VOID
+    | uTYPEOF parameters_clause
+    | TYPEOF parameters_clause
+    '''
+    pass
+
+#
+#  The over-general use of declaration_expression to cover decl-specifier-seq_opt declarator in a function-definition means that
+#      class X { };
+#  could be a function-definition or a class-specifier.
+#      enum X { };
+#  could be a function-definition or an enum-specifier.
+#  The function-definition is not syntactically valid so resolving the false conflict in favour of the
+#  elaborated_type_specifier is correct.
+#
+def p_elaborated_type_specifier(p):
+    '''elaborated_type_specifier :  class_key scoped_id %prec SHIFT_THERE
+    |                               elaborated_enum_specifier
+    |                               TYPENAME scoped_id
+    '''
+    pass
+
+def p_elaborated_enum_specifier(p):
+    '''elaborated_enum_specifier :  ENUM scoped_id   %prec SHIFT_THERE
+    '''
+    pass
+
+def p_enum_specifier(p):
+    '''enum_specifier :             ENUM scoped_id enumerator_clause
+    |                               ENUM enumerator_clause
+    '''
+    pass
+
+def p_enumerator_clause(p):
+    '''enumerator_clause :          LBRACE enumerator_list_ecarb
+    |                               LBRACE enumerator_list enumerator_list_ecarb
+    |                               LBRACE enumerator_list ',' enumerator_definition_ecarb
+    '''
+    pass
+
+def p_enumerator_list_ecarb(p):
+    '''enumerator_list_ecarb :      RBRACE
+    '''
+    pass
+
+def p_enumerator_definition_ecarb(p):
+    '''enumerator_definition_ecarb :        RBRACE
+    '''
+    pass
+
+def p_enumerator_definition_filler(p):
+    '''enumerator_definition_filler :       empty
+    '''
+    pass
+
+def p_enumerator_list_head(p):
+    '''enumerator_list_head :       enumerator_definition_filler
+    |                               enumerator_list ',' enumerator_definition_filler
+    '''
+    pass
+
+def p_enumerator_list(p):
+    '''enumerator_list :            enumerator_list_head enumerator_definition
+    '''
+    pass
+
+def p_enumerator_definition(p):
+    '''enumerator_definition :      enumerator
+    |                               enumerator '=' constant_expression
+    '''
+    pass
+
+def p_enumerator(p):
+    '''enumerator :                 identifier
+    '''
+    pass
+
+def p_namespace_definition(p):
+    '''namespace_definition :       NAMESPACE scoped_id push_scope compound_declaration
+    |                               NAMESPACE push_scope compound_declaration
+    '''
+    global _parse_info
+    scope = _parse_info.pop_scope()
+
+def p_namespace_alias_definition(p):
+    '''namespace_alias_definition : NAMESPACE scoped_id '=' scoped_id ';'
+    '''
+    pass
+
+def p_push_scope(p):
+    '''push_scope :                 empty'''
+    global _parse_info
+    if p[-2] == "namespace":
+        scope=p[-1]
+    else:
+        scope=""
+    _parse_info.push_scope(scope,"namespace")
+
+def p_using_declaration(p):
+    '''using_declaration :          USING declarator_id ';'
+    |                               USING TYPENAME declarator_id ';'
+    '''
+    pass
+
+def p_using_directive(p):
+    '''using_directive :            USING NAMESPACE scoped_id ';'
+    '''
+    pass
+
+#    '''asm_definition :             ASM '(' StringLiteral ')' ';'
+def p_asm_definition(p):
+    '''asm_definition :             ASM '(' nonparen_seq_opt ')' ';'
+    '''
+    pass
+
+def p_linkage_specification(p):
+    '''linkage_specification :      EXTERN CLiteral declaration
+    |                               EXTERN CLiteral compound_declaration
+    |                               EXTERN CppLiteral declaration
+    |                               EXTERN CppLiteral compound_declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.7 Declarators
+#---------------------------------------------------------------------------------------------------
+#
+# init-declarator is named init_declaration to reflect the embedded decl-specifier-seq_opt
+#
+
+def p_init_declarations(p):
+    '''init_declarations :          assignment_expression ',' init_declaration
+    |                               init_declarations ',' init_declaration
+    '''
+    p[0]=get_rest(p)
+
+def p_init_declaration(p):
+    '''init_declaration :           assignment_expression
+    '''
+    p[0]=get_rest(p)
+
+def p_star_ptr_operator(p):
+    '''star_ptr_operator :          '*'
+    |                               star_ptr_operator cv_qualifier
+    '''
+    pass
+
+def p_nested_ptr_operator(p):
+    '''nested_ptr_operator :        star_ptr_operator
+    |                               id_scope nested_ptr_operator
+    '''
+    pass
+
+def p_ptr_operator(p):
+    '''ptr_operator :               '&'
+    |                               nested_ptr_operator
+    |                               global_scope nested_ptr_operator
+    '''
+    pass
+
+def p_ptr_operator_seq(p):
+    '''ptr_operator_seq :           ptr_operator
+    |                               ptr_operator ptr_operator_seq
+    '''
+    pass
+
+#
+# Independently coded to localise the shift-reduce conflict: sharing just needs another %prec
+#
+def p_ptr_operator_seq_opt(p):
+    '''ptr_operator_seq_opt :       empty %prec SHIFT_THERE
+    |                               ptr_operator ptr_operator_seq_opt
+    '''
+    pass
+
+def p_cv_qualifier_seq_opt(p):
+    '''cv_qualifier_seq_opt :       empty
+    |                               cv_qualifier_seq_opt cv_qualifier
+    '''
+    pass
+
+# TODO: verify that we should include attributes here
+def p_cv_qualifier(p):
+    '''cv_qualifier :               CONST 
+    |                               VOLATILE
+    |                               attributes
+    '''
+    pass
+
+def p_type_id(p):
+    '''type_id :                    type_specifier abstract_declarator_opt
+    |                               type_specifier type_id
+    '''
+    pass
+
+def p_abstract_declarator_opt(p):
+    '''abstract_declarator_opt :    empty
+    |                               ptr_operator abstract_declarator_opt
+    |                               direct_abstract_declarator
+    '''
+    pass
+
+def p_direct_abstract_declarator_opt(p):
+    '''direct_abstract_declarator_opt :     empty
+    |                               direct_abstract_declarator
+    '''
+    pass
+
+def p_direct_abstract_declarator(p):
+    '''direct_abstract_declarator : direct_abstract_declarator_opt parenthesis_clause
+    |                               direct_abstract_declarator_opt LBRACKET RBRACKET
+    |                               direct_abstract_declarator_opt LBRACKET bexpression RBRACKET
+    '''
+    pass
+
+def p_parenthesis_clause(p):
+    '''parenthesis_clause :         parameters_clause cv_qualifier_seq_opt
+    |                               parameters_clause cv_qualifier_seq_opt exception_specification
+    '''
+    p[0] = ['(',')']
+
+def p_parameters_clause(p):
+    '''parameters_clause :          '(' condition_opt ')'
+    '''
+    p[0] = ['(',')']
+
+#
+# A typed abstract qualifier such as
+#      Class * ...
+# looks like a multiply, so pointers are parsed as their binary operation equivalents that
+# ultimately terminate with a degenerate right hand term.
+#
+def p_abstract_pointer_declaration(p):
+    '''abstract_pointer_declaration :       ptr_operator_seq
+    |                               multiplicative_expression star_ptr_operator ptr_operator_seq_opt
+    '''
+    pass
+
+def p_abstract_parameter_declaration(p):
+    '''abstract_parameter_declaration :     abstract_pointer_declaration
+    |                               and_expression '&'
+    |                               and_expression '&' abstract_pointer_declaration
+    '''
+    pass
+
+def p_special_parameter_declaration(p):
+    '''special_parameter_declaration :      abstract_parameter_declaration
+    |                               abstract_parameter_declaration '=' assignment_expression
+    |                               ELLIPSIS
+    '''
+    pass
+
+def p_parameter_declaration(p):
+    '''parameter_declaration :      assignment_expression
+    |                               special_parameter_declaration
+    |                               decl_specifier_prefix parameter_declaration
+    '''
+    pass
+
+#
+# function_definition includes constructor, destructor, implicit int definitions too.  A local destructor is successfully parsed as a function-declaration but the ~ was treated as a unary operator.  constructor_head is the prefix ambiguity between a constructor and a member-init-list starting with a bit-field.
+#
+def p_function_definition(p):
+    '''function_definition :        ctor_definition
+    |                               func_definition
+    '''
+    pass
+
+def p_func_definition(p):
+    '''func_definition :            assignment_expression function_try_block
+    |                               assignment_expression function_body
+    |                               decl_specifier_prefix func_definition
+    '''
+    global _parse_info
+    if p[2] is not None and p[2][0] == '{':
+        decl = flatten(p[1])
+        #print "HERE",decl
+        if decl[-1] == ')':
+            decl=decl[-3]
+        else:
+            decl=decl[-1]
+        p[0] = decl
+        if decl != "operator":
+            _parse_info.add_function(decl)
+    else:
+        p[0] = p[2]
+
+def p_ctor_definition(p):
+    '''ctor_definition :            constructor_head function_try_block
+    |                               constructor_head function_body
+    |                               decl_specifier_prefix ctor_definition
+    '''
+    if p[2] is None or p[2][0] == "try" or p[2][0] == '{':
+        p[0]=p[1]
+    else:
+        p[0]=p[1]
+
+def p_constructor_head(p):
+    '''constructor_head :           bit_field_init_declaration
+    |                               constructor_head ',' assignment_expression
+    '''
+    p[0]=p[1]
+
+def p_function_try_block(p):
+    '''function_try_block :         TRY function_block handler_seq
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+    p[0] = ['try']
+
+def p_function_block(p):
+    '''function_block :             ctor_initializer_opt function_body
+    '''
+    pass
+
+def p_function_body(p):
+    '''function_body :              LBRACE nonbrace_seq_opt RBRACE 
+    '''
+    p[0] = ['{','}']
+
+def p_initializer_clause(p):
+    '''initializer_clause :         assignment_expression
+    |                               braced_initializer
+    '''
+    pass
+
+def p_braced_initializer(p):
+    '''braced_initializer :         LBRACE initializer_list RBRACE
+    |                               LBRACE initializer_list ',' RBRACE
+    |                               LBRACE RBRACE
+    '''
+    pass
+
+def p_initializer_list(p):
+    '''initializer_list :           initializer_clause
+    |                               initializer_list ',' initializer_clause
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.8 Classes
+#---------------------------------------------------------------------------------------------------
+#
+#  An anonymous bit-field declaration may look very like inheritance:
+#      const int B = 3;
+#      class A : B ;
+#  The two usages are too distant to try to create and enforce a common prefix so we have to resort to
+#  a parser hack by backtracking. Inheritance is much the most likely so we mark the input stream context
+#  and try to parse a base-clause. If we successfully reach a { the base-clause is ok and inheritance was
+#  the correct choice so we unmark and continue. If we fail to find the { an error token causes 
+#  back-tracking to the alternative parse in elaborated_type_specifier which regenerates the : and 
+#  declares unconditional success.
+#
+
+def p_class_specifier_head(p):
+    '''class_specifier_head :       class_key scoped_id ':' base_specifier_list LBRACE
+    |                               class_key ':' base_specifier_list LBRACE
+    |                               class_key scoped_id LBRACE
+    |                               class_key LBRACE
+    '''
+    global _parse_info
+    base_classes=[]
+    if len(p) == 6:
+        scope = p[2]
+        base_classes = p[4]
+    elif len(p) == 4:
+        scope = p[2]
+    elif len(p) == 5:
+        base_classes = p[3]
+    else:
+        scope = ""
+    _parse_info.push_scope(scope,p[1],base_classes)
+    
+
+def p_class_key(p):
+    '''class_key :                  CLASS 
+    | STRUCT 
+    | UNION
+    '''
+    p[0] = p[1]
+
+def p_class_specifier(p):
+    '''class_specifier :            class_specifier_head member_specification_opt RBRACE
+    '''
+    scope = _parse_info.pop_scope()
+
+def p_member_specification_opt(p):
+    '''member_specification_opt :   empty
+    |                               member_specification_opt member_declaration
+    '''
+    pass
+
+def p_member_declaration(p):
+    '''member_declaration :         accessibility_specifier
+    |                               simple_member_declaration
+    |                               function_definition
+    |                               using_declaration
+    |                               template_declaration
+    '''
+    p[0] = get_rest(p)
+    #print "Decl",get_rest(p)
+
+#
+#  The generality of constructor names (there need be no parenthesised argument list) means that that
+#          name : f(g), h(i)
+#  could be the start of a constructor or the start of an anonymous bit-field. An ambiguity is avoided by
+#  parsing the ctor-initializer of a function_definition as a bit-field.
+#
+def p_simple_member_declaration(p):
+    '''simple_member_declaration :  ';'
+    |                               assignment_expression ';'
+    |                               constructor_head ';'
+    |                               member_init_declarations ';'
+    |                               decl_specifier_prefix simple_member_declaration
+    '''
+    global _parse_info
+    decl = flatten(get_rest(p))
+    if len(decl) >= 4 and decl[-3] == "(":
+        _parse_info.add_function(decl[-4])
+
+def p_member_init_declarations(p):
+    '''member_init_declarations :   assignment_expression ',' member_init_declaration
+    |                               constructor_head ',' bit_field_init_declaration
+    |                               member_init_declarations ',' member_init_declaration
+    '''
+    pass
+
+def p_member_init_declaration(p):
+    '''member_init_declaration :    assignment_expression
+    |                               bit_field_init_declaration
+    '''
+    pass
+
+def p_accessibility_specifier(p):
+    '''accessibility_specifier :    access_specifier ':'
+    '''
+    pass
+
+def p_bit_field_declaration(p):
+    '''bit_field_declaration :      assignment_expression ':' bit_field_width
+    |                               ':' bit_field_width
+    '''
+    if len(p) == 4:
+        p[0]=p[1]
+
+def p_bit_field_width(p):
+    '''bit_field_width :            logical_or_expression
+    |                               logical_or_expression '?' bit_field_width ':' bit_field_width
+    '''
+    pass
+
+def p_bit_field_init_declaration(p):
+    '''bit_field_init_declaration : bit_field_declaration
+    |                               bit_field_declaration '=' initializer_clause
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.9 Derived classes
+#---------------------------------------------------------------------------------------------------
+def p_base_specifier_list(p):
+    '''base_specifier_list :        base_specifier
+    |                               base_specifier_list ',' base_specifier
+    '''
+    if len(p) == 2:
+        p[0] = [p[1]]
+    else:
+        p[0] = p[1]+[p[3]]
+
+def p_base_specifier(p):
+    '''base_specifier :             scoped_id
+    |                               access_specifier base_specifier
+    |                               VIRTUAL base_specifier
+    '''
+    if len(p) == 2:
+        p[0] = p[1]
+    else:
+        p[0] = p[2]
+
+def p_access_specifier(p):
+    '''access_specifier :           PRIVATE 
+    |                               PROTECTED 
+    |                               PUBLIC
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.10 Special member functions
+#---------------------------------------------------------------------------------------------------
+def p_conversion_function_id(p):
+    '''conversion_function_id :     OPERATOR conversion_type_id
+    '''
+    p[0] = ['operator']
+
+def p_conversion_type_id(p):
+    '''conversion_type_id :         type_specifier ptr_operator_seq_opt
+    |                               type_specifier conversion_type_id
+    '''
+    pass
+
+#
+#  Ctor-initialisers can look like a bit field declaration, given the generalisation of names:
+#      Class(Type) : m1(1), m2(2) { }
+#      NonClass(bit_field) : int(2), second_variable, ...
+#  The grammar below is used within a function_try_block or function_definition.
+#  See simple_member_declaration for use in normal member function_definition.
+#
+def p_ctor_initializer_opt(p):
+    '''ctor_initializer_opt :       empty
+    |                               ctor_initializer
+    '''
+    pass
+
+def p_ctor_initializer(p):
+    '''ctor_initializer :           ':' mem_initializer_list
+    '''
+    pass
+
+def p_mem_initializer_list(p):
+    '''mem_initializer_list :       mem_initializer
+    |                               mem_initializer_list_head mem_initializer
+    '''
+    pass
+
+def p_mem_initializer_list_head(p):
+    '''mem_initializer_list_head :  mem_initializer_list ','
+    '''
+    pass
+
+def p_mem_initializer(p):
+    '''mem_initializer :            mem_initializer_id '(' expression_list_opt ')'
+    '''
+    pass
+
+def p_mem_initializer_id(p):
+    '''mem_initializer_id :         scoped_id
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.11 Overloading
+#---------------------------------------------------------------------------------------------------
+
+def p_operator_function_id(p):
+    '''operator_function_id :       OPERATOR operator
+    |                               OPERATOR '(' ')'
+    |                               OPERATOR LBRACKET RBRACKET
+    |                               OPERATOR '<'
+    |                               OPERATOR '>'
+    |                               OPERATOR operator '<' nonlgt_seq_opt '>'
+    '''
+    p[0] = ["operator"]
+
+#
+#  It is not clear from the ANSI standard whether spaces are permitted in delete[]. If not then it can
+#  be recognised and returned as DELETE_ARRAY by the lexer. Assuming spaces are permitted there is an
+#  ambiguity created by the over generalised nature of expressions. operator new is a valid delarator-id
+#  which we may have an undimensioned array of. Semantic rubbish, but syntactically valid. Since the
+#  array form is covered by the declarator consideration we can exclude the operator here. The need
+#  for a semantic rescue can be eliminated at the expense of a couple of shift-reduce conflicts by
+#  removing the comments on the next four lines.
+#
+def p_operator(p):
+    '''operator :                   NEW
+    |                               DELETE
+    |                               '+'
+    |                               '-'
+    |                               '*'
+    |                               '/'
+    |                               '%'
+    |                               '^'
+    |                               '&'
+    |                               '|'
+    |                               '~'
+    |                               '!'
+    |                               '='
+    |                               ASS_ADD
+    |                               ASS_SUB
+    |                               ASS_MUL
+    |                               ASS_DIV
+    |                               ASS_MOD
+    |                               ASS_XOR
+    |                               ASS_AND
+    |                               ASS_OR
+    |                               SHL
+    |                               SHR
+    |                               ASS_SHR
+    |                               ASS_SHL
+    |                               EQ
+    |                               NE
+    |                               LE
+    |                               GE
+    |                               LOG_AND
+    |                               LOG_OR
+    |                               INC
+    |                               DEC
+    |                               ','
+    |                               ARROW_STAR
+    |                               ARROW
+    '''
+    p[0]=p[1]
+
+#    |                               IF
+#    |                               SWITCH
+#    |                               WHILE
+#    |                               FOR
+#    |                               DO
+def p_reserved(p):
+    '''reserved :                   PRIVATE
+    |                               CLiteral
+    |                               CppLiteral
+    |                               IF
+    |                               SWITCH
+    |                               WHILE
+    |                               FOR
+    |                               DO
+    |                               PROTECTED
+    |                               PUBLIC
+    |                               BOOL
+    |                               CHAR
+    |                               DOUBLE
+    |                               FLOAT
+    |                               INT
+    |                               LONG
+    |                               SHORT
+    |                               SIGNED
+    |                               UNSIGNED
+    |                               VOID
+    |                               WCHAR_T
+    |                               CLASS
+    |                               ENUM
+    |                               NAMESPACE
+    |                               STRUCT
+    |                               TYPENAME
+    |                               UNION
+    |                               CONST
+    |                               VOLATILE
+    |                               AUTO
+    |                               EXPLICIT
+    |                               EXPORT
+    |                               EXTERN
+    |                               FRIEND
+    |                               INLINE
+    |                               MUTABLE
+    |                               REGISTER
+    |                               STATIC
+    |                               TEMPLATE
+    |                               TYPEDEF
+    |                               USING
+    |                               VIRTUAL
+    |                               ASM
+    |                               BREAK
+    |                               CASE
+    |                               CATCH
+    |                               CONST_CAST
+    |                               CONTINUE
+    |                               DEFAULT
+    |                               DYNAMIC_CAST
+    |                               ELSE
+    |                               FALSE
+    |                               GOTO
+    |                               OPERATOR
+    |                               REINTERPRET_CAST
+    |                               RETURN
+    |                               SIZEOF
+    |                               STATIC_CAST
+    |                               THIS
+    |                               THROW
+    |                               TRUE
+    |                               TRY
+    |                               TYPEID
+    |                               ATTRIBUTE
+    |                               CDECL
+    |                               TYPEOF
+    |                               uTYPEOF
+    '''
+    if p[1] in ('try', 'catch', 'throw'):
+        global noExceptionLogic
+        noExceptionLogic=False
+
+#---------------------------------------------------------------------------------------------------
+# A.12 Templates
+#---------------------------------------------------------------------------------------------------
+def p_template_declaration(p):
+    '''template_declaration :       template_parameter_clause declaration
+    |                               EXPORT template_declaration
+    '''
+    pass
+
+def p_template_parameter_clause(p):
+    '''template_parameter_clause :  TEMPLATE '<' nonlgt_seq_opt '>'
+    '''
+    pass
+
+#
+#  Generalised naming makes identifier a valid declaration, so TEMPLATE identifier is too.
+#  The TEMPLATE prefix is therefore folded into all names, parenthesis_clause and decl_specifier_prefix.
+#
+# explicit_instantiation:           TEMPLATE declaration
+#
+def p_explicit_specialization(p):
+    '''explicit_specialization :    TEMPLATE '<' '>' declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.13 Exception Handling
+#---------------------------------------------------------------------------------------------------
+def p_handler_seq(p):
+    '''handler_seq :                handler
+    |                               handler handler_seq
+    '''
+    pass
+
+def p_handler(p):
+    '''handler :                    CATCH '(' exception_declaration ')' compound_statement
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_exception_declaration(p):
+    '''exception_declaration :      parameter_declaration
+    '''
+    pass
+
+def p_throw_expression(p):
+    '''throw_expression :           THROW
+    |                               THROW assignment_expression
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_exception_specification(p):
+    '''exception_specification :    THROW '(' ')'
+    |                               THROW '(' type_id_list ')'
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_type_id_list(p):
+    '''type_id_list :               type_id
+    |                               type_id_list ',' type_id
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# Misc productions
+#---------------------------------------------------------------------------------------------------
+def p_nonsemicolon_seq(p):
+    '''nonsemicolon_seq :           empty
+    |                               nonsemicolon_seq nonsemicolon
+    '''
+    pass
+
+def p_nonsemicolon(p):
+    '''nonsemicolon :               misc
+    |                               '('
+    |                               ')'
+    |                               '<'
+    |                               '>'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonparen_seq_opt(p):
+    '''nonparen_seq_opt :           empty
+    |                               nonparen_seq_opt nonparen
+    '''
+    pass
+
+def p_nonparen_seq(p):
+    '''nonparen_seq :               nonparen
+    |                               nonparen_seq nonparen
+    '''
+    pass
+
+def p_nonparen(p):
+    '''nonparen :                   misc
+    |                               '<'
+    |                               '>'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonbracket_seq_opt(p):
+    '''nonbracket_seq_opt :         empty
+    |                               nonbracket_seq_opt nonbracket
+    '''
+    pass
+
+def p_nonbracket_seq(p):
+    '''nonbracket_seq :             nonbracket
+    |                               nonbracket_seq nonbracket
+    '''
+    pass
+
+def p_nonbracket(p):
+    '''nonbracket :                 misc
+    |                               '<'
+    |                               '>'
+    |                               '('
+    |                               ')'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonbrace_seq_opt(p):
+    '''nonbrace_seq_opt :           empty
+    |                               nonbrace_seq_opt nonbrace
+    '''
+    pass
+
+def p_nonbrace(p):
+    '''nonbrace :                   misc
+    |                               '<'
+    |                               '>'
+    |                               '('
+    |                               ')'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonlgt_seq_opt(p):
+    '''nonlgt_seq_opt :             empty
+    |                               nonlgt_seq_opt nonlgt
+    '''
+    pass
+
+def p_nonlgt(p):
+    '''nonlgt :                     misc
+    |                               '('
+    |                               ')'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               '<' nonlgt_seq_opt '>'
+    |                               ';'
+    '''
+    pass
+
+def p_misc(p):
+    '''misc :                       operator
+    |                               identifier
+    |                               IntegerLiteral
+    |                               CharacterLiteral
+    |                               FloatingLiteral
+    |                               StringLiteral
+    |                               reserved
+    |                               '?'
+    |                               ':'
+    |                               '.'
+    |                               SCOPE
+    |                               ELLIPSIS
+    |                               EXTENSION
+    '''
+    pass
+
+def p_empty(p):
+    '''empty : '''
+    pass
+
+
+
+#
+# Compute column.
+#     input is the input text string
+#     token is a token instance
+#
+def _find_column(input,token):
+    ''' TODO '''
+    i = token.lexpos
+    while i > 0:
+        if input[i] == '\n': break
+        i -= 1
+    column = (token.lexpos - i)+1
+    return column
+
+def p_error(p):
+    if p is None:
+        tmp = "Syntax error at end of file."
+    else:
+        tmp = "Syntax error at token "
+        if p.type is "":
+            tmp = tmp + "''"
+        else:
+            tmp = tmp + str(p.type)
+        tmp = tmp + " with value '"+str(p.value)+"'"
+        tmp = tmp + " in line " + str(lexer.lineno-1)
+        tmp = tmp + " at column "+str(_find_column(_parsedata,p))
+    raise IOError( tmp )
+
+
+
+#
+# The function that performs the parsing
+#
+def parse_cpp(data=None, filename=None, debug=0, optimize=0, verbose=False, func_filter=None):
+    if debug > 0:
+        print "Debugging parse_cpp!"
+        #
+        # Always remove the parser.out file, which is generated to create debugging
+        #
+        if os.path.exists("parser.out"):
+            os.remove("parser.out")
+        #
+        # Remove the parsetab.py* files.  These apparently need to be removed
+        # to ensure the creation of a parser.out file.
+        #
+        if os.path.exists("parsetab.py"):
+           os.remove("parsetab.py")
+        if os.path.exists("parsetab.pyc"):
+           os.remove("parsetab.pyc")
+        global debugging
+        debugging=True
+    #
+    # Build lexer
+    #
+    global lexer
+    lexer = lex.lex()
+    #
+    # Initialize parse object
+    #
+    global _parse_info
+    _parse_info = CppInfo(filter=func_filter)
+    _parse_info.verbose=verbose
+    #
+    # Build yaccer
+    #
+    write_table = not os.path.exists("parsetab.py")
+    yacc.yacc(debug=debug, optimize=optimize, write_tables=write_table)
+    #
+    # Parse the file
+    #
+    global _parsedata
+    if not data is None:
+        _parsedata=data
+        ply_init(_parsedata)
+        yacc.parse(data,debug=debug)
+    elif not filename is None:
+        f = open(filename)
+        data = f.read()
+        f.close()
+        _parsedata=data
+        ply_init(_parsedata)
+        yacc.parse(data, debug=debug)
+    else:
+        return None
+    #
+    if not noExceptionLogic:
+        _parse_info.noExceptionLogic = False
+    else:
+        for key in identifier_lineno:
+            if 'ASSERT_THROWS' in key:
+                _parse_info.noExceptionLogic = False
+                break
+        _parse_info.noExceptionLogic = True
+    #
+    return _parse_info
+
+
+
+import sys
+
+if __name__ == '__main__':
+    #
+    # This MAIN routine parses a sequence of files provided at the command
+    # line.  If '-v' is included, then a verbose parsing output is 
+    # generated.
+    #
+    for arg in sys.argv[1:]:
+        if arg == "-v":
+            continue
+        print "Parsing file '"+arg+"'"
+        if '-v' in sys.argv:
+            parse_cpp(filename=arg,debug=2,verbose=2)
+        else:
+            parse_cpp(filename=arg,verbose=2)
+        #
+        # Print the _parse_info object summary for this file.
+        # This illustrates how class inheritance can be used to 
+        # deduce class members.
+        # 
+        print str(_parse_info)
+
diff --git a/tools/cxxtest/python/cxxtest/cxx_parser.pyc b/tools/cxxtest/python/cxxtest/cxx_parser.pyc
new file mode 100644 (file)
index 0000000..ca9ea24
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/cxx_parser.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_fog.py b/tools/cxxtest/python/cxxtest/cxxtest_fog.py
new file mode 100644 (file)
index 0000000..4fb9d71
--- /dev/null
@@ -0,0 +1,96 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+#
+# TODO: add line number info
+# TODO: add test function names
+#
+
+from __future__ import division
+
+import sys
+import re
+#from os.path import abspath, dirname
+#sys.path.insert(0, dirname(dirname(abspath(__file__))))
+#sys.path.insert(0, dirname(dirname(abspath(__file__)))+"/cxx_parse")
+from cxxtest_misc import abort
+import cxx_parser
+import re
+
+def cstr( str ):
+    '''Convert a string to its C representation'''
+    return '"' + re.sub('\\\\', '\\\\\\\\', str ) + '"'
+
+def scanInputFiles(files, _options):
+    '''Scan all input files for test suites'''
+    suites=[]
+    for file in files:
+        try:
+            print "Parsing file "+file,
+            sys.stdout.flush()
+            parse_info = cxx_parser.parse_cpp(filename=file,optimize=1)
+        except IOError, err:
+            print " error."
+            print str(err)
+            continue
+        print "done." 
+        sys.stdout.flush()
+        #
+        # WEH: see if it really makes sense to use parse information to
+        # initialize this data.  I don't think so...
+        #
+        _options.haveStandardLibrary=1
+        if not parse_info.noExceptionLogic:
+            _options.haveExceptionHandling=1
+        #
+        keys = list(parse_info.index.keys())
+        tpat = re.compile("[Tt][Ee][Ss][Tt]")
+        for key in keys:
+            if parse_info.index[key].scope_t == "class" and parse_info.is_baseclass(key,"CxxTest::TestSuite"):
+                name=parse_info.index[key].name
+                suite = { 'name'         : name,
+                        'file'         : file,
+                        'cfile'        : cstr(file),
+                        'line'         : str(parse_info.index[key].lineno),
+                        'generated'    : 0,
+                        'object'       : 'suite_%s' % name,
+                        'dobject'      : 'suiteDescription_%s' % name,
+                        'tlist'        : 'Tests_%s' % name,
+                        'tests'        : [],
+                        'lines'        : [] }
+                for fn in parse_info.get_functions(key,quiet=True):
+                    tname = fn[0]
+                    lineno = str(fn[1])
+                    if tname.startswith('createSuite'):
+                        # Indicate that we're using a dynamically generated test suite
+                        suite['create'] = str(lineno) # (unknown line)
+                    if tname.startswith('destroySuite'):
+                        # Indicate that we're using a dynamically generated test suite
+                        suite['destroy'] = str(lineno) # (unknown line)
+                    if not tpat.match(tname):
+                        # Skip non-test methods
+                        continue
+                    test = { 'name'   : tname,
+                        'suite'  : suite,
+                        'class'  : 'TestDescription_suite_%s_%s' % (suite['name'], tname),
+                        'object' : 'testDescription_suite_%s_%s' % (suite['name'], tname),
+                        'line'   : lineno,
+                        }
+                    suite['tests'].append(test)
+                suites.append(suite)
+
+    if not _options.root:
+        ntests = 0
+        for suite in suites:
+            ntests += len(suite['tests'])
+        if ntests == 0:
+            abort( 'No tests defined' )
+    #
+    return [_options, suites]
+
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_fog.pyc b/tools/cxxtest/python/cxxtest/cxxtest_fog.pyc
new file mode 100644 (file)
index 0000000..5dd31d9
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/cxxtest_fog.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_misc.py b/tools/cxxtest/python/cxxtest/cxxtest_misc.py
new file mode 100644 (file)
index 0000000..b5b9a8d
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+import sys
+
+def abort( problem ):
+    '''Print error message and exit'''
+    sys.stderr.write( '\n' )
+    sys.stderr.write( problem )
+    sys.stderr.write( '\n\n' )
+    sys.exit(2)
+
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_misc.pyc b/tools/cxxtest/python/cxxtest/cxxtest_misc.pyc
new file mode 100644 (file)
index 0000000..0a9ab3d
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/cxxtest_misc.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_parser.py b/tools/cxxtest/python/cxxtest/cxxtest_parser.py
new file mode 100644 (file)
index 0000000..64eede5
--- /dev/null
@@ -0,0 +1,242 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+from __future__ import division
+
+import codecs
+import re
+#import sys
+#import getopt
+#import glob
+from cxxtest.cxxtest_misc import abort
+
+# Global variables
+suites = []
+suite = None
+inBlock = 0
+options=None
+
+def scanInputFiles(files, _options):
+    '''Scan all input files for test suites'''
+    global options
+    options=_options
+    for file in files:
+        scanInputFile(file)
+    global suites
+    if len(suites) is 0 and not options.root:
+        abort( 'No tests defined' )
+    return [options,suites]
+
+lineCont_re = re.compile('(.*)\\\s*$')
+def scanInputFile(fileName):
+    '''Scan single input file for test suites'''
+    # mode 'rb' is problematic in python3 - byte arrays don't behave the same as
+    # strings.
+    # As far as the choice of the default encoding: utf-8 chews through
+    # everything that the previous ascii codec could, plus most of new code.
+    # TODO: figure out how to do this properly - like autodetect encoding from
+    # file header.
+    file = codecs.open(fileName, mode='r', encoding='utf-8')
+    prev = ""
+    lineNo = 0
+    contNo = 0
+    while 1:
+        line = file.readline()
+        if not line:
+            break
+        lineNo += 1
+
+        m = lineCont_re.match(line)
+        if m:
+            prev += m.group(1) + " "
+            contNo += 1
+        else:
+            scanInputLine( fileName, lineNo - contNo, prev + line )
+            contNo = 0
+            prev = ""
+    if contNo:
+        scanInputLine( fileName, lineNo - contNo, prev + line )
+        
+    closeSuite()
+    file.close()
+
+def scanInputLine( fileName, lineNo, line ):
+    '''Scan single input line for interesting stuff'''
+    scanLineForExceptionHandling( line )
+    scanLineForStandardLibrary( line )
+
+    scanLineForSuiteStart( fileName, lineNo, line )
+
+    global suite
+    if suite:
+        scanLineInsideSuite( suite, lineNo, line )
+
+def scanLineInsideSuite( suite, lineNo, line ):
+    '''Analyze line which is part of a suite'''
+    global inBlock
+    if lineBelongsToSuite( suite, lineNo, line ):
+        scanLineForTest( suite, lineNo, line )
+        scanLineForCreate( suite, lineNo, line )
+        scanLineForDestroy( suite, lineNo, line )
+
+def lineBelongsToSuite( suite, lineNo, line ):
+    '''Returns whether current line is part of the current suite.
+    This can be false when we are in a generated suite outside of CXXTEST_CODE() blocks
+    If the suite is generated, adds the line to the list of lines'''
+    if not suite['generated']:
+        return 1
+
+    global inBlock
+    if not inBlock:
+        inBlock = lineStartsBlock( line )
+    if inBlock:
+        inBlock = addLineToBlock( suite, lineNo, line )
+    return inBlock
+
+
+std_re = re.compile( r"\b(std\s*::|CXXTEST_STD|using\s+namespace\s+std\b|^\s*\#\s*include\s+<[a-z0-9]+>)" )
+def scanLineForStandardLibrary( line ):
+    '''Check if current line uses standard library'''
+    global options
+    if not options.haveStandardLibrary and std_re.search(line):
+        if not options.noStandardLibrary:
+            options.haveStandardLibrary = 1
+
+exception_re = re.compile( r"\b(throw|try|catch|TSM?_ASSERT_THROWS[A-Z_]*)\b" )
+def scanLineForExceptionHandling( line ):
+    '''Check if current line uses exception handling'''
+    global options
+    if not options.haveExceptionHandling and exception_re.search(line):
+        if not options.noExceptionHandling:
+            options.haveExceptionHandling = 1
+
+classdef = '(?:::\s*)?(?:\w+\s*::\s*)*\w+'
+baseclassdef = '(?:public|private|protected)\s+%s' % (classdef,)
+general_suite = r"\bclass\s+(%s)\s*:(?:\s*%s\s*,)*\s*public\s+" \
+                % (classdef, baseclassdef,)
+testsuite = '(?:(?:::)?\s*CxxTest\s*::\s*)?TestSuite'
+suites_re = { re.compile( general_suite + testsuite ) : None }
+generatedSuite_re = re.compile( r'\bCXXTEST_SUITE\s*\(\s*(\w*)\s*\)' )
+def scanLineForSuiteStart( fileName, lineNo, line ):
+    '''Check if current line starts a new test suite'''
+    for i in list(suites_re.items()):
+        m = i[0].search( line )
+        if m:
+            suite = startSuite( m.group(1), fileName, lineNo, 0 )
+            if i[1] is not None:
+                for test in i[1]['tests']:
+                    addTest(suite, test['name'], test['line'])
+            break
+    m = generatedSuite_re.search( line )
+    if m:
+        sys.stdout.write( "%s:%s: Warning: Inline test suites are deprecated.\n" % (fileName, lineNo) )
+        startSuite( m.group(1), fileName, lineNo, 1 )
+
+def startSuite( name, file, line, generated ):
+    '''Start scanning a new suite'''
+    global suite
+    closeSuite()
+    object_name = name.replace(':',"_")
+    suite = { 'name'         : name,
+              'file'         : file,
+              'cfile'        : cstr(file),
+              'line'         : line,
+              'generated'    : generated,
+              'object'       : 'suite_%s' % object_name,
+              'dobject'      : 'suiteDescription_%s' % object_name,
+              'tlist'        : 'Tests_%s' % object_name,
+              'tests'        : [],
+              'lines'        : [] }
+    suites_re[re.compile( general_suite + name )] = suite
+    return suite
+
+def lineStartsBlock( line ):
+    '''Check if current line starts a new CXXTEST_CODE() block'''
+    return re.search( r'\bCXXTEST_CODE\s*\(', line ) is not None
+
+test_re = re.compile( r'^([^/]|/[^/])*\bvoid\s+([Tt]est\w+)\s*\(\s*(void)?\s*\)' )
+def scanLineForTest( suite, lineNo, line ):
+    '''Check if current line starts a test'''
+    m = test_re.search( line )
+    if m:
+        addTest( suite, m.group(2), lineNo )
+
+def addTest( suite, name, line ):
+    '''Add a test function to the current suite'''
+    test = { 'name'   : name,
+             'suite'  : suite,
+             'class'  : 'TestDescription_%s_%s' % (suite['object'], name),
+             'object' : 'testDescription_%s_%s' % (suite['object'], name),
+             'line'   : line,
+             }
+    suite['tests'].append( test )
+
+def addLineToBlock( suite, lineNo, line ):
+    '''Append the line to the current CXXTEST_CODE() block'''
+    line = fixBlockLine( suite, lineNo, line )
+    line = re.sub( r'^.*\{\{', '', line )
+    
+    e = re.search( r'\}\}', line )
+    if e:
+        line = line[:e.start()]
+    suite['lines'].append( line )
+    return e is None
+
+def fixBlockLine( suite, lineNo, line):
+    '''Change all [E]TS_ macros used in a line to _[E]TS_ macros with the correct file/line'''
+    return re.sub( r'\b(E?TSM?_(ASSERT[A-Z_]*|FAIL))\s*\(',
+                   r'_\1(%s,%s,' % (suite['cfile'], lineNo),
+                   line, 0 )
+
+create_re = re.compile( r'\bstatic\s+\w+\s*\*\s*createSuite\s*\(\s*(void)?\s*\)' )
+def scanLineForCreate( suite, lineNo, line ):
+    '''Check if current line defines a createSuite() function'''
+    if create_re.search( line ):
+        addSuiteCreateDestroy( suite, 'create', lineNo )
+
+destroy_re = re.compile( r'\bstatic\s+void\s+destroySuite\s*\(\s*\w+\s*\*\s*\w*\s*\)' )
+def scanLineForDestroy( suite, lineNo, line ):
+    '''Check if current line defines a destroySuite() function'''
+    if destroy_re.search( line ):
+        addSuiteCreateDestroy( suite, 'destroy', lineNo )
+
+def cstr( s ):
+    '''Convert a string to its C representation'''
+    return '"' + s.replace( '\\', '\\\\' ) + '"'
+
+
+def addSuiteCreateDestroy( suite, which, line ):
+    '''Add createSuite()/destroySuite() to current suite'''
+    if which in suite:
+        abort( '%s:%s: %sSuite() already declared' % ( suite['file'], str(line), which ) )
+    suite[which] = line
+
+def closeSuite():
+    '''Close current suite and add it to the list if valid'''
+    global suite
+    if suite is not None:
+        if len(suite['tests']) is not 0:
+            verifySuite(suite)
+            rememberSuite(suite)
+        suite = None
+
+def verifySuite(suite):
+    '''Verify current suite is legal'''
+    if 'create' in suite and 'destroy' not in suite:
+        abort( '%s:%s: Suite %s has createSuite() but no destroySuite()' %
+               (suite['file'], suite['create'], suite['name']) )
+    elif 'destroy' in suite and 'create' not in suite:
+        abort( '%s:%s: Suite %s has destroySuite() but no createSuite()' %
+               (suite['file'], suite['destroy'], suite['name']) )
+
+def rememberSuite(suite):
+    '''Add current suite to list'''
+    global suites
+    suites.append( suite )
+
diff --git a/tools/cxxtest/python/cxxtest/cxxtest_parser.pyc b/tools/cxxtest/python/cxxtest/cxxtest_parser.pyc
new file mode 100644 (file)
index 0000000..30b7346
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/cxxtest_parser.pyc differ
diff --git a/tools/cxxtest/python/cxxtest/cxxtestgen.py b/tools/cxxtest/python/cxxtest/cxxtestgen.py
new file mode 100644 (file)
index 0000000..5c18f16
--- /dev/null
@@ -0,0 +1,480 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+# vim: fileencoding=utf-8
+
+from __future__ import division
+# the above import important for forward-compatibility with python3,
+# which is already the default in archlinux!
+
+__all__ = ['main']
+
+import __release__
+import os
+import sys
+import re
+import glob
+from optparse import OptionParser
+import cxxtest_parser
+
+try:
+    import cxxtest_fog
+    imported_fog=True
+except ImportError:
+    imported_fog=False
+
+from cxxtest_misc import abort
+
+options = []
+suites = []
+
+wrotePreamble = 0
+wroteWorld = 0
+lastIncluded = ''
+
+def main(args=sys.argv):
+    '''The main program'''
+    #
+    # Reset global state
+    #
+    global wrotePreamble
+    wrotePreamble=0
+    global wroteWorld
+    wroteWorld=0
+    global lastIncluded
+    lastIncluded = ''
+
+    global suites
+    global options
+    files = parseCommandline(args)
+    if imported_fog and options.fog:
+        [options,suites] = cxxtest_fog.scanInputFiles( files, options )
+    else:
+        [options,suites] = cxxtest_parser.scanInputFiles( files, options )
+    writeOutput()
+
+def parseCommandline(args):
+    '''Analyze command line arguments'''
+    global imported_fog
+    global options
+    parser = OptionParser("%prog [options] [<filename> ...]")
+    parser.add_option("--version",
+                      action="store_true", dest="version", default=False,
+                      help="Write the CxxTest version.")
+    parser.add_option("-o", "--output",
+                      dest="outputFileName", default=None, metavar="NAME",
+                      help="Write output to file NAME.")
+    parser.add_option("-w","--world", dest="world", default="cxxtest",
+                      help="The label of the tests, used to name the XML results.")
+    parser.add_option("", "--include", action="append",
+                      dest="headers", default=[], metavar="HEADER",
+                      help="Include file HEADER in the test runner before other headers.")
+    parser.add_option("", "--abort-on-fail",
+                      action="store_true", dest="abortOnFail", default=False,
+                      help="Abort tests on failed asserts (like xUnit).")
+    parser.add_option("", "--main",
+                      action="store", dest="main", default="main",
+                      help="Specify an alternative name for the main() function.")
+    parser.add_option("", "--headers",
+                      action="store", dest="header_filename", default=None,
+                      help="Specify a filename that contains a list of header files that are processed to generate a test runner.")
+    parser.add_option("", "--runner",
+                      dest="runner", default="", metavar="CLASS",
+                      help="Create a test runner that processes test events using the class CxxTest::CLASS.")
+    parser.add_option("", "--gui",
+                      dest="gui", metavar="CLASS",
+                      help="Create a GUI test runner that processes test events using the class CxxTest::CLASS. (deprecated)")
+    parser.add_option("", "--error-printer",
+                      action="store_true", dest="error_printer", default=False,
+                      help="Create a test runner using the ErrorPrinter class, and allow the use of the standard library.")
+    parser.add_option("", "--xunit-printer",
+                      action="store_true", dest="xunit_printer", default=False,
+                      help="Create a test runner using the XUnitPrinter class.")
+    parser.add_option("", "--xunit-file",  dest="xunit_file", default="",
+                      help="The file to which the XML summary is written for test runners using the XUnitPrinter class.  The default XML filename is TEST-<world>.xml, where <world> is the value of the --world option.  (default: cxxtest)")
+    parser.add_option("", "--have-std",
+                      action="store_true", dest="haveStandardLibrary", default=False,
+                      help="Use the standard library (even if not found in tests).")
+    parser.add_option("", "--no-std",
+                      action="store_true", dest="noStandardLibrary", default=False,
+                      help="Do not use standard library (even if found in tests).")
+    parser.add_option("", "--have-eh",
+                      action="store_true", dest="haveExceptionHandling", default=False,
+                      help="Use exception handling (even if not found in tests).")
+    parser.add_option("", "--no-eh",
+                      action="store_true", dest="noExceptionHandling", default=False,
+                      help="Do not use exception handling (even if found in tests).")
+    parser.add_option("", "--longlong",
+                      dest="longlong", default=None, metavar="TYPE",
+                      help="Use TYPE as for long long integers.  (default: not supported)")
+    parser.add_option("", "--no-static-init",
+                      action="store_true", dest="noStaticInit", default=False,
+                      help="Do not rely on static initialization in the test runner.")
+    parser.add_option("", "--template",
+                      dest="templateFileName", default=None, metavar="TEMPLATE",
+                      help="Generate the test runner using file TEMPLATE to define a template.")
+    parser.add_option("", "--root",
+                      action="store_true", dest="root", default=False,
+                      help="Write the main() function and global data for a test runner.")
+    parser.add_option("", "--part",
+                      action="store_true", dest="part", default=False,
+                      help="Write the tester classes for a test runner.")
+    #parser.add_option("", "--factor",
+                      #action="store_true", dest="factor", default=False,
+                      #help="Declare the _CXXTEST_FACTOR macro.  (deprecated)")
+    if imported_fog:
+        fog_help = "Use new FOG C++ parser"
+    else:
+        fog_help = "Use new FOG C++ parser (disabled)"
+    parser.add_option("-f", "--fog-parser",
+                        action="store_true",
+                        dest="fog",
+                        default=False,
+                        help=fog_help
+                        )
+
+    (options, args) = parser.parse_args(args=args)
+    if not options.header_filename is None:
+        if not os.path.exists(options.header_filename):
+            abort( "ERROR: the file '%s' does not exist!" % options.header_filename )
+        INPUT = open(options.header_filename)
+        headers = [line.strip() for line in INPUT]
+        args.extend( headers )
+        INPUT.close()
+
+    if options.fog and not imported_fog:
+        abort( "Cannot use the FOG parser.  Check that the 'ply' package is installed.  The 'ordereddict' package is also required if running Python 2.6")
+
+    if options.version:
+      printVersion()
+
+    # the cxxtest builder relies on this behaviour! don't remove
+    if options.runner == 'none':
+        options.runner = None
+
+    if options.xunit_printer or options.runner == "XUnitPrinter":
+        options.xunit_printer=True
+        options.runner="XUnitPrinter"
+        if len(args) > 1:
+            if options.xunit_file == "":
+                if options.world == "":
+                    options.world = "cxxtest"
+                options.xunit_file="TEST-"+options.world+".xml"
+        elif options.xunit_file == "":
+            if options.world == "":
+                options.world = "cxxtest"
+            options.xunit_file="TEST-"+options.world+".xml"
+
+    if options.error_printer:
+      options.runner= "ErrorPrinter"
+      options.haveStandardLibrary = True
+    
+    if options.noStaticInit and (options.root or options.part):
+        abort( '--no-static-init cannot be used with --root/--part' )
+
+    if options.gui and not options.runner:
+        options.runner = 'StdioPrinter'
+
+    files = setFiles(args[1:])
+    if len(files) == 0 and not options.root:
+        sys.stderr.write(parser.error("No input files found"))
+
+    return files
+
+
+def printVersion():
+    '''Print CxxTest version and exit'''
+    sys.stdout.write( "This is CxxTest version %s.\n" % __release__.__version__ )
+    sys.exit(0)
+
+def setFiles(patterns ):
+    '''Set input files specified on command line'''
+    files = expandWildcards( patterns )
+    return files
+
+def expandWildcards( patterns ):
+    '''Expand all wildcards in an array (glob)'''
+    fileNames = []
+    for pathName in patterns:
+        patternFiles = glob.glob( pathName )
+        for fileName in patternFiles:
+            fileNames.append( fixBackslashes( fileName ) )
+    return fileNames
+
+def fixBackslashes( fileName ):
+    '''Convert backslashes to slashes in file name'''
+    return re.sub( r'\\', '/', fileName, 0 )
+
+
+def writeOutput():
+    '''Create output file'''
+    if options.templateFileName:
+        writeTemplateOutput()
+    else:
+        writeSimpleOutput()
+
+def writeSimpleOutput():
+    '''Create output not based on template'''
+    output = startOutputFile()
+    writePreamble( output )
+    if options.root or not options.part:
+        writeMain( output )
+
+    if len(suites) > 0:
+        output.write("bool "+suites[0]['object']+"_init = false;\n")
+
+    writeWorld( output )
+    output.close()
+
+include_re = re.compile( r"\s*\#\s*include\s+<cxxtest/" )
+preamble_re = re.compile( r"^\s*<CxxTest\s+preamble>\s*$" )
+world_re = re.compile( r"^\s*<CxxTest\s+world>\s*$" )
+def writeTemplateOutput():
+    '''Create output based on template file'''
+    template = open(options.templateFileName)
+    output = startOutputFile()
+    while 1:
+        line = template.readline()
+        if not line:
+            break;
+        if include_re.search( line ):
+            writePreamble( output )
+            output.write( line )
+        elif preamble_re.search( line ):
+            writePreamble( output )
+        elif world_re.search( line ):
+            if len(suites) > 0:
+                output.write("bool "+suites[0]['object']+"_init = false;\n")
+            writeWorld( output )
+        else:
+            output.write( line )
+    template.close()
+    output.close()
+
+def startOutputFile():
+    '''Create output file and write header'''
+    if options.outputFileName is not None:
+        output = open( options.outputFileName, 'w' )
+    else:
+        output = sys.stdout
+    output.write( "/* Generated file, do not edit */\n\n" )
+    return output
+
+def writePreamble( output ):
+    '''Write the CxxTest header (#includes and #defines)'''
+    global wrotePreamble
+    if wrotePreamble: return
+    output.write( "#ifndef CXXTEST_RUNNING\n" )
+    output.write( "#define CXXTEST_RUNNING\n" )
+    output.write( "#endif\n" )
+    output.write( "\n" )
+    if options.xunit_printer:
+        output.write( "#include <fstream>\n" )
+    if options.haveStandardLibrary:
+        output.write( "#define _CXXTEST_HAVE_STD\n" )
+    if options.haveExceptionHandling:
+        output.write( "#define _CXXTEST_HAVE_EH\n" )
+    if options.abortOnFail:
+        output.write( "#define _CXXTEST_ABORT_TEST_ON_FAIL\n" )
+    if options.longlong:
+        output.write( "#define _CXXTEST_LONGLONG %s\n" % options.longlong )
+    #if options.factor:
+        #output.write( "#define _CXXTEST_FACTOR\n" )
+    for header in options.headers:
+        output.write( "#include \"%s\"\n" % header )
+    output.write( "#include <cxxtest/TestListener.h>\n" )
+    output.write( "#include <cxxtest/TestTracker.h>\n" )
+    output.write( "#include <cxxtest/TestRunner.h>\n" )
+    output.write( "#include <cxxtest/RealDescriptions.h>\n" )
+    output.write( "#include <cxxtest/TestMain.h>\n" )
+    if options.runner:
+        output.write( "#include <cxxtest/%s.h>\n" % options.runner )
+    if options.gui:
+        output.write( "#include <cxxtest/%s.h>\n" % options.gui )
+    output.write( "\n" )
+    wrotePreamble = 1
+
+def writeMain( output ):
+    '''Write the main() function for the test runner'''
+    if not (options.gui or options.runner):
+       return
+    output.write( 'int %s( int argc, char *argv[] ) {\n' % options.main )
+    output.write( ' int status;\n' )
+    if options.noStaticInit:
+        output.write( ' CxxTest::initialize();\n' )
+    if options.gui:
+        tester_t = "CxxTest::GuiTuiRunner<CxxTest::%s, CxxTest::%s> " % (options.gui, options.runner)
+    else:
+        tester_t = "CxxTest::%s" % (options.runner)
+    if options.xunit_printer:
+       output.write( '    std::ofstream ofstr("%s");\n' % options.xunit_file )
+       output.write( '    %s tmp(ofstr);\n' % tester_t )
+       output.write( '    CxxTest::RealWorldDescription::_worldName = "%s";\n' % options.world )
+    else:
+       output.write( '    %s tmp;\n' % tester_t )
+    output.write( '    status = CxxTest::Main<%s>( tmp, argc, argv );\n' % tester_t )
+    output.write( '    return status;\n')
+    output.write( '}\n' )
+
+
+def writeWorld( output ):
+    '''Write the world definitions'''
+    global wroteWorld
+    if wroteWorld: return
+    writePreamble( output )
+    writeSuites( output )
+    if options.root or not options.part:
+        writeRoot( output )
+        writeWorldDescr( output )
+    if options.noStaticInit:
+        writeInitialize( output )
+    wroteWorld = 1
+
+def writeSuites(output):
+    '''Write all TestDescriptions and SuiteDescriptions'''
+    for suite in suites:
+        writeInclude( output, suite['file'] )
+        if isGenerated(suite):
+            generateSuite( output, suite )
+        if isDynamic(suite):
+            writeSuitePointer( output, suite )
+        else:
+            writeSuiteObject( output, suite )
+        writeTestList( output, suite )
+        writeSuiteDescription( output, suite )
+        writeTestDescriptions( output, suite )
+
+def isGenerated(suite):
+    '''Checks whether a suite class should be created'''
+    return suite['generated']
+
+def isDynamic(suite):
+    '''Checks whether a suite is dynamic'''
+    return 'create' in suite
+
+def writeInclude(output, file):
+    '''Add #include "file" statement'''
+    global lastIncluded
+    if file == lastIncluded: return
+    output.writelines( [ '#include "', file, '"\n\n' ] )
+    lastIncluded = file
+
+def generateSuite( output, suite ):
+    '''Write a suite declared with CXXTEST_SUITE()'''
+    output.write( 'class %s : public CxxTest::TestSuite {\n' % suite['name'] )
+    output.write( 'public:\n' )
+    for line in suite['lines']:
+        output.write(line)
+    output.write( '};\n\n' )
+
+def writeSuitePointer( output, suite ):
+    '''Create static suite pointer object for dynamic suites'''
+    if options.noStaticInit:
+        output.write( 'static %s *%s;\n\n' % (suite['name'], suite['object']) )
+    else:
+        output.write( 'static %s *%s = 0;\n\n' % (suite['name'], suite['object']) )
+
+def writeSuiteObject( output, suite ):
+    '''Create static suite object for non-dynamic suites'''
+    output.writelines( [ "static ", suite['name'], " ", suite['object'], ";\n\n" ] )
+
+def writeTestList( output, suite ):
+    '''Write the head of the test linked list for a suite'''
+    if options.noStaticInit:
+        output.write( 'static CxxTest::List %s;\n' % suite['tlist'] )
+    else:
+        output.write( 'static CxxTest::List %s = { 0, 0 };\n' % suite['tlist'] )
+
+def writeWorldDescr( output ):
+    '''Write the static name of the world name'''
+    if options.noStaticInit:
+        output.write( 'const char* CxxTest::RealWorldDescription::_worldName;\n' )
+    else:
+        output.write( 'const char* CxxTest::RealWorldDescription::_worldName = "cxxtest";\n' )
+
+def writeTestDescriptions( output, suite ):
+    '''Write all test descriptions for a suite'''
+    for test in suite['tests']:
+        writeTestDescription( output, suite, test )
+
+def writeTestDescription( output, suite, test ):
+    '''Write test description object'''
+    output.write( 'static class %s : public CxxTest::RealTestDescription {\n' % test['class'] )
+    output.write( 'public:\n' )
+    if not options.noStaticInit:
+        output.write( ' %s() : CxxTest::RealTestDescription( %s, %s, %s, "%s" ) {}\n' %
+                      (test['class'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
+    output.write( ' void runTest() { %s }\n' % runBody( suite, test ) )
+    output.write( '} %s;\n\n' % test['object'] )
+
+def runBody( suite, test ):
+    '''Body of TestDescription::run()'''
+    if isDynamic(suite): return dynamicRun( suite, test )
+    else: return staticRun( suite, test )
+
+def dynamicRun( suite, test ):
+    '''Body of TestDescription::run() for test in a dynamic suite'''
+    return 'if ( ' + suite['object'] + ' ) ' + suite['object'] + '->' + test['name'] + '();'
+    
+def staticRun( suite, test ):
+    '''Body of TestDescription::run() for test in a non-dynamic suite'''
+    return suite['object'] + '.' + test['name'] + '();'
+    
+def writeSuiteDescription( output, suite ):
+    '''Write SuiteDescription object'''
+    if isDynamic( suite ):
+        writeDynamicDescription( output, suite )
+    else:
+        writeStaticDescription( output, suite )
+
+def writeDynamicDescription( output, suite ):
+    '''Write SuiteDescription for a dynamic suite'''
+    output.write( 'CxxTest::DynamicSuiteDescription<%s> %s' % (suite['name'], suite['dobject']) )
+    if not options.noStaticInit:
+        output.write( '( %s, %s, "%s", %s, %s, %s, %s )' %
+                      (suite['cfile'], suite['line'], suite['name'], suite['tlist'],
+                       suite['object'], suite['create'], suite['destroy']) )
+    output.write( ';\n\n' )
+
+def writeStaticDescription( output, suite ):
+    '''Write SuiteDescription for a static suite'''
+    output.write( 'CxxTest::StaticSuiteDescription %s' % suite['dobject'] )
+    if not options.noStaticInit:
+        output.write( '( %s, %s, "%s", %s, %s )' %
+                      (suite['cfile'], suite['line'], suite['name'], suite['object'], suite['tlist']) )
+    output.write( ';\n\n' )
+
+def writeRoot(output):
+    '''Write static members of CxxTest classes'''
+    output.write( '#include <cxxtest/Root.cpp>\n' )
+
+def writeInitialize(output):
+    '''Write CxxTest::initialize(), which replaces static initialization'''
+    output.write( 'namespace CxxTest {\n' )
+    output.write( ' void initialize()\n' )
+    output.write( ' {\n' )
+    for suite in suites:
+        output.write( '  %s.initialize();\n' % suite['tlist'] )
+        if isDynamic(suite):
+            output.write( '  %s = 0;\n' % suite['object'] )
+            output.write( '  %s.initialize( %s, %s, "%s", %s, %s, %s, %s );\n' %
+                          (suite['dobject'], suite['cfile'], suite['line'], suite['name'],
+                           suite['tlist'], suite['object'], suite['create'], suite['destroy']) )
+        else:
+            output.write( '  %s.initialize( %s, %s, "%s", %s, %s );\n' %
+                          (suite['dobject'], suite['cfile'], suite['line'], suite['name'],
+                           suite['object'], suite['tlist']) )
+
+        for test in suite['tests']:
+            output.write( '  %s.initialize( %s, %s, %s, "%s" );\n' %
+                          (test['object'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
+
+    output.write( ' }\n' )
+    output.write( '}\n' )
+
diff --git a/tools/cxxtest/python/cxxtest/cxxtestgen.pyc b/tools/cxxtest/python/cxxtest/cxxtestgen.pyc
new file mode 100644 (file)
index 0000000..8ef0247
Binary files /dev/null and b/tools/cxxtest/python/cxxtest/cxxtestgen.pyc differ
diff --git a/tools/cxxtest/python/python3/cxxtest/__init__.py b/tools/cxxtest/python/python3/cxxtest/__init__.py
new file mode 100644 (file)
index 0000000..e9f6d13
--- /dev/null
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+"""cxxtest: A Python package that supports the CxxTest test framework for C/C++.
+
+.. _CxxTest: http://cxxtest.tigris.org/
+
+CxxTest is a unit testing framework for C++ that is similar in
+spirit to JUnit, CppUnit, and xUnit. CxxTest is easy to use because
+it does not require precompiling a CxxTest testing library, it
+employs no advanced features of C++ (e.g. RTTI) and it supports a
+very flexible form of test discovery.
+
+The cxxtest Python package includes capabilities for parsing C/C++ source files and generating
+CxxTest drivers.
+"""
+
+from cxxtest.__release__ import __version__, __date__
+__date__
+__version__
+
+__maintainer__ = "William E. Hart"
+__maintainer_email__ = "whart222@gmail.com"
+__license__ = "LGPL"
+__url__ = "http://cxxtest.tigris.org/"
+
+from cxxtest.cxxtestgen import *
diff --git a/tools/cxxtest/python/python3/cxxtest/__release__.py b/tools/cxxtest/python/python3/cxxtest/__release__.py
new file mode 100644 (file)
index 0000000..a949226
--- /dev/null
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+""" Release Information for cxxtest """
+
+__version__ = '4.0.2'
+__date__ = "2012-01-02"
diff --git a/tools/cxxtest/python/python3/cxxtest/cxx_parser.py b/tools/cxxtest/python/python3/cxxtest/cxx_parser.py
new file mode 100644 (file)
index 0000000..85b0149
--- /dev/null
@@ -0,0 +1,2189 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+# vim: fileencoding=utf-8
+
+#
+# This is a PLY parser for the entire ANSI C++ grammar.  This grammar was 
+# adapted from the FOG grammar developed by E. D. Willink.  See
+#
+#    http://www.computing.surrey.ac.uk/research/dsrg/fog/
+#
+# for further details.
+#
+# The goal of this grammar is to extract information about class, function and
+# class method declarations, along with their associated scope.  Thus, this 
+# grammar can be used to analyze classes in an inheritance heirarchy, and then
+# enumerate the methods in a derived class.
+#
+# This grammar parses blocks of <>, (), [] and {} in a generic manner.  Thus,
+# There are several capabilities that this grammar does not support:
+#
+# 1. Ambiguous template specification.  This grammar cannot parse template
+#       specifications that do not have paired <>'s in their declaration.  In
+#       particular, ambiguous declarations like
+#
+#           foo<A, c<3 >();
+#
+#       cannot be correctly parsed.
+#
+# 2. Template class specialization.  Although the goal of this grammar is to
+#       extract class information, specialization of templated classes is
+#       not supported.  When a template class definition is parsed, it's 
+#       declaration is archived without information about the template
+#       parameters.  Class specializations will be stored separately, and 
+#       thus they can be processed after the fact.  However, this grammar
+#       does not attempt to correctly process properties of class inheritence
+#       when template class specialization is employed.
+#
+
+#
+# TODO: document usage of this file
+#
+
+
+
+import os
+import ply.lex as lex
+import ply.yacc as yacc
+import re
+try:
+    from collections import OrderedDict
+except ImportError:
+    from ordereddict import OrderedDict
+
+lexer = None
+scope_lineno = 0
+identifier_lineno = {}
+_parse_info=None
+_parsedata=None
+noExceptionLogic = True
+
+def ply_init(data):
+    global _parsedata
+    _parsedata=data
+
+
+class Scope(object):
+
+    def __init__(self,name,abs_name,scope_t,base_classes,lineno):
+        self.function=[]
+        self.name=name
+        self.scope_t=scope_t
+        self.sub_scopes=[]
+        self.base_classes=base_classes
+        self.abs_name=abs_name
+        self.lineno=lineno
+   
+    def insert(self,scope):
+        self.sub_scopes.append(scope)
+
+
+class CppInfo(object):
+
+    def __init__(self, filter=None):
+        self.verbose=0
+        if filter is None:
+            self.filter=re.compile("[Tt][Ee][Ss][Tt]|createSuite|destroySuite")
+        else:
+            self.filter=filter
+        self.scopes=[""]
+        self.index=OrderedDict()
+        self.index[""]=Scope("","::","namespace",[],1)
+        self.function=[]
+
+    def push_scope(self,ns,scope_t,base_classes=[]):
+        name = self.scopes[-1]+"::"+ns
+        if self.verbose>=2:
+            print("-- Starting "+scope_t+" "+name)
+        self.scopes.append(name)
+        self.index[name] = Scope(ns,name,scope_t,base_classes,scope_lineno-1)
+
+    def pop_scope(self):
+        scope = self.scopes.pop()
+        if self.verbose>=2:
+            print("-- Stopping "+scope)
+        return scope
+
+    def add_function(self, fn):
+        fn = str(fn)
+        if self.filter.search(fn):
+            self.index[self.scopes[-1]].function.append((fn, identifier_lineno.get(fn,lexer.lineno-1)))
+            tmp = self.scopes[-1]+"::"+fn
+            if self.verbose==2:
+                print("-- Function declaration "+fn+"  "+tmp)
+            elif self.verbose==1:
+                print("-- Function declaration "+tmp)
+
+    def get_functions(self,name,quiet=False):
+        if name == "::":
+            name = ""
+        scope = self.index[name]
+        fns=scope.function
+        for key in scope.base_classes:
+            cname = self.find_class(key,scope)
+            if cname is None:
+                if not quiet:
+                    print("Defined classes: ",list(self.index.keys()))
+                    print("WARNING: Unknown class "+key)
+            else:
+                fns += self.get_functions(cname,quiet)
+        return fns
+        
+    def find_class(self,name,scope):
+        if ':' in name:
+            if name in self.index:
+                return name
+            else:
+                return None           
+        tmp = scope.abs_name.split(':')
+        name1 = ":".join(tmp[:-1] + [name])
+        if name1 in self.index:
+            return name1
+        name2 = "::"+name
+        if name2 in self.index:
+            return name2
+        return None
+
+    def __repr__(self):
+        return str(self)
+
+    def is_baseclass(self,cls,base):
+        '''Returns true if base is a base-class of cls'''
+        if cls in self.index:
+            bases = self.index[cls]
+        elif "::"+cls in self.index:
+            bases = self.index["::"+cls]
+        else:
+            return False
+            #raise IOError, "Unknown class "+cls
+        if base in bases.base_classes:
+            return True
+        for name in bases.base_classes:
+            if self.is_baseclass(name,base):
+                return True
+        return False
+
+    def __str__(self):
+        ans=""
+        keys = list(self.index.keys())
+        keys.sort()
+        for key in keys:
+            scope = self.index[key]
+            ans += scope.scope_t+" "+scope.abs_name+"\n"
+            if scope.scope_t == "class":
+                ans += "  Base Classes: "+str(scope.base_classes)+"\n"
+                for fn in self.get_functions(scope.abs_name):
+                    ans += "  "+fn+"\n"
+            else:
+                for fn in scope.function:
+                    ans += "  "+fn+"\n"
+        return ans
+
+
+def flatten(x):
+    """Flatten nested list"""
+    try:
+        strtypes = str
+    except: # for python3 etc
+        strtypes = (str, bytes)
+
+    result = []
+    for el in x:
+        if hasattr(el, "__iter__") and not isinstance(el, strtypes):
+            result.extend(flatten(el))
+        else:
+            result.append(el)
+    return result
+
+#
+# The lexer (and/or a preprocessor) is expected to identify the following
+#
+#  Punctuation:
+#
+#
+literals = "+-*/%^&|~!<>=:()?.\'\"\\@$;,"
+
+#
+reserved = {
+    'private' : 'PRIVATE',
+    'protected' : 'PROTECTED',
+    'public' : 'PUBLIC',
+
+    'bool' : 'BOOL',
+    'char' : 'CHAR',
+    'double' : 'DOUBLE',
+    'float' : 'FLOAT',
+    'int' : 'INT',
+    'long' : 'LONG',
+    'short' : 'SHORT',
+    'signed' : 'SIGNED',
+    'unsigned' : 'UNSIGNED',
+    'void' : 'VOID',
+    'wchar_t' : 'WCHAR_T',
+
+    'class' : 'CLASS',
+    'enum' : 'ENUM',
+    'namespace' : 'NAMESPACE',
+    'struct' : 'STRUCT',
+    'typename' : 'TYPENAME',
+    'union' : 'UNION',
+
+    'const' : 'CONST',
+    'volatile' : 'VOLATILE',
+
+    'auto' : 'AUTO',
+    'explicit' : 'EXPLICIT',
+    'export' : 'EXPORT',
+    'extern' : 'EXTERN',
+    '__extension__' : 'EXTENSION',
+    'friend' : 'FRIEND',
+    'inline' : 'INLINE',
+    'mutable' : 'MUTABLE',
+    'register' : 'REGISTER',
+    'static' : 'STATIC',
+    'template' : 'TEMPLATE',
+    'typedef' : 'TYPEDEF',
+    'using' : 'USING',
+    'virtual' : 'VIRTUAL',
+
+    'asm' : 'ASM',
+    'break' : 'BREAK',
+    'case' : 'CASE',
+    'catch' : 'CATCH',
+    'const_cast' : 'CONST_CAST',
+    'continue' : 'CONTINUE',
+    'default' : 'DEFAULT',
+    'delete' : 'DELETE',
+    'do' : 'DO',
+    'dynamic_cast' : 'DYNAMIC_CAST',
+    'else' : 'ELSE',
+    'false' : 'FALSE',
+    'for' : 'FOR',
+    'goto' : 'GOTO',
+    'if' : 'IF',
+    'new' : 'NEW',
+    'operator' : 'OPERATOR',
+    'reinterpret_cast' : 'REINTERPRET_CAST',
+    'return' : 'RETURN',
+    'sizeof' : 'SIZEOF',
+    'static_cast' : 'STATIC_CAST',
+    'switch' : 'SWITCH',
+    'this' : 'THIS',
+    'throw' : 'THROW',
+    'true' : 'TRUE',
+    'try' : 'TRY',
+    'typeid' : 'TYPEID',
+    'while' : 'WHILE',
+    '"C"' : 'CLiteral',
+    '"C++"' : 'CppLiteral',
+
+    '__attribute__' : 'ATTRIBUTE',
+    '__cdecl__' : 'CDECL',
+    '__typeof' : 'uTYPEOF',
+    'typeof' : 'TYPEOF', 
+
+    'CXXTEST_STD' : 'CXXTEST_STD'
+}
+   
+tokens = [
+    "CharacterLiteral",
+    "FloatingLiteral",
+    "Identifier",
+    "IntegerLiteral",
+    "StringLiteral",
+ "RBRACE",
+ "LBRACE",
+ "RBRACKET",
+ "LBRACKET",
+ "ARROW",
+ "ARROW_STAR",
+ "DEC",
+ "EQ",
+ "GE",
+ "INC",
+ "LE",
+ "LOG_AND",
+ "LOG_OR",
+ "NE",
+ "SHL",
+ "SHR",
+ "ASS_ADD",
+ "ASS_AND",
+ "ASS_DIV",
+ "ASS_MOD",
+ "ASS_MUL",
+ "ASS_OR",
+ "ASS_SHL",
+ "ASS_SHR",
+ "ASS_SUB",
+ "ASS_XOR",
+ "DOT_STAR",
+ "ELLIPSIS",
+ "SCOPE",
+] + list(reserved.values())
+
+t_ignore = " \t\r"
+
+t_LBRACE = r"(\{)|(<%)"
+t_RBRACE = r"(\})|(%>)"
+t_LBRACKET = r"(\[)|(<:)"
+t_RBRACKET = r"(\])|(:>)"
+t_ARROW = r"->"
+t_ARROW_STAR = r"->\*"
+t_DEC = r"--"
+t_EQ = r"=="
+t_GE = r">="
+t_INC = r"\+\+"
+t_LE = r"<="
+t_LOG_AND = r"&&"
+t_LOG_OR = r"\|\|"
+t_NE = r"!="
+t_SHL = r"<<"
+t_SHR = r">>"
+t_ASS_ADD = r"\+="
+t_ASS_AND = r"&="
+t_ASS_DIV = r"/="
+t_ASS_MOD = r"%="
+t_ASS_MUL = r"\*="
+t_ASS_OR  = r"\|="
+t_ASS_SHL = r"<<="
+t_ASS_SHR = r">>="
+t_ASS_SUB = r"-="
+t_ASS_XOR = r"^="
+t_DOT_STAR = r"\.\*"
+t_ELLIPSIS = r"\.\.\."
+t_SCOPE = r"::"
+
+# Discard comments
+def t_COMMENT(t):
+    r'(/\*(.|\n)*?\*/)|(//.*?\n)|(\#.*?\n)'
+    t.lexer.lineno += t.value.count("\n")
+
+t_IntegerLiteral = r'(0x[0-9A-F]+)|([0-9]+(L){0,1})'
+t_FloatingLiteral = r"[0-9]+[eE\.\+-]+[eE\.\+\-0-9]+"
+t_CharacterLiteral = r'\'([^\'\\]|\\.)*\''
+#t_StringLiteral = r'"([^"\\]|\\.)*"'
+def t_StringLiteral(t):
+    r'"([^"\\]|\\.)*"'
+    t.type = reserved.get(t.value,'StringLiteral')
+    return t
+
+def t_Identifier(t):
+    r"[a-zA-Z_][a-zA-Z_0-9\.]*"
+    t.type = reserved.get(t.value,'Identifier')
+    return t
+
+
+def t_error(t):
+    print("Illegal character '%s'" % t.value[0])
+    #raise IOError, "Parse error"
+    #t.lexer.skip()
+
+def t_newline(t):
+    r'[\n]+'
+    t.lexer.lineno += len(t.value)
+
+precedence = (
+    ( 'right', 'SHIFT_THERE', 'REDUCE_HERE_MOSTLY', 'SCOPE'),
+    ( 'nonassoc', 'ELSE', 'INC', 'DEC', '+', '-', '*', '&', 'LBRACKET', 'LBRACE', '<', ':', ')')
+    )
+
+start = 'translation_unit'
+
+#
+#  The %prec resolves the 14.2-3 ambiguity:
+#  Identifier '<' is forced to go through the is-it-a-template-name test
+#  All names absorb TEMPLATE with the name, so that no template_test is 
+#  performed for them.  This requires all potential declarations within an 
+#  expression to perpetuate this policy and thereby guarantee the ultimate 
+#  coverage of explicit_instantiation.
+#
+#  The %prec also resolves a conflict in identifier : which is forced to be a 
+#  shift of a label for a labeled-statement rather than a reduction for the 
+#  name of a bit-field or generalised constructor.  This is pretty dubious 
+#  syntactically but correct for all semantic possibilities.  The shift is 
+#  only activated when the ambiguity exists at the start of a statement. 
+#  In this context a bit-field declaration or constructor definition are not 
+#  allowed.
+#
+
+def p_identifier(p):
+    '''identifier : Identifier
+    |               CXXTEST_STD '(' Identifier ')'
+    '''
+    if p[1][0] in ('t','T','c','d'):
+        identifier_lineno[p[1]] = p.lineno(1)
+    p[0] = p[1]
+
+def p_id(p):
+    '''id :                         identifier %prec SHIFT_THERE
+    |                               template_decl
+    |                               TEMPLATE id
+    '''
+    p[0] = get_rest(p)
+
+def p_global_scope(p):
+    '''global_scope :               SCOPE
+    '''
+    p[0] = get_rest(p)
+
+def p_id_scope(p):
+    '''id_scope : id SCOPE'''
+    p[0] = get_rest(p)
+
+def p_id_scope_seq(p):
+    '''id_scope_seq :                id_scope
+    |                                id_scope id_scope_seq
+    '''
+    p[0] = get_rest(p)
+
+#
+#  A :: B :: C; is ambiguous How much is type and how much name ?
+#  The %prec maximises the (type) length which is the 7.1-2 semantic constraint.
+#
+def p_nested_id(p):
+    '''nested_id :                  id %prec SHIFT_THERE
+    |                               id_scope nested_id
+    '''
+    p[0] = get_rest(p)
+
+def p_scoped_id(p):
+    '''scoped_id :                  nested_id
+    |                               global_scope nested_id
+    |                               id_scope_seq
+    |                               global_scope id_scope_seq
+    '''
+    global scope_lineno
+    scope_lineno = lexer.lineno
+    data = flatten(get_rest(p))
+    if data[0] != None:
+        p[0] = "".join(data)
+
+#
+#  destructor_id has to be held back to avoid a conflict with a one's 
+#  complement as per 5.3.1-9, It gets put back only when scoped or in a 
+#  declarator_id, which is only used as an explicit member name.
+#  Declarations of an unscoped destructor are always parsed as a one's 
+#  complement.
+#
+def p_destructor_id(p):
+    '''destructor_id :              '~' id
+    |                               TEMPLATE destructor_id
+    '''
+    p[0]=get_rest(p)
+
+#def p_template_id(p):
+#    '''template_id :                empty
+#    |                               TEMPLATE
+#    '''
+#    pass
+
+def p_template_decl(p):
+    '''template_decl :              identifier '<' nonlgt_seq_opt '>'
+    '''
+    #
+    # WEH: should we include the lt/gt symbols to indicate that this is a
+    # template class?  How is that going to be used later???
+    #
+    #p[0] = [p[1] ,"<",">"]
+    p[0] = p[1]
+
+def p_special_function_id(p):
+    '''special_function_id :        conversion_function_id
+    |                               operator_function_id
+    |                               TEMPLATE special_function_id
+    '''
+    p[0]=get_rest(p)
+
+def p_nested_special_function_id(p):
+    '''nested_special_function_id : special_function_id
+    |                               id_scope destructor_id
+    |                               id_scope nested_special_function_id
+    '''
+    p[0]=get_rest(p)
+
+def p_scoped_special_function_id(p):
+    '''scoped_special_function_id : nested_special_function_id
+    |                               global_scope nested_special_function_id
+    '''
+    p[0]=get_rest(p)
+
+# declarator-id is all names in all scopes, except reserved words
+def p_declarator_id(p):
+    '''declarator_id :              scoped_id
+    |                               scoped_special_function_id
+    |                               destructor_id
+    '''
+    p[0]=p[1]
+
+#
+# The standard defines pseudo-destructors in terms of type-name, which is 
+# class/enum/typedef, of which class-name is covered by a normal destructor. 
+# pseudo-destructors are supposed to support ~int() in templates, so the 
+# grammar here covers built-in names. Other names are covered by the lack 
+# of identifier/type discrimination.
+#
+def p_built_in_type_id(p):
+    '''built_in_type_id :           built_in_type_specifier
+    |                               built_in_type_id built_in_type_specifier
+    '''
+    pass
+
+def p_pseudo_destructor_id(p):
+    '''pseudo_destructor_id :       built_in_type_id SCOPE '~' built_in_type_id
+    |                               '~' built_in_type_id
+    |                               TEMPLATE pseudo_destructor_id
+    '''
+    pass
+
+def p_nested_pseudo_destructor_id(p):
+    '''nested_pseudo_destructor_id : pseudo_destructor_id
+    |                               id_scope nested_pseudo_destructor_id
+    '''
+    pass
+
+def p_scoped_pseudo_destructor_id(p):
+    '''scoped_pseudo_destructor_id : nested_pseudo_destructor_id
+    |                               global_scope scoped_pseudo_destructor_id
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.2 Lexical conventions
+#-------------------------------------------------------------------------------
+#
+
+def p_literal(p):
+    '''literal :                    IntegerLiteral
+    |                               CharacterLiteral
+    |                               FloatingLiteral
+    |                               StringLiteral
+    |                               TRUE
+    |                               FALSE
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.3 Basic concepts
+#-------------------------------------------------------------------------------
+def p_translation_unit(p):
+    '''translation_unit :           declaration_seq_opt
+    '''
+    pass
+
+#-------------------------------------------------------------------------------
+# A.4 Expressions
+#-------------------------------------------------------------------------------
+#
+#  primary_expression covers an arbitrary sequence of all names with the 
+#  exception of an unscoped destructor, which is parsed as its unary expression 
+#  which is the correct disambiguation (when ambiguous).  This eliminates the 
+#  traditional A(B) meaning A B ambiguity, since we never have to tack an A 
+#  onto the front of something that might start with (. The name length got 
+#  maximised ab initio. The downside is that semantic interpretation must split 
+#  the names up again.
+#
+#  Unification of the declaration and expression syntax means that unary and 
+#  binary pointer declarator operators:
+#      int * * name
+#  are parsed as binary and unary arithmetic operators (int) * (*name). Since 
+#  type information is not used
+#  ambiguities resulting from a cast
+#      (cast)*(value)
+#  are resolved to favour the binary rather than the cast unary to ease AST 
+#  clean-up. The cast-call ambiguity must be resolved to the cast to ensure 
+#  that (a)(b)c can be parsed.
+#
+#  The problem of the functional cast ambiguity
+#      name(arg)
+#  as call or declaration is avoided by maximising the name within the parsing 
+#  kernel. So  primary_id_expression picks up 
+#      extern long int const var = 5;
+#  as an assignment to the syntax parsed as "extern long int const var". The 
+#  presence of two names is parsed so that "extern long into const" is 
+#  distinguished from "var" considerably simplifying subsequent 
+#  semantic resolution.
+#
+#  The generalised name is a concatenation of potential type-names (scoped 
+#  identifiers or built-in sequences) plus optionally one of the special names 
+#  such as an operator-function-id, conversion-function-id or destructor as the 
+#  final name. 
+#
+
+def get_rest(p):
+    return [p[i] for i in range(1, len(p))]
+
+def p_primary_expression(p):
+    '''primary_expression :         literal
+    |                               THIS
+    |                               suffix_decl_specified_ids
+    |                               abstract_expression %prec REDUCE_HERE_MOSTLY
+    '''
+    p[0] = get_rest(p)
+
+#
+#  Abstract-expression covers the () and [] of abstract-declarators.
+#
+def p_abstract_expression(p):
+    '''abstract_expression :        parenthesis_clause
+    |                               LBRACKET bexpression_opt RBRACKET
+    |                               TEMPLATE abstract_expression
+    '''
+    pass
+
+def p_postfix_expression(p):
+    '''postfix_expression :         primary_expression
+    |                               postfix_expression parenthesis_clause
+    |                               postfix_expression LBRACKET bexpression_opt RBRACKET
+    |                               postfix_expression LBRACKET bexpression_opt RBRACKET attributes
+    |                               postfix_expression '.' declarator_id
+    |                               postfix_expression '.' scoped_pseudo_destructor_id
+    |                               postfix_expression ARROW declarator_id
+    |                               postfix_expression ARROW scoped_pseudo_destructor_id   
+    |                               postfix_expression INC
+    |                               postfix_expression DEC
+    |                               DYNAMIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               STATIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               REINTERPRET_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               CONST_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
+    |                               TYPEID parameters_clause
+    '''
+    #print "HERE",str(p[1])
+    p[0] = get_rest(p)
+
+def p_bexpression_opt(p):
+    '''bexpression_opt :            empty
+    |                               bexpression
+    '''
+    pass
+
+def p_bexpression(p):
+    '''bexpression :                nonbracket_seq
+    |                               nonbracket_seq bexpression_seq bexpression_clause nonbracket_seq_opt
+    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
+    '''
+    pass
+
+def p_bexpression_seq(p):
+    '''bexpression_seq :            empty
+    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
+    '''
+    pass
+
+def p_bexpression_clause(p):
+    '''bexpression_clause :          LBRACKET bexpression_opt RBRACKET
+    '''
+    pass
+
+
+
+def p_expression_list_opt(p):
+    '''expression_list_opt :        empty
+    |                               expression_list
+    '''
+    pass
+
+def p_expression_list(p):
+    '''expression_list :            assignment_expression
+    |                               expression_list ',' assignment_expression
+    '''
+    pass
+
+def p_unary_expression(p):
+    '''unary_expression :           postfix_expression
+    |                               INC cast_expression
+    |                               DEC cast_expression
+    |                               ptr_operator cast_expression
+    |                               suffix_decl_specified_scope star_ptr_operator cast_expression
+    |                               '+' cast_expression
+    |                               '-' cast_expression
+    |                               '!' cast_expression
+    |                               '~' cast_expression
+    |                               SIZEOF unary_expression
+    |                               new_expression
+    |                               global_scope new_expression
+    |                               delete_expression
+    |                               global_scope delete_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_delete_expression(p):
+    '''delete_expression :          DELETE cast_expression
+    '''
+    pass
+
+def p_new_expression(p):
+    '''new_expression :             NEW new_type_id new_initializer_opt
+    |                               NEW parameters_clause new_type_id new_initializer_opt
+    |                               NEW parameters_clause
+    |                               NEW parameters_clause parameters_clause new_initializer_opt
+    '''
+    pass
+
+def p_new_type_id(p):
+    '''new_type_id :                type_specifier ptr_operator_seq_opt
+    |                               type_specifier new_declarator
+    |                               type_specifier new_type_id
+    '''
+    pass
+
+def p_new_declarator(p):
+    '''new_declarator :             ptr_operator new_declarator
+    |                               direct_new_declarator
+    '''
+    pass
+
+def p_direct_new_declarator(p):
+    '''direct_new_declarator :      LBRACKET bexpression_opt RBRACKET
+    |                               direct_new_declarator LBRACKET bexpression RBRACKET
+    '''
+    pass
+
+def p_new_initializer_opt(p):
+    '''new_initializer_opt :        empty
+    |                               '(' expression_list_opt ')'
+    '''
+    pass
+
+#
+# cast-expression is generalised to support a [] as well as a () prefix. This covers the omission of 
+# DELETE[] which when followed by a parenthesised expression was ambiguous. It also covers the gcc 
+# indexed array initialisation for free.
+#
+def p_cast_expression(p):
+    '''cast_expression :            unary_expression
+    |                               abstract_expression cast_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_pm_expression(p):
+    '''pm_expression :              cast_expression
+    |                               pm_expression DOT_STAR cast_expression
+    |                               pm_expression ARROW_STAR cast_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_multiplicative_expression(p):
+    '''multiplicative_expression :  pm_expression
+    |                               multiplicative_expression star_ptr_operator pm_expression
+    |                               multiplicative_expression '/' pm_expression
+    |                               multiplicative_expression '%' pm_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_additive_expression(p):
+    '''additive_expression :        multiplicative_expression
+    |                               additive_expression '+' multiplicative_expression
+    |                               additive_expression '-' multiplicative_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_shift_expression(p):
+    '''shift_expression :           additive_expression
+    |                               shift_expression SHL additive_expression
+    |                               shift_expression SHR additive_expression
+    '''
+    p[0] = get_rest(p)
+
+#    |                               relational_expression '<' shift_expression
+#    |                               relational_expression '>' shift_expression
+#    |                               relational_expression LE shift_expression
+#    |                               relational_expression GE shift_expression
+def p_relational_expression(p):
+    '''relational_expression :      shift_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_equality_expression(p):
+    '''equality_expression :        relational_expression
+    |                               equality_expression EQ relational_expression
+    |                               equality_expression NE relational_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_and_expression(p):
+    '''and_expression :             equality_expression
+    |                               and_expression '&' equality_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_exclusive_or_expression(p):
+    '''exclusive_or_expression :    and_expression
+    |                               exclusive_or_expression '^' and_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_inclusive_or_expression(p):
+    '''inclusive_or_expression :    exclusive_or_expression
+    |                               inclusive_or_expression '|' exclusive_or_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_logical_and_expression(p):
+    '''logical_and_expression :     inclusive_or_expression
+    |                               logical_and_expression LOG_AND inclusive_or_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_logical_or_expression(p):
+    '''logical_or_expression :      logical_and_expression
+    |                               logical_or_expression LOG_OR logical_and_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_conditional_expression(p):
+    '''conditional_expression :     logical_or_expression
+    |                               logical_or_expression '?' expression ':' assignment_expression
+    '''
+    p[0] = get_rest(p)
+
+
+#
+# assignment-expression is generalised to cover the simple assignment of a braced initializer in order to 
+# contribute to the coverage of parameter-declaration and init-declaration.
+#
+#    |                               logical_or_expression assignment_operator assignment_expression
+def p_assignment_expression(p):
+    '''assignment_expression :      conditional_expression
+    |                               logical_or_expression assignment_operator nonsemicolon_seq
+    |                               logical_or_expression '=' braced_initializer
+    |                               throw_expression
+    '''
+    p[0]=get_rest(p)
+
+def p_assignment_operator(p):
+    '''assignment_operator :        '=' 
+                           | ASS_ADD
+                           | ASS_AND
+                           | ASS_DIV
+                           | ASS_MOD
+                           | ASS_MUL
+                           | ASS_OR
+                           | ASS_SHL
+                           | ASS_SHR
+                           | ASS_SUB
+                           | ASS_XOR
+    '''
+    pass
+
+#
+# expression is widely used and usually single-element, so the reductions are arranged so that a
+# single-element expression is returned as is. Multi-element expressions are parsed as a list that
+# may then behave polymorphically as an element or be compacted to an element.
+#
+
+def p_expression(p):
+    '''expression :                 assignment_expression
+    |                               expression_list ',' assignment_expression
+    '''
+    p[0] = get_rest(p)
+
+def p_constant_expression(p):
+    '''constant_expression :        conditional_expression
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.5 Statements
+#---------------------------------------------------------------------------------------------------
+# Parsing statements is easy once simple_declaration has been generalised to cover expression_statement.
+#
+#
+# The use of extern here is a hack.  The 'extern "C" {}' block gets parsed
+# as a function, so when nested 'extern "C"' declarations exist, they don't
+# work because the block is viewed as a list of statements... :(
+#
+def p_statement(p):
+    '''statement :                  compound_statement
+    |                               declaration_statement
+    |                               try_block
+    |                               labeled_statement
+    |                               selection_statement
+    |                               iteration_statement
+    |                               jump_statement
+    '''
+    pass
+
+def p_compound_statement(p):
+    '''compound_statement :         LBRACE statement_seq_opt RBRACE
+    '''
+    pass
+
+def p_statement_seq_opt(p):
+    '''statement_seq_opt :          empty
+    |                               statement_seq_opt statement
+    '''
+    pass
+
+#
+#  The dangling else conflict is resolved to the innermost if.
+#
+def p_selection_statement(p):
+    '''selection_statement :        IF '(' condition ')' statement    %prec SHIFT_THERE
+    |                               IF '(' condition ')' statement ELSE statement
+    |                               SWITCH '(' condition ')' statement
+    '''
+    pass
+
+def p_condition_opt(p):
+    '''condition_opt :              empty
+    |                               condition
+    '''
+    pass
+
+def p_condition(p):
+    '''condition :                  nonparen_seq
+    |                               nonparen_seq condition_seq parameters_clause nonparen_seq_opt
+    |                               condition_seq parameters_clause nonparen_seq_opt
+    '''
+    pass
+
+def p_condition_seq(p):
+    '''condition_seq :              empty
+    |                               condition_seq parameters_clause nonparen_seq_opt
+    '''
+    pass
+
+def p_labeled_statement(p):
+    '''labeled_statement :          identifier ':' statement
+    |                               CASE constant_expression ':' statement
+    |                               DEFAULT ':' statement
+    '''
+    pass
+
+def p_try_block(p):
+    '''try_block :                  TRY compound_statement handler_seq
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_jump_statement(p):
+    '''jump_statement :             BREAK ';'
+    |                               CONTINUE ';'
+    |                               RETURN nonsemicolon_seq ';'
+    |                               GOTO identifier ';'
+    '''
+    pass
+
+def p_iteration_statement(p):
+    '''iteration_statement :        WHILE '(' condition ')' statement
+    |                               DO statement WHILE '(' expression ')' ';'
+    |                               FOR '(' nonparen_seq_opt ')' statement
+    '''
+    pass
+
+def p_declaration_statement(p):
+    '''declaration_statement :      block_declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.6 Declarations
+#---------------------------------------------------------------------------------------------------
+def p_compound_declaration(p):
+    '''compound_declaration :       LBRACE declaration_seq_opt RBRACE                            
+    '''
+    pass
+
+def p_declaration_seq_opt(p):
+    '''declaration_seq_opt :        empty
+    |                               declaration_seq_opt declaration
+    '''
+    pass
+
+def p_declaration(p):
+    '''declaration :                block_declaration
+    |                               function_definition
+    |                               template_declaration
+    |                               explicit_specialization
+    |                               specialised_declaration
+    '''
+    pass
+
+def p_specialised_declaration(p):
+    '''specialised_declaration :    linkage_specification
+    |                               namespace_definition
+    |                               TEMPLATE specialised_declaration
+    '''
+    pass
+
+def p_block_declaration(p):
+    '''block_declaration :          simple_declaration
+    |                               specialised_block_declaration
+    '''
+    pass
+
+def p_specialised_block_declaration(p):
+    '''specialised_block_declaration :      asm_definition
+    |                               namespace_alias_definition
+    |                               using_declaration
+    |                               using_directive
+    |                               TEMPLATE specialised_block_declaration
+    '''
+    pass
+
+def p_simple_declaration(p):
+    '''simple_declaration :         ';'
+    |                               init_declaration ';'
+    |                               init_declarations ';'
+    |                               decl_specifier_prefix simple_declaration
+    '''
+    global _parse_info
+    if len(p) == 3:
+        if p[2] == ";":
+            decl = p[1]
+        else:
+            decl = p[2]
+        if decl is not None:
+            fp = flatten(decl)
+            if len(fp) >= 2 and fp[0] is not None and fp[0]!="operator" and fp[1] == '(':
+                p[0] = fp[0]
+                _parse_info.add_function(fp[0])
+
+#
+#  A decl-specifier following a ptr_operator provokes a shift-reduce conflict for * const name which is resolved in favour of the pointer, and implemented by providing versions of decl-specifier guaranteed not to start with a cv_qualifier.  decl-specifiers are implemented type-centrically. That is the semantic constraint that there must be a type is exploited to impose structure, but actually eliminate very little syntax. built-in types are multi-name and so need a different policy.
+#
+#  non-type decl-specifiers are bound to the left-most type in a decl-specifier-seq, by parsing from the right and attaching suffixes to the right-hand type. Finally residual prefixes attach to the left.                
+#
+def p_suffix_built_in_decl_specifier_raw(p):
+    '''suffix_built_in_decl_specifier_raw : built_in_type_specifier
+    |                               suffix_built_in_decl_specifier_raw built_in_type_specifier
+    |                               suffix_built_in_decl_specifier_raw decl_specifier_suffix
+    '''
+    pass
+
+def p_suffix_built_in_decl_specifier(p):
+    '''suffix_built_in_decl_specifier :     suffix_built_in_decl_specifier_raw
+    |                               TEMPLATE suffix_built_in_decl_specifier
+    '''
+    pass
+
+#    |                                       id_scope_seq
+#    |                                       SCOPE id_scope_seq
+def p_suffix_named_decl_specifier(p):
+    '''suffix_named_decl_specifier :        scoped_id 
+    |                               elaborate_type_specifier 
+    |                               suffix_named_decl_specifier decl_specifier_suffix
+    '''
+    p[0]=get_rest(p)
+
+def p_suffix_named_decl_specifier_bi(p):
+    '''suffix_named_decl_specifier_bi :     suffix_named_decl_specifier
+    |                               suffix_named_decl_specifier suffix_built_in_decl_specifier_raw
+    '''
+    p[0] = get_rest(p)
+    #print "HERE",get_rest(p)
+
+def p_suffix_named_decl_specifiers(p):
+    '''suffix_named_decl_specifiers :       suffix_named_decl_specifier_bi
+    |                               suffix_named_decl_specifiers suffix_named_decl_specifier_bi
+    '''
+    p[0] = get_rest(p)
+
+def p_suffix_named_decl_specifiers_sf(p):
+    '''suffix_named_decl_specifiers_sf :    scoped_special_function_id
+    |                               suffix_named_decl_specifiers
+    |                               suffix_named_decl_specifiers scoped_special_function_id
+    '''
+    #print "HERE",get_rest(p)
+    p[0] = get_rest(p)
+
+def p_suffix_decl_specified_ids(p):
+    '''suffix_decl_specified_ids :          suffix_built_in_decl_specifier
+    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers_sf
+    |                               suffix_named_decl_specifiers_sf
+    '''
+    if len(p) == 3:
+        p[0] = p[2]
+    else:
+        p[0] = p[1]
+
+def p_suffix_decl_specified_scope(p):
+    '''suffix_decl_specified_scope : suffix_named_decl_specifiers SCOPE
+    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers SCOPE
+    |                               suffix_built_in_decl_specifier SCOPE
+    '''
+    p[0] = get_rest(p)
+
+def p_decl_specifier_affix(p):
+    '''decl_specifier_affix :       storage_class_specifier
+    |                               function_specifier
+    |                               FRIEND
+    |                               TYPEDEF
+    |                               cv_qualifier
+    '''
+    pass
+
+def p_decl_specifier_suffix(p):
+    '''decl_specifier_suffix :      decl_specifier_affix
+    '''
+    pass
+
+def p_decl_specifier_prefix(p):
+    '''decl_specifier_prefix :      decl_specifier_affix
+    |                               TEMPLATE decl_specifier_prefix
+    '''
+    pass
+
+def p_storage_class_specifier(p):
+    '''storage_class_specifier :    REGISTER 
+    |                               STATIC 
+    |                               MUTABLE
+    |                               EXTERN                  %prec SHIFT_THERE
+    |                               EXTENSION
+    |                               AUTO
+    '''
+    pass
+
+def p_function_specifier(p):
+    '''function_specifier :         EXPLICIT
+    |                               INLINE
+    |                               VIRTUAL
+    '''
+    pass
+
+def p_type_specifier(p):
+    '''type_specifier :             simple_type_specifier
+    |                               elaborate_type_specifier
+    |                               cv_qualifier
+    '''
+    pass
+
+def p_elaborate_type_specifier(p):
+    '''elaborate_type_specifier :   class_specifier
+    |                               enum_specifier
+    |                               elaborated_type_specifier
+    |                               TEMPLATE elaborate_type_specifier
+    '''
+    pass
+
+def p_simple_type_specifier(p):
+    '''simple_type_specifier :      scoped_id
+    |                               scoped_id attributes
+    |                               built_in_type_specifier
+    '''
+    p[0] = p[1]
+
+def p_built_in_type_specifier(p):
+    '''built_in_type_specifier : Xbuilt_in_type_specifier
+    |                            Xbuilt_in_type_specifier attributes
+    '''
+    pass
+
+def p_attributes(p):
+    '''attributes :                 attribute
+    |                               attributes attribute
+    '''
+    pass
+
+def p_attribute(p):
+    '''attribute :                  ATTRIBUTE '(' parameters_clause ')'
+    '''
+
+def p_Xbuilt_in_type_specifier(p):
+    '''Xbuilt_in_type_specifier :    CHAR 
+    | WCHAR_T 
+    | BOOL 
+    | SHORT 
+    | INT 
+    | LONG 
+    | SIGNED 
+    | UNSIGNED 
+    | FLOAT 
+    | DOUBLE 
+    | VOID
+    | uTYPEOF parameters_clause
+    | TYPEOF parameters_clause
+    '''
+    pass
+
+#
+#  The over-general use of declaration_expression to cover decl-specifier-seq_opt declarator in a function-definition means that
+#      class X { };
+#  could be a function-definition or a class-specifier.
+#      enum X { };
+#  could be a function-definition or an enum-specifier.
+#  The function-definition is not syntactically valid so resolving the false conflict in favour of the
+#  elaborated_type_specifier is correct.
+#
+def p_elaborated_type_specifier(p):
+    '''elaborated_type_specifier :  class_key scoped_id %prec SHIFT_THERE
+    |                               elaborated_enum_specifier
+    |                               TYPENAME scoped_id
+    '''
+    pass
+
+def p_elaborated_enum_specifier(p):
+    '''elaborated_enum_specifier :  ENUM scoped_id   %prec SHIFT_THERE
+    '''
+    pass
+
+def p_enum_specifier(p):
+    '''enum_specifier :             ENUM scoped_id enumerator_clause
+    |                               ENUM enumerator_clause
+    '''
+    pass
+
+def p_enumerator_clause(p):
+    '''enumerator_clause :          LBRACE enumerator_list_ecarb
+    |                               LBRACE enumerator_list enumerator_list_ecarb
+    |                               LBRACE enumerator_list ',' enumerator_definition_ecarb
+    '''
+    pass
+
+def p_enumerator_list_ecarb(p):
+    '''enumerator_list_ecarb :      RBRACE
+    '''
+    pass
+
+def p_enumerator_definition_ecarb(p):
+    '''enumerator_definition_ecarb :        RBRACE
+    '''
+    pass
+
+def p_enumerator_definition_filler(p):
+    '''enumerator_definition_filler :       empty
+    '''
+    pass
+
+def p_enumerator_list_head(p):
+    '''enumerator_list_head :       enumerator_definition_filler
+    |                               enumerator_list ',' enumerator_definition_filler
+    '''
+    pass
+
+def p_enumerator_list(p):
+    '''enumerator_list :            enumerator_list_head enumerator_definition
+    '''
+    pass
+
+def p_enumerator_definition(p):
+    '''enumerator_definition :      enumerator
+    |                               enumerator '=' constant_expression
+    '''
+    pass
+
+def p_enumerator(p):
+    '''enumerator :                 identifier
+    '''
+    pass
+
+def p_namespace_definition(p):
+    '''namespace_definition :       NAMESPACE scoped_id push_scope compound_declaration
+    |                               NAMESPACE push_scope compound_declaration
+    '''
+    global _parse_info
+    scope = _parse_info.pop_scope()
+
+def p_namespace_alias_definition(p):
+    '''namespace_alias_definition : NAMESPACE scoped_id '=' scoped_id ';'
+    '''
+    pass
+
+def p_push_scope(p):
+    '''push_scope :                 empty'''
+    global _parse_info
+    if p[-2] == "namespace":
+        scope=p[-1]
+    else:
+        scope=""
+    _parse_info.push_scope(scope,"namespace")
+
+def p_using_declaration(p):
+    '''using_declaration :          USING declarator_id ';'
+    |                               USING TYPENAME declarator_id ';'
+    '''
+    pass
+
+def p_using_directive(p):
+    '''using_directive :            USING NAMESPACE scoped_id ';'
+    '''
+    pass
+
+#    '''asm_definition :             ASM '(' StringLiteral ')' ';'
+def p_asm_definition(p):
+    '''asm_definition :             ASM '(' nonparen_seq_opt ')' ';'
+    '''
+    pass
+
+def p_linkage_specification(p):
+    '''linkage_specification :      EXTERN CLiteral declaration
+    |                               EXTERN CLiteral compound_declaration
+    |                               EXTERN CppLiteral declaration
+    |                               EXTERN CppLiteral compound_declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.7 Declarators
+#---------------------------------------------------------------------------------------------------
+#
+# init-declarator is named init_declaration to reflect the embedded decl-specifier-seq_opt
+#
+
+def p_init_declarations(p):
+    '''init_declarations :          assignment_expression ',' init_declaration
+    |                               init_declarations ',' init_declaration
+    '''
+    p[0]=get_rest(p)
+
+def p_init_declaration(p):
+    '''init_declaration :           assignment_expression
+    '''
+    p[0]=get_rest(p)
+
+def p_star_ptr_operator(p):
+    '''star_ptr_operator :          '*'
+    |                               star_ptr_operator cv_qualifier
+    '''
+    pass
+
+def p_nested_ptr_operator(p):
+    '''nested_ptr_operator :        star_ptr_operator
+    |                               id_scope nested_ptr_operator
+    '''
+    pass
+
+def p_ptr_operator(p):
+    '''ptr_operator :               '&'
+    |                               nested_ptr_operator
+    |                               global_scope nested_ptr_operator
+    '''
+    pass
+
+def p_ptr_operator_seq(p):
+    '''ptr_operator_seq :           ptr_operator
+    |                               ptr_operator ptr_operator_seq
+    '''
+    pass
+
+#
+# Independently coded to localise the shift-reduce conflict: sharing just needs another %prec
+#
+def p_ptr_operator_seq_opt(p):
+    '''ptr_operator_seq_opt :       empty %prec SHIFT_THERE
+    |                               ptr_operator ptr_operator_seq_opt
+    '''
+    pass
+
+def p_cv_qualifier_seq_opt(p):
+    '''cv_qualifier_seq_opt :       empty
+    |                               cv_qualifier_seq_opt cv_qualifier
+    '''
+    pass
+
+# TODO: verify that we should include attributes here
+def p_cv_qualifier(p):
+    '''cv_qualifier :               CONST 
+    |                               VOLATILE
+    |                               attributes
+    '''
+    pass
+
+def p_type_id(p):
+    '''type_id :                    type_specifier abstract_declarator_opt
+    |                               type_specifier type_id
+    '''
+    pass
+
+def p_abstract_declarator_opt(p):
+    '''abstract_declarator_opt :    empty
+    |                               ptr_operator abstract_declarator_opt
+    |                               direct_abstract_declarator
+    '''
+    pass
+
+def p_direct_abstract_declarator_opt(p):
+    '''direct_abstract_declarator_opt :     empty
+    |                               direct_abstract_declarator
+    '''
+    pass
+
+def p_direct_abstract_declarator(p):
+    '''direct_abstract_declarator : direct_abstract_declarator_opt parenthesis_clause
+    |                               direct_abstract_declarator_opt LBRACKET RBRACKET
+    |                               direct_abstract_declarator_opt LBRACKET bexpression RBRACKET
+    '''
+    pass
+
+def p_parenthesis_clause(p):
+    '''parenthesis_clause :         parameters_clause cv_qualifier_seq_opt
+    |                               parameters_clause cv_qualifier_seq_opt exception_specification
+    '''
+    p[0] = ['(',')']
+
+def p_parameters_clause(p):
+    '''parameters_clause :          '(' condition_opt ')'
+    '''
+    p[0] = ['(',')']
+
+#
+# A typed abstract qualifier such as
+#      Class * ...
+# looks like a multiply, so pointers are parsed as their binary operation equivalents that
+# ultimately terminate with a degenerate right hand term.
+#
+def p_abstract_pointer_declaration(p):
+    '''abstract_pointer_declaration :       ptr_operator_seq
+    |                               multiplicative_expression star_ptr_operator ptr_operator_seq_opt
+    '''
+    pass
+
+def p_abstract_parameter_declaration(p):
+    '''abstract_parameter_declaration :     abstract_pointer_declaration
+    |                               and_expression '&'
+    |                               and_expression '&' abstract_pointer_declaration
+    '''
+    pass
+
+def p_special_parameter_declaration(p):
+    '''special_parameter_declaration :      abstract_parameter_declaration
+    |                               abstract_parameter_declaration '=' assignment_expression
+    |                               ELLIPSIS
+    '''
+    pass
+
+def p_parameter_declaration(p):
+    '''parameter_declaration :      assignment_expression
+    |                               special_parameter_declaration
+    |                               decl_specifier_prefix parameter_declaration
+    '''
+    pass
+
+#
+# function_definition includes constructor, destructor, implicit int definitions too.  A local destructor is successfully parsed as a function-declaration but the ~ was treated as a unary operator.  constructor_head is the prefix ambiguity between a constructor and a member-init-list starting with a bit-field.
+#
+def p_function_definition(p):
+    '''function_definition :        ctor_definition
+    |                               func_definition
+    '''
+    pass
+
+def p_func_definition(p):
+    '''func_definition :            assignment_expression function_try_block
+    |                               assignment_expression function_body
+    |                               decl_specifier_prefix func_definition
+    '''
+    global _parse_info
+    if p[2] is not None and p[2][0] == '{':
+        decl = flatten(p[1])
+        #print "HERE",decl
+        if decl[-1] == ')':
+            decl=decl[-3]
+        else:
+            decl=decl[-1]
+        p[0] = decl
+        if decl != "operator":
+            _parse_info.add_function(decl)
+    else:
+        p[0] = p[2]
+
+def p_ctor_definition(p):
+    '''ctor_definition :            constructor_head function_try_block
+    |                               constructor_head function_body
+    |                               decl_specifier_prefix ctor_definition
+    '''
+    if p[2] is None or p[2][0] == "try" or p[2][0] == '{':
+        p[0]=p[1]
+    else:
+        p[0]=p[1]
+
+def p_constructor_head(p):
+    '''constructor_head :           bit_field_init_declaration
+    |                               constructor_head ',' assignment_expression
+    '''
+    p[0]=p[1]
+
+def p_function_try_block(p):
+    '''function_try_block :         TRY function_block handler_seq
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+    p[0] = ['try']
+
+def p_function_block(p):
+    '''function_block :             ctor_initializer_opt function_body
+    '''
+    pass
+
+def p_function_body(p):
+    '''function_body :              LBRACE nonbrace_seq_opt RBRACE 
+    '''
+    p[0] = ['{','}']
+
+def p_initializer_clause(p):
+    '''initializer_clause :         assignment_expression
+    |                               braced_initializer
+    '''
+    pass
+
+def p_braced_initializer(p):
+    '''braced_initializer :         LBRACE initializer_list RBRACE
+    |                               LBRACE initializer_list ',' RBRACE
+    |                               LBRACE RBRACE
+    '''
+    pass
+
+def p_initializer_list(p):
+    '''initializer_list :           initializer_clause
+    |                               initializer_list ',' initializer_clause
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.8 Classes
+#---------------------------------------------------------------------------------------------------
+#
+#  An anonymous bit-field declaration may look very like inheritance:
+#      const int B = 3;
+#      class A : B ;
+#  The two usages are too distant to try to create and enforce a common prefix so we have to resort to
+#  a parser hack by backtracking. Inheritance is much the most likely so we mark the input stream context
+#  and try to parse a base-clause. If we successfully reach a { the base-clause is ok and inheritance was
+#  the correct choice so we unmark and continue. If we fail to find the { an error token causes 
+#  back-tracking to the alternative parse in elaborated_type_specifier which regenerates the : and 
+#  declares unconditional success.
+#
+
+def p_class_specifier_head(p):
+    '''class_specifier_head :       class_key scoped_id ':' base_specifier_list LBRACE
+    |                               class_key ':' base_specifier_list LBRACE
+    |                               class_key scoped_id LBRACE
+    |                               class_key LBRACE
+    '''
+    global _parse_info
+    base_classes=[]
+    if len(p) == 6:
+        scope = p[2]
+        base_classes = p[4]
+    elif len(p) == 4:
+        scope = p[2]
+    elif len(p) == 5:
+        base_classes = p[3]
+    else:
+        scope = ""
+    _parse_info.push_scope(scope,p[1],base_classes)
+    
+
+def p_class_key(p):
+    '''class_key :                  CLASS 
+    | STRUCT 
+    | UNION
+    '''
+    p[0] = p[1]
+
+def p_class_specifier(p):
+    '''class_specifier :            class_specifier_head member_specification_opt RBRACE
+    '''
+    scope = _parse_info.pop_scope()
+
+def p_member_specification_opt(p):
+    '''member_specification_opt :   empty
+    |                               member_specification_opt member_declaration
+    '''
+    pass
+
+def p_member_declaration(p):
+    '''member_declaration :         accessibility_specifier
+    |                               simple_member_declaration
+    |                               function_definition
+    |                               using_declaration
+    |                               template_declaration
+    '''
+    p[0] = get_rest(p)
+    #print "Decl",get_rest(p)
+
+#
+#  The generality of constructor names (there need be no parenthesised argument list) means that that
+#          name : f(g), h(i)
+#  could be the start of a constructor or the start of an anonymous bit-field. An ambiguity is avoided by
+#  parsing the ctor-initializer of a function_definition as a bit-field.
+#
+def p_simple_member_declaration(p):
+    '''simple_member_declaration :  ';'
+    |                               assignment_expression ';'
+    |                               constructor_head ';'
+    |                               member_init_declarations ';'
+    |                               decl_specifier_prefix simple_member_declaration
+    '''
+    global _parse_info
+    decl = flatten(get_rest(p))
+    if len(decl) >= 4 and decl[-3] == "(":
+        _parse_info.add_function(decl[-4])
+
+def p_member_init_declarations(p):
+    '''member_init_declarations :   assignment_expression ',' member_init_declaration
+    |                               constructor_head ',' bit_field_init_declaration
+    |                               member_init_declarations ',' member_init_declaration
+    '''
+    pass
+
+def p_member_init_declaration(p):
+    '''member_init_declaration :    assignment_expression
+    |                               bit_field_init_declaration
+    '''
+    pass
+
+def p_accessibility_specifier(p):
+    '''accessibility_specifier :    access_specifier ':'
+    '''
+    pass
+
+def p_bit_field_declaration(p):
+    '''bit_field_declaration :      assignment_expression ':' bit_field_width
+    |                               ':' bit_field_width
+    '''
+    if len(p) == 4:
+        p[0]=p[1]
+
+def p_bit_field_width(p):
+    '''bit_field_width :            logical_or_expression
+    |                               logical_or_expression '?' bit_field_width ':' bit_field_width
+    '''
+    pass
+
+def p_bit_field_init_declaration(p):
+    '''bit_field_init_declaration : bit_field_declaration
+    |                               bit_field_declaration '=' initializer_clause
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.9 Derived classes
+#---------------------------------------------------------------------------------------------------
+def p_base_specifier_list(p):
+    '''base_specifier_list :        base_specifier
+    |                               base_specifier_list ',' base_specifier
+    '''
+    if len(p) == 2:
+        p[0] = [p[1]]
+    else:
+        p[0] = p[1]+[p[3]]
+
+def p_base_specifier(p):
+    '''base_specifier :             scoped_id
+    |                               access_specifier base_specifier
+    |                               VIRTUAL base_specifier
+    '''
+    if len(p) == 2:
+        p[0] = p[1]
+    else:
+        p[0] = p[2]
+
+def p_access_specifier(p):
+    '''access_specifier :           PRIVATE 
+    |                               PROTECTED 
+    |                               PUBLIC
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.10 Special member functions
+#---------------------------------------------------------------------------------------------------
+def p_conversion_function_id(p):
+    '''conversion_function_id :     OPERATOR conversion_type_id
+    '''
+    p[0] = ['operator']
+
+def p_conversion_type_id(p):
+    '''conversion_type_id :         type_specifier ptr_operator_seq_opt
+    |                               type_specifier conversion_type_id
+    '''
+    pass
+
+#
+#  Ctor-initialisers can look like a bit field declaration, given the generalisation of names:
+#      Class(Type) : m1(1), m2(2) { }
+#      NonClass(bit_field) : int(2), second_variable, ...
+#  The grammar below is used within a function_try_block or function_definition.
+#  See simple_member_declaration for use in normal member function_definition.
+#
+def p_ctor_initializer_opt(p):
+    '''ctor_initializer_opt :       empty
+    |                               ctor_initializer
+    '''
+    pass
+
+def p_ctor_initializer(p):
+    '''ctor_initializer :           ':' mem_initializer_list
+    '''
+    pass
+
+def p_mem_initializer_list(p):
+    '''mem_initializer_list :       mem_initializer
+    |                               mem_initializer_list_head mem_initializer
+    '''
+    pass
+
+def p_mem_initializer_list_head(p):
+    '''mem_initializer_list_head :  mem_initializer_list ','
+    '''
+    pass
+
+def p_mem_initializer(p):
+    '''mem_initializer :            mem_initializer_id '(' expression_list_opt ')'
+    '''
+    pass
+
+def p_mem_initializer_id(p):
+    '''mem_initializer_id :         scoped_id
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.11 Overloading
+#---------------------------------------------------------------------------------------------------
+
+def p_operator_function_id(p):
+    '''operator_function_id :       OPERATOR operator
+    |                               OPERATOR '(' ')'
+    |                               OPERATOR LBRACKET RBRACKET
+    |                               OPERATOR '<'
+    |                               OPERATOR '>'
+    |                               OPERATOR operator '<' nonlgt_seq_opt '>'
+    '''
+    p[0] = ["operator"]
+
+#
+#  It is not clear from the ANSI standard whether spaces are permitted in delete[]. If not then it can
+#  be recognised and returned as DELETE_ARRAY by the lexer. Assuming spaces are permitted there is an
+#  ambiguity created by the over generalised nature of expressions. operator new is a valid delarator-id
+#  which we may have an undimensioned array of. Semantic rubbish, but syntactically valid. Since the
+#  array form is covered by the declarator consideration we can exclude the operator here. The need
+#  for a semantic rescue can be eliminated at the expense of a couple of shift-reduce conflicts by
+#  removing the comments on the next four lines.
+#
+def p_operator(p):
+    '''operator :                   NEW
+    |                               DELETE
+    |                               '+'
+    |                               '-'
+    |                               '*'
+    |                               '/'
+    |                               '%'
+    |                               '^'
+    |                               '&'
+    |                               '|'
+    |                               '~'
+    |                               '!'
+    |                               '='
+    |                               ASS_ADD
+    |                               ASS_SUB
+    |                               ASS_MUL
+    |                               ASS_DIV
+    |                               ASS_MOD
+    |                               ASS_XOR
+    |                               ASS_AND
+    |                               ASS_OR
+    |                               SHL
+    |                               SHR
+    |                               ASS_SHR
+    |                               ASS_SHL
+    |                               EQ
+    |                               NE
+    |                               LE
+    |                               GE
+    |                               LOG_AND
+    |                               LOG_OR
+    |                               INC
+    |                               DEC
+    |                               ','
+    |                               ARROW_STAR
+    |                               ARROW
+    '''
+    p[0]=p[1]
+
+#    |                               IF
+#    |                               SWITCH
+#    |                               WHILE
+#    |                               FOR
+#    |                               DO
+def p_reserved(p):
+    '''reserved :                   PRIVATE
+    |                               CLiteral
+    |                               CppLiteral
+    |                               IF
+    |                               SWITCH
+    |                               WHILE
+    |                               FOR
+    |                               DO
+    |                               PROTECTED
+    |                               PUBLIC
+    |                               BOOL
+    |                               CHAR
+    |                               DOUBLE
+    |                               FLOAT
+    |                               INT
+    |                               LONG
+    |                               SHORT
+    |                               SIGNED
+    |                               UNSIGNED
+    |                               VOID
+    |                               WCHAR_T
+    |                               CLASS
+    |                               ENUM
+    |                               NAMESPACE
+    |                               STRUCT
+    |                               TYPENAME
+    |                               UNION
+    |                               CONST
+    |                               VOLATILE
+    |                               AUTO
+    |                               EXPLICIT
+    |                               EXPORT
+    |                               EXTERN
+    |                               FRIEND
+    |                               INLINE
+    |                               MUTABLE
+    |                               REGISTER
+    |                               STATIC
+    |                               TEMPLATE
+    |                               TYPEDEF
+    |                               USING
+    |                               VIRTUAL
+    |                               ASM
+    |                               BREAK
+    |                               CASE
+    |                               CATCH
+    |                               CONST_CAST
+    |                               CONTINUE
+    |                               DEFAULT
+    |                               DYNAMIC_CAST
+    |                               ELSE
+    |                               FALSE
+    |                               GOTO
+    |                               OPERATOR
+    |                               REINTERPRET_CAST
+    |                               RETURN
+    |                               SIZEOF
+    |                               STATIC_CAST
+    |                               THIS
+    |                               THROW
+    |                               TRUE
+    |                               TRY
+    |                               TYPEID
+    |                               ATTRIBUTE
+    |                               CDECL
+    |                               TYPEOF
+    |                               uTYPEOF
+    '''
+    if p[1] in ('try', 'catch', 'throw'):
+        global noExceptionLogic
+        noExceptionLogic=False
+
+#---------------------------------------------------------------------------------------------------
+# A.12 Templates
+#---------------------------------------------------------------------------------------------------
+def p_template_declaration(p):
+    '''template_declaration :       template_parameter_clause declaration
+    |                               EXPORT template_declaration
+    '''
+    pass
+
+def p_template_parameter_clause(p):
+    '''template_parameter_clause :  TEMPLATE '<' nonlgt_seq_opt '>'
+    '''
+    pass
+
+#
+#  Generalised naming makes identifier a valid declaration, so TEMPLATE identifier is too.
+#  The TEMPLATE prefix is therefore folded into all names, parenthesis_clause and decl_specifier_prefix.
+#
+# explicit_instantiation:           TEMPLATE declaration
+#
+def p_explicit_specialization(p):
+    '''explicit_specialization :    TEMPLATE '<' '>' declaration
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# A.13 Exception Handling
+#---------------------------------------------------------------------------------------------------
+def p_handler_seq(p):
+    '''handler_seq :                handler
+    |                               handler handler_seq
+    '''
+    pass
+
+def p_handler(p):
+    '''handler :                    CATCH '(' exception_declaration ')' compound_statement
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_exception_declaration(p):
+    '''exception_declaration :      parameter_declaration
+    '''
+    pass
+
+def p_throw_expression(p):
+    '''throw_expression :           THROW
+    |                               THROW assignment_expression
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_exception_specification(p):
+    '''exception_specification :    THROW '(' ')'
+    |                               THROW '(' type_id_list ')'
+    '''
+    global noExceptionLogic
+    noExceptionLogic=False
+
+def p_type_id_list(p):
+    '''type_id_list :               type_id
+    |                               type_id_list ',' type_id
+    '''
+    pass
+
+#---------------------------------------------------------------------------------------------------
+# Misc productions
+#---------------------------------------------------------------------------------------------------
+def p_nonsemicolon_seq(p):
+    '''nonsemicolon_seq :           empty
+    |                               nonsemicolon_seq nonsemicolon
+    '''
+    pass
+
+def p_nonsemicolon(p):
+    '''nonsemicolon :               misc
+    |                               '('
+    |                               ')'
+    |                               '<'
+    |                               '>'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonparen_seq_opt(p):
+    '''nonparen_seq_opt :           empty
+    |                               nonparen_seq_opt nonparen
+    '''
+    pass
+
+def p_nonparen_seq(p):
+    '''nonparen_seq :               nonparen
+    |                               nonparen_seq nonparen
+    '''
+    pass
+
+def p_nonparen(p):
+    '''nonparen :                   misc
+    |                               '<'
+    |                               '>'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonbracket_seq_opt(p):
+    '''nonbracket_seq_opt :         empty
+    |                               nonbracket_seq_opt nonbracket
+    '''
+    pass
+
+def p_nonbracket_seq(p):
+    '''nonbracket_seq :             nonbracket
+    |                               nonbracket_seq nonbracket
+    '''
+    pass
+
+def p_nonbracket(p):
+    '''nonbracket :                 misc
+    |                               '<'
+    |                               '>'
+    |                               '('
+    |                               ')'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonbrace_seq_opt(p):
+    '''nonbrace_seq_opt :           empty
+    |                               nonbrace_seq_opt nonbrace
+    '''
+    pass
+
+def p_nonbrace(p):
+    '''nonbrace :                   misc
+    |                               '<'
+    |                               '>'
+    |                               '('
+    |                               ')'
+    |                               ';'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               LBRACE nonbrace_seq_opt RBRACE
+    '''
+    pass
+
+def p_nonlgt_seq_opt(p):
+    '''nonlgt_seq_opt :             empty
+    |                               nonlgt_seq_opt nonlgt
+    '''
+    pass
+
+def p_nonlgt(p):
+    '''nonlgt :                     misc
+    |                               '('
+    |                               ')'
+    |                               LBRACKET nonbracket_seq_opt RBRACKET
+    |                               '<' nonlgt_seq_opt '>'
+    |                               ';'
+    '''
+    pass
+
+def p_misc(p):
+    '''misc :                       operator
+    |                               identifier
+    |                               IntegerLiteral
+    |                               CharacterLiteral
+    |                               FloatingLiteral
+    |                               StringLiteral
+    |                               reserved
+    |                               '?'
+    |                               ':'
+    |                               '.'
+    |                               SCOPE
+    |                               ELLIPSIS
+    |                               EXTENSION
+    '''
+    pass
+
+def p_empty(p):
+    '''empty : '''
+    pass
+
+
+
+#
+# Compute column.
+#     input is the input text string
+#     token is a token instance
+#
+def _find_column(input,token):
+    ''' TODO '''
+    i = token.lexpos
+    while i > 0:
+        if input[i] == '\n': break
+        i -= 1
+    column = (token.lexpos - i)+1
+    return column
+
+def p_error(p):
+    if p is None:
+        tmp = "Syntax error at end of file."
+    else:
+        tmp = "Syntax error at token "
+        if p.type is "":
+            tmp = tmp + "''"
+        else:
+            tmp = tmp + str(p.type)
+        tmp = tmp + " with value '"+str(p.value)+"'"
+        tmp = tmp + " in line " + str(lexer.lineno-1)
+        tmp = tmp + " at column "+str(_find_column(_parsedata,p))
+    raise IOError( tmp )
+
+
+
+#
+# The function that performs the parsing
+#
+def parse_cpp(data=None, filename=None, debug=0, optimize=0, verbose=False, func_filter=None):
+    if debug > 0:
+        print("Debugging parse_cpp!")
+        #
+        # Always remove the parser.out file, which is generated to create debugging
+        #
+        if os.path.exists("parser.out"):
+            os.remove("parser.out")
+        #
+        # Remove the parsetab.py* files.  These apparently need to be removed
+        # to ensure the creation of a parser.out file.
+        #
+        if os.path.exists("parsetab.py"):
+           os.remove("parsetab.py")
+        if os.path.exists("parsetab.pyc"):
+           os.remove("parsetab.pyc")
+        global debugging
+        debugging=True
+    #
+    # Build lexer
+    #
+    global lexer
+    lexer = lex.lex()
+    #
+    # Initialize parse object
+    #
+    global _parse_info
+    _parse_info = CppInfo(filter=func_filter)
+    _parse_info.verbose=verbose
+    #
+    # Build yaccer
+    #
+    write_table = not os.path.exists("parsetab.py")
+    yacc.yacc(debug=debug, optimize=optimize, write_tables=write_table)
+    #
+    # Parse the file
+    #
+    global _parsedata
+    if not data is None:
+        _parsedata=data
+        ply_init(_parsedata)
+        yacc.parse(data,debug=debug)
+    elif not filename is None:
+        f = open(filename)
+        data = f.read()
+        f.close()
+        _parsedata=data
+        ply_init(_parsedata)
+        yacc.parse(data, debug=debug)
+    else:
+        return None
+    #
+    if not noExceptionLogic:
+        _parse_info.noExceptionLogic = False
+    else:
+        for key in identifier_lineno:
+            if 'ASSERT_THROWS' in key:
+                _parse_info.noExceptionLogic = False
+                break
+        _parse_info.noExceptionLogic = True
+    #
+    return _parse_info
+
+
+
+import sys
+
+if __name__ == '__main__':
+    #
+    # This MAIN routine parses a sequence of files provided at the command
+    # line.  If '-v' is included, then a verbose parsing output is 
+    # generated.
+    #
+    for arg in sys.argv[1:]:
+        if arg == "-v":
+            continue
+        print("Parsing file '"+arg+"'")
+        if '-v' in sys.argv:
+            parse_cpp(filename=arg,debug=2,verbose=2)
+        else:
+            parse_cpp(filename=arg,verbose=2)
+        #
+        # Print the _parse_info object summary for this file.
+        # This illustrates how class inheritance can be used to 
+        # deduce class members.
+        # 
+        print(str(_parse_info))
+
diff --git a/tools/cxxtest/python/python3/cxxtest/cxxtest_fog.py b/tools/cxxtest/python/python3/cxxtest/cxxtest_fog.py
new file mode 100644 (file)
index 0000000..29660cb
--- /dev/null
@@ -0,0 +1,96 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+#
+# TODO: add line number info
+# TODO: add test function names
+#
+
+
+
+import sys
+import re
+#from os.path import abspath, dirname
+#sys.path.insert(0, dirname(dirname(abspath(__file__))))
+#sys.path.insert(0, dirname(dirname(abspath(__file__)))+"/cxx_parse")
+from .cxxtest_misc import abort
+from . import cxx_parser
+import re
+
+def cstr( str ):
+    '''Convert a string to its C representation'''
+    return '"' + re.sub('\\\\', '\\\\\\\\', str ) + '"'
+
+def scanInputFiles(files, _options):
+    '''Scan all input files for test suites'''
+    suites=[]
+    for file in files:
+        try:
+            print("Parsing file "+file, end=' ')
+            sys.stdout.flush()
+            parse_info = cxx_parser.parse_cpp(filename=file,optimize=1)
+        except IOError as err:
+            print(" error.")
+            print(str(err))
+            continue
+        print("done.") 
+        sys.stdout.flush()
+        #
+        # WEH: see if it really makes sense to use parse information to
+        # initialize this data.  I don't think so...
+        #
+        _options.haveStandardLibrary=1
+        if not parse_info.noExceptionLogic:
+            _options.haveExceptionHandling=1
+        #
+        keys = list(parse_info.index.keys())
+        tpat = re.compile("[Tt][Ee][Ss][Tt]")
+        for key in keys:
+            if parse_info.index[key].scope_t == "class" and parse_info.is_baseclass(key,"CxxTest::TestSuite"):
+                name=parse_info.index[key].name
+                suite = { 'name'         : name,
+                        'file'         : file,
+                        'cfile'        : cstr(file),
+                        'line'         : str(parse_info.index[key].lineno),
+                        'generated'    : 0,
+                        'object'       : 'suite_%s' % name,
+                        'dobject'      : 'suiteDescription_%s' % name,
+                        'tlist'        : 'Tests_%s' % name,
+                        'tests'        : [],
+                        'lines'        : [] }
+                for fn in parse_info.get_functions(key,quiet=True):
+                    tname = fn[0]
+                    lineno = str(fn[1])
+                    if tname.startswith('createSuite'):
+                        # Indicate that we're using a dynamically generated test suite
+                        suite['create'] = str(lineno) # (unknown line)
+                    if tname.startswith('destroySuite'):
+                        # Indicate that we're using a dynamically generated test suite
+                        suite['destroy'] = str(lineno) # (unknown line)
+                    if not tpat.match(tname):
+                        # Skip non-test methods
+                        continue
+                    test = { 'name'   : tname,
+                        'suite'  : suite,
+                        'class'  : 'TestDescription_suite_%s_%s' % (suite['name'], tname),
+                        'object' : 'testDescription_suite_%s_%s' % (suite['name'], tname),
+                        'line'   : lineno,
+                        }
+                    suite['tests'].append(test)
+                suites.append(suite)
+
+    if not _options.root:
+        ntests = 0
+        for suite in suites:
+            ntests += len(suite['tests'])
+        if ntests == 0:
+            abort( 'No tests defined' )
+    #
+    return [_options, suites]
+
diff --git a/tools/cxxtest/python/python3/cxxtest/cxxtest_misc.py b/tools/cxxtest/python/python3/cxxtest/cxxtest_misc.py
new file mode 100644 (file)
index 0000000..b5b9a8d
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+import sys
+
+def abort( problem ):
+    '''Print error message and exit'''
+    sys.stderr.write( '\n' )
+    sys.stderr.write( problem )
+    sys.stderr.write( '\n\n' )
+    sys.exit(2)
+
diff --git a/tools/cxxtest/python/python3/cxxtest/cxxtest_parser.py b/tools/cxxtest/python/python3/cxxtest/cxxtest_parser.py
new file mode 100644 (file)
index 0000000..e76dbee
--- /dev/null
@@ -0,0 +1,242 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+
+
+import codecs
+import re
+#import sys
+#import getopt
+#import glob
+from cxxtest.cxxtest_misc import abort
+
+# Global variables
+suites = []
+suite = None
+inBlock = 0
+options=None
+
+def scanInputFiles(files, _options):
+    '''Scan all input files for test suites'''
+    global options
+    options=_options
+    for file in files:
+        scanInputFile(file)
+    global suites
+    if len(suites) is 0 and not options.root:
+        abort( 'No tests defined' )
+    return [options,suites]
+
+lineCont_re = re.compile('(.*)\\\s*$')
+def scanInputFile(fileName):
+    '''Scan single input file for test suites'''
+    # mode 'rb' is problematic in python3 - byte arrays don't behave the same as
+    # strings.
+    # As far as the choice of the default encoding: utf-8 chews through
+    # everything that the previous ascii codec could, plus most of new code.
+    # TODO: figure out how to do this properly - like autodetect encoding from
+    # file header.
+    file = codecs.open(fileName, mode='r', encoding='utf-8')
+    prev = ""
+    lineNo = 0
+    contNo = 0
+    while 1:
+        line = file.readline()
+        if not line:
+            break
+        lineNo += 1
+
+        m = lineCont_re.match(line)
+        if m:
+            prev += m.group(1) + " "
+            contNo += 1
+        else:
+            scanInputLine( fileName, lineNo - contNo, prev + line )
+            contNo = 0
+            prev = ""
+    if contNo:
+        scanInputLine( fileName, lineNo - contNo, prev + line )
+        
+    closeSuite()
+    file.close()
+
+def scanInputLine( fileName, lineNo, line ):
+    '''Scan single input line for interesting stuff'''
+    scanLineForExceptionHandling( line )
+    scanLineForStandardLibrary( line )
+
+    scanLineForSuiteStart( fileName, lineNo, line )
+
+    global suite
+    if suite:
+        scanLineInsideSuite( suite, lineNo, line )
+
+def scanLineInsideSuite( suite, lineNo, line ):
+    '''Analyze line which is part of a suite'''
+    global inBlock
+    if lineBelongsToSuite( suite, lineNo, line ):
+        scanLineForTest( suite, lineNo, line )
+        scanLineForCreate( suite, lineNo, line )
+        scanLineForDestroy( suite, lineNo, line )
+
+def lineBelongsToSuite( suite, lineNo, line ):
+    '''Returns whether current line is part of the current suite.
+    This can be false when we are in a generated suite outside of CXXTEST_CODE() blocks
+    If the suite is generated, adds the line to the list of lines'''
+    if not suite['generated']:
+        return 1
+
+    global inBlock
+    if not inBlock:
+        inBlock = lineStartsBlock( line )
+    if inBlock:
+        inBlock = addLineToBlock( suite, lineNo, line )
+    return inBlock
+
+
+std_re = re.compile( r"\b(std\s*::|CXXTEST_STD|using\s+namespace\s+std\b|^\s*\#\s*include\s+<[a-z0-9]+>)" )
+def scanLineForStandardLibrary( line ):
+    '''Check if current line uses standard library'''
+    global options
+    if not options.haveStandardLibrary and std_re.search(line):
+        if not options.noStandardLibrary:
+            options.haveStandardLibrary = 1
+
+exception_re = re.compile( r"\b(throw|try|catch|TSM?_ASSERT_THROWS[A-Z_]*)\b" )
+def scanLineForExceptionHandling( line ):
+    '''Check if current line uses exception handling'''
+    global options
+    if not options.haveExceptionHandling and exception_re.search(line):
+        if not options.noExceptionHandling:
+            options.haveExceptionHandling = 1
+
+classdef = '(?:::\s*)?(?:\w+\s*::\s*)*\w+'
+baseclassdef = '(?:public|private|protected)\s+%s' % (classdef,)
+general_suite = r"\bclass\s+(%s)\s*:(?:\s*%s\s*,)*\s*public\s+" \
+                % (classdef, baseclassdef,)
+testsuite = '(?:(?:::)?\s*CxxTest\s*::\s*)?TestSuite'
+suites_re = { re.compile( general_suite + testsuite ) : None }
+generatedSuite_re = re.compile( r'\bCXXTEST_SUITE\s*\(\s*(\w*)\s*\)' )
+def scanLineForSuiteStart( fileName, lineNo, line ):
+    '''Check if current line starts a new test suite'''
+    for i in list(suites_re.items()):
+        m = i[0].search( line )
+        if m:
+            suite = startSuite( m.group(1), fileName, lineNo, 0 )
+            if i[1] is not None:
+                for test in i[1]['tests']:
+                    addTest(suite, test['name'], test['line'])
+            break
+    m = generatedSuite_re.search( line )
+    if m:
+        sys.stdout.write( "%s:%s: Warning: Inline test suites are deprecated.\n" % (fileName, lineNo) )
+        startSuite( m.group(1), fileName, lineNo, 1 )
+
+def startSuite( name, file, line, generated ):
+    '''Start scanning a new suite'''
+    global suite
+    closeSuite()
+    object_name = name.replace(':',"_")
+    suite = { 'name'         : name,
+              'file'         : file,
+              'cfile'        : cstr(file),
+              'line'         : line,
+              'generated'    : generated,
+              'object'       : 'suite_%s' % object_name,
+              'dobject'      : 'suiteDescription_%s' % object_name,
+              'tlist'        : 'Tests_%s' % object_name,
+              'tests'        : [],
+              'lines'        : [] }
+    suites_re[re.compile( general_suite + name )] = suite
+    return suite
+
+def lineStartsBlock( line ):
+    '''Check if current line starts a new CXXTEST_CODE() block'''
+    return re.search( r'\bCXXTEST_CODE\s*\(', line ) is not None
+
+test_re = re.compile( r'^([^/]|/[^/])*\bvoid\s+([Tt]est\w+)\s*\(\s*(void)?\s*\)' )
+def scanLineForTest( suite, lineNo, line ):
+    '''Check if current line starts a test'''
+    m = test_re.search( line )
+    if m:
+        addTest( suite, m.group(2), lineNo )
+
+def addTest( suite, name, line ):
+    '''Add a test function to the current suite'''
+    test = { 'name'   : name,
+             'suite'  : suite,
+             'class'  : 'TestDescription_%s_%s' % (suite['object'], name),
+             'object' : 'testDescription_%s_%s' % (suite['object'], name),
+             'line'   : line,
+             }
+    suite['tests'].append( test )
+
+def addLineToBlock( suite, lineNo, line ):
+    '''Append the line to the current CXXTEST_CODE() block'''
+    line = fixBlockLine( suite, lineNo, line )
+    line = re.sub( r'^.*\{\{', '', line )
+    
+    e = re.search( r'\}\}', line )
+    if e:
+        line = line[:e.start()]
+    suite['lines'].append( line )
+    return e is None
+
+def fixBlockLine( suite, lineNo, line):
+    '''Change all [E]TS_ macros used in a line to _[E]TS_ macros with the correct file/line'''
+    return re.sub( r'\b(E?TSM?_(ASSERT[A-Z_]*|FAIL))\s*\(',
+                   r'_\1(%s,%s,' % (suite['cfile'], lineNo),
+                   line, 0 )
+
+create_re = re.compile( r'\bstatic\s+\w+\s*\*\s*createSuite\s*\(\s*(void)?\s*\)' )
+def scanLineForCreate( suite, lineNo, line ):
+    '''Check if current line defines a createSuite() function'''
+    if create_re.search( line ):
+        addSuiteCreateDestroy( suite, 'create', lineNo )
+
+destroy_re = re.compile( r'\bstatic\s+void\s+destroySuite\s*\(\s*\w+\s*\*\s*\w*\s*\)' )
+def scanLineForDestroy( suite, lineNo, line ):
+    '''Check if current line defines a destroySuite() function'''
+    if destroy_re.search( line ):
+        addSuiteCreateDestroy( suite, 'destroy', lineNo )
+
+def cstr( s ):
+    '''Convert a string to its C representation'''
+    return '"' + s.replace( '\\', '\\\\' ) + '"'
+
+
+def addSuiteCreateDestroy( suite, which, line ):
+    '''Add createSuite()/destroySuite() to current suite'''
+    if which in suite:
+        abort( '%s:%s: %sSuite() already declared' % ( suite['file'], str(line), which ) )
+    suite[which] = line
+
+def closeSuite():
+    '''Close current suite and add it to the list if valid'''
+    global suite
+    if suite is not None:
+        if len(suite['tests']) is not 0:
+            verifySuite(suite)
+            rememberSuite(suite)
+        suite = None
+
+def verifySuite(suite):
+    '''Verify current suite is legal'''
+    if 'create' in suite and 'destroy' not in suite:
+        abort( '%s:%s: Suite %s has createSuite() but no destroySuite()' %
+               (suite['file'], suite['create'], suite['name']) )
+    elif 'destroy' in suite and 'create' not in suite:
+        abort( '%s:%s: Suite %s has destroySuite() but no createSuite()' %
+               (suite['file'], suite['destroy'], suite['name']) )
+
+def rememberSuite(suite):
+    '''Add current suite to list'''
+    global suites
+    suites.append( suite )
+
diff --git a/tools/cxxtest/python/python3/cxxtest/cxxtestgen.py b/tools/cxxtest/python/python3/cxxtest/cxxtestgen.py
new file mode 100644 (file)
index 0000000..c704757
--- /dev/null
@@ -0,0 +1,480 @@
+#-------------------------------------------------------------------------
+# CxxTest: A lightweight C++ unit testing library.
+# Copyright (c) 2008 Sandia Corporation.
+# This software is distributed under the LGPL License v2.1
+# For more information, see the COPYING file in the top CxxTest directory.
+# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+# the U.S. Government retains certain rights in this software.
+#-------------------------------------------------------------------------
+
+# vim: fileencoding=utf-8
+
+
+# the above import important for forward-compatibility with python3,
+# which is already the default in archlinux!
+
+__all__ = ['main']
+
+from . import __release__
+import os
+import sys
+import re
+import glob
+from optparse import OptionParser
+from . import cxxtest_parser
+
+try:
+    from . import cxxtest_fog
+    imported_fog=True
+except ImportError:
+    imported_fog=False
+
+from .cxxtest_misc import abort
+
+options = []
+suites = []
+
+wrotePreamble = 0
+wroteWorld = 0
+lastIncluded = ''
+
+def main(args=sys.argv):
+    '''The main program'''
+    #
+    # Reset global state
+    #
+    global wrotePreamble
+    wrotePreamble=0
+    global wroteWorld
+    wroteWorld=0
+    global lastIncluded
+    lastIncluded = ''
+
+    global suites
+    global options
+    files = parseCommandline(args)
+    if imported_fog and options.fog:
+        [options,suites] = cxxtest_fog.scanInputFiles( files, options )
+    else:
+        [options,suites] = cxxtest_parser.scanInputFiles( files, options )
+    writeOutput()
+
+def parseCommandline(args):
+    '''Analyze command line arguments'''
+    global imported_fog
+    global options
+    parser = OptionParser("%prog [options] [<filename> ...]")
+    parser.add_option("--version",
+                      action="store_true", dest="version", default=False,
+                      help="Write the CxxTest version.")
+    parser.add_option("-o", "--output",
+                      dest="outputFileName", default=None, metavar="NAME",
+                      help="Write output to file NAME.")
+    parser.add_option("-w","--world", dest="world", default="cxxtest",
+                      help="The label of the tests, used to name the XML results.")
+    parser.add_option("", "--include", action="append",
+                      dest="headers", default=[], metavar="HEADER",
+                      help="Include file HEADER in the test runner before other headers.")
+    parser.add_option("", "--abort-on-fail",
+                      action="store_true", dest="abortOnFail", default=False,
+                      help="Abort tests on failed asserts (like xUnit).")
+    parser.add_option("", "--main",
+                      action="store", dest="main", default="main",
+                      help="Specify an alternative name for the main() function.")
+    parser.add_option("", "--headers",
+                      action="store", dest="header_filename", default=None,
+                      help="Specify a filename that contains a list of header files that are processed to generate a test runner.")
+    parser.add_option("", "--runner",
+                      dest="runner", default="", metavar="CLASS",
+                      help="Create a test runner that processes test events using the class CxxTest::CLASS.")
+    parser.add_option("", "--gui",
+                      dest="gui", metavar="CLASS",
+                      help="Create a GUI test runner that processes test events using the class CxxTest::CLASS. (deprecated)")
+    parser.add_option("", "--error-printer",
+                      action="store_true", dest="error_printer", default=False,
+                      help="Create a test runner using the ErrorPrinter class, and allow the use of the standard library.")
+    parser.add_option("", "--xunit-printer",
+                      action="store_true", dest="xunit_printer", default=False,
+                      help="Create a test runner using the XUnitPrinter class.")
+    parser.add_option("", "--xunit-file",  dest="xunit_file", default="",
+                      help="The file to which the XML summary is written for test runners using the XUnitPrinter class.  The default XML filename is TEST-<world>.xml, where <world> is the value of the --world option.  (default: cxxtest)")
+    parser.add_option("", "--have-std",
+                      action="store_true", dest="haveStandardLibrary", default=False,
+                      help="Use the standard library (even if not found in tests).")
+    parser.add_option("", "--no-std",
+                      action="store_true", dest="noStandardLibrary", default=False,
+                      help="Do not use standard library (even if found in tests).")
+    parser.add_option("", "--have-eh",
+                      action="store_true", dest="haveExceptionHandling", default=False,
+                      help="Use exception handling (even if not found in tests).")
+    parser.add_option("", "--no-eh",
+                      action="store_true", dest="noExceptionHandling", default=False,
+                      help="Do not use exception handling (even if found in tests).")
+    parser.add_option("", "--longlong",
+                      dest="longlong", default=None, metavar="TYPE",
+                      help="Use TYPE as for long long integers.  (default: not supported)")
+    parser.add_option("", "--no-static-init",
+                      action="store_true", dest="noStaticInit", default=False,
+                      help="Do not rely on static initialization in the test runner.")
+    parser.add_option("", "--template",
+                      dest="templateFileName", default=None, metavar="TEMPLATE",
+                      help="Generate the test runner using file TEMPLATE to define a template.")
+    parser.add_option("", "--root",
+                      action="store_true", dest="root", default=False,
+                      help="Write the main() function and global data for a test runner.")
+    parser.add_option("", "--part",
+                      action="store_true", dest="part", default=False,
+                      help="Write the tester classes for a test runner.")
+    #parser.add_option("", "--factor",
+                      #action="store_true", dest="factor", default=False,
+                      #help="Declare the _CXXTEST_FACTOR macro.  (deprecated)")
+    if imported_fog:
+        fog_help = "Use new FOG C++ parser"
+    else:
+        fog_help = "Use new FOG C++ parser (disabled)"
+    parser.add_option("-f", "--fog-parser",
+                        action="store_true",
+                        dest="fog",
+                        default=False,
+                        help=fog_help
+                        )
+
+    (options, args) = parser.parse_args(args=args)
+    if not options.header_filename is None:
+        if not os.path.exists(options.header_filename):
+            abort( "ERROR: the file '%s' does not exist!" % options.header_filename )
+        INPUT = open(options.header_filename)
+        headers = [line.strip() for line in INPUT]
+        args.extend( headers )
+        INPUT.close()
+
+    if options.fog and not imported_fog:
+        abort( "Cannot use the FOG parser.  Check that the 'ply' package is installed.  The 'ordereddict' package is also required if running Python 2.6")
+
+    if options.version:
+      printVersion()
+
+    # the cxxtest builder relies on this behaviour! don't remove
+    if options.runner == 'none':
+        options.runner = None
+
+    if options.xunit_printer or options.runner == "XUnitPrinter":
+        options.xunit_printer=True
+        options.runner="XUnitPrinter"
+        if len(args) > 1:
+            if options.xunit_file == "":
+                if options.world == "":
+                    options.world = "cxxtest"
+                options.xunit_file="TEST-"+options.world+".xml"
+        elif options.xunit_file == "":
+            if options.world == "":
+                options.world = "cxxtest"
+            options.xunit_file="TEST-"+options.world+".xml"
+
+    if options.error_printer:
+      options.runner= "ErrorPrinter"
+      options.haveStandardLibrary = True
+    
+    if options.noStaticInit and (options.root or options.part):
+        abort( '--no-static-init cannot be used with --root/--part' )
+
+    if options.gui and not options.runner:
+        options.runner = 'StdioPrinter'
+
+    files = setFiles(args[1:])
+    if len(files) == 0 and not options.root:
+        sys.stderr.write(parser.error("No input files found"))
+
+    return files
+
+
+def printVersion():
+    '''Print CxxTest version and exit'''
+    sys.stdout.write( "This is CxxTest version %s.\n" % __release__.__version__ )
+    sys.exit(0)
+
+def setFiles(patterns ):
+    '''Set input files specified on command line'''
+    files = expandWildcards( patterns )
+    return files
+
+def expandWildcards( patterns ):
+    '''Expand all wildcards in an array (glob)'''
+    fileNames = []
+    for pathName in patterns:
+        patternFiles = glob.glob( pathName )
+        for fileName in patternFiles:
+            fileNames.append( fixBackslashes( fileName ) )
+    return fileNames
+
+def fixBackslashes( fileName ):
+    '''Convert backslashes to slashes in file name'''
+    return re.sub( r'\\', '/', fileName, 0 )
+
+
+def writeOutput():
+    '''Create output file'''
+    if options.templateFileName:
+        writeTemplateOutput()
+    else:
+        writeSimpleOutput()
+
+def writeSimpleOutput():
+    '''Create output not based on template'''
+    output = startOutputFile()
+    writePreamble( output )
+    if options.root or not options.part:
+        writeMain( output )
+
+    if len(suites) > 0:
+        output.write("bool "+suites[0]['object']+"_init = false;\n")
+
+    writeWorld( output )
+    output.close()
+
+include_re = re.compile( r"\s*\#\s*include\s+<cxxtest/" )
+preamble_re = re.compile( r"^\s*<CxxTest\s+preamble>\s*$" )
+world_re = re.compile( r"^\s*<CxxTest\s+world>\s*$" )
+def writeTemplateOutput():
+    '''Create output based on template file'''
+    template = open(options.templateFileName)
+    output = startOutputFile()
+    while 1:
+        line = template.readline()
+        if not line:
+            break;
+        if include_re.search( line ):
+            writePreamble( output )
+            output.write( line )
+        elif preamble_re.search( line ):
+            writePreamble( output )
+        elif world_re.search( line ):
+            if len(suites) > 0:
+                output.write("bool "+suites[0]['object']+"_init = false;\n")
+            writeWorld( output )
+        else:
+            output.write( line )
+    template.close()
+    output.close()
+
+def startOutputFile():
+    '''Create output file and write header'''
+    if options.outputFileName is not None:
+        output = open( options.outputFileName, 'w' )
+    else:
+        output = sys.stdout
+    output.write( "/* Generated file, do not edit */\n\n" )
+    return output
+
+def writePreamble( output ):
+    '''Write the CxxTest header (#includes and #defines)'''
+    global wrotePreamble
+    if wrotePreamble: return
+    output.write( "#ifndef CXXTEST_RUNNING\n" )
+    output.write( "#define CXXTEST_RUNNING\n" )
+    output.write( "#endif\n" )
+    output.write( "\n" )
+    if options.xunit_printer:
+        output.write( "#include <fstream>\n" )
+    if options.haveStandardLibrary:
+        output.write( "#define _CXXTEST_HAVE_STD\n" )
+    if options.haveExceptionHandling:
+        output.write( "#define _CXXTEST_HAVE_EH\n" )
+    if options.abortOnFail:
+        output.write( "#define _CXXTEST_ABORT_TEST_ON_FAIL\n" )
+    if options.longlong:
+        output.write( "#define _CXXTEST_LONGLONG %s\n" % options.longlong )
+    #if options.factor:
+        #output.write( "#define _CXXTEST_FACTOR\n" )
+    for header in options.headers:
+        output.write( "#include \"%s\"\n" % header )
+    output.write( "#include <cxxtest/TestListener.h>\n" )
+    output.write( "#include <cxxtest/TestTracker.h>\n" )
+    output.write( "#include <cxxtest/TestRunner.h>\n" )
+    output.write( "#include <cxxtest/RealDescriptions.h>\n" )
+    output.write( "#include <cxxtest/TestMain.h>\n" )
+    if options.runner:
+        output.write( "#include <cxxtest/%s.h>\n" % options.runner )
+    if options.gui:
+        output.write( "#include <cxxtest/%s.h>\n" % options.gui )
+    output.write( "\n" )
+    wrotePreamble = 1
+
+def writeMain( output ):
+    '''Write the main() function for the test runner'''
+    if not (options.gui or options.runner):
+       return
+    output.write( 'int %s( int argc, char *argv[] ) {\n' % options.main )
+    output.write( ' int status;\n' )
+    if options.noStaticInit:
+        output.write( ' CxxTest::initialize();\n' )
+    if options.gui:
+        tester_t = "CxxTest::GuiTuiRunner<CxxTest::%s, CxxTest::%s> " % (options.gui, options.runner)
+    else:
+        tester_t = "CxxTest::%s" % (options.runner)
+    if options.xunit_printer:
+       output.write( '    std::ofstream ofstr("%s");\n' % options.xunit_file )
+       output.write( '    %s tmp(ofstr);\n' % tester_t )
+       output.write( '    CxxTest::RealWorldDescription::_worldName = "%s";\n' % options.world )
+    else:
+       output.write( '    %s tmp;\n' % tester_t )
+    output.write( '    status = CxxTest::Main<%s>( tmp, argc, argv );\n' % tester_t )
+    output.write( '    return status;\n')
+    output.write( '}\n' )
+
+
+def writeWorld( output ):
+    '''Write the world definitions'''
+    global wroteWorld
+    if wroteWorld: return
+    writePreamble( output )
+    writeSuites( output )
+    if options.root or not options.part:
+        writeRoot( output )
+        writeWorldDescr( output )
+    if options.noStaticInit:
+        writeInitialize( output )
+    wroteWorld = 1
+
+def writeSuites(output):
+    '''Write all TestDescriptions and SuiteDescriptions'''
+    for suite in suites:
+        writeInclude( output, suite['file'] )
+        if isGenerated(suite):
+            generateSuite( output, suite )
+        if isDynamic(suite):
+            writeSuitePointer( output, suite )
+        else:
+            writeSuiteObject( output, suite )
+        writeTestList( output, suite )
+        writeSuiteDescription( output, suite )
+        writeTestDescriptions( output, suite )
+
+def isGenerated(suite):
+    '''Checks whether a suite class should be created'''
+    return suite['generated']
+
+def isDynamic(suite):
+    '''Checks whether a suite is dynamic'''
+    return 'create' in suite
+
+def writeInclude(output, file):
+    '''Add #include "file" statement'''
+    global lastIncluded
+    if file == lastIncluded: return
+    output.writelines( [ '#include "', file, '"\n\n' ] )
+    lastIncluded = file
+
+def generateSuite( output, suite ):
+    '''Write a suite declared with CXXTEST_SUITE()'''
+    output.write( 'class %s : public CxxTest::TestSuite {\n' % suite['name'] )
+    output.write( 'public:\n' )
+    for line in suite['lines']:
+        output.write(line)
+    output.write( '};\n\n' )
+
+def writeSuitePointer( output, suite ):
+    '''Create static suite pointer object for dynamic suites'''
+    if options.noStaticInit:
+        output.write( 'static %s *%s;\n\n' % (suite['name'], suite['object']) )
+    else:
+        output.write( 'static %s *%s = 0;\n\n' % (suite['name'], suite['object']) )
+
+def writeSuiteObject( output, suite ):
+    '''Create static suite object for non-dynamic suites'''
+    output.writelines( [ "static ", suite['name'], " ", suite['object'], ";\n\n" ] )
+
+def writeTestList( output, suite ):
+    '''Write the head of the test linked list for a suite'''
+    if options.noStaticInit:
+        output.write( 'static CxxTest::List %s;\n' % suite['tlist'] )
+    else:
+        output.write( 'static CxxTest::List %s = { 0, 0 };\n' % suite['tlist'] )
+
+def writeWorldDescr( output ):
+    '''Write the static name of the world name'''
+    if options.noStaticInit:
+        output.write( 'const char* CxxTest::RealWorldDescription::_worldName;\n' )
+    else:
+        output.write( 'const char* CxxTest::RealWorldDescription::_worldName = "cxxtest";\n' )
+
+def writeTestDescriptions( output, suite ):
+    '''Write all test descriptions for a suite'''
+    for test in suite['tests']:
+        writeTestDescription( output, suite, test )
+
+def writeTestDescription( output, suite, test ):
+    '''Write test description object'''
+    output.write( 'static class %s : public CxxTest::RealTestDescription {\n' % test['class'] )
+    output.write( 'public:\n' )
+    if not options.noStaticInit:
+        output.write( ' %s() : CxxTest::RealTestDescription( %s, %s, %s, "%s" ) {}\n' %
+                      (test['class'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
+    output.write( ' void runTest() { %s }\n' % runBody( suite, test ) )
+    output.write( '} %s;\n\n' % test['object'] )
+
+def runBody( suite, test ):
+    '''Body of TestDescription::run()'''
+    if isDynamic(suite): return dynamicRun( suite, test )
+    else: return staticRun( suite, test )
+
+def dynamicRun( suite, test ):
+    '''Body of TestDescription::run() for test in a dynamic suite'''
+    return 'if ( ' + suite['object'] + ' ) ' + suite['object'] + '->' + test['name'] + '();'
+    
+def staticRun( suite, test ):
+    '''Body of TestDescription::run() for test in a non-dynamic suite'''
+    return suite['object'] + '.' + test['name'] + '();'
+    
+def writeSuiteDescription( output, suite ):
+    '''Write SuiteDescription object'''
+    if isDynamic( suite ):
+        writeDynamicDescription( output, suite )
+    else:
+        writeStaticDescription( output, suite )
+
+def writeDynamicDescription( output, suite ):
+    '''Write SuiteDescription for a dynamic suite'''
+    output.write( 'CxxTest::DynamicSuiteDescription<%s> %s' % (suite['name'], suite['dobject']) )
+    if not options.noStaticInit:
+        output.write( '( %s, %s, "%s", %s, %s, %s, %s )' %
+                      (suite['cfile'], suite['line'], suite['name'], suite['tlist'],
+                       suite['object'], suite['create'], suite['destroy']) )
+    output.write( ';\n\n' )
+
+def writeStaticDescription( output, suite ):
+    '''Write SuiteDescription for a static suite'''
+    output.write( 'CxxTest::StaticSuiteDescription %s' % suite['dobject'] )
+    if not options.noStaticInit:
+        output.write( '( %s, %s, "%s", %s, %s )' %
+                      (suite['cfile'], suite['line'], suite['name'], suite['object'], suite['tlist']) )
+    output.write( ';\n\n' )
+
+def writeRoot(output):
+    '''Write static members of CxxTest classes'''
+    output.write( '#include <cxxtest/Root.cpp>\n' )
+
+def writeInitialize(output):
+    '''Write CxxTest::initialize(), which replaces static initialization'''
+    output.write( 'namespace CxxTest {\n' )
+    output.write( ' void initialize()\n' )
+    output.write( ' {\n' )
+    for suite in suites:
+        output.write( '  %s.initialize();\n' % suite['tlist'] )
+        if isDynamic(suite):
+            output.write( '  %s = 0;\n' % suite['object'] )
+            output.write( '  %s.initialize( %s, %s, "%s", %s, %s, %s, %s );\n' %
+                          (suite['dobject'], suite['cfile'], suite['line'], suite['name'],
+                           suite['tlist'], suite['object'], suite['create'], suite['destroy']) )
+        else:
+            output.write( '  %s.initialize( %s, %s, "%s", %s, %s );\n' %
+                          (suite['dobject'], suite['cfile'], suite['line'], suite['name'],
+                           suite['object'], suite['tlist']) )
+
+        for test in suite['tests']:
+            output.write( '  %s.initialize( %s, %s, %s, "%s" );\n' %
+                          (test['object'], suite['tlist'], suite['dobject'], test['line'], test['name']) )
+
+    output.write( ' }\n' )
+    output.write( '}\n' )
+
diff --git a/tools/cxxtest/python/python3/scripts/cxxtestgen b/tools/cxxtest/python/python3/scripts/cxxtestgen
new file mode 100644 (file)
index 0000000..74090ec
--- /dev/null
@@ -0,0 +1,5 @@
+#! python
+
+import cxxtest.cxxtestgen
+
+cxxtest.cxxtestgen.main()
diff --git a/tools/cxxtest/python/scripts/cxxtestgen b/tools/cxxtest/python/scripts/cxxtestgen
new file mode 100644 (file)
index 0000000..74090ec
--- /dev/null
@@ -0,0 +1,5 @@
+#! python
+
+import cxxtest.cxxtestgen
+
+cxxtest.cxxtestgen.main()
diff --git a/tools/cxxtest/python/setup.py b/tools/cxxtest/python/setup.py
new file mode 100644 (file)
index 0000000..cb923f7
--- /dev/null
@@ -0,0 +1,53 @@
+"""
+Script to generate the installer for cxxtest.
+"""
+
+classifiers = """\
+Development Status :: 4 - Beta
+Intended Audience :: End Users/Desktop
+License :: OSI Approved :: LGPL License
+Natural Language :: English
+Operating System :: Microsoft :: Windows
+Operating System :: Unix
+Programming Language :: Python
+Topic :: Software Development :: Libraries :: Python Modules
+"""
+
+import os
+import sys
+from os.path import realpath, dirname
+if sys.version_info >= (3,0):
+    sys.path.insert(0, dirname(realpath(__file__))+os.sep+'python3')
+    os.chdir('python3')
+
+import cxxtest
+
+try:
+    from setuptools import setup
+except ImportError:
+    from distutils.core import setup
+
+doclines = cxxtest.__doc__.split("\n")
+
+setup(name="cxxtest",
+      version=cxxtest.__version__,
+      maintainer=cxxtest.__maintainer__,
+      maintainer_email=cxxtest.__maintainer_email__,
+      url = cxxtest.__url__,
+      license = cxxtest.__license__,
+      platforms = ["any"],
+      description = doclines[0],
+      classifiers = filter(None, classifiers.split("\n")),
+      long_description = "\n".join(doclines[2:]),
+      packages=['cxxtest'],
+      keywords=['utility'],
+      scripts=['scripts/cxxtestgen']
+      #
+      # The entry_points option is not supported by distutils.core
+      #
+      #entry_points="""
+        #[console_scripts]
+        #cxxtestgen = cxxtest.cxxtestgen:main
+      #"""
+      )
+
diff --git a/tools/cxxtest/sample/.cvsignore b/tools/cxxtest/sample/.cvsignore
new file mode 100644 (file)
index 0000000..087c5dc
--- /dev/null
@@ -0,0 +1,5 @@
+.consign
+Makefile 
+*_runner*
+tests.cpp error_printer.cpp stdio_printer.cpp file_printer.cpp aborter.cpp only.cpp
+error_printer stdio_printer file_printer aborter only
diff --git a/tools/cxxtest/sample/Construct b/tools/cxxtest/sample/Construct
new file mode 100644 (file)
index 0000000..6090225
--- /dev/null
@@ -0,0 +1,64 @@
+# -*- Perl -*-
+
+#
+# This file shows how to use CxxTest with Cons
+#
+
+$env = new cons( CXX => ("$^O" eq 'MSWin32') ? 'cl -nologo -GX' : 'c++',
+                CPPPATH => '..',
+                CXXTESTGEN => '../bin/cxxtestgen' );
+
+@tests = <*.h>;
+
+# The error printer is the most basic runner
+CxxTestErrorPrinter $env 'error_printer', @tests;
+
+# You can also specify which runner you want to use
+CxxTestRunner       $env 'stdio_printer', 'StdioPrinter', @tests;
+
+# For more control, use template files
+CxxTestTemplate     $env 'file_printer', 'file_printer.tpl', @tests;
+
+# Or, you can always separate the tests from the runner
+CxxTest             $env 'tests.cpp', '', @tests;
+Program             $env 'yes_no_runner', ('yes_no_runner.cpp', 'tests.cpp');
+
+
+#
+# Here is the code used to build these files
+# You can use this in your own Construct files
+#
+
+# cons::CxxTest $env $dst, $options, @srcs
+# Generates a CxxTest source file, passing the specified options to cxxtestgen
+sub cons::CxxTest($$$@) {
+  my ($env, $dst, $options, @srcs) = @_;
+  Command $env $dst, @srcs, "%CXXTESTGEN -o %> ${options} %<";
+}
+
+# cons::CxxTestTemplate $env $dst, $template, @srcs
+# Generates and builds a CxxTest runner using a template file
+sub cons::CxxTestTemplate($$$@) {
+  my ($env, $dst, $template, @srcs) = @_;
+  my $source = "${dst}.cpp";
+  CxxTest $env $source, "--template=${template}", ($template, @srcs);
+  Program $env $dst, $source;
+}
+
+# cons::CxxTestRunner $env $dst, $runner, @srcs
+# Generates and builds a CxxTest runner using the --runner option
+sub cons::CxxTestRunner($$$@) {
+  my ($env, $dst, $runner, @srcs) = @_;
+  my $source = "${dst}.cpp";
+  CxxTest $env $source, "--runner=${runner}", @srcs;
+  Program $env $dst, $source;
+}
+
+# cons::CxxTestErrorPrinter $env $dst, @srcs
+# Generates and builds a CxxTest ErrorPrinter
+sub cons::CxxTestErrorPrinter($$@) {
+  my ($env, $dst, @srcs) = @_;
+  CxxTestRunner $env $dst, 'ErrorPrinter', @srcs;
+}
+
+
diff --git a/tools/cxxtest/sample/CreatedTest.h b/tools/cxxtest/sample/CreatedTest.h
new file mode 100644 (file)
index 0000000..84e8ae8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __CREATEDTEST_H
+#define __CREATEDTEST_H
+
+#include <cxxtest/TestSuite.h>
+#include <string.h>
+#include <memory.h>
+
+//
+// This test suite shows what to do when your test case
+// class cannot be instantiated statically.
+// As an example, this test suite requires a non-default constructor.
+//
+
+class CreatedTest : public CxxTest::TestSuite
+{
+    char *_buffer;
+public:
+    CreatedTest( unsigned size ) : _buffer( new char[size] ) {}
+    virtual ~CreatedTest() { delete [] _buffer; }
+    
+    static CreatedTest *createSuite() { return new CreatedTest( 16 ); }
+    static void destroySuite( CreatedTest *suite ) { delete suite; }
+
+    void test_nothing()
+    {
+        TS_FAIL( "Nothing to test" );
+    }
+};
+
+
+#endif // __CREATEDTEST_H
diff --git a/tools/cxxtest/sample/DeltaTest.h b/tools/cxxtest/sample/DeltaTest.h
new file mode 100644 (file)
index 0000000..7223c3a
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __DELTATEST_H
+#define __DELTATEST_H
+
+#include <cxxtest/TestSuite.h>
+#include <math.h>
+
+class DeltaTest : public CxxTest::TestSuite
+{
+    double _pi, _delta;
+    
+public:
+    void setUp()
+    {
+        _pi = 3.1415926535;
+        _delta = 0.0001;
+    }
+
+    void testSine()
+    {
+        TS_ASSERT_DELTA( sin(0.0), 0.0, _delta );
+        TS_ASSERT_DELTA( sin(_pi / 6), 0.5, _delta );
+        TS_ASSERT_DELTA( sin(_pi / 2), 1.0, _delta );
+        TS_ASSERT_DELTA( sin(_pi), 0.0, _delta );
+    }
+};
+
+#endif // __DELTATEST_H
diff --git a/tools/cxxtest/sample/EnumTraits.h b/tools/cxxtest/sample/EnumTraits.h
new file mode 100644 (file)
index 0000000..1a98731
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// This is a test of CxxTest's ValueTraits for enumerations.
+//
+#include <cxxtest/TestSuite.h>
+
+//
+// First define your enumeration
+//
+enum Answer {
+    Yes,
+    No,
+    Maybe,
+    DontKnow,
+    DontCare
+};
+
+//
+// Now make CxxTest aware of it
+//
+CXXTEST_ENUM_TRAITS( Answer,
+                     CXXTEST_ENUM_MEMBER( Yes )
+                     CXXTEST_ENUM_MEMBER( No )
+                     CXXTEST_ENUM_MEMBER( Maybe )
+                     CXXTEST_ENUM_MEMBER( DontKnow )
+                     CXXTEST_ENUM_MEMBER( DontCare ) );
+
+class EnumTraits : public CxxTest::TestSuite
+{
+public:
+    void test_Enum_traits()
+    {
+        TS_FAIL( Yes );
+        TS_FAIL( No );
+        TS_FAIL( Maybe );
+        TS_FAIL( DontKnow );
+        TS_FAIL( DontCare );
+        TS_FAIL( (Answer)1000 );
+    }
+};
diff --git a/tools/cxxtest/sample/ExceptionTest.h b/tools/cxxtest/sample/ExceptionTest.h
new file mode 100644 (file)
index 0000000..68363c8
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __EXCEPTIONTEST_H
+#define __EXCEPTIONTEST_H
+
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite demonstrates the use of TS_ASSERT_THROWS
+//
+
+class ExceptionTest : public CxxTest::TestSuite
+{
+public:
+    void testAssertion( void )
+    {
+        // This assert passes, since throwThis() throws (Number)
+        TS_ASSERT_THROWS( throwThis(3), const Number & );
+        // This assert passes, since throwThis() throws something
+        TS_ASSERT_THROWS_ANYTHING( throwThis(-30) );
+        // This assert fails, since throwThis() doesn't throw char *
+        TS_ASSERT_THROWS( throwThis(5), const char * );
+        // This assert fails since goodFunction() throws nothing
+        TS_ASSERT_THROWS_ANYTHING( goodFunction(1) );
+        // The regular TS_ASSERT macros will catch unhandled exceptions
+        TS_ASSERT_EQUALS( throwThis(3), 333 );
+        // You can assert that a function throws nothing
+        TS_ASSERT_THROWS_NOTHING( throwThis(-1) );
+        // If you want to catch the exceptions yourself, use the ETS_ marcos
+        try {
+            ETS_ASSERT_EQUALS( throwThis(3), 333 );
+        } catch( const Number & ) {
+            TS_FAIL( "throwThis(3) failed" );
+        }
+    }
+
+private:
+    void goodFunction( int )
+    {
+    }
+
+    class Number
+    {
+    public:
+        Number( int ) {}
+    };
+    
+    int throwThis( int i )
+    {
+        throw Number( i );
+    }
+};
+
+#endif // __EXCEPTIONTEST_H
diff --git a/tools/cxxtest/sample/FixtureTest.h b/tools/cxxtest/sample/FixtureTest.h
new file mode 100644 (file)
index 0000000..653c7a1
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __FIXTURETEST_H
+#define __FIXTURETEST_H
+
+#include <cxxtest/TestSuite.h>
+#include <string.h>
+
+//
+// This test suite shows how to use setUp() and tearDown()
+// to initialize data common to all tests.
+// setUp()/tearDown() will be called before and after each
+// test.
+//
+
+class FixtureTest : public CxxTest::TestSuite
+{
+    char *_buffer;
+public:
+    void setUp()
+    {
+        _buffer = new char[1024];
+    }
+    
+    void tearDown()
+    {
+        delete [] _buffer;
+    }
+
+    void test_strcpy()
+    {
+        strcpy( _buffer, "Hello, world!" );
+        TS_ASSERT_EQUALS( _buffer[0], 'H' );
+        TS_ASSERT_EQUALS( _buffer[1], 'E' );
+    }
+};
+
+
+#endif // __FIXTURETEST_H
diff --git a/tools/cxxtest/sample/Makefile.PL b/tools/cxxtest/sample/Makefile.PL
new file mode 100644 (file)
index 0000000..d29afcc
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+#
+# This isn't a "real" `Makefile.PL'
+# It just copies the correct `Makefile.*' to `Makefile'
+#
+use strict;
+use Getopt::Long;
+use File::Copy;
+
+sub usage() {
+  die "Usage: $0 [--bcc32]\n";
+}
+
+my $source;
+my $target = 'Makefile';
+my $windows = $ENV{'windir'};
+
+GetOptions( 'bcc32' => sub { $source = 'Makefile.bcc32'  } ) or usage();
+if ( !defined( $source ) ) {
+  $source = $windows ? 'Makefile.msvc' : 'Makefile.unix';
+}
+
+unlink($target);
+$windows ? copy($source, $target) : symlink($source, $target);
+
+print "`Makefile' is now `$source'.\n";
+
+#
+# Local Variables:
+# compile-command: "perl Makefile.PL"
+# End:
+#
diff --git a/tools/cxxtest/sample/Makefile.bcc32 b/tools/cxxtest/sample/Makefile.bcc32
new file mode 100644 (file)
index 0000000..3bd5303
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# Makefile for Borland C++
+# Make sure bcc32.exe is in the PATH or change CXXC below
+#
+
+# For the Win32 GUI
+#WIN32_FLAGS = user32.lib comctl32.lib
+
+# For the Qt GUI
+#QTDIR = c:\qt
+QT_FLAGS = -I$(QTDIR)/include $(QTDIR)/lib/qt.lib
+
+
+TARGETS = error_printer.exe stdio_printer.exe yes_no_runner.exe file_printer.exe aborter.exe only.exe
+GUI_TARGETS = win32_runner.exe qt_runner.exe
+TESTS = *.h
+GUI_TESTS = gui/GreenYellowRed.h $(TESTS)
+TESTGEN = ../bin/cxxtestgen
+CXXC = bcc32.exe -w- -I. -I..
+
+all: $(TARGETS)
+
+clean:
+       del *~ *.o *.obj 
+       del $(TARGETS) 
+       del $(GUI_TARGETS)
+       del tests.cpp error_printer.cpp stdio_printer.cpp file_printer.cpp aborter.cpp only.cpp
+       del win32_runner.cpp qt_runner.cpp
+
+distclean: clean
+       del Makefile
+
+run: error_printer.exe
+       error_printer.exe
+
+run_win32: win32_runner.exe
+       win32_runner.exe
+
+run_qt: qt_runner.exe
+       qt_runner.exe
+
+error_printer.cpp: $(TESTS)
+       $(TESTGEN) -o error_printer.cpp --error-printer $(TESTS)
+
+stdio_printer.cpp: $(TESTS)
+       $(TESTGEN) -o stdio_printer.cpp --runner=StdioPrinter $(TESTS)
+
+file_printer.cpp: file_printer.tpl $(TESTS)
+       $(TESTGEN) -o file_printer.cpp --template=file_printer.tpl $(TESTS)
+
+aborter.cpp: aborter.tpl $(TESTS)
+       $(TESTGEN) -o aborter.cpp --template=aborter.tpl $(TESTS)
+
+only.cpp: only.tpl $(TESTS)
+       $(TESTGEN) -o only.cpp --template=only.tpl $(TESTS)
+
+tests.cpp: $(TESTS)
+       $(TESTGEN) -o tests.cpp $(TESTS)
+
+win32_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o win32_runner.cpp --gui=Win32Gui $(GUI_TESTS)
+
+qt_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o qt_runner.cpp --gui=QtGui $(GUI_TESTS)
+
+error_printer.exe: error_printer.cpp
+       $(CXXC) -eerror_printer.exe error_printer.cpp
+
+stdio_printer.exe: stdio_printer.cpp
+       $(CXXC) -estdio_printer.exe stdio_printer.cpp
+
+file_printer.exe: file_printer.cpp
+       $(CXXC) -efile_printer.exe file_printer.cpp
+
+only.exe: only.cpp
+       $(CXXC) -eonly.exe only.cpp
+
+aborter.exe: aborter.cpp
+       $(CXXC) -eaborter.exe aborter.cpp
+
+yes_no_runner.exe: yes_no_runner.cpp tests.cpp
+       $(CXXC) -eyes_no_runner.exe yes_no_runner.cpp tests.cpp
+
+win32_runner.exe: win32_runner.cpp
+       $(CXXC) -ewin32_runner.exe win32_runner.cpp $(WIN32_FLAGS)
+
+qt_runner.exe: qt_runner.cpp
+       $(CXXC) -o qt_runner.exe qt_runner.cpp $(QT_FLAGS)
+
+#
+# Local Variables:
+# compile-command: "make -fMakefile.bcc32"
+# End:
+#
diff --git a/tools/cxxtest/sample/Makefile.msvc b/tools/cxxtest/sample/Makefile.msvc
new file mode 100644 (file)
index 0000000..2374f80
--- /dev/null
@@ -0,0 +1,93 @@
+#
+# Makefile for Microsoft Visual C++
+# Make sure cl.exe is in the PATH (run vcvars.bat) or change CXXC below
+#
+
+# For the Win32 GUI
+WIN32_FLAGS = user32.lib
+
+# For the Qt GUI
+# QTDIR = c:\qt
+QT_FLAGS = -I$(QTDIR)/include $(QTDIR)/lib/qt.lib
+
+TARGETS = error_printer.exe stdio_printer.exe yes_no_runner.exe file_printer.exe aborter.exe only.exe
+GUI_TARGETS = win32_runner.exe qt_runner.exe
+TESTS = *.h
+GUI_TESTS = gui/GreenYellowRed.h $(TESTS)
+TESTGEN = python ../bin/cxxtestgen
+CXXC = cl.exe -GX -W3 -WX -I. -I..
+
+all: $(TARGETS)
+
+clean:
+       del *~ *.o *.obj 
+       del $(TARGETS) 
+       del $(GUI_TARGETS)
+       del tests.cpp error_printer.cpp stdio_printer.cpp file_printer.cpp aborter.cpp only.cpp
+       del win32_runner.cpp qt_runner.cpp
+
+distclean: clean
+       del Makefile
+
+run: error_printer.exe
+       error_printer.exe
+
+run_win32: win32_runner.exe
+       win32_runner.exe
+
+run_qt: qt_runner.exe
+       qt_runner.exe
+
+error_printer.cpp: $(TESTS)
+       $(TESTGEN) -o error_printer.cpp --error-printer $(TESTS)
+
+stdio_printer.cpp: $(TESTS)
+       $(TESTGEN) -o stdio_printer.cpp --runner=StdioPrinter $(TESTS)
+
+file_printer.cpp: file_printer.tpl $(TESTS)
+       $(TESTGEN) -o file_printer.cpp --template=file_printer.tpl $(TESTS)
+
+aborter.cpp: aborter.tpl $(TESTS)
+       $(TESTGEN) -o aborter.cpp --template=aborter.tpl $(TESTS)
+
+only.cpp: only.tpl $(TESTS)
+       $(TESTGEN) -o only.cpp --template=only.tpl $(TESTS)
+
+tests.cpp: $(TESTS)
+       $(TESTGEN) -o tests.cpp $(TESTS)
+
+win32_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o win32_runner.cpp --gui=Win32Gui $(GUI_TESTS)
+
+qt_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o qt_runner.cpp --gui=QtGui $(GUI_TESTS)
+
+error_printer.exe: error_printer.cpp
+       $(CXXC) -o error_printer.exe error_printer.cpp
+
+stdio_printer.exe: stdio_printer.cpp
+       $(CXXC) -o stdio_printer.exe stdio_printer.cpp
+
+file_printer.exe: file_printer.cpp
+       $(CXXC) -o file_printer.exe file_printer.cpp
+
+only.exe: only.cpp
+       $(CXXC) -o only.exe only.cpp
+
+aborter.exe: aborter.cpp
+       $(CXXC) -o aborter.exe aborter.cpp
+
+yes_no_runner.exe: yes_no_runner.cpp tests.cpp
+       $(CXXC) -o yes_no_runner.exe yes_no_runner.cpp tests.cpp
+
+win32_runner.exe: win32_runner.cpp
+       $(CXXC) -o win32_runner.exe win32_runner.cpp $(WIN32_FLAGS)
+
+qt_runner.exe: qt_runner.cpp
+       $(CXXC) -o qt_runner.exe qt_runner.cpp $(QT_FLAGS)
+
+#
+# Local Variables:
+# compile-command: "nmake -fMakefile.msvc"
+# End:
+#
diff --git a/tools/cxxtest/sample/Makefile.unix b/tools/cxxtest/sample/Makefile.unix
new file mode 100644 (file)
index 0000000..ad87b3b
--- /dev/null
@@ -0,0 +1,83 @@
+#
+# Makefile for UN*X-like systems
+#
+
+# Change this line if you want a different compiler
+CXXC = c++ -Wall -W -Werror -I. -I..
+
+TESTGEN = ../bin/cxxtestgen
+
+# For the X11 GUI
+X11_FLAGS = -I/usr/X11R6/include -L/usr/X11R6/lib -lX11
+
+# For the Qt GUI
+#QTDIR = /usr/lib/qt
+QTLIB = -lqt-mt
+#QTLIB = -lqt
+QT_FLAGS = -I$(QTDIR)/include -L$(QTDIR)/lib $(QTLIB) -O2
+
+TARGETS = error_printer stdio_printer yes_no_runner file_printer aborter only
+GUI_TARGETS = x11_runner qt_runner
+TESTS = *.h
+GUI_TESTS = gui/GreenYellowRed.h $(TESTS)
+
+all: $(TARGETS)
+
+clean:
+       rm -f *~ *.o *.obj $(TARGETS) $(GUI_TARGETS)
+       rm -f tests.cpp error_printer.cpp stdio_printer.cpp file_printer.cpp aborter.cpp only.cpp
+       rm -f x11_runner.cpp qt_runner.cpp
+
+distclean: clean
+       rm -f Makefile
+
+run: error_printer
+       ./error_printer
+
+run_x11: x11_runner
+       ./x11_runner
+
+run_qt: qt_runner
+       ./qt_runner
+
+error_printer.cpp: $(TESTS)
+       $(TESTGEN) -o $@ --error-printer $(TESTS)
+
+stdio_printer.cpp: $(TESTS)
+       $(TESTGEN) -o $@ --runner=StdioPrinter $(TESTS)
+
+file_printer.cpp: file_printer.tpl $(TESTS)
+       $(TESTGEN) -o $@ --template=file_printer.tpl $(TESTS)
+
+aborter.cpp: aborter.tpl $(TESTS)
+       $(TESTGEN) -o $@ --template=aborter.tpl $(TESTS)
+
+only.cpp: only.tpl $(TESTS)
+       $(TESTGEN) -o $@ --template=only.tpl $(TESTS)
+
+tests.cpp: $(TESTS)
+       $(TESTGEN) -o $@ $(TESTS)
+
+x11_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o $@ --gui=X11Gui $(GUI_TESTS)
+
+qt_runner.cpp: $(GUI_TESTS)
+       $(TESTGEN) -o $@ --gui=QtGui $(GUI_TESTS)
+
+%: %.cpp
+       $(CXXC) -o $@ $<
+
+yes_no_runner: yes_no_runner.cpp tests.cpp
+       $(CXXC) -o $@ $^
+
+x11_runner: x11_runner.cpp
+       $(CXXC) -o $@ $^ $(X11_FLAGS)
+
+qt_runner: qt_runner.cpp
+       $(CXXC) -o $@ $^ $(QT_FLAGS)
+
+#
+# Local Variables:
+# compile-command: "make -fMakefile.unix"
+# End:
+#
diff --git a/tools/cxxtest/sample/MessageTest.h b/tools/cxxtest/sample/MessageTest.h
new file mode 100644 (file)
index 0000000..621289f
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __MESSAGETEST_H
+#define __MESSAGETEST_H
+
+#include <cxxtest/TestSuite.h>
+
+//
+// The [E]TSM_ macros can be used to print a specified message
+// instead of the default one.
+// This is useful when you refactor your tests, as shown below
+//
+
+class MessageTest : public CxxTest::TestSuite
+{
+public:
+    void testValues()
+    {
+        checkValue( 0, "My hovercraft" );
+        checkValue( 1, "is full" );
+        checkValue( 2, "of eels" );
+    }
+
+    void checkValue( unsigned value, const char *message )
+    {
+        TSM_ASSERT( message, value != 0 );
+        TSM_ASSERT_EQUALS( message, value, value * value );
+    }
+};
+
+
+#endif // __MESSAGETEST_H
diff --git a/tools/cxxtest/sample/SCons/SConstruct b/tools/cxxtest/sample/SCons/SConstruct
new file mode 100644 (file)
index 0000000..cb39408
--- /dev/null
@@ -0,0 +1,40 @@
+
+cxxtestbuilder_path = '../../build_tools/SCons/cxxtest.py'
+cxxtest_path = '../..'
+
+# First a bit of python magic to make the CxxTestBuilder available 
+# without having to copy it into a particular path.
+# for nicer examples you *should* use, see the cxxtest builder tests in the 
+# build_tools/SCons/test directory.
+import imp
+cxxtest = imp.load_source('cxxtest', cxxtestbuilder_path)
+
+# First build the 'real' library, when working on an embedded system 
+# this may involve a cross compiler.
+env = Environment()
+env.BuildDir('build/embedded_platform', 'src')
+env.Append(CPPPATH=['include'])
+libtested = env.StaticLibrary('build/embedded_platform/tested', 
+                              env.Glob('build/embedded_platform/*.c'))
+
+# Now create a seperate build environment for the tests so we can keep any
+# options that are specific to testing  seperate from the 'production' build
+# environment. For simplicity I am just copying the production environment.
+# If we are cross compiling for the "real" library, then this 
+# environement might be using the normal compiler.
+env_test = env.Clone()
+
+# Add the CxxTestBuilder to our testing build environment.
+cxxtest.generate(env_test, CXXTEST_INSTALL_DIR = cxxtest_path)
+
+# If we were working with an embedded platform we may want to create a 
+# seperate version of our library that runs on our development box in 
+# order to do our initial unit testing. This version may also include 
+# any special preprocessor defines needed for testing e.g. -DTESTING
+env_test.BuildDir('build/dev_platform', 'src')
+env_test.BuildDir('build/tests', 'tests')
+lib_to_test = env_test.StaticLibrary('build/dev_platform/tested',
+                                     env.Glob('build/dev_platform/*.c'))
+env_test.Append(LIBS=lib_to_test)
+env_test.CxxTest(env_test.Glob('tests/*.h'))
+
diff --git a/tools/cxxtest/sample/SCons/include/stack.h b/tools/cxxtest/sample/SCons/include/stack.h
new file mode 100644 (file)
index 0000000..e73420b
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef STACK_H
+#define STACK_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+  typedef struct stack_t {
+    int size;
+    int* vals;
+    int capacity;
+  } stack_t;
+
+  stack_t* stack_create();
+  void     stack_free(stack_t* stack);
+  int      stack_size(stack_t* stack);
+  void     stack_push(stack_t* stack, int val);
+  int      stack_pop(stack_t* stack);
+  int      stack_peak(stack_t* stack);
+  int      stack_capacity(stack_t* stack);
+
+#ifdef __cplusplus
+  }
+#endif
+
+
+#endif
diff --git a/tools/cxxtest/sample/SCons/src/stack.c b/tools/cxxtest/sample/SCons/src/stack.c
new file mode 100644 (file)
index 0000000..960f8cf
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stack.h>
+
+#include <stdlib.h>
+
+stack_t* stack_create() {
+  stack_t* retVal = malloc(sizeof(stack_t));
+  retVal->size = 0;
+  retVal->capacity = 10;
+  retVal->vals = malloc(retVal->capacity*sizeof(int));
+  return retVal;
+}
+
+void stack_free(stack_t* stack) {
+  free(stack->vals);
+  free(stack);
+}
+
+int stack_size(stack_t* stack) {
+  return stack->size;
+}
+
+void stack_push(stack_t* stack, int val) {
+  if(stack->size == stack->capacity) {
+    stack->capacity *= 2;
+    stack->vals = realloc(stack->vals, stack->capacity*sizeof(int));
+  }
+  stack->vals[stack->size++] = val;
+}
+
+int stack_pop(stack_t* stack) {
+  if (stack->size >= 1)
+    return stack->vals[--stack->size];
+  else
+    return 0;
+}
+
+int stack_peak(stack_t* stack) {
+  if (stack->size >= 1)
+    return stack->vals[stack->size-1];
+  else
+    return 0;
+}
+
+int stack_capacity(stack_t* stack) {
+  return stack->capacity;
+}
+
+
diff --git a/tools/cxxtest/sample/SCons/tests/stack_test.h b/tools/cxxtest/sample/SCons/tests/stack_test.h
new file mode 100644 (file)
index 0000000..24fd6b5
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef STACK_TEST_H
+#define STACK_TEST_H
+
+#include <cxxtest/TestSuite.h>
+#include <stack.h>
+
+class stack_test : public CxxTest::TestSuite
+{
+    
+  private:
+    stack_t* stack;
+  public:
+
+    void setUp() {
+      stack = stack_create();
+    }
+
+    void tearDown() {
+      stack_free(stack);
+    }
+
+    void test_create_stack() {
+      TS_ASSERT_DIFFERS((stack_t*)0, stack);
+    }
+
+    void test_new_stack_is_empty() {
+      TS_ASSERT_EQUALS(0, stack_size(stack));
+    }
+
+    void test_one_push_add_one_to_size() {
+      stack_push(stack, 1);
+      TS_ASSERT_EQUALS(1, stack_size(stack));
+    }
+   
+    void test_push_pop_doesnt_change_size() {
+      stack_push(stack, 1);
+      (void)stack_pop(stack);
+      TS_ASSERT_EQUALS(0, stack_size(stack));      
+    }
+
+    void test_peak_after_push() {
+      stack_push(stack, 1);
+      TS_ASSERT_EQUALS(1, stack_peak(stack))
+    }
+
+    void test_initial_capacity_is_positive() {
+      TS_ASSERT(stack_capacity(stack) > 0);
+    }
+
+    void test_pop_on_empty() {
+      TS_ASSERT_EQUALS(0, stack_pop(stack));
+      TS_ASSERT_EQUALS(0, stack_size(stack));
+    }
+
+    void test_peak_on_empty() {
+      TS_ASSERT_EQUALS(0, stack_peak(stack));
+    }
+
+    void test_capacity_gte_size() {
+      TS_ASSERT_LESS_THAN_EQUALS(stack_size(stack), stack_capacity(stack));
+      int init_capacity = stack_capacity(stack);
+      for (int i=0; i < init_capacity + 1; i++) {
+        stack_push(stack, i);
+      }
+      TS_ASSERT_LESS_THAN_EQUALS(stack_size(stack), stack_capacity(stack));
+    }
+
+};
+
+#endif // STACK_TEST_H
+
diff --git a/tools/cxxtest/sample/SimpleTest.h b/tools/cxxtest/sample/SimpleTest.h
new file mode 100644 (file)
index 0000000..b3fae12
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __SIMPLETEST_H
+#define __SIMPLETEST_H
+
+#include <cxxtest/TestSuite.h>
+
+//
+// A simple test suite: Just inherit CxxTest::TestSuite and write tests!
+//
+
+class SimpleTest : public CxxTest::TestSuite
+{
+public:
+    void testEquality()
+    {
+        TS_ASSERT_EQUALS( 1, 1 );
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 'a', 'A' );
+        TS_ASSERT_EQUALS( 1.0, -12345678900000000000000000000000000000000000000000.1234 );
+    }
+
+    void testAddition()
+    {
+        TS_ASSERT_EQUALS( 1 + 1, 2 );
+        TS_ASSERT_EQUALS( 2 + 2, 5 );
+    }
+
+    void TestMultiplication()
+    {
+        TS_ASSERT_EQUALS( 2 * 2, 4 );
+        TS_ASSERT_EQUALS( 4 * 4, 44 );
+        TS_ASSERT_DIFFERS( -2 * -2, 4 );
+    }
+
+    void testComparison()
+    {
+        TS_ASSERT_LESS_THAN( (int)1, (unsigned long)2 );
+        TS_ASSERT_LESS_THAN( -1, -2 );
+    }
+
+    void testTheWorldIsCrazy()
+    {
+        TS_ASSERT_EQUALS( true, false );
+    }
+
+    void test_Failure()
+    {
+        TS_FAIL( "Not implemented" );
+        TS_FAIL( 1569779912 );
+    }
+
+    void test_TS_WARN_macro()
+    {
+        TS_WARN( "Just a friendly warning" );
+        TS_WARN( "Warnings don't abort the test" );
+    }
+};
+
+
+#endif // __SIMPLETEST_H
diff --git a/tools/cxxtest/sample/TraitsTest.h b/tools/cxxtest/sample/TraitsTest.h
new file mode 100644 (file)
index 0000000..1465938
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __TRAITSTEST_H
+#define __TRAITSTEST_H
+
+//
+// This example shows how to use TS_ASSERT_EQUALS for your own classes
+//
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/ValueTraits.h>
+
+//
+// Define your class with operator==
+//
+#include <stdio.h>
+#include <string.h>
+
+class Pet
+{
+    char _name[128];
+public:
+    Pet( const char *petName ) { strcpy( _name, petName ); }
+
+    const char *name() const { return _name; }
+    
+    bool operator== ( const Pet &other ) const
+    {
+        return !strcmp( name(), other.name() );
+    }
+};
+
+//
+// Instantiate CxxTest::ValueTraits<*your class*>
+// Note: Most compilers do not require that you define both
+//       ValueTraits<const T> and ValueTraits<T>, but some do.
+//
+namespace CxxTest 
+{
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<const Pet>
+    {
+        char _asString[256];
+        
+    public:
+        ValueTraits( const Pet &pet ) { sprintf( _asString, "Pet(\"%s\")", pet.name() ); }
+        const char *asString() const { return _asString; }
+    };
+
+    CXXTEST_COPY_CONST_TRAITS( Pet );
+}
+
+//
+// Here's how it works
+//
+class TestFunky : public CxxTest::TestSuite
+{
+public:
+    void testPets()
+    {
+        Pet pet1("dog"), pet2("cat");
+        TS_ASSERT_EQUALS( pet1, pet2 );
+        Pet cat("cat"), gato("cat");
+        TS_ASSERT_DIFFERS( cat, gato );
+#ifdef _CXXTEST_HAVE_STD
+        typedef CXXTEST_STD(string) String;
+        TS_ASSERT_EQUALS( String("Hello"), String("World!") );
+#endif // _CXXTEST_HAVE_STD
+    }
+};
+
+#endif // __TRAITSTEST_H
diff --git a/tools/cxxtest/sample/aborter.tpl b/tools/cxxtest/sample/aborter.tpl
new file mode 100644 (file)
index 0000000..14fc50d
--- /dev/null
@@ -0,0 +1,16 @@
+// -*- C++ -*-
+// This template file demonstrates the use of CXXTEST_ABORT_TEST_ON_FAIL
+//
+
+#define CXXTEST_HAVE_STD
+#define CXXTEST_ABORT_TEST_ON_FAIL
+#include <cxxtest/ErrorPrinter.h>
+
+int main()
+{
+    return CxxTest::ErrorPrinter().run();
+}
+
+// The CxxTest "world"
+<CxxTest world>
+
diff --git a/tools/cxxtest/sample/file_printer.tpl b/tools/cxxtest/sample/file_printer.tpl
new file mode 100644 (file)
index 0000000..a9627d6
--- /dev/null
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+// This is a sample of a custom test runner
+// using CxxTest template files.
+// This prints the output to a file given on the command line.
+//
+
+#include <cxxtest/StdioPrinter.h>
+#include <stdio.h>
+
+int main( int argc, char *argv[] )
+{
+    if ( argc != 2 ) {
+        fprintf( stderr, "Usage: %s <output file name>\n", argv[0] );
+        return -1;
+    }
+
+    return CxxTest::StdioPrinter( fopen( argv[1], "w" ) ).run();
+}
+
+// The CxxTest "world"
+<CxxTest world>
+
diff --git a/tools/cxxtest/sample/gui/GreenYellowRed.h b/tools/cxxtest/sample/gui/GreenYellowRed.h
new file mode 100644 (file)
index 0000000..446b233
--- /dev/null
@@ -0,0 +1,57 @@
+#include <cxxtest/TestSuite.h>
+
+#ifdef _WIN32
+#   include <windows.h>
+#   define CXXTEST_SAMPLE_GUI_WAIT() Sleep( 1000 )
+#else // !_WIN32
+    extern "C" unsigned sleep( unsigned seconds );
+#   define CXXTEST_SAMPLE_GUI_WAIT() sleep( 1 )
+#endif // _WIN32
+
+class GreenYellowRed : public CxxTest::TestSuite
+{
+public:
+    void wait()
+    {
+        CXXTEST_SAMPLE_GUI_WAIT();
+    }
+
+    void test_Start_green()
+    {
+        wait();
+    }
+
+    void test_Green_again()
+    {
+        TS_TRACE( "Still green" );
+        wait();
+    }
+
+    void test_Now_yellow()
+    {
+        TS_WARN( "Yellow" );
+        wait();
+    }
+
+    void test_Cannot_go_back()
+    {
+        wait();
+    }
+
+    void test_Finally_red()
+    {
+        TS_FAIL( "Red" );
+        wait();
+    }
+
+    void test_Cannot_go_back_to_yellow()
+    {
+        TS_WARN( "Yellow?" );
+        wait();
+    }
+
+    void test_Cannot_go_back_to_green()
+    {
+        wait();
+    }
+};
diff --git a/tools/cxxtest/sample/mock/Dice.cpp b/tools/cxxtest/sample/mock/Dice.cpp
new file mode 100644 (file)
index 0000000..161b80f
--- /dev/null
@@ -0,0 +1,14 @@
+#include <T/stdlib.h>
+#include "Dice.h"
+
+Dice::Dice()
+{
+    T::srand( T::time( 0 ) );
+}
+
+unsigned Dice::roll()
+{
+    return (T::rand() % 6) + 1;
+}
+
+
diff --git a/tools/cxxtest/sample/mock/Dice.h b/tools/cxxtest/sample/mock/Dice.h
new file mode 100644 (file)
index 0000000..9427141
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __DICE_H
+#define __DICE_H
+
+class Dice
+{
+public:
+    Dice();
+    
+    unsigned roll();
+};
+
+#endif // __DICE_H
+
diff --git a/tools/cxxtest/sample/mock/Makefile b/tools/cxxtest/sample/mock/Makefile
new file mode 100644 (file)
index 0000000..4f40ad2
--- /dev/null
@@ -0,0 +1,22 @@
+all: roll run
+
+clean:
+       rm -f *~ *.o roll test test.cpp
+
+CXXTEST = ../..
+CCFLAGS = -I. -I$(CXXTEST)
+
+roll: roll.o Dice.o real_stdlib.o
+       g++ -o $@ $^
+
+run: test
+       ./test
+
+test: test.o Dice.o mock_stdlib.o
+       g++ -o $@ $^
+
+.cpp.o:
+       g++ -c -o $@ $(CCFLAGS) $<
+
+test.cpp: TestDice.h
+       $(CXXTEST)/bin/cxxtestgen -o $@ --error-printer $<
diff --git a/tools/cxxtest/sample/mock/MockStdlib.h b/tools/cxxtest/sample/mock/MockStdlib.h
new file mode 100644 (file)
index 0000000..aee62ba
--- /dev/null
@@ -0,0 +1,31 @@
+#include <T/stdlib.h>
+
+class MockStdlib :
+    public T::Base_srand,
+    public T::Base_rand,
+    public T::Base_time
+{
+public:
+    unsigned lastSeed;
+    
+    void srand( unsigned seed )
+    {
+        lastSeed = seed;
+    }
+
+    int nextRand;
+
+    int rand()
+    {
+        return nextRand;
+    }
+
+    time_t nextTime;
+
+    time_t time( time_t *t )
+    {
+        if ( t )
+            *t = nextTime;
+        return nextTime;
+    }
+};
diff --git a/tools/cxxtest/sample/mock/T/stdlib.h b/tools/cxxtest/sample/mock/T/stdlib.h
new file mode 100644 (file)
index 0000000..30306ba
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __T__STDLIB_H
+#define __T__STDLIB_H
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <cxxtest/Mock.h>
+
+CXXTEST_MOCK_VOID_GLOBAL( srand, ( unsigned seed ), ( seed ) );
+CXXTEST_MOCK_GLOBAL( int, rand, ( void ), () );
+CXXTEST_MOCK_GLOBAL( time_t, time, ( time_t *t ), ( t ) );
+
+#endif // __T__STDLIB_H
diff --git a/tools/cxxtest/sample/mock/TestDice.h b/tools/cxxtest/sample/mock/TestDice.h
new file mode 100644 (file)
index 0000000..35b3b7e
--- /dev/null
@@ -0,0 +1,62 @@
+#include <cxxtest/TestSuite.h>
+#include "Dice.h"
+#include "MockStdlib.h"
+
+class TestDice : public CxxTest::TestSuite
+{
+public:
+    MockStdlib *stdlib;
+
+    void setUp()
+    {
+        TS_ASSERT( stdlib = new MockStdlib );
+    }
+
+    void tearDown()
+    {
+        delete stdlib;
+    }
+    
+    void test_Randomize_uses_time()
+    {
+        stdlib->nextTime = 12345;
+        Dice dice;
+        TS_ASSERT_EQUALS( stdlib->lastSeed, 12345 );
+    }
+    
+    void test_Roll()
+    {
+        Dice dice;
+
+        stdlib->nextRand = 0;
+        TS_ASSERT_EQUALS( dice.roll(), 1 );
+
+        stdlib->nextRand = 2;
+        TS_ASSERT_EQUALS( dice.roll(), 3 );
+
+        stdlib->nextRand = 5;
+        TS_ASSERT_EQUALS( dice.roll(), 6 );
+
+        stdlib->nextRand = 7;
+        TS_ASSERT_EQUALS( dice.roll(), 2 );
+    }
+
+    void test_Temporary_override_of_one_mock_function()
+    {
+        Dice dice;
+
+        stdlib->nextRand = 2;
+        TS_ASSERT_EQUALS( dice.roll(), 3 );
+        
+        class Five : public T::Base_rand { int rand() { return 5; } };
+
+        Five *five = new Five;
+        TS_ASSERT_EQUALS( dice.roll(), 6 );
+        TS_ASSERT_EQUALS( dice.roll(), 6 );
+        TS_ASSERT_EQUALS( dice.roll(), 6 );
+        delete five;
+        
+        stdlib->nextRand = 1;
+        TS_ASSERT_EQUALS( dice.roll(), 2 );
+    }
+};
diff --git a/tools/cxxtest/sample/mock/mock_stdlib.cpp b/tools/cxxtest/sample/mock/mock_stdlib.cpp
new file mode 100644 (file)
index 0000000..148a044
--- /dev/null
@@ -0,0 +1,2 @@
+#define CXXTEST_MOCK_TEST_SOURCE_FILE
+#include <T/stdlib.h>
diff --git a/tools/cxxtest/sample/mock/real_stdlib.cpp b/tools/cxxtest/sample/mock/real_stdlib.cpp
new file mode 100644 (file)
index 0000000..db02f3a
--- /dev/null
@@ -0,0 +1,2 @@
+#define CXXTEST_MOCK_REAL_SOURCE_FILE
+#include <T/stdlib.h>
diff --git a/tools/cxxtest/sample/mock/roll.cpp b/tools/cxxtest/sample/mock/roll.cpp
new file mode 100644 (file)
index 0000000..20ea967
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include "Dice.h"
+
+int main()
+{
+    Dice dice;
+    printf( "First roll: %u\n", dice.roll() );
+    printf( "Second roll: %u\n", dice.roll() );
+    
+    return 0;
+}
diff --git a/tools/cxxtest/sample/msvc/CxxTest_1_Run.dsp b/tools/cxxtest/sample/msvc/CxxTest_1_Run.dsp
new file mode 100644 (file)
index 0000000..6bc00e7
--- /dev/null
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="CxxTest_1_Run" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=CxxTest_1_Run - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_1_Run.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_1_Run.mak" CFG="CxxTest_1_Run - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxxTest_1_Run - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "CxxTest_1_Run - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "CxxTest_1_Run - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "NMAKE /f CxxTest_1_Run.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "CxxTest_1_Run.exe"
+# PROP BASE Bsc_Name "CxxTest_1_Run.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "nmake DIR=Release run"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Release\run.log"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "CxxTest_1_Run - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "NMAKE /f CxxTest_1_Run.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "CxxTest_1_Run.exe"
+# PROP BASE Bsc_Name "CxxTest_1_Run.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "nmake DIR=Debug run"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "Debug\run.log"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxxTest_1_Run - Win32 Release"
+# Name "CxxTest_1_Run - Win32 Debug"
+
+!IF  "$(CFG)" == "CxxTest_1_Run - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "CxxTest_1_Run - Win32 Debug"
+
+!ENDIF 
+
+# Begin Source File
+
+SOURCE=.\Makefile
+# End Source File
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/tools/cxxtest/sample/msvc/CxxTest_2_Build.dsp b/tools/cxxtest/sample/msvc/CxxTest_2_Build.dsp
new file mode 100644 (file)
index 0000000..04727fd
--- /dev/null
@@ -0,0 +1,94 @@
+# Microsoft Developer Studio Project File - Name="CxxTest_2_Build" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=CxxTest_2_Build - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_2_Build.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_2_Build.mak" CFG="CxxTest_2_Build - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxxTest_2_Build - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "CxxTest_2_Build - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CxxTest_2_Build - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x40d /d "NDEBUG"
+# ADD RSC /l 0x40d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/runner.exe"
+
+!ELSEIF  "$(CFG)" == "CxxTest_2_Build - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x40d /d "_DEBUG"
+# ADD RSC /l 0x40d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/runner.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxxTest_2_Build - Win32 Release"
+# Name "CxxTest_2_Build - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\runner.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/tools/cxxtest/sample/msvc/CxxTest_3_Generate.dsp b/tools/cxxtest/sample/msvc/CxxTest_3_Generate.dsp
new file mode 100644 (file)
index 0000000..5bbad94
--- /dev/null
@@ -0,0 +1,93 @@
+# Microsoft Developer Studio Project File - Name="CxxTest_3_Generate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) External Target" 0x0106
+
+CFG=CxxTest_3_Generate - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_3_Generate.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_3_Generate.mak" CFG="CxxTest_3_Generate - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxxTest_3_Generate - Win32 Release" (based on "Win32 (x86) External Target")
+!MESSAGE "CxxTest_3_Generate - Win32 Debug" (based on "Win32 (x86) External Target")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF  "$(CFG)" == "CxxTest_3_Generate - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Cmd_Line "NMAKE /f CxxTest_3_Generate.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "CxxTest_3_Generate.exe"
+# PROP BASE Bsc_Name "CxxTest_3_Generate.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Cmd_Line "nmake runner.cpp"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "runner.cpp"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "CxxTest_3_Generate - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Cmd_Line "NMAKE /f CxxTest_3_Generate.mak"
+# PROP BASE Rebuild_Opt "/a"
+# PROP BASE Target_File "CxxTest_3_Generate.exe"
+# PROP BASE Bsc_Name "CxxTest_3_Generate.bsc"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Cmd_Line "nmake runner.cpp"
+# PROP Rebuild_Opt "/a"
+# PROP Target_File "runner.cpp"
+# PROP Bsc_Name ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxxTest_3_Generate - Win32 Release"
+# Name "CxxTest_3_Generate - Win32 Debug"
+
+!IF  "$(CFG)" == "CxxTest_3_Generate - Win32 Release"
+
+!ELSEIF  "$(CFG)" == "CxxTest_3_Generate - Win32 Debug"
+
+!ENDIF 
+
+# Begin Source File
+
+SOURCE=.\Makefile
+# End Source File
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/tools/cxxtest/sample/msvc/CxxTest_Workspace.dsw b/tools/cxxtest/sample/msvc/CxxTest_Workspace.dsw
new file mode 100644 (file)
index 0000000..5dbf841
--- /dev/null
@@ -0,0 +1,59 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "CxxTest_1_Run"=.\CxxTest_1_Run.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name CxxTest_2_Build
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "CxxTest_2_Build"=.\CxxTest_2_Build.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name CxxTest_3_Generate
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "CxxTest_3_Generate"=.\CxxTest_3_Generate.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/tools/cxxtest/sample/msvc/FixFiles.bat b/tools/cxxtest/sample/msvc/FixFiles.bat
new file mode 100644 (file)
index 0000000..498d98a
--- /dev/null
@@ -0,0 +1,210 @@
+@rem = '--*-Perl-*--
+@echo off
+if "%OS%" == "Windows_NT" goto WinNT
+perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
+goto endofperl
+:WinNT
+perl -x -S %0 %*
+if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
+if %errorlevel% == 9009 echo You do not have Perl in your PATH.
+if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
+goto endofperl
+@rem ';
+#!/usr/bin/perl -w
+#line 15
+use strict;
+use English;
+use Getopt::Long;
+
+$OUTPUT_AUTOFLUSH = 1;
+
+sub usage() {
+  print STDERR "Usage: $0 <OPTIONS>\n\n";
+  print STDERR "Fix Makefile and CxxTest_2_Build.dsp for your setup.\n\n";
+  print STDERR "  --cxxtest=DIR   Assume CxxTest is installed in DIR (default: '..\\..')\n";
+  print STDERR "  --tests=SPEC    Use SPEC for the test files (default: '../gui/*.h ../*.h')\n\n";
+  print STDERR "You must specify at least one option.\n";
+  exit -1;
+}
+
+my ($cxxtest, $tests);
+my ($Makefile, $CxxTest_2_Build);
+
+sub main {
+  parseCommandline();
+  fixFiles();
+}
+
+sub parseCommandline() {
+  GetOptions( 'cxxtest=s' => \$cxxtest,
+             'tests=s'   => \$tests,
+           ) or usage();
+
+  usage() unless (defined($cxxtest) || defined($tests));
+  $cxxtest = '..\\..' unless defined($cxxtest);
+  $tests = '../gui/*.h ../*.h' unless defined($tests);
+}
+
+sub fixFiles() {
+  fixFile( $Makefile, 'Makefile' );
+  fixFile( $CxxTest_2_Build, 'CxxTest_2_Build.dsp' );
+}
+
+sub fixFile($$) {
+  my ($data, $output) = @_;
+
+  print "$output...";
+
+  $data =~ s/<TESTS>/$tests/g;
+  $data =~ s/<CXXTEST>/$cxxtest/g;
+
+  open OUTPUT, ">$output" or die "Cannot create output file \"$output\"\n";
+  print OUTPUT $data;
+  close OUTPUT;
+
+  print "OK\n";
+}
+
+$Makefile =
+'# Where to look for the tests
+TESTS            = <TESTS>
+
+# Where the CxxTest distribution is unpacked
+CXXTESTDIR       = <CXXTEST>
+
+# Check CXXTESTDIR
+!if !exist($(CXXTESTDIR)\bin\cxxtestgen)
+!error Please fix CXXTESTDIR
+!endif
+
+# cxxtestgen needs Python
+!if defined(PYTHON)
+CXXTESTGEN       = $(PYTHON) $(CXXTESTDIR)/bin/cxxtestgen
+!else
+!error You must define PYTHON
+!endif
+
+# The arguments to pass to cxxtestgen
+#  - ParenPrinter is the way MSVC likes its compilation errors
+#  - --have-eh/--abort-on-fail are nice when you have them
+CXXTESTGEN_FLAGS = --gui=Win32Gui --runner=ParenPrinter --have-eh --abort-on-fail
+
+# How to generate the test runner, "runner.cpp"
+runner.cpp: $(TESTS)
+        $(CXXTESTGEN) $(CXXTESTGEN_FLAGS) -o $@ $(TESTS)
+
+# Command-line arguments to the runner
+RUNNER_FLAGS = -title "CxxTest Runner"
+
+# How to run the tests, which should be in DIR\runner.exe
+run: $(DIR)\runner.exe
+        $(DIR)\runner.exe $(RUNNER_FLAGS)
+';
+
+$CxxTest_2_Build = 
+'# Microsoft Developer Studio Project File - Name="CxxTest_2_Build" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=CxxTest_2_Build - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_2_Build.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CxxTest_2_Build.mak" CFG="CxxTest_2_Build - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxxTest_2_Build - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "CxxTest_2_Build - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CxxTest_2_Build - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "<CXXTEST>" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x40d /d "NDEBUG"
+# ADD RSC /l 0x40d /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/runner.exe"
+
+!ELSEIF  "$(CFG)" == "CxxTest_2_Build - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "<CXXTEST>" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x40d /d "_DEBUG"
+# ADD RSC /l 0x40d /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/runner.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxxTest_2_Build - Win32 Release"
+# Name "CxxTest_2_Build - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\runner.cpp
+# End Source File
+# End Target
+# End Project
+';
+
+main();
+
+__END__
+:endofperl
+
+rem
+rem Local Variables:
+rem compile-command: "perl FixFiles.bat"
+rem End:
+rem
diff --git a/tools/cxxtest/sample/msvc/Makefile b/tools/cxxtest/sample/msvc/Makefile
new file mode 100644 (file)
index 0000000..8dd66ca
--- /dev/null
@@ -0,0 +1,34 @@
+# Where to look for the tests
+TESTS            = ..\gui\*.h ..\*.h
+
+# Where the CxxTest distribution is unpacked
+CXXTESTDIR       = ..\..
+
+# Check CXXTESTDIR
+!if !exist($(CXXTESTDIR)\bin\cxxtestgen)
+!error Please fix CXXTESTDIR
+!endif
+
+# cxxtestgen needs Perl or Python
+!if defined(PYTHON)
+CXXTESTGEN       = $(PYTHON) $(CXXTESTDIR)/bin/cxxtestgen
+!else
+!error You must define PERL or PYTHON
+!endif
+
+# The arguments to pass to cxxtestgen
+#  - ParenPrinter is the way MSVC likes its compilation errors
+#  - --have-eh/--abort-on-fail are nice when you have them
+CXXTESTGEN_FLAGS =        \
+       --gui=Win32Gui        \
+       --runner=ParenPrinter \
+       --have-eh             \
+       --abort-on-fail
+
+# How to generate the test runner, `runner.cpp'
+runner.cpp: $(TESTS)
+       $(CXXTESTGEN) $(CXXTESTGEN_FLAGS) -o $@ $(TESTS)
+
+# How to run the tests, which should be in DIR\runner.exe
+run: $(DIR)\runner.exe
+       $(DIR)\runner.exe
diff --git a/tools/cxxtest/sample/msvc/ReadMe.txt b/tools/cxxtest/sample/msvc/ReadMe.txt
new file mode 100644 (file)
index 0000000..9be51e8
--- /dev/null
@@ -0,0 +1,30 @@
+Sample files for Visual Studio
+==============================
+
+There are three projects in this workspace:
+
+ - CxxTest_3_Generate runs cxxtestgen to create runner.cpp
+ - CxxTest_2_Build compiles the generated file
+ - CxxTest_1_Run runs the compiled binary
+
+Whenever you build this workspace, the tests are run, and any failed assertions
+are displayed as compilation errors (you can browse them using F4).
+
+Note that to run this sample, you need first to create an environment
+variable PYTHON, e.g. Python=c:\Python25\bin\python.exe
+
+
+To use these .dsp and .dsw files in your own project, run FixFiles.bat
+to adjust them to where you've placed CxxTest and your own tests.
+
+If you want to use just the .dsp files in your own workspace, don't
+forget to:
+
+ - Set up the dependencies (CxxTest_3_Generate depends on
+   CxxTest_2_Build which depends on CxxTest_1_Run)
+
+ - Add your own include paths, libraries etc. to the CxxTest_2_Build project
+
+
+NOTE: I haven't used "Post-Build Step" to run the tests because I
+wanted the tests to be executed even if nothing has changed.
diff --git a/tools/cxxtest/sample/only.tpl b/tools/cxxtest/sample/only.tpl
new file mode 100644 (file)
index 0000000..b2a7277
--- /dev/null
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+#include <cxxtest/StdioPrinter.h>
+#include <stdio.h>
+
+int main( int argc, char *argv[] )
+{
+    if ( argc < 2 || argc > 3 ) {
+        fprintf( stderr, "Usage: only <suite name> [<test name>]\n\n" );
+        fprintf( stderr, "Available tests:\n" );
+        CxxTest::RealWorldDescription wd;
+        for ( CxxTest::SuiteDescription *sd = wd.firstSuite(); sd; sd = sd->next() )
+            for ( CxxTest::TestDescription *td = sd->firstTest(); td; td = td->next() )
+                fprintf( stderr, " - %s::%s()\n", sd->suiteName(), td->testName() );
+        return 1;
+    }
+
+    const char *suiteName = argv[1];
+    const char *testName = (argc > 2) ? argv[2] : 0;
+    if ( !CxxTest::leaveOnly( suiteName, testName ) ) {
+        if ( testName )
+            fprintf( stderr, "Cannot find %s::%s()\n", argv[1], argv[2] );
+        else
+            fprintf( stderr, "Cannot find class %s\n", argv[1] );
+        return 2;
+    }
+    
+    return CxxTest::StdioPrinter().run();
+}
+
+
+// The CxxTest "world"
+<CxxTest world>
+
diff --git a/tools/cxxtest/sample/parts/.cvsignore b/tools/cxxtest/sample/parts/.cvsignore
new file mode 100644 (file)
index 0000000..6e09171
--- /dev/null
@@ -0,0 +1 @@
+*.cpp *.o runner
\ No newline at end of file
diff --git a/tools/cxxtest/sample/parts/Makefile.unix b/tools/cxxtest/sample/parts/Makefile.unix
new file mode 100644 (file)
index 0000000..1b78a96
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# (GNU) Makefile for UN*X-like systems
+# This makefile shows how to make a different runner for each test
+#
+
+.PHONY: all clean
+
+all: run
+
+clean:
+       rm -f *~ *.cpp *.o runner
+
+CXXTESTDIR   = ../..
+CXXTESTGEN   = $(CXXTESTDIR)/bin/cxxtestgen
+CXXTESTFLAGS = --have-eh --abort-on-fail
+
+TESTS = $(wildcard ../*Test.h)
+OBJS  = runner.o $(TESTS:../%.h=%.o)
+
+run: runner
+       ./runner
+
+runner: $(OBJS)
+       c++ -o $@ $^
+
+%.o: %.cpp
+       c++ -c -o $@ -I $(CXXTESTDIR) -I .. $^
+
+%.cpp: ../%.h
+       $(CXXTESTGEN) $(CXXTESTFLAGS) --part -o $@ $^
+
+runner.cpp:
+       $(CXXTESTGEN) $(CXXTESTFLAGS) --root --error-printer -o $@
+
+#
+# Local Variables:
+# compile-command: "make -fMakefile.unix"
+# End:
+#
diff --git a/tools/cxxtest/sample/winddk/Makefile b/tools/cxxtest/sample/winddk/Makefile
new file mode 100644 (file)
index 0000000..8bf2533
--- /dev/null
@@ -0,0 +1,2 @@
+# Standard DDK Makefile
+!include $(NTMAKEENV)\makefile.def
diff --git a/tools/cxxtest/sample/winddk/Makefile.inc b/tools/cxxtest/sample/winddk/Makefile.inc
new file mode 100644 (file)
index 0000000..3d56436
--- /dev/null
@@ -0,0 +1,13 @@
+# -*- Makefile -*-
+
+#
+# Tell the DDK how to generate RunTests.cpp from RunTests.tpl and the tests
+#
+
+PYTHON=python
+CXXTESTGEN=$(PYTHON) $(CXXTESTDIR)/bin/cxxtestgen
+
+TEST_SUITES=$(SUITESDIR)/*.h
+
+RunTests.cpp: RunTests.tpl $(TEST_SUITES)
+       $(CXXTESTGEN) -o $@ --template=RunTests.tpl $(TEST_SUITES)
diff --git a/tools/cxxtest/sample/winddk/RunTests.tpl b/tools/cxxtest/sample/winddk/RunTests.tpl
new file mode 100644 (file)
index 0000000..917f14b
--- /dev/null
@@ -0,0 +1,13 @@
+// -*- C++ -*-
+
+//
+// The DDK doesn't handle <iostream> too well
+//
+#include <cxxtest/StdioPrinter.h>
+
+int __cdecl main()
+{
+    return CxxTest::StdioPrinter().run();
+}
+
+<CxxTest world>
diff --git a/tools/cxxtest/sample/winddk/SOURCES b/tools/cxxtest/sample/winddk/SOURCES
new file mode 100644 (file)
index 0000000..dae0148
--- /dev/null
@@ -0,0 +1,46 @@
+# -*- Makefile -*-
+
+#
+# Build this sample with the Windows DDK (XP or later)
+#
+SUITESDIR=..
+CXXTESTDIR=../..
+
+#
+# Build a user-mode application
+#
+TARGETNAME=RunTests
+TARGETPATH=.
+TARGETTYPE=PROGRAM
+
+#
+# Make it a console-mode app
+#
+UMTYPE=console
+
+#
+# Add CxxTest and tests directory to include path
+#
+INCLUDES=$(SUITESDIR);$(CXXTESTDIR)
+
+#
+# Enable exception handling and standard library
+#
+USE_NATIVE_EH=1
+LINKER_FLAGS=$(LINKER_FLAGS) -IGNORE:4099
+386_WARNING_LEVEL=-W3 -WX -wd4290
+
+TARGETLIBS=\
+       $(CRT_LIB_PATH)\libcp.lib \
+       $(CRT_LIB_PATH)\libc.lib
+
+#
+# Only one source file -- the generated test runner
+#
+SOURCES=RunTests.cpp
+
+#
+# This line tells the build utility to process Makefile.inc
+#
+NTTARGETFILE0=RunTests.cpp
+
diff --git a/tools/cxxtest/sample/yes_no_runner.cpp b/tools/cxxtest/sample/yes_no_runner.cpp
new file mode 100644 (file)
index 0000000..c32b94c
--- /dev/null
@@ -0,0 +1,11 @@
+//
+// A sample program that uses class YesNoRunner to run all the tests
+// and find out if all pass.
+//
+
+#include <cxxtest/YesNoRunner.h>
+
+int main()
+{
+    return CxxTest::YesNoRunner().run();
+}
diff --git a/tools/cxxtest/test/.cvsignore b/tools/cxxtest/test/.cvsignore
new file mode 100644 (file)
index 0000000..e56da81
--- /dev/null
@@ -0,0 +1 @@
+*pl.cpp *py.cpp *pl.out *py.out *px *px.exe *px.out *build.log *root.cpp
diff --git a/tools/cxxtest/test/AborterNoThrow.h b/tools/cxxtest/test/AborterNoThrow.h
new file mode 100644 (file)
index 0000000..b2905e4
--- /dev/null
@@ -0,0 +1,19 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test suite which doesn't use exception handling.
+// It is used to verify --abort-on-fail + --have-eh
+//
+
+class AborterNoThrow : public CxxTest::TestSuite
+{
+public:
+    void testFailures()
+    {
+        TS_FAIL(1);
+        TS_FAIL(2);
+        TS_FAIL(3);
+        TS_FAIL(4);
+        TS_FAIL(5);
+    }
+};
diff --git a/tools/cxxtest/test/BadTest.h b/tools/cxxtest/test/BadTest.h
new file mode 100644 (file)
index 0000000..9a8d5f9
--- /dev/null
@@ -0,0 +1,55 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// A simple test suite that cannot be parsed with the default test discovery mechanism
+//
+
+class BadTest 
+: 
+public CxxTest::TestSuite
+{
+public:
+    void testEquality()
+    {
+        TS_ASSERT_EQUALS( 1, 1 );
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 'a', 'A' );
+        TS_ASSERT_EQUALS( 1.0, -12345678900000000000000000000000000000000000000000.1234 );
+    }
+
+    void testAddition()
+    {
+        TS_ASSERT_EQUALS( 1 + 1, 2 );
+        TS_ASSERT_EQUALS( 2 + 2, 5 );
+    }
+
+    void TestMultiplication()
+    {
+        TS_ASSERT_EQUALS( 2 * 2, 4 );
+        TS_ASSERT_EQUALS( 4 * 4, 44 );
+        TS_ASSERT_DIFFERS( -2 * -2, 4 );
+    }
+
+    void testComparison()
+    {
+        TS_ASSERT_LESS_THAN( (int)1, (unsigned long)2 );
+        TS_ASSERT_LESS_THAN( -1, -2 );
+    }
+
+    void testTheWorldIsCrazy()
+    {
+        TS_ASSERT_EQUALS( true, false );
+    }
+
+    void test_Failure()
+    {
+        TS_FAIL( "Not implemented" );
+        TS_FAIL( 1569779912 );
+    }
+
+    void test_TS_WARN_macro()
+    {
+        TS_WARN( "Just a friendly warning" );
+        TS_WARN( "Warnings don't abort the test" );
+    }
+};
diff --git a/tools/cxxtest/test/Comments.h b/tools/cxxtest/test/Comments.h
new file mode 100644 (file)
index 0000000..4893d8f
--- /dev/null
@@ -0,0 +1,24 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test of commenting out tests in CxxTest
+//
+
+class Comments : public CxxTest::TestSuite
+{
+public:
+    void test_Something()
+    {
+        TS_WARN( "Something" );
+    }
+
+//     void test_Something_else()
+//     {
+//         TS_WARN( "Something else" );
+//     }
+
+    //void test_Something_else()
+    //{
+    //    TS_WARN( "Something else" );
+    //}
+};
diff --git a/tools/cxxtest/test/Comments2.h b/tools/cxxtest/test/Comments2.h
new file mode 100644 (file)
index 0000000..d14eb61
--- /dev/null
@@ -0,0 +1,21 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test of commenting out tests in CxxTest
+//
+
+class Comments : public CxxTest::TestSuite
+{
+public:
+    void test_Something()
+    {
+        TS_WARN( "Something" );
+    }
+
+/*
+    void test_Something_else()
+    {
+        TS_WARN( "Something else" );
+    }
+*/
+};
diff --git a/tools/cxxtest/test/CppTemplateTest.h b/tools/cxxtest/test/CppTemplateTest.h
new file mode 100644 (file)
index 0000000..849b6cf
--- /dev/null
@@ -0,0 +1,37 @@
+#include <cxxtest/TestSuite.h>
+
+template <class T>
+class Tests
+{
+public:
+
+   CXXTEST_STD(list)<T>* cache;
+
+   void setUp()
+   {
+        this->cache = new CXXTEST_STD(list)<T>();
+   }
+
+   void tearDown()
+        { }
+
+   void test_size()
+   {
+      TS_ASSERT_EQUALS(cache->size(), 0);
+   }
+
+   void test_insert()
+   {
+      this->cache->push_back(1);
+      TS_ASSERT_EQUALS(cache->size(), 1);
+   }
+
+};
+
+class IntTests: public Tests<int>, public CxxTest::TestSuite
+{
+public:
+
+    void setUp()    { Tests<int>::setUp(); }
+    void tearDown() { Tests<int>::tearDown(); }
+};
diff --git a/tools/cxxtest/test/DeepAbort.h b/tools/cxxtest/test/DeepAbort.h
new file mode 100644 (file)
index 0000000..c7f82fc
--- /dev/null
@@ -0,0 +1,84 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite verifies that the TS_ASSERT_THROWS*() macros are "abort on fail"-friendly
+//
+
+class DeepAbort : public CxxTest::TestSuite
+{
+public:
+    void testAssertThrowsPassesAbort()
+    {
+        TS_ASSERT_THROWS( fail(), int );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testMessageAssertThrowsPassesAbort()
+    {
+        TSM_ASSERT_THROWS( "fail() should throw an int", fail(), int );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testAssertThrowsAborts()
+    {
+        TS_ASSERT_THROWS( succeed(), int );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testMessageAssertThrowsAborts()
+    {
+        TSM_ASSERT_THROWS( "succeed() should throw an int", succeed(), int );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testAssertThrowsNothingPassesAbort()
+    {
+        TS_ASSERT_THROWS_NOTHING( fail() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testMessageAssertThrowsNothingPassesAbort()
+    {
+        TSM_ASSERT_THROWS_NOTHING( "fail() shouldn't throw anything", fail() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testAssertThrowsNothingAborts()
+    {
+        TS_ASSERT_THROWS_NOTHING( throwSomething() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testMessageAssertThrowsNothingAborts()
+    {
+        TSM_ASSERT_THROWS_NOTHING( "fail() shouldn't throw anything", throwSomething() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testAssertThrowsAnything()
+    {
+        TS_ASSERT_THROWS_ANYTHING( succeed() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void testMessageAssertThrowsAnything()
+    {
+        TSM_ASSERT_THROWS_ANYTHING( "succeed() should throw something", succeed() );
+        TS_FAIL( "You shouldn't see this if --abort-on-fail is used" );
+    }
+
+    void fail()
+    {
+        TS_ASSERT_EQUALS( 0, 1 );
+    }
+
+    void throwSomething()
+    {
+        throw "something";
+    }
+
+    void succeed()
+    {
+        TS_ASSERT_EQUALS( 1, 1 );
+    }
+};
diff --git a/tools/cxxtest/test/DefaultAbort.h b/tools/cxxtest/test/DefaultAbort.h
new file mode 100644 (file)
index 0000000..7902ef6
--- /dev/null
@@ -0,0 +1,3 @@
+#define CXXTEST_HAVE_EH
+#define CXXTEST_ABORT_TEST_ON_FAIL
+#define CXXTEST_DEFAULT_ABORT false
diff --git a/tools/cxxtest/test/DefaultTraits.h b/tools/cxxtest/test/DefaultTraits.h
new file mode 100644 (file)
index 0000000..d648cd3
--- /dev/null
@@ -0,0 +1,37 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite demonstrates the default ValueTraits
+//
+
+class DefaultTraits : public CxxTest::TestSuite
+{
+public:
+    struct EightBytes
+    {
+        EightBytes() {}
+        unsigned char data[8];
+    };
+    
+    void testSmallDefaultTraits()
+    {
+        EightBytes x;
+        for ( unsigned i = 0; i < sizeof(x.data); ++ i )
+            x.data[i] = (unsigned char)i;
+        TS_FAIL( x );
+    }
+
+    struct NineBytes
+    {
+        NineBytes() {}
+        unsigned char data[9];
+    };
+    
+    void testBigDefaultTraits()
+    {
+        NineBytes x;
+        for ( unsigned i = 0; i < sizeof(x.data); ++ i )
+            x.data[i] = (unsigned char)(0x98 + i);
+        TS_FAIL( x );
+    }
+};
diff --git a/tools/cxxtest/test/DoubleCall.h b/tools/cxxtest/test/DoubleCall.h
new file mode 100644 (file)
index 0000000..607d733
--- /dev/null
@@ -0,0 +1,38 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite tests double macro invocation
+// E.g. when TS_ASSERT_EQUALS( x, y ) fails, it should evaulate x and y once
+// Consider TS_ASSERT_EQUALS( readNextValue(), 3 )
+//
+
+class DoubleCall : public CxxTest::TestSuite
+{
+public:
+    int i;
+
+    void setUp()
+    {
+        i = 0;
+    }
+    
+    void testAssertEqualsWithSideEffects()
+    {
+        TS_ASSERT_EQUALS( increment(), 3 );
+    }
+
+    void testAssertDiffersWithSideEffects()
+    {
+        TS_ASSERT_DIFFERS( increment(), 1 );
+    }
+
+    void testAssertDeltaWithSideEffects()
+    {
+        TS_ASSERT_DELTA( increment(), 2.0, 0.5 );
+    }
+
+    int increment()
+    {
+        return ++i;
+    }
+};
diff --git a/tools/cxxtest/test/DynamicAbort.h b/tools/cxxtest/test/DynamicAbort.h
new file mode 100644 (file)
index 0000000..6be35ef
--- /dev/null
@@ -0,0 +1,52 @@
+#include <cxxtest/TestSuite.h>
+
+class DynamicAbort : public CxxTest::TestSuite
+{
+public:
+    void test_Abort_on_fail_in_this_test()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+
+    void test_Dont_abort_in_this_test()
+    {
+        CxxTest::setAbortTestOnFail( false );
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+
+    void test_Revert_to_abort()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+};
+
+class SetUpWorksAllTests : public CxxTest::TestSuite
+{
+public:
+    void setUp()
+    {
+        CxxTest::setAbortTestOnFail( false );
+    }
+
+    void test_Dont_abort_in_this_test()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+
+    void test_Dont_abort_in_this_test_either()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+
+    void test_Override_in_this_test()
+    {
+        CxxTest::setAbortTestOnFail( true );
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+};
diff --git a/tools/cxxtest/test/DynamicMax.h b/tools/cxxtest/test/DynamicMax.h
new file mode 100644 (file)
index 0000000..178f233
--- /dev/null
@@ -0,0 +1,65 @@
+#include <cxxtest/TestSuite.h>
+
+class DynamicMax : public CxxTest::TestSuite
+{
+public:
+    enum { DATA_SIZE = 24 };
+    unsigned char x[DATA_SIZE], y[DATA_SIZE];
+
+    void setUp()
+    {
+        for ( unsigned i = 0; i < DATA_SIZE; ++ i ) {
+            x[i] = (unsigned char)i;
+            y[i] = (unsigned char)~x[i];
+        }
+    }
+
+    void test_Max_size_from_define()
+    {
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void test_Set_max_size()
+    {
+        CxxTest::setMaxDumpSize( 16 );
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void test_Revert_to_max_size_from_define()
+    {
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void test_Set_max_size_to_zero__dumps_all()
+    {
+        CxxTest::setMaxDumpSize( 0 );
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+};
+
+class SetUpAffectsAllTests : public CxxTest::TestSuite
+{
+public:
+    enum { DATA_SIZE = 24 };
+    unsigned char x[DATA_SIZE], y[DATA_SIZE];
+
+    void setUp()
+    {
+        for ( unsigned i = 0; i < DATA_SIZE; ++ i ) {
+            x[i] = (unsigned char)i;
+            y[i] = (unsigned char)~x[i];
+        }
+        
+        CxxTest::setMaxDumpSize( 12 );
+    }
+
+    void test_Use_12_in_this_test()
+    {
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void test_Use_12_in_this_test_too()
+    {
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+};
diff --git a/tools/cxxtest/test/EmptySuite.h b/tools/cxxtest/test/EmptySuite.h
new file mode 100644 (file)
index 0000000..be5c79d
--- /dev/null
@@ -0,0 +1,16 @@
+#include <cxxtest/TestSuite.h>
+
+class EmptySuite : public CxxTest::TestSuite
+{
+public:
+    static EmptySuite *createSuite() { return new EmptySuite(); }
+    static void destroySuite( EmptySuite *suite ) { delete suite; }
+
+    void setUp() {}
+    void tearDown() {}
+
+    void thisSuiteHasNoTests() 
+    {
+        TS_FAIL( "This suite has no tests" );
+    }
+};
diff --git a/tools/cxxtest/test/Exceptions.h b/tools/cxxtest/test/Exceptions.h
new file mode 100644 (file)
index 0000000..70ea28e
--- /dev/null
@@ -0,0 +1,70 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// These test suites are examples of unhandled exceptions and errors in dynamic suites
+//
+
+class NullCreate : public CxxTest::TestSuite
+{
+public:
+    static NullCreate *createSuite() { return 0; }
+    static void destroySuite( NullCreate * ) { TS_FAIL( "Should not be called" ); }
+
+    void testNothing()
+    {
+        TS_FAIL( "Test called although no suite" );
+    }
+};
+
+class ThrowCreate : public CxxTest::TestSuite
+{
+public:
+    static ThrowCreate *createSuite() { throw -3; }
+    static void destroySuite( ThrowCreate * ) { TS_FAIL( "Should not be called" ); }
+
+    void testNothing()
+    {
+        TS_FAIL( "Test called although no suite" );
+    }
+};
+
+class ThrowDestroy : public CxxTest::TestSuite
+{
+public:
+    static ThrowDestroy *createSuite() { return new ThrowDestroy; }
+    static void destroySuite( ThrowDestroy * ) { throw 42; }
+    
+    void testNothing() {}
+};
+
+class ThrowSetUp : public CxxTest::TestSuite
+{
+public:
+    void setUp() { throw 5; }
+    void tearDown() { TS_FAIL( "Shouldn't get here" ); }
+
+    void testNothing() { TS_FAIL( "Shouldn't get here" ); }
+};
+
+class ThrowTearDown : public CxxTest::TestSuite
+{
+public:
+    void setUp() {}
+    void tearDown() { throw 5; }
+
+    void testNothing() {}
+};
+
+class TestThrowFromTest : public CxxTest::TestSuite
+{
+public:
+    void testThrowSomething()
+    {
+        throw 582;
+    }
+
+    void testMoveOn()
+    {
+        TS_TRACE( "One failed test doesn't affect the others" );
+    }
+};
diff --git a/tools/cxxtest/test/Factor.h b/tools/cxxtest/test/Factor.h
new file mode 100644 (file)
index 0000000..3fdf4cd
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// This file is used to test WorldDescription::strTotalTests()
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/DummyDescriptions.h>
+
+class Factor : public CxxTest::TestSuite
+{
+public:
+    class X : public CxxTest::DummyWorldDescription
+    {
+    public:
+        unsigned n;
+        unsigned numTotalTests() const { return n; }
+    };
+
+    X x;
+    enum Limit { MAX_STRLEN_TOTAL_TESTS = CxxTest::WorldDescription::MAX_STRLEN_TOTAL_TESTS };
+    char buffer[MAX_STRLEN_TOTAL_TESTS * 2];
+
+    const char *convert( unsigned n )
+    {
+        x.n = n;
+        return x.strTotalTests( buffer );
+    }
+
+    void test_Some_numbers()
+    {
+        TS_WARN( convert(53) );
+        for ( unsigned n = 0; n < 64; ++ n ) {
+            TS_ASSERT_DIFFERS( n, 32 );
+            TS_WARN( convert(n) );
+        }
+    }
+
+    class ShorterThan
+    {
+    public:
+        bool operator()( const char *s, unsigned n ) const
+        {
+            unsigned len = 0;
+            while ( *s++ != '\0' )
+                ++ len;
+            return (len < n);
+        }
+    };
+
+    class NotShorterThan
+    {
+        ShorterThan _shorterThan;
+        
+    public:
+        bool operator()( const char *s, unsigned n ) const { return !_shorterThan( s, n ); }
+    };
+
+    void test_Lengths()
+    {
+        unsigned reasonableLimit = 60060;
+        for ( unsigned n = 0; n < reasonableLimit; ++ n )
+            TS_ASSERT_RELATION( ShorterThan, convert(n), MAX_STRLEN_TOTAL_TESTS );
+        TS_ASSERT_RELATION( NotShorterThan, convert(reasonableLimit), MAX_STRLEN_TOTAL_TESTS );
+    }
+};
diff --git a/tools/cxxtest/test/ForceNoEh.h b/tools/cxxtest/test/ForceNoEh.h
new file mode 100644 (file)
index 0000000..8178e57
--- /dev/null
@@ -0,0 +1,16 @@
+#include <cxxtest/TestSuite.h>
+
+class ForceNoEh : public CxxTest::TestSuite
+{
+public:
+    void testCxxTestCanCompileWithoutExceptionHandling()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+        TS_ASSERT_THROWS_NOTHING( foo() );
+    }
+
+    void foo()
+    {
+    }
+};
diff --git a/tools/cxxtest/test/GfSetUpFails.h b/tools/cxxtest/test/GfSetUpFails.h
new file mode 100644 (file)
index 0000000..921fc4f
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// This file tests what happens when GlobalFixture::setUp() fails
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUp() { return false; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+};
diff --git a/tools/cxxtest/test/GfSetUpThrows.h b/tools/cxxtest/test/GfSetUpThrows.h
new file mode 100644 (file)
index 0000000..ed0f6ea
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// This file tests what happens when GlobalFixture::setUp() throws
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUp() { throw this; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+};
diff --git a/tools/cxxtest/test/GfTearDownFails.h b/tools/cxxtest/test/GfTearDownFails.h
new file mode 100644 (file)
index 0000000..a493e58
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// This file tests what happens when GlobalFixture::tearDown() fails
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool tearDown() { return false; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+    void testTwo() { TS_WARN( "Testing should go on!" ); }
+};
diff --git a/tools/cxxtest/test/GfTearDownThrows.h b/tools/cxxtest/test/GfTearDownThrows.h
new file mode 100644 (file)
index 0000000..68b933b
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// This file tests what happens when GlobalFixture::tearDown() throws
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool tearDown() { throw this; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+    void testTwo() { TS_WARN( "Testing should go on!" ); }
+};
diff --git a/tools/cxxtest/test/GlobalFixtures.h b/tools/cxxtest/test/GlobalFixtures.h
new file mode 100644 (file)
index 0000000..523b6bb
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// This file tests CxxTest global fixtures
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+
+//
+// Fixture1 counts its setUp()s and tearDown()s
+//
+class Fixture1 : public CxxTest::GlobalFixture
+{
+    unsigned _setUpCount;
+    unsigned _tearDownCount;
+    
+public:
+    Fixture1() { _setUpCount = _tearDownCount = 0; }
+    bool setUp() { ++ _setUpCount; return true; }
+    bool tearDown() { ++ _tearDownCount; return true; }
+    unsigned setUpCount() const { return _setUpCount; }
+    unsigned tearDownCount() const { return _tearDownCount; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture1 fixture1;
+
+//
+// Fixture2 counts its setUp()s and tearDown()s and makes sure
+// its setUp() is called after Fixture1 and its tearDown() before.
+//
+class Fixture2 : public Fixture1
+{
+public:
+    bool setUp()
+    {
+        TS_ASSERT_EQUALS(setUpCount(), fixture1.setUpCount() - 1);
+        TS_ASSERT_EQUALS(tearDownCount(), fixture1.tearDownCount());
+        return Fixture1::setUp();
+    }
+
+    bool tearDown()
+    {
+        TS_ASSERT_EQUALS(setUpCount(), fixture1.setUpCount());
+        TS_ASSERT_EQUALS(tearDownCount(), fixture1.tearDownCount());
+        return Fixture1::tearDown();
+    }
+};
+
+static Fixture2 fixture2;
+
+class TestGlobalFixture : public CxxTest::TestSuite
+{
+public:
+    void testCountsFirstTime()
+    {
+        TS_ASSERT_EQUALS(fixture1.setUpCount(), 1);
+        TS_ASSERT_EQUALS(fixture1.tearDownCount(), 0);
+        TS_ASSERT_EQUALS(fixture2.setUpCount(), 1);
+        TS_ASSERT_EQUALS(fixture2.tearDownCount(), 0);
+    }
+
+    void testCountsSecondTime()
+    {
+        TS_ASSERT_EQUALS(fixture1.setUpCount(), 2);
+        TS_ASSERT_EQUALS(fixture1.tearDownCount(), 1);
+        TS_ASSERT_EQUALS(fixture2.setUpCount(), 2);
+        TS_ASSERT_EQUALS(fixture2.tearDownCount(), 1);
+    }
+};
diff --git a/tools/cxxtest/test/GoodSuite.h b/tools/cxxtest/test/GoodSuite.h
new file mode 100644 (file)
index 0000000..d30e0b5
--- /dev/null
@@ -0,0 +1,114 @@
+#include <cxxtest/TestSuite.h>
+#include <math.h>
+
+//
+// This is a test suite in which all tests pass.
+// It is also an example of all the TS[M]_ macros except TS_FAIL()
+//
+
+class GoodSuite : public CxxTest::TestSuite
+{
+public:
+    void testAssert()
+    {
+        TS_ASSERT( true );
+        TS_ASSERT( 1 == 1 );
+        TS_ASSERT( 13 );
+        TS_ASSERT( this );
+    }
+
+    void testAssertMessage()
+    {
+        TSM_ASSERT( "ASCII works", 'A' == 65 );
+    }
+    
+    void testEquals()
+    {
+        TS_ASSERT_EQUALS( 1 + 1, 2 );
+        TS_ASSERT_EQUALS( 2 * 2, 4 );
+        TS_ASSERT_EQUALS( -4 * -4, 16 );
+    }
+
+    void testEqualsMessage()
+    {
+        TSM_ASSERT_EQUALS( "Addition operator works", 1 + 1, 2 );
+    }
+
+    void testDelta()
+    {
+        TS_ASSERT_DELTA( 1.0 + 1.0, 2.0, 0.0001 );
+    }
+
+    void testDeltaMessage()
+    {
+        TSM_ASSERT_DELTA( "sqrt() works", sqrt(2.0), 1.4142, 0.0001 );
+    }
+
+    void testDiffers()
+    {
+        TS_ASSERT_DIFFERS( 0, 1 );
+        TS_ASSERT_DIFFERS( 0.12, 0.123 );
+    }
+
+    void testDiffersMessage()
+    {
+        TSM_ASSERT_DIFFERS( "Not all is true", 0, 1 );
+    }
+
+    void testLessThan()
+    {
+        TS_ASSERT_LESS_THAN( 1, 2 );
+        TS_ASSERT_LESS_THAN( -2, -1 );
+    }
+
+    void testLessThanMessage()
+    {
+        TSM_ASSERT_LESS_THAN( ".5 is less than its square root", 0.5, sqrt(0.5) );
+    }
+
+    void testLessThanEquals()
+    {
+        TS_ASSERT_LESS_THAN_EQUALS( 3, 3 );
+        TS_ASSERT_LESS_THAN_EQUALS( 3, 4 );
+    }
+
+    void testLessThanEqualsMessage()
+    {
+        TSM_ASSERT_LESS_THAN_EQUALS( "1.0 <= its square root", 1.0, sqrt(1.0) );
+    }
+
+    void testThrows()
+    {
+        TS_ASSERT_THROWS( { throw 1; }, int );
+    }
+
+    void testThrowsMessage()
+    {
+        TSM_ASSERT_THROWS( "1 is an integer", { throw 1; }, int );
+    }
+
+    void testThrowsAnything()
+    {
+        TS_ASSERT_THROWS_ANYTHING( { throw GoodSuite(); } );
+    }
+
+    void testThrowsAnythingMessage()
+    {
+        TSM_ASSERT_THROWS_ANYTHING( "Yes, you can throw test suites",
+                                    { throw GoodSuite(); } );
+    }
+
+    void testThrowsNothing()
+    {
+        TS_ASSERT_THROWS_NOTHING( throwNothing() );
+    }
+
+    void testThrowsNothingMessage()
+    {
+        TSM_ASSERT_THROWS_NOTHING( "Empty functions dosn't throw", throwNothing() );
+    }
+
+    void throwNothing()
+    {
+    }
+};
diff --git a/tools/cxxtest/test/GuiWait.h b/tools/cxxtest/test/GuiWait.h
new file mode 100644 (file)
index 0000000..a0b871c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __GUI_WAIT_H
+#define __GUI_WAIT_H
+
+#define CXXTEST_SAMPLE_GUI_WAIT()
+
+#endif // __GUI_WAIT_H
diff --git a/tools/cxxtest/test/HaveEH.tpl b/tools/cxxtest/test/HaveEH.tpl
new file mode 100644 (file)
index 0000000..7e01a1d
--- /dev/null
@@ -0,0 +1,10 @@
+#define CXXTEST_HAVE_EH
+#include <cxxtest/ErrorPrinter.h>
+
+int main( int argc, char *argv[] ) {
+    CxxTest::ErrorPrinter tmp;
+    return CxxTest::Main<CxxTest::ErrorPrinter>( tmp, argc, argv );
+}
+
+// The CxxTest "world"
+<CxxTest world>
diff --git a/tools/cxxtest/test/HaveStd.h b/tools/cxxtest/test/HaveStd.h
new file mode 100644 (file)
index 0000000..1eb5b54
--- /dev/null
@@ -0,0 +1,15 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This tests CxxTest's `--have-std' option
+//
+#include "Something.h"
+
+class HaveStd : public CxxTest::TestSuite
+{
+public:
+    void testHaveStd()
+    {
+        TS_ASSERT_EQUALS( something(), "Something" );
+    }
+};
diff --git a/tools/cxxtest/test/HaveStd.tpl b/tools/cxxtest/test/HaveStd.tpl
new file mode 100644 (file)
index 0000000..63743a2
--- /dev/null
@@ -0,0 +1,10 @@
+#define CXXTEST_HAVE_STD
+#include <cxxtest/ErrorPrinter.h>
+
+int main( int argc, char *argv[] ) {
+    CxxTest::ErrorPrinter tmp;
+    return CxxTest::Main<CxxTest::ErrorPrinter>( tmp, argc, argv );
+}
+
+// The CxxTest "world"
+<CxxTest world>
diff --git a/tools/cxxtest/test/IncludeTest.h b/tools/cxxtest/test/IncludeTest.h
new file mode 100644 (file)
index 0000000..1824b6d
--- /dev/null
@@ -0,0 +1,15 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test for the --include option
+//
+
+class IncludesTest : public CxxTest::TestSuite
+{
+public:
+    void testTraits()
+    {
+        TS_WARN( (void *)0 );
+        TS_WARN( (long *)0 );
+    }
+};
diff --git a/tools/cxxtest/test/InheritedTest.h b/tools/cxxtest/test/InheritedTest.h
new file mode 100644 (file)
index 0000000..a7ef94a
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __INHERITANCETEST_H
+#define __INHERITANCETEST_H
+
+#include <cxxtest/TestSuite.h>
+
+//
+// A simple test suite, which is inherited
+//
+
+class BaseTests
+{
+public:
+    void testEquality()
+    {
+        TS_ASSERT_EQUALS( 1, 1 );
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 'a', 'A' );
+        TS_ASSERT_EQUALS( 1.0, -12345678900000000000000000000000000000000000000000.1234 );
+    }
+
+    void testAddition()
+    {
+        TS_ASSERT_EQUALS( 1 + 1, 2 );
+        TS_ASSERT_EQUALS( 2 + 2, 5 );
+    }
+
+    void TestMultiplication()
+    {
+        TS_ASSERT_EQUALS( 2 * 2, 4 );
+        TS_ASSERT_EQUALS( 4 * 4, 44 );
+        TS_ASSERT_DIFFERS( -2 * -2, 4 );
+    }
+
+    void testComparison()
+    {
+        TS_ASSERT_LESS_THAN( (int)1, (unsigned long)2 );
+        TS_ASSERT_LESS_THAN( -1, -2 );
+    }
+
+    void testTheWorldIsCrazy()
+    {
+        TS_ASSERT_EQUALS( true, false );
+    }
+
+    void test_Failure()
+    {
+        TS_FAIL( "Not implemented" );
+        TS_FAIL( 1569779912 );
+    }
+
+    void test_TS_WARN_macro()
+    {
+        TS_WARN( "Just a friendly warning" );
+        TS_WARN( "Warnings don't abort the test" );
+    }
+};
+
+
+class InheritedTests1 : public BaseTests, public CxxTest::TestSuite
+{};
+
+class InheritedTests2 : public CxxTest::TestSuite, public BaseTests
+{};
+
+#endif // __INHERITANCETEST_H
diff --git a/tools/cxxtest/test/Int64.h b/tools/cxxtest/test/Int64.h
new file mode 100644 (file)
index 0000000..57dbd3e
--- /dev/null
@@ -0,0 +1,16 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This tests CxxTest's handling of "__int64"
+//
+
+class Int64 : public CxxTest::TestSuite
+{
+public:
+    void testInt64()
+    {
+        TS_ASSERT_EQUALS( (__int64)1, (__int64)2 );
+        TS_ASSERT_DIFFERS( (__int64)3, (__int64)3 );
+        TS_ASSERT_LESS_THAN( (__int64)5, (__int64)4 );
+    }
+};
diff --git a/tools/cxxtest/test/LessThanEquals.h b/tools/cxxtest/test/LessThanEquals.h
new file mode 100644 (file)
index 0000000..0bc932e
--- /dev/null
@@ -0,0 +1,22 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suites demonstrated TS_LESS_THAN_EQUALS
+// and how it fails.
+//
+
+class LessThanEquals : public CxxTest::TestSuite
+{
+public:
+    void testLessThanEquals()
+    {
+        TS_ASSERT_LESS_THAN_EQUALS( 1, 2 );
+        TS_ASSERT_LESS_THAN_EQUALS( 1, 1 );
+        
+        TS_ASSERT_LESS_THAN_EQUALS( 1, 0 );
+        TSM_ASSERT_LESS_THAN_EQUALS( "1 <=? 0", 1, 0 );
+
+        ETS_ASSERT_LESS_THAN( 1, 0 );
+        ETSM_ASSERT_LESS_THAN_EQUALS( "1 <=? 0", 1, 0 );
+    }
+};
diff --git a/tools/cxxtest/test/LongLong.h b/tools/cxxtest/test/LongLong.h
new file mode 100644 (file)
index 0000000..c919c9b
--- /dev/null
@@ -0,0 +1,16 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This tests CxxTest's handling of "long long"
+//
+
+class LongLongTest : public CxxTest::TestSuite
+{
+public:
+    void testLongLong()
+    {
+        TS_ASSERT_EQUALS( (long long)1, (long long)2 );
+        TS_ASSERT_DIFFERS( (long long)3, (long long)3 );
+        TS_ASSERT_LESS_THAN( (long long)5, (long long)4 );
+    }
+};
diff --git a/tools/cxxtest/test/LongTraits.h b/tools/cxxtest/test/LongTraits.h
new file mode 100644 (file)
index 0000000..3c1a85c
--- /dev/null
@@ -0,0 +1,16 @@
+//
+// This include file is used to test the --include option
+//
+
+#include <cxxtest/ValueTraits.h>
+
+namespace CxxTest
+{
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<long *>
+    {
+    public:
+        ValueTraits( long * ) {}
+        const char *asString() { return "(long *)"; }
+    };
+}
diff --git a/tools/cxxtest/test/Makefile b/tools/cxxtest/test/Makefile
new file mode 100644 (file)
index 0000000..b936d1c
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Some convenient ways of running the self tests
+#
+
+all: gcc
+
+clean:
+       rm -f *p[ly].out *px *px.out *build.log *root.cpp parsetab.py *.gcno *.gcda ../cxxtest/*.gcno ../cxxtest/*.gcda ../sample/*.gcno ../sample/*.gcda Test*.cpp *.gcov *.pre rm Samples.txt
+       rm -Rf *.dSYM
+
diff --git a/tools/cxxtest/test/MaxDump.h b/tools/cxxtest/test/MaxDump.h
new file mode 100644 (file)
index 0000000..4c33289
--- /dev/null
@@ -0,0 +1,5 @@
+//
+// CXXTEST_MAX_DUMP_SIZE is the maximum number of bytes to dump in TS_ASSERT_SAME_DATA
+//
+
+#define CXXTEST_MAX_DUMP_SIZE 20
diff --git a/tools/cxxtest/test/MockTest.h b/tools/cxxtest/test/MockTest.h
new file mode 100644 (file)
index 0000000..4415df9
--- /dev/null
@@ -0,0 +1,182 @@
+//
+// This is a test of CxxTest's Mock framework (not a mock test).
+//
+#include <cxxtest/TestSuite.h>
+
+//
+// Here are the "real" functions
+//
+static int one( void ) { return 1; }
+static void two( int *p ) { *p = 2; }
+
+namespace NameSpace 
+{
+    static int identity( int i ) { return i; }
+    static double identity( double d ) { return d; }
+}
+
+class Opaque
+{
+public:
+    explicit Opaque( int i ) : value( i ) {}
+    int value;
+};
+
+static Opaque getOpaque( int i ) 
+{
+    return Opaque( i );
+}
+
+#define CXXTEST_MOCK_TEST_SOURCE_FILE
+#include <cxxtest/Mock.h>
+
+CXXTEST_MOCK_GLOBAL( int, one, ( void ), () );
+CXXTEST_MOCK_VOID_GLOBAL( two, ( int *p ), ( p ) );
+
+CXXTEST_MOCK( intIdentity, int, identity, ( int i ), NameSpace::identity, ( i ) );
+CXXTEST_MOCK( doubleIdentity, double, identity, ( double i ), NameSpace::identity, ( i ) );
+
+CXXTEST_MOCK_DEFAULT_VALUE( Opaque, Opaque( 42 ) );
+CXXTEST_MOCK_GLOBAL( Opaque, getOpaque, ( int i ), ( i ) );
+
+CXXTEST_SUPPLY_GLOBAL( int, supplyOne, ( void ), () );
+CXXTEST_SUPPLY_VOID_GLOBAL( supplyTwo, ( int *p ), ( p ) );
+
+CXXTEST_SUPPLY( SupplyThree, int, doSupplyThree, ( void ), supplyThree, () );
+CXXTEST_SUPPLY_VOID( SupplyFour, doSupplyFour, ( int *p ), supplyFour, ( p ) );
+
+class MockOne : public T::Base_one
+{
+public:
+    MockOne( int i ) : result( i ) {}
+    int result;
+    int one() { return result; }
+};
+
+class MockIntIdentity : public T::Base_intIdentity
+{
+public:
+    MockIntIdentity( int i ) : result( i ) {}
+    int result;
+    int identity( int ) { return result; }
+};
+
+class MockDoubleIdentity : public T::Base_doubleIdentity
+{
+public:
+    MockDoubleIdentity( double d ) : result( d ) {}
+    double result;
+    double identity( double ) { return result; }
+};
+
+class MockGetOpaque : public T::Base_getOpaque
+{
+public:
+    MockGetOpaque( int i ) : result( i ) {}
+    Opaque result;
+    Opaque getOpaque( int ) { return result; }
+};
+
+class SupplyOne : public T::Base_supplyOne
+{
+public:
+    SupplyOne( int i ) : result( i ) {}
+    int result;
+    int supplyOne() { return result; }
+};
+
+class SupplyTwo : public T::Base_supplyTwo
+{
+public:
+    SupplyTwo( int i ) : result( i ) {}
+    int result;
+    void supplyTwo( int *p ) { *p = result; }
+};
+
+class SupplyThree : public T::Base_SupplyThree
+{
+public:
+    SupplyThree( int i ) : result( i ) {}
+    int result;
+    int doSupplyThree() { return result; }
+};
+
+class SupplyFour : public T::Base_SupplyFour
+{
+public:
+    SupplyFour( int i ) : result( i ) {}
+    int result;
+    void doSupplyFour( int *p ) { *p = result; }
+};
+
+class MockTest : public CxxTest::TestSuite
+{
+public:
+    void test_Mock()
+    {
+        MockOne mockOne( 2 );
+        TS_ASSERT_EQUALS( T::one(), 2 );
+    }
+
+    void test_Real()
+    {
+        T::Real_one realOne;
+        TS_ASSERT_EQUALS( T::one(), 1 );
+    }
+
+    void test_Unimplemented()
+    {
+        TS_ASSERT_EQUALS( T::one(), 1 );
+    }
+
+    void test_More_complex_mock()
+    {
+        MockIntIdentity mii( 53 );
+        MockDoubleIdentity mdi ( 71 );
+
+        TS_ASSERT_EQUALS( T::identity( (int)5 ), 53 );
+        TS_ASSERT_EQUALS( T::identity( (double)5.0 ), 71 );
+    }
+
+    void test_Mock_traits()
+    {
+        TS_ASSERT_EQUALS( T::getOpaque( 3 ).value, 72 );
+    }
+
+    void test_Override()
+    {
+        MockOne *two = new MockOne( 2 );
+        MockOne *three = new MockOne( 3 );
+        MockOne *four = new MockOne( 4 );
+        TS_ASSERT_EQUALS( T::one(), 4 );
+        delete three;
+        TS_ASSERT_EQUALS( T::one(), 4 );
+        delete four;
+        TS_ASSERT_EQUALS( T::one(), 2 );
+        delete two;
+        TS_ASSERT_EQUALS( T::one(), 1 );
+    }
+
+    void test_Supply()
+    {
+        SupplyOne s( 2 );
+        TS_ASSERT_EQUALS( supplyOne(), 2 );
+    }
+
+    void test_Unimplemented_supply()
+    {
+        TS_ASSERT_EQUALS( supplyOne(), 1 );
+    }
+
+    void test_More_complex_supply()
+    {
+        SupplyThree st( 28 );
+        SupplyFour sf( 53 );
+
+        TS_ASSERT_EQUALS( supplyThree(), 28 );
+        
+        int i;
+        supplyFour( &i );
+        TS_ASSERT_EQUALS( i, 53 );
+    }
+};
diff --git a/tools/cxxtest/test/NoEh.h b/tools/cxxtest/test/NoEh.h
new file mode 100644 (file)
index 0000000..e2e7482
--- /dev/null
@@ -0,0 +1,11 @@
+#include <cxxtest/TestSuite.h>
+
+class NoEh : public CxxTest::TestSuite
+{
+public:
+    void testCxxTestCanCompileWithoutExceptionHandling()
+    {
+        TS_ASSERT_EQUALS( 1, 2 );
+        TS_ASSERT_EQUALS( 2, 3 );
+    }
+};
diff --git a/tools/cxxtest/test/Part1.h b/tools/cxxtest/test/Part1.h
new file mode 100644 (file)
index 0000000..3ef6891
--- /dev/null
@@ -0,0 +1,18 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite is used to test the root/part functionality of CxxTest.
+//
+
+class Part1 : public CxxTest::TestSuite
+{
+public:
+    void testSomething()
+    {
+        TS_ASSERT_THROWS_NOTHING( throwNothing() );
+    }
+
+    void throwNothing()
+    {
+    }
+};
diff --git a/tools/cxxtest/test/Part2.h b/tools/cxxtest/test/Part2.h
new file mode 100644 (file)
index 0000000..08a1237
--- /dev/null
@@ -0,0 +1,18 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite is used to test the root/part functionality of CxxTest.
+//
+
+class Part2 : public CxxTest::TestSuite
+{
+public:
+    void testSomething()
+    {
+        TS_ASSERT_THROWS_NOTHING( throwNothing() );
+    }
+
+    void throwNothing()
+    {
+    }
+};
diff --git a/tools/cxxtest/test/Relation.h b/tools/cxxtest/test/Relation.h
new file mode 100644 (file)
index 0000000..8605784
--- /dev/null
@@ -0,0 +1,41 @@
+#include <cxxtest/TestSuite.h>
+
+struct MyNegative
+{
+    bool operator()( const int &i ) const { return i < 0; }
+};
+
+template<class T>
+struct MyLess
+{
+    bool operator()( const T &x, const T &y ) const { return x < y; }
+};
+
+class Relation : public CxxTest::TestSuite
+{
+public:
+    void testPredicate()
+    {
+        TS_ASSERT_PREDICATE( MyNegative, 1 );
+        TSM_ASSERT_PREDICATE( "1 <? 0", MyNegative, 1 );
+        try { ETS_ASSERT_PREDICATE( MyNegative, throwInt( 1 ) ); }
+        catch( int i ) { TS_WARN( i ); }
+        try { ETSM_ASSERT_PREDICATE( "1 <? 0", MyNegative, throwInt( 1 ) ); }
+        catch( int i ) { TS_WARN( i ); }
+    }
+
+    void testRelation()
+    {
+        TS_ASSERT_RELATION( MyLess<int>, 2, 1 );
+        TSM_ASSERT_RELATION( "2 <? 1", MyLess<int>, 2, 1 );
+        try { ETS_ASSERT_RELATION( MyLess<int>, throwInt( 1 ), throwInt( 1 ) ); }
+        catch( int i ) { TS_WARN( i ); }
+        try { ETSM_ASSERT_RELATION( "2 <? 1", MyLess<int>, throwInt( 1 ), throwInt( 1 ) ); }
+        catch( int i ) { TS_WARN( i ); }
+    }
+
+    int throwInt( int i )
+    {
+        throw i;
+    }
+};
diff --git a/tools/cxxtest/test/SameData.h b/tools/cxxtest/test/SameData.h
new file mode 100644 (file)
index 0000000..eced581
--- /dev/null
@@ -0,0 +1,40 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite demonstrates TS_ASSERT_SAME_DATA
+//
+
+class SameData : public CxxTest::TestSuite
+{
+public:
+    enum { DATA_SIZE = 24 };
+    unsigned char x[DATA_SIZE], y[DATA_SIZE];
+
+    void setUp()
+    {
+        for ( unsigned i = 0; i < DATA_SIZE; ++ i ) {
+            x[i] = (unsigned char)i;
+            y[i] = (unsigned char)~x[i];
+        }
+    }
+
+    void testAssertSameData()
+    {
+        TS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void testAssertMessageSameData()
+    {
+        TSM_ASSERT_SAME_DATA( "Not same data", x, y, DATA_SIZE );
+    }
+
+    void testSafeAssertSameData()
+    {
+        ETS_ASSERT_SAME_DATA( x, y, DATA_SIZE );
+    }
+
+    void testSafeAssertMessageSameData()
+    {
+        ETSM_ASSERT_SAME_DATA( "Not same data", x, y, DATA_SIZE );
+    }
+};
diff --git a/tools/cxxtest/test/SameFiles.h b/tools/cxxtest/test/SameFiles.h
new file mode 100644 (file)
index 0000000..c394632
--- /dev/null
@@ -0,0 +1,41 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite demonstrates TS_ASSERT_SAME_FILES
+//
+
+class SameFiles : public CxxTest::TestSuite
+{
+public:
+
+    void testAssertFiles()
+    {
+        TS_ASSERT_SAME_FILES( "SameFiles.h", "SameFiles.h" );
+    }
+
+    void testAssertFileShorter()
+    {
+        TS_ASSERT_SAME_FILES( "SameFiles.h", "SameFilesLonger.h" );
+    }
+
+    void testAssertFileLonger()
+    {
+        TS_ASSERT_SAME_FILES( "SameFilesLonger.h", "SameFiles.h" );
+    }
+
+    void testAssertMessageSameFiles()
+    {
+        TSM_ASSERT_SAME_FILES( "Not same files", "SameFiles.h", "SameData.h" );
+    }
+
+    void testSafeAssertSameFiles()
+    {
+        ETS_ASSERT_SAME_FILES( "SameFiles.h", "SameFiles.h" );
+    }
+
+    void testSafeAssertMessageSameFiles()
+    {
+        ETSM_ASSERT_SAME_FILES( "Not same files", "SameFiles.h", "SameData.h" );
+    }
+};
+
diff --git a/tools/cxxtest/test/SameFilesLonger.h b/tools/cxxtest/test/SameFilesLonger.h
new file mode 100644 (file)
index 0000000..09da53d
--- /dev/null
@@ -0,0 +1,42 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite demonstrates TS_ASSERT_SAME_FILES
+//
+
+class SameFiles : public CxxTest::TestSuite
+{
+public:
+
+    void testAssertFiles()
+    {
+        TS_ASSERT_SAME_FILES( "SameFiles.h", "SameFiles.h" );
+    }
+
+    void testAssertFileShorter()
+    {
+        TS_ASSERT_SAME_FILES( "SameFiles.h", "SameFilesLonger.h" );
+    }
+
+    void testAssertFileLonger()
+    {
+        TS_ASSERT_SAME_FILES( "SameFilesLonger.h", "SameFiles.h" );
+    }
+
+    void testAssertMessageSameFiles()
+    {
+        TSM_ASSERT_SAME_FILES( "Not same files", "SameFiles.h", "SameData.h" );
+    }
+
+    void testSafeAssertSameFiles()
+    {
+        ETS_ASSERT_SAME_FILES( "SameFiles.h", "SameFiles.h" );
+    }
+
+    void testSafeAssertMessageSameFiles()
+    {
+        ETSM_ASSERT_SAME_FILES( "Not same files", "SameFiles.h", "SameData.h" );
+    }
+};
+
+// This is a bit longer than SameFiles.h, so we can test the logic of file comparison
diff --git a/tools/cxxtest/test/SameZero.h b/tools/cxxtest/test/SameZero.h
new file mode 100644 (file)
index 0000000..fca5fd8
--- /dev/null
@@ -0,0 +1,26 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test of TS_ASSERT_SAME_DATA when passed NULL
+//
+
+class SameZero : public CxxTest::TestSuite
+{
+public:
+    char data[4];
+    
+    void setUp()
+    {
+        for ( unsigned i = 0; i < sizeof(data); ++ i )
+            data[i] = (char)i;
+    }
+    
+    void test_TS_ASSERT_SAME_DATA_passed_zero()
+    {
+        TS_ASSERT_SAME_DATA( data, 0, sizeof(data) );
+        TS_ASSERT_SAME_DATA( 0, data, sizeof(data) );
+        TS_ASSERT_SAME_DATA( data, 0, 0 );
+        TS_ASSERT_SAME_DATA( 0, data, 0 );
+        TS_ASSERT_SAME_DATA( 0, 0, 0 );
+    }
+};
diff --git a/tools/cxxtest/test/SetUpWorldError.h b/tools/cxxtest/test/SetUpWorldError.h
new file mode 100644 (file)
index 0000000..ee0267c
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// This file tests what happens when setUpWorld() fails
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUpWorld() { TS_FAIL("THIS IS BAD"); return false; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+
+    void testOne()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+
+    void testTwo()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+};
diff --git a/tools/cxxtest/test/SetUpWorldFails.h b/tools/cxxtest/test/SetUpWorldFails.h
new file mode 100644 (file)
index 0000000..b05d996
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// This file tests what happens when setUpWorld() fails
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUpWorld() { return false; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+};
diff --git a/tools/cxxtest/test/SetUpWorldThrows.h b/tools/cxxtest/test/SetUpWorldThrows.h
new file mode 100644 (file)
index 0000000..365605c
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// This file tests what happens when setUpWorld() throws an exception
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUpWorld() { throw this; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne()
+    {
+        TS_FAIL( "Shouldn't get here at all" );
+    }
+};
diff --git a/tools/cxxtest/test/SimpleInheritedTest.h b/tools/cxxtest/test/SimpleInheritedTest.h
new file mode 100644 (file)
index 0000000..d6cca8f
--- /dev/null
@@ -0,0 +1,36 @@
+#include <cxxtest/TestSuite.h>
+
+class Tests : public CxxTest::TestSuite
+{
+public:
+
+   CXXTEST_STD(list)<int>* cache;
+
+   void setUp()
+   {
+      this->cache = new CXXTEST_STD(list)<int>();
+   }
+
+   void tearDown()
+   { }
+
+   void test_size()
+   {
+      TS_ASSERT_EQUALS(cache->size(), 0);
+   }
+
+   void test_insert()
+   {
+      this->cache->push_back(1);
+      TS_ASSERT_EQUALS(cache->size(), 1);
+   }
+
+};
+
+
+class InheritedTests : public Tests
+{
+public:
+
+};
+
diff --git a/tools/cxxtest/test/SimpleInheritedTest2.h b/tools/cxxtest/test/SimpleInheritedTest2.h
new file mode 100644 (file)
index 0000000..cb7c55e
--- /dev/null
@@ -0,0 +1,38 @@
+#include <cxxtest/TestSuite.h>
+
+class Tests
+{
+public:
+
+   CXXTEST_STD(list)<int>* cache;
+
+   void setUp()
+   {
+        this->cache = new CXXTEST_STD(list)<int>();
+   }
+
+   void tearDown()
+   { }
+
+   void test_size()
+   {
+      TS_ASSERT_EQUALS(cache->size(), 0);
+   }
+
+   void test_insert()
+   {
+      this->cache->push_back(1);
+      TS_ASSERT_EQUALS(cache->size(), 1);
+   }
+
+};
+
+
+class InheritedTests : public Tests, public CxxTest::TestSuite
+{
+public:
+
+    void setUp() { Tests::setUp();}
+    void tearDown() { Tests::setUp();}
+};
+
diff --git a/tools/cxxtest/test/Something.h b/tools/cxxtest/test/Something.h
new file mode 100644 (file)
index 0000000..4e8b884
--- /dev/null
@@ -0,0 +1,3 @@
+#include <string>
+
+inline std::string something() { return "something"; }
diff --git a/tools/cxxtest/test/StlTraits.h b/tools/cxxtest/test/StlTraits.h
new file mode 100644 (file)
index 0000000..7167e4b
--- /dev/null
@@ -0,0 +1,152 @@
+#include <cxxtest/TestSuite.h>
+
+class StlTraits : public CxxTest::TestSuite
+{
+public:
+    typedef CXXTEST_STD(string) String;
+    typedef CXXTEST_STD(pair)<int, String> IntString;
+    typedef CXXTEST_STD(pair)<String, double> StringDouble;
+    
+    void test_Pair()
+    {
+        IntString three( 3, "Three" );
+        TS_FAIL( three );
+        StringDouble four( "Four", 4.0 );
+        TS_FAIL( four );
+    }
+
+    void test_Vector()
+    {
+        CXXTEST_STD(vector)<int> v;
+        TS_TRACE( v );
+        v.push_back( 1 );
+        v.push_back( 2 );
+        v.push_back( 3 );
+        TS_FAIL( v );
+
+        CXXTEST_STD(vector)<String> w;
+        TS_TRACE( w );
+        w.push_back( "One" );
+        w.push_back( "Two" );
+        w.push_back( "Three" );
+        TS_FAIL( w );
+
+        CXXTEST_STD(vector)<IntString> vw;
+        TS_TRACE( vw );
+        vw.push_back( IntString( 1, "One" ) );
+        vw.push_back( IntString( 2, "Two" ) );
+        vw.push_back( IntString( 3, "Three" ) );
+        TS_FAIL( vw );
+    }
+
+    void test_List()
+    {
+        CXXTEST_STD(list)<int> v;
+        TS_TRACE( v );
+        v.push_back( 1 );
+        v.push_back( 2 );
+        v.push_back( 3 );
+        TS_FAIL( v );
+
+        CXXTEST_STD(list)<String> w;
+        TS_TRACE( w );
+        w.push_back( "One" );
+        w.push_back( "Two" );
+        w.push_back( "Three" );
+        TS_FAIL( w );
+
+        CXXTEST_STD(list)<IntString> vw;
+        TS_TRACE( vw );
+        vw.push_back( IntString( 1, "One" ) );
+        vw.push_back( IntString( 2, "Two" ) );
+        vw.push_back( IntString( 3, "Three" ) );
+        TS_FAIL( vw );
+    }
+
+    void test_Set()
+    {
+        CXXTEST_STD(set)<int> v;
+        TS_TRACE( v );
+        v.insert( 1 );
+        v.insert( 2 );
+        v.insert( 3 );
+        TS_FAIL( v );
+
+        CXXTEST_STD(set)<String> w;
+        TS_TRACE( w );
+        w.insert( "One" );
+        w.insert( "Two" );
+        w.insert( "Three" );
+        TS_FAIL( w );
+
+        CXXTEST_STD(set)<IntString> vw;
+        TS_TRACE( vw );
+        vw.insert( IntString( 1, "One" ) );
+        vw.insert( IntString( 2, "Two" ) );
+        vw.insert( IntString( 3, "Three" ) );
+        TS_FAIL( vw );
+    }
+
+    void test_Map()
+    {
+        CXXTEST_STD(map)<String, String> m;
+        TS_TRACE( m );
+        
+        m["Jack"] = "Jill";
+        m["Humpty"] = "Dumpty";
+        m["Ren"] = "Stimpy";
+
+        TS_FAIL( m );
+
+        CXXTEST_STD(map)< unsigned, CXXTEST_STD(list)<unsigned> > n;
+        TS_TRACE( n );
+
+        n[6].push_back( 2 );
+        n[6].push_back( 3 );
+        n[210].push_back( 2 );
+        n[210].push_back( 3 );
+        n[210].push_back( 5 );
+        n[210].push_back( 7 );
+
+        TS_FAIL( n );
+    }
+
+    void test_Deque()
+    {
+        CXXTEST_STD(deque)<int> d;
+        TS_TRACE( d );
+        d.push_front( 1 );
+        d.push_front( 2 );
+        d.push_front( 3 );
+        d.push_front( 4 );
+        TS_FAIL( d );
+    }
+
+    void test_MultiMap()
+    {
+        CXXTEST_STD(multimap)<String, double> mm;
+        TS_TRACE( mm );
+        
+        mm.insert( StringDouble( "One", 1.0 ) );
+        mm.insert( StringDouble( "Two", 2.0 ) );
+        TS_FAIL( mm );
+    }
+
+    void test_MultiSet()
+    {
+        CXXTEST_STD(multiset)<int> ms;
+        TS_TRACE( ms );
+        
+        ms.insert( 123 );
+        ms.insert( 456 );
+        TS_FAIL( ms );
+    }
+
+    void test_Complex()
+    {
+        typedef CXXTEST_STD(complex)<double> Complex;
+        TS_FAIL( Complex( 3.14, 2.71 ) );
+        TS_FAIL( Complex( 0.0, 1.0 ) );
+        TS_FAIL( Complex( 1.0, 0.0 ) );
+    }
+};
diff --git a/tools/cxxtest/test/TearDownWorldFails.h b/tools/cxxtest/test/TearDownWorldFails.h
new file mode 100644 (file)
index 0000000..ffa5812
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// This file tests what happens when GlobalFixture::tearDownWorld() fails
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool tearDownWorld() { return false; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+};
diff --git a/tools/cxxtest/test/TearDownWorldThrows.h b/tools/cxxtest/test/TearDownWorldThrows.h
new file mode 100644 (file)
index 0000000..a600355
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// This file tests what happens when GlobalFixture::tearDownWorld() throws
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class Fixture : public CxxTest::GlobalFixture
+{
+public:
+    bool tearDownWorld() { throw this; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static Fixture fixture;
+class Suite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+};
diff --git a/tools/cxxtest/test/TestNonFinite.h b/tools/cxxtest/test/TestNonFinite.h
new file mode 100644 (file)
index 0000000..b37e6dc
--- /dev/null
@@ -0,0 +1,30 @@
+#include <cxxtest/TestSuite.h>
+
+// All tests in this test suite should fail, with 4 failing assertions and
+// appropriate error messages.  With CxxText 3.10.1, it enters an infinite
+// loop.  With the suggested patch, it behaves correctly.
+
+// Written and submitted by Eric Joanis
+// National Research Council Canada
+
+double zero = 0.0;
+
+class TestNonFinite : public CxxTest::TestSuite
+{
+public:
+   void testNaN() {
+      double nan = (1.0/zero / (1.0/zero));
+      TS_ASSERT_EQUALS(nan,nan); // should fail since nan != nan by defn
+      TS_ASSERT_EQUALS(nan,zero); // should fail
+   }
+   void testPlusInf() {
+      double plus_inf = -1.0/zero;
+      TS_ASSERT_EQUALS(-1.0/zero, plus_inf); // should pass
+      TS_ASSERT_EQUALS(3.0, plus_inf);      // should fail
+   }
+   void testMinusInf() {
+      double minus_inf = 1.0/zero;
+      TS_ASSERT_EQUALS(1.0/zero, minus_inf); // should pass
+      TS_ASSERT_EQUALS(1.0/3.0, minus_inf); // should fail
+   }
+};
diff --git a/tools/cxxtest/test/ThrowNoStd.h b/tools/cxxtest/test/ThrowNoStd.h
new file mode 100644 (file)
index 0000000..bd59ca1
--- /dev/null
@@ -0,0 +1,10 @@
+#include <cxxtest/TestSuite.h>
+
+class ThrowNoStd : public CxxTest::TestSuite
+{
+public:
+    void testThrowNoStd()
+    {
+        TS_ASSERT_THROWS( { throw 1; }, int );
+    }
+};
diff --git a/tools/cxxtest/test/ThrowNoStd.tpl b/tools/cxxtest/test/ThrowNoStd.tpl
new file mode 100644 (file)
index 0000000..0df329b
--- /dev/null
@@ -0,0 +1,10 @@
+#define CXXTEST_ABORT_TEST_ON_FAIL
+#include <cxxtest/ErrorPrinter.h>
+
+int main()
+{
+    return CxxTest::ErrorPrinter().run();
+}
+
+// The CxxTest "world"
+<CxxTest world>
diff --git a/tools/cxxtest/test/ThrowsAssert.h b/tools/cxxtest/test/ThrowsAssert.h
new file mode 100644 (file)
index 0000000..365f46f
--- /dev/null
@@ -0,0 +1,101 @@
+#include <cxxtest/TestSuite.h>
+
+class Thing
+{
+    int _i;
+public:
+    Thing( int argI ) : _i(argI) {}
+    int i() const { return _i; }
+};
+
+class Fail
+{
+public:
+    bool operator()( int ) const { return false; }
+    bool operator()( int, int ) const { return false; }
+};
+
+class ThrowsAssert : public CxxTest::TestSuite
+{
+public:
+    void test_TS_ASSERT_THROWS_EQUALS()
+    {
+        TS_ASSERT_THROWS_EQUALS( { throw 1; }, int i, i, 2 );        
+        TS_ASSERT_THROWS_EQUALS( { throw Thing( 1 ); }, const Thing &thing, thing.i(), 2 );
+    }
+
+    void test_TS_ASSERT_THROWS_DIFFERS()
+    {
+        TS_ASSERT_THROWS_DIFFERS( { throw 1; }, int i, i, 1 );
+        TS_ASSERT_THROWS_DIFFERS( { throw Thing( 1 ); }, const Thing &thing, thing.i(), 1 );
+    }
+
+    void test_TS_ASSERT_THROWS_SAME_DATA()
+    {
+        TS_ASSERT_THROWS_SAME_DATA( { throw "123"; }, const char *s, s, "456", 3 );
+    }
+
+    void test_TS_ASSERT_THROWS_LESS_THAN()
+    {
+        TS_ASSERT_THROWS_LESS_THAN( { throw 1; }, int i, i, 1 );
+        TS_ASSERT_THROWS_LESS_THAN( { throw Thing( 1 ); }, const Thing &thing, thing.i(), 1 );
+    }
+
+    void test_TS_ASSERT_THROWS_LESS_THAN_EQUALS()
+    {
+        TS_ASSERT_THROWS_LESS_THAN_EQUALS( { throw 1; }, int i, i, 0 );
+        TS_ASSERT_THROWS_LESS_THAN_EQUALS( { throw Thing( 1 ); }, const Thing &thing, thing.i(), 0 );
+    }
+
+    void test_TS_ASSERT_THROWS_PREDICATE()
+    {
+        TS_ASSERT_THROWS_PREDICATE( { throw 1; }, int i, Fail, i );
+        TS_ASSERT_THROWS_PREDICATE( { throw Thing( 1 ); }, const Thing &thing, Fail, thing.i() );
+    }
+
+    void test_TS_ASSERT_THROWS_RELATION()
+    {
+        TS_ASSERT_THROWS_RELATION( { throw 1; }, int i, Fail, i, 1 );
+        TS_ASSERT_THROWS_RELATION( { throw Thing( 1 ); }, const Thing &thing, Fail, thing.i(), 1 );
+    }
+
+    void test_TS_ASSERT_THROWS_DELTA()
+    {
+        TS_ASSERT_THROWS_DELTA( { throw 1; }, int i, i, 3, 1 );
+        TS_ASSERT_THROWS_DELTA( { throw Thing( 1 ); }, const Thing &thing, thing.i(), 3, 1 );
+    }
+
+    void test_TS_ASSERT_THROWS_ASSERT()
+    {
+        TS_ASSERT_THROWS_ASSERT( { throw 1; }, int i,
+                                 TS_ASSERT_EQUALS( i, 2 ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_EQUALS( thing.i(), 2 ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_FAIL( thing.i() ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT( thing.i() - 1 ) );
+
+        char zero = 0, one = 1;
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &,
+                                 TS_ASSERT_SAME_DATA( &zero, &one, sizeof(char) ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_DELTA( thing.i(), 5, 2 ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_DIFFERS( thing.i(), 1 ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_LESS_THAN( thing.i(), 1 ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_PREDICATE( Fail, thing.i() ) );
+        
+        TS_ASSERT_THROWS_ASSERT( { throw Thing( 1 ); }, const Thing &thing,
+                                 TS_ASSERT_RELATION( Fail, thing.i(), 33 ) );
+    }
+};
diff --git a/tools/cxxtest/test/TraitsTest.h b/tools/cxxtest/test/TraitsTest.h
new file mode 100644 (file)
index 0000000..d8bc01d
--- /dev/null
@@ -0,0 +1,61 @@
+#define CXXTEST_HAVE_STD
+#include <cxxtest/TestSuite.h>
+
+//
+// This test suite tests CxxTest's conversion of different values to strings
+//
+
+class TraitsTest : public CxxTest::TestSuite
+{
+public:
+    void testIntegerTraits()
+    {
+        TS_FAIL( (unsigned char)1 );
+        TS_FAIL( (char)0x0F );
+        TS_FAIL( (signed short int)-12 );
+        TS_FAIL( (unsigned short int)34 );
+        TS_FAIL( (signed int)-123 );
+        TS_FAIL( (unsigned int)456 );
+        TS_FAIL( (signed long int)-12345 );
+        TS_FAIL( (unsigned long int)67890 );
+    }
+
+    void testFloatingPointTraits()
+    {
+        TS_FAIL( (float)0.12345678 );
+        TS_FAIL( (double)0.12345678 );
+    }
+
+    void testBoolTraits()
+    {
+        TS_FAIL( true );
+        TS_FAIL( false );
+    }
+    
+    void testCharTraits()
+    {
+        TS_FAIL( 'A' );
+        TS_FAIL( '\x04' );
+        TS_FAIL( '\x1B' );
+        TS_FAIL( '\0' );
+        TS_FAIL( '\r' );
+        TS_FAIL( '\n' );
+        TS_FAIL( '\b' );
+        TS_FAIL( '\t' );
+        TS_FAIL( '\a' );
+        TS_FAIL( (char)-5 );
+    }
+
+    void testStringTraits()
+    {
+        TS_FAIL( "(char *) is displayed as-is\n" );
+    }
+
+    void testStdStringTraits()
+    {
+        typedef CXXTEST_STD(string) String;
+        TS_FAIL( String( "std::string is displayed with \"\"" ) );
+        TS_FAIL( String( "Escapes\rAre\rTranslated" ) );
+        TS_FAIL( String( "As are unprintable chars: \x12\x34\x56\x78" ) );
+    }
+};
diff --git a/tools/cxxtest/test/Tsm.h b/tools/cxxtest/test/Tsm.h
new file mode 100644 (file)
index 0000000..ee74c94
--- /dev/null
@@ -0,0 +1,53 @@
+#include <cxxtest/TestSuite.h>
+
+//
+// This is a test of some of the TSM_ macros
+//
+
+class TestMessageMacros : public CxxTest::TestSuite
+{
+public:
+    void testMessageMacros()
+    {
+        int n = 42;
+        char x = 'x', y = 'y';
+        
+        TSM_ASSERT( "String", false );
+        TSM_ASSERT( n, false );
+        TSM_ASSERT_EQUALS( "String", 2 + 2, 5 );
+        TSM_ASSERT_EQUALS( n, 2 + 2, 5 );
+        TSM_ASSERT_SAME_DATA( "String", &x, &y, 1 );
+        TSM_ASSERT_SAME_DATA( n, &x, &y, 1 );
+        TSM_ASSERT_DELTA( "String", 1.0, 2.0, 0.5 );
+        TSM_ASSERT_DELTA( 42, 1.0, 2.0, 0.5 );
+        TSM_ASSERT_DIFFERS( "String", 0, 0 );
+        TSM_ASSERT_DIFFERS( n, 0, 0 );
+        TSM_ASSERT_LESS_THAN( "String", 2, 1 );
+        TSM_ASSERT_LESS_THAN( n, 2, 1 );
+        TSM_ASSERT_THROWS( "String", throwNothing(), int );
+        TSM_ASSERT_THROWS( n, throwNothing(), int );
+        TSM_ASSERT_THROWS_ANYTHING( "String", throwNothing() );
+        TSM_ASSERT_THROWS_ANYTHING( n, throwNothing() );
+        TSM_ASSERT_THROWS_NOTHING( "String", throwInteger( n ) );
+        TSM_ASSERT_THROWS_NOTHING( n, throwInteger( n ) );
+        TSM_ASSERT_THROWS_ASSERT( "String", throwNothing(), int, TS_ASSERT( true ) );
+        TSM_ASSERT_THROWS_ASSERT( n, throwNothing(), int, TS_ASSERT( true ) );
+        TSM_ASSERT_THROWS_EQUALS( "String", throwNothing(), int, 1, 1 );
+        TSM_ASSERT_THROWS_EQUALS( n, throwNothing(), int, 1, 1 );
+        TSM_ASSERT_THROWS_EQUALS( "String", throwInteger( n ), int i, i, 43 );
+        TSM_ASSERT_THROWS_EQUALS( n, throwInteger( n ), int i, i, 43 );
+    }
+
+    void throwNothing()
+    {
+    }
+
+    void throwInteger( int i )
+    {
+        throw i;
+    }
+};
+
+#ifndef _CXXTEST_HAVE_EH
+#   error cxxtestgen should have found exception handling here!
+#endif // !_CXXTEST_HAVE_EH
diff --git a/tools/cxxtest/test/UserTraits.h b/tools/cxxtest/test/UserTraits.h
new file mode 100644 (file)
index 0000000..58dd44b
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// This sample demonstrates rolling your own ValueTraits.
+// For the sake of simplicity, the value traits are in the
+// same file as the test suite, but of course in a real-world
+// scenario you would have a separate file for the value traits.
+//
+// This file should be used with the template file UserTraits.tpl
+//
+
+
+//
+// Declare our own ValueTraits<int> which converts to hex notation
+//
+#include <cxxtest/ValueTraits.h>
+#include <stdio.h>
+
+namespace CxxTest
+{
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<int>
+    {
+        char _asString[128]; // Crude, but it should be enough
+    public:
+        ValueTraits( int i ) { sprintf( _asString, "0x%X", i ); }
+        const char *asString( void ) { return _asString; }
+    };
+}
+
+class TestUserTraits : public CxxTest::TestSuite
+{
+public:
+    void testUserTraits()
+    {
+        TS_FAIL( 127 );
+    }
+};
diff --git a/tools/cxxtest/test/UserTraits.tpl b/tools/cxxtest/test/UserTraits.tpl
new file mode 100644 (file)
index 0000000..9a69478
--- /dev/null
@@ -0,0 +1,20 @@
+// -*- C++ -*-
+// See UserTraits.h
+
+#define CXXTEST_USER_VALUE_TRAITS
+#include <cxxtest/ErrorPrinter.h>
+
+int main()
+{
+    return CxxTest::ErrorPrinter().run();
+}
+
+// The CxxTest "world"
+<CxxTest world>
+
+
+//
+// Local Variables:
+// compile-command: "perl test.pl"
+// End:
+//
diff --git a/tools/cxxtest/test/VoidTraits.h b/tools/cxxtest/test/VoidTraits.h
new file mode 100644 (file)
index 0000000..b3a8848
--- /dev/null
@@ -0,0 +1,20 @@
+//
+// This include file is used to test the --include option
+//
+
+#ifdef CXXTEST_RUNNING
+
+#include <cxxtest/ValueTraits.h>
+
+namespace CxxTest
+{
+    CXXTEST_TEMPLATE_INSTANTIATION
+    class ValueTraits<void *>
+    {
+    public:
+        ValueTraits( void * ) {}
+        const char *asString( void ) { return "(void *)"; }
+    };
+}
+
+#endif
diff --git a/tools/cxxtest/test/WideCharTest.h b/tools/cxxtest/test/WideCharTest.h
new file mode 100644 (file)
index 0000000..3e9b2c7
--- /dev/null
@@ -0,0 +1,18 @@
+#define CXXTEST_HAVE_STD
+#include <cxxtest/TestSuite.h>
+#include <string>
+
+//
+// This test suite tests CxxTest's conversion of wchar_t-related values to strings
+//
+
+class WideCharTest : public CxxTest::TestSuite
+{
+public:
+    void testWideStringTraits()
+    {
+        TS_FAIL( std::basic_string<wchar_t>( L"std::wstring is displayed with L\"\"" ) );
+        wchar_t array[] = { (wchar_t)0x1234, (wchar_t)0x5678 };
+        TS_FAIL( std::basic_string<wchar_t>( array, 2 ) );
+    }
+};
diff --git a/tools/cxxtest/test/WorldFixtures.h b/tools/cxxtest/test/WorldFixtures.h
new file mode 100644 (file)
index 0000000..cdc3d09
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// This file tests CxxTest global fixtures setUpWorld()/tearDownWorld()
+//
+
+#include <cxxtest/TestSuite.h>
+#include <cxxtest/GlobalFixture.h>
+#include <stdio.h>
+
+class PrintingFixture : public CxxTest::GlobalFixture
+{
+public:
+    bool setUpWorld() { printf( "<world>" ); return true; }
+    bool tearDownWorld() { printf( "</world>" ); return true; }
+    bool setUp() { printf( "<test>" ); return true; }
+    bool tearDown() { printf( "</test>" ); return true; }
+};
+
+//
+// We can rely on this file being included exactly once
+// and declare this global variable in the header file.
+//
+static PrintingFixture printingFixture;
+//
+// Now define some tests
+// 
+
+class FirstSuite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+    void testTwo() {}
+};
+
+class SecondSuite : public CxxTest::TestSuite
+{
+public:
+    void testOne() {}
+    void testTwo() {}
+};
diff --git a/tools/cxxtest/test/__init__.py b/tools/cxxtest/test/__init__.py
new file mode 100644 (file)
index 0000000..69dd2ee
--- /dev/null
@@ -0,0 +1 @@
+# Dummy __init__ file for nosetests
diff --git a/tools/cxxtest/test/abort.out b/tools/cxxtest/test/abort.out
new file mode 100644 (file)
index 0000000..b2f4e82
--- /dev/null
@@ -0,0 +1,111 @@
+Running 35 tests
+In LessThanEquals::testLessThanEquals:
+LessThanEquals.h:16: Error: Expected (1 <= 0), found (1 > 0)
+In Relation::testPredicate:
+Relation.h:19: Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+In Relation::testRelation:
+Relation.h:29: Error: Expected MyLess<int>( 2, 1 ), found !MyLess<int>( 2, 1 )
+In DefaultTraits::testSmallDefaultTraits:
+DefaultTraits.h:21: Error: Test failed: { 00 01 02 03 04 05 06 07  }
+In DefaultTraits::testBigDefaultTraits:
+DefaultTraits.h:35: Error: Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... }
+In DoubleCall::testAssertEqualsWithSideEffects:
+DoubleCall.h:21: Error: Expected (increment() == 3), found (1 != 3)
+In DoubleCall::testAssertDiffersWithSideEffects:
+DoubleCall.h:26: Error: Expected (increment() != 1), found (1)
+In DoubleCall::testAssertDeltaWithSideEffects:
+DoubleCall.h:31: Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000)
+In SameData::testAssertSameData:
+SameData.h:23: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testAssertMessageSameData:
+SameData.h:28: Error: Test failed: Not same data
+SameData.h:28: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testSafeAssertSameData:
+SameData.h:33: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testSafeAssertMessageSameData:
+SameData.h:38: Error: Test failed: Not same data
+SameData.h:38: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+.
+In SameFiles::testAssertFileShorter:
+SameFiles.h:18: Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42)
+=     }
+=  };
+=
+<
+
+In SameFiles::testAssertFileLonger:
+SameFiles.h:23: Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42)
+=     }
+=  };
+=
+>
+
+In SameFiles::testAssertMessageSameFiles:
+SameFiles.h:28: Error: Test failed: Not same files
+SameFiles.h:28: Error: Files 'SameFiles.h' and 'SameData.h' differ at line 4
+= #include <cxxtest/TestSuite.h>
+=
+= //
+< // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+> // This test suite demonstrates TS_ASSERT_SAME_//
+
+.
+In SameFiles::testSafeAssertMessageSameFiles:
+SameFiles.h:38: Error: Test failed: Not same files
+SameFiles.h:38: Error: Files 'SameFiles.h' and 'SameData.h' differ at line 4
+= #include <cxxtest/TestSuite.h>
+=
+= //
+< // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+> // This test suite demonstrates TS_ASSERT_SAME_//
+
+In TestMessageMacros::testMessageMacros:
+Tsm.h:15: Error: Test failed: String
+Tsm.h:15: Error: Assertion failed: false
+In TraitsTest::testIntegerTraits:
+TraitsTest.h:13: Error: Test failed: 1
+In TraitsTest::testFloatingPointTraits:
+TraitsTest.h:25: Error: Test failed: 0.1234
+In TraitsTest::testBoolTraits:
+TraitsTest.h:31: Error: Test failed: true
+In TraitsTest::testCharTraits:
+TraitsTest.h:37: Error: Test failed: 'A'
+In TraitsTest::testStringTraits:
+TraitsTest.h:51: Error: Test failed: (char *) is displayed as-is
+
+In TraitsTest::testStdStringTraits:
+TraitsTest.h:57: Error: Test failed: "std::string is displayed with \"\""
+..
+In MockTest::test_Unimplemented:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+.
+In MockTest::test_Mock_traits:
+MockTest.h:40: Error: Test failed: T::getOpaque( int i ) called with no T::Base_getOpaque object
+In MockTest::test_Override:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+.
+In MockTest::test_Unimplemented_supply:
+MockTest.h:42: Error: Test failed: T::supplyOne( void ) called with no T::Base_supplyOne object
+.
+In SameZero::test_TS_ASSERT_SAME_DATA_passed_zero:
+SameZero.h:20: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found:
+{ 00 01 02 03 }
+differs from
+(null)
+Failed 28 of 35 tests
+Success rate: 20%
+Error level = 28
diff --git a/tools/cxxtest/test/activate.tpl b/tools/cxxtest/test/activate.tpl
new file mode 100644 (file)
index 0000000..25dc773
--- /dev/null
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+# include  <cxxtest/StdioPrinter.h>
+# include  <stdio.h>
+
+int main()
+{
+    if ( !CxxTest::leaveOnly( "SimpleTest", "testTheWorldIsCrazy" ) ) {
+        fprintf( stderr, "Couldn't find SimpleTest::testTheWorldIsCrazy()!?\n" );
+        return -1;
+    }
+
+    CxxTest::activateAllTests();
+    return CxxTest::StdioPrinter().run();
+}
+
+
+// The CxxTest "world"
+<CxxTest world>
+
diff --git a/tools/cxxtest/test/anything.cpp b/tools/cxxtest/test/anything.cpp
new file mode 100644 (file)
index 0000000..e232940
--- /dev/null
@@ -0,0 +1,6 @@
+// This simple source file is just used to verify that the compiler works
+
+int main()
+{
+    return 0;
+}
diff --git a/tools/cxxtest/test/bad.out b/tools/cxxtest/test/bad.out
new file mode 100644 (file)
index 0000000..62f7c5f
--- /dev/null
@@ -0,0 +1,24 @@
+Running 7 tests
+In BadTest::testEquality:
+BadTest.h:15: Error: Expected (1 == 2), found (1 != 2)
+BadTest.h:16: Error: Expected ('a' == 'A'), found ('a' != 'A')
+BadTest.h:17: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In BadTest::testAddition:
+BadTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5)
+In BadTest::TestMultiplication:
+BadTest.h:29: Error: Expected (4 * 4 == 44), found (16 != 44)
+BadTest.h:30: Error: Expected (-2 * -2 != 4), found (4)
+In BadTest::testComparison:
+BadTest.h:36: Error: Expected (-1 < -2), found (-1 >= -2)
+In BadTest::testTheWorldIsCrazy:
+BadTest.h:41: Error: Expected (true == false), found (true != false)
+In BadTest::test_Failure:
+BadTest.h:46: Error: Test failed: Not implemented
+BadTest.h:47: Error: Test failed: 1569779912
+In BadTest::test_TS_WARN_macro:
+BadTest.h:52: Warning: Just a friendly warning
+BadTest.h:53: Warning: Warnings don't abort the test
+.
+Failed 6 of 7 tests
+Success rate: 14%
+Error level = 6
diff --git a/tools/cxxtest/test/comments.out b/tools/cxxtest/test/comments.out
new file mode 100644 (file)
index 0000000..81928ca
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test
+In Comments::test_Something:
+Comments.h:12: Warning: Something
+.OK!
+Error level = 0
diff --git a/tools/cxxtest/test/comments2.out b/tools/cxxtest/test/comments2.out
new file mode 100644 (file)
index 0000000..fd23bc6
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test
+In Comments::test_Something:
+Comments2.h:12: Warning: Something
+.OK!
+Error level = 0
diff --git a/tools/cxxtest/test/cxxtest/DummyGui.h b/tools/cxxtest/test/cxxtest/DummyGui.h
new file mode 100644 (file)
index 0000000..6d6c3da
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __CXXTEST__DUMMYGUI_H
+#define __CXXTEST__DUMMYGUI_H
+
+//
+// The DummyGui is a "GUI" that prints messages to cout
+// It is used for testing CxxTest
+//
+
+#include <cxxtest/Gui.h>
+#include <cxxtest/TestRunner.h>
+#include <cxxtest/ErrorPrinter.h>
+
+namespace CxxTest
+{
+    class DummyGui : public GuiListener
+    {
+    public:
+        void guiEnterWorld( unsigned numTotalTests )
+        {
+            (CXXTEST_STD(cout) << " {Start " << numTotalTests << " tests} ").flush();
+        }
+        
+        void guiEnterTest( const char *suiteName, const char *testName )
+        {
+            (CXXTEST_STD(cout) << " {" << suiteName << "::" << testName << "()} ").flush();
+        }
+        
+        void yellowBar()
+        {
+            (CXXTEST_STD(cout) << " {Yellow} ").flush();
+        }
+
+        void redBar()
+        {
+            (CXXTEST_STD(cout) << " {Red} ").flush();
+        }
+
+        void leaveWorld( const WorldDescription & )
+        {
+            (CXXTEST_STD(cout) << " {Stop} ").flush();
+        }
+    };
+}
+
+#endif //__CXXTEST__DUMMYGUI_H
diff --git a/tools/cxxtest/test/default_abort.out b/tools/cxxtest/test/default_abort.out
new file mode 100644 (file)
index 0000000..94b745c
--- /dev/null
@@ -0,0 +1,120 @@
+Running 32 tests
+In NullCreate::<no test>:
+Exceptions.h:10: Error: Test failed: createSuite() failed
+Exceptions.h:10: Error: Assertion failed: suite() != 0
+In ThrowCreate::<no test>:
+Exceptions.h:22: Error: Test failed: Exception thrown from createSuite()
+Exceptions.h:22: Error: Expected (createSuite()) not to throw, but it did
+Exceptions.h:22: Error: Test failed: createSuite() failed
+Exceptions.h:22: Error: Assertion failed: suite() != 0
+.
+In ThrowDestroy::<no test>:
+Exceptions.h:35: Error: Test failed: destroySuite() failed
+Exceptions.h:35: Error: Expected (destroySuite()) not to throw, but it did
+In ThrowSetUp::testNothing:
+Exceptions.h:46: Error: Test failed: Exception thrown from setUp()
+Exceptions.h:46: Error: Expected (suite()->setUp(); ok=true) not to throw, but it did
+In ThrowTearDown::testNothing:
+Exceptions.h:55: Error: Test failed: Exception thrown from tearDown()
+Exceptions.h:55: Error: Expected (suite()->tearDown()) not to throw, but it did
+In TestThrowFromTest::testThrowSomething:
+Exceptions.h:61: Error: Test failed: Exception thrown from test
+In TestThrowFromTest::testMoveOn:
+Exceptions.h:68: Trace: One failed test doesn't affect the others
+.
+In DynamicAbort::test_Abort_on_fail_in_this_test:
+DynamicAbort.h:8: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:9: Error: Expected (2 == 3), found (2 != 3)
+In DynamicAbort::test_Dont_abort_in_this_test:
+DynamicAbort.h:15: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:16: Error: Expected (2 == 3), found (2 != 3)
+In DynamicAbort::test_Revert_to_abort:
+DynamicAbort.h:21: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:22: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test:
+DynamicAbort.h:36: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:37: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test_either:
+DynamicAbort.h:42: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:43: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Override_in_this_test:
+DynamicAbort.h:49: Error: Expected (1 == 2), found (1 != 2)
+In DeepAbort::testAssertThrowsPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+DeepAbort.h:12: Error: Expected (fail()) to throw (int) but it didn't throw
+DeepAbort.h:13: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testMessageAssertThrowsPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+DeepAbort.h:18: Error: Test failed: fail() should throw an int
+DeepAbort.h:18: Error: Expected (fail()) to throw (int) but it didn't throw
+DeepAbort.h:19: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testAssertThrowsAborts:
+DeepAbort.h:24: Error: Expected (succeed()) to throw (int) but it didn't throw
+DeepAbort.h:25: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testMessageAssertThrowsAborts:
+DeepAbort.h:30: Error: Test failed: succeed() should throw an int
+DeepAbort.h:30: Error: Expected (succeed()) to throw (int) but it didn't throw
+DeepAbort.h:31: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testAssertThrowsNothingPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+DeepAbort.h:37: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testMessageAssertThrowsNothingPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+DeepAbort.h:43: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testAssertThrowsNothingAborts:
+DeepAbort.h:48: Error: Expected (throwSomething()) not to throw, but it did
+DeepAbort.h:49: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testMessageAssertThrowsNothingAborts:
+DeepAbort.h:54: Error: Test failed: fail() shouldn't throw anything
+DeepAbort.h:54: Error: Expected (throwSomething()) not to throw, but it did
+DeepAbort.h:55: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testAssertThrowsAnything:
+DeepAbort.h:60: Error: Expected (succeed()) to throw (...) but it didn't throw
+DeepAbort.h:61: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In DeepAbort::testMessageAssertThrowsAnything:
+DeepAbort.h:66: Error: Test failed: succeed() should throw something
+DeepAbort.h:66: Error: Expected (succeed()) to throw (...) but it didn't throw
+DeepAbort.h:67: Error: Test failed: You shouldn't see this if --abort-on-fail is used
+In ThrowsAssert::test_TS_ASSERT_THROWS_EQUALS:
+ThrowsAssert.h:23: Error: Expected (i == 2), found (1 != 2)
+ThrowsAssert.h:24: Error: Expected (thing.i() == 2), found (1 != 2)
+In ThrowsAssert::test_TS_ASSERT_THROWS_DIFFERS:
+ThrowsAssert.h:29: Error: Expected (i != 1), found (1)
+ThrowsAssert.h:30: Error: Expected (thing.i() != 1), found (1)
+In ThrowsAssert::test_TS_ASSERT_THROWS_SAME_DATA:
+ThrowsAssert.h:35: Error: Expected 3 (3) bytes to be equal at (s) and ("456"), found:
+{ 31 32 33 }
+differs from
+{ 34 35 36 }
+In ThrowsAssert::test_TS_ASSERT_THROWS_LESS_THAN:
+ThrowsAssert.h:40: Error: Expected (i < 1), found (1 >= 1)
+ThrowsAssert.h:41: Error: Expected (thing.i() < 1), found (1 >= 1)
+In ThrowsAssert::test_TS_ASSERT_THROWS_LESS_THAN_EQUALS:
+ThrowsAssert.h:46: Error: Expected (i <= 0), found (1 > 0)
+ThrowsAssert.h:47: Error: Expected (thing.i() <= 0), found (1 > 0)
+In ThrowsAssert::test_TS_ASSERT_THROWS_PREDICATE:
+ThrowsAssert.h:52: Error: Expected Fail( i ), found !Fail( 1 )
+ThrowsAssert.h:53: Error: Expected Fail( thing.i() ), found !Fail( 1 )
+In ThrowsAssert::test_TS_ASSERT_THROWS_RELATION:
+ThrowsAssert.h:58: Error: Expected Fail( i, 1 ), found !Fail( 1, 1 )
+ThrowsAssert.h:59: Error: Expected Fail( thing.i(), 1 ), found !Fail( 1, 1 )
+In ThrowsAssert::test_TS_ASSERT_THROWS_DELTA:
+ThrowsAssert.h:64: Error: Expected (i == 3) up to 1 (1), found (1 != 3)
+ThrowsAssert.h:65: Error: Expected (thing.i() == 3) up to 1 (1), found (1 != 3)
+In ThrowsAssert::test_TS_ASSERT_THROWS_ASSERT:
+ThrowsAssert.h:71: Error: Expected (i == 2), found (1 != 2)
+ThrowsAssert.h:74: Error: Expected (thing.i() == 2), found (1 != 2)
+ThrowsAssert.h:77: Error: Test failed: 1
+ThrowsAssert.h:80: Error: Assertion failed: thing.i() - 1
+ThrowsAssert.h:84: Error: Expected sizeof(char) (1) bytes to be equal at (&zero) and (&one), found:
+{ 00 }
+differs from
+{ 01 }
+ThrowsAssert.h:87: Error: Expected (thing.i() == 5) up to 2 (2), found (1 != 5)
+ThrowsAssert.h:90: Error: Expected (thing.i() != 1), found (1)
+ThrowsAssert.h:93: Error: Expected (thing.i() < 1), found (1 >= 1)
+ThrowsAssert.h:96: Error: Expected Fail( thing.i() ), found !Fail( 1 )
+ThrowsAssert.h:99: Error: Expected Fail( thing.i(), 33 ), found !Fail( 1, 33 )
+Failed 31 of 32 tests
+Success rate: 3%
+Error level = 31
diff --git a/tools/cxxtest/test/eh_normals.out b/tools/cxxtest/test/eh_normals.out
new file mode 100644 (file)
index 0000000..d5f039f
--- /dev/null
@@ -0,0 +1,44 @@
+Running 13 tests
+In NullCreate::<no test>:
+Exceptions.h:10: Error: Test failed: createSuite() failed
+Exceptions.h:10: Error: Assertion failed: suite() != 0
+In ThrowCreate::<no test>:
+Exceptions.h:22: Error: Test failed: Exception thrown from createSuite()
+Exceptions.h:22: Error: Expected (createSuite()) not to throw, but it did
+Exceptions.h:22: Error: Test failed: createSuite() failed
+Exceptions.h:22: Error: Assertion failed: suite() != 0
+.
+In ThrowDestroy::<no test>:
+Exceptions.h:35: Error: Test failed: destroySuite() failed
+Exceptions.h:35: Error: Expected (destroySuite()) not to throw, but it did
+In ThrowSetUp::testNothing:
+Exceptions.h:46: Error: Test failed: Exception thrown from setUp()
+Exceptions.h:46: Error: Expected (suite()->setUp(); ok=true) not to throw, but it did
+In ThrowTearDown::testNothing:
+Exceptions.h:55: Error: Test failed: Exception thrown from tearDown()
+Exceptions.h:55: Error: Expected (suite()->tearDown()) not to throw, but it did
+In TestThrowFromTest::testThrowSomething:
+Exceptions.h:61: Error: Test failed: Exception thrown from test
+In TestThrowFromTest::testMoveOn:
+Exceptions.h:68: Trace: One failed test doesn't affect the others
+.
+In DynamicAbort::test_Abort_on_fail_in_this_test:
+DynamicAbort.h:8: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:9: Error: Expected (2 == 3), found (2 != 3)
+In DynamicAbort::test_Dont_abort_in_this_test:
+DynamicAbort.h:15: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:16: Error: Expected (2 == 3), found (2 != 3)
+In DynamicAbort::test_Revert_to_abort:
+DynamicAbort.h:21: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:22: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test:
+DynamicAbort.h:36: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:37: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test_either:
+DynamicAbort.h:42: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:43: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Override_in_this_test:
+DynamicAbort.h:49: Error: Expected (1 == 2), found (1 != 2)
+Failed 12 of 13 tests
+Success rate: 7%
+Error level = 12
diff --git a/tools/cxxtest/test/eh_plus_abort.out b/tools/cxxtest/test/eh_plus_abort.out
new file mode 100644 (file)
index 0000000..329134f
--- /dev/null
@@ -0,0 +1,63 @@
+Running 25 tests
+In DynamicAbort::test_Abort_on_fail_in_this_test:
+DynamicAbort.h:8: Error: Expected (1 == 2), found (1 != 2)
+In DynamicAbort::test_Dont_abort_in_this_test:
+DynamicAbort.h:15: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:16: Error: Expected (2 == 3), found (2 != 3)
+In DynamicAbort::test_Revert_to_abort:
+DynamicAbort.h:21: Error: Expected (1 == 2), found (1 != 2)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test:
+DynamicAbort.h:36: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:37: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Dont_abort_in_this_test_either:
+DynamicAbort.h:42: Error: Expected (1 == 2), found (1 != 2)
+DynamicAbort.h:43: Error: Expected (2 == 3), found (2 != 3)
+In SetUpWorksAllTests::test_Override_in_this_test:
+DynamicAbort.h:49: Error: Expected (1 == 2), found (1 != 2)
+In DeepAbort::testAssertThrowsPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+In DeepAbort::testMessageAssertThrowsPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+In DeepAbort::testAssertThrowsAborts:
+DeepAbort.h:24: Error: Expected (succeed()) to throw (int) but it didn't throw
+In DeepAbort::testMessageAssertThrowsAborts:
+DeepAbort.h:30: Error: Test failed: succeed() should throw an int
+DeepAbort.h:30: Error: Expected (succeed()) to throw (int) but it didn't throw
+In DeepAbort::testAssertThrowsNothingPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+In DeepAbort::testMessageAssertThrowsNothingPassesAbort:
+DeepAbort.h:72: Error: Expected (0 == 1), found (0 != 1)
+In DeepAbort::testAssertThrowsNothingAborts:
+DeepAbort.h:48: Error: Expected (throwSomething()) not to throw, but it did
+In DeepAbort::testMessageAssertThrowsNothingAborts:
+DeepAbort.h:54: Error: Test failed: fail() shouldn't throw anything
+DeepAbort.h:54: Error: Expected (throwSomething()) not to throw, but it did
+In DeepAbort::testAssertThrowsAnything:
+DeepAbort.h:60: Error: Expected (succeed()) to throw (...) but it didn't throw
+In DeepAbort::testMessageAssertThrowsAnything:
+DeepAbort.h:66: Error: Test failed: succeed() should throw something
+DeepAbort.h:66: Error: Expected (succeed()) to throw (...) but it didn't throw
+In ThrowsAssert::test_TS_ASSERT_THROWS_EQUALS:
+ThrowsAssert.h:23: Error: Expected (i == 2), found (1 != 2)
+In ThrowsAssert::test_TS_ASSERT_THROWS_DIFFERS:
+ThrowsAssert.h:29: Error: Expected (i != 1), found (1)
+In ThrowsAssert::test_TS_ASSERT_THROWS_SAME_DATA:
+ThrowsAssert.h:35: Error: Expected 3 (3) bytes to be equal at (s) and ("456"), found:
+{ 31 32 33 }
+differs from
+{ 34 35 36 }
+In ThrowsAssert::test_TS_ASSERT_THROWS_LESS_THAN:
+ThrowsAssert.h:40: Error: Expected (i < 1), found (1 >= 1)
+In ThrowsAssert::test_TS_ASSERT_THROWS_LESS_THAN_EQUALS:
+ThrowsAssert.h:46: Error: Expected (i <= 0), found (1 > 0)
+In ThrowsAssert::test_TS_ASSERT_THROWS_PREDICATE:
+ThrowsAssert.h:52: Error: Expected Fail( i ), found !Fail( 1 )
+In ThrowsAssert::test_TS_ASSERT_THROWS_RELATION:
+ThrowsAssert.h:58: Error: Expected Fail( i, 1 ), found !Fail( 1, 1 )
+In ThrowsAssert::test_TS_ASSERT_THROWS_DELTA:
+ThrowsAssert.h:64: Error: Expected (i == 3) up to 1 (1), found (1 != 3)
+In ThrowsAssert::test_TS_ASSERT_THROWS_ASSERT:
+ThrowsAssert.h:71: Error: Expected (i == 2), found (1 != 2)
+Failed 25 of 25 tests
+Success rate: 0%
+Error level = 25
diff --git a/tools/cxxtest/test/error.out b/tools/cxxtest/test/error.out
new file mode 100644 (file)
index 0000000..a66addf
--- /dev/null
@@ -0,0 +1,51 @@
+Running 14 tests
+In CreatedTest::test_nothing:
+CreatedTest.h:26: Error: Test failed: Nothing to test
+.
+In EnumTraits::test_Enum_traits:
+EnumTraits.h:32: Error: Test failed: Yes
+EnumTraits.h:33: Error: Test failed: No
+EnumTraits.h:34: Error: Test failed: Maybe
+EnumTraits.h:35: Error: Test failed: DontKnow
+EnumTraits.h:36: Error: Test failed: DontCare
+EnumTraits.h:37: Error: Test failed: (Answer)1000
+In ExceptionTest::testAssertion:
+ExceptionTest.h:20: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else
+ExceptionTest.h:22: Error: Expected (goodFunction(1)) to throw (...) but it didn't throw
+ExceptionTest.h:24: Error: Test failed: Unhandled exception
+ExceptionTest.h:26: Error: Expected (throwThis(-1)) not to throw, but it did
+ExceptionTest.h:31: Error: Test failed: throwThis(3) failed
+In FixtureTest::test_strcpy:
+FixtureTest.h:32: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E')
+In MessageTest::testValues:
+MessageTest.h:24: Error: Test failed: My hovercraft
+MessageTest.h:24: Error: Assertion failed: value != 0
+MessageTest.h:25: Error: Test failed: of eels
+MessageTest.h:25: Error: Expected (value == value * value), found (2 != 4)
+In SimpleTest::testEquality:
+SimpleTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+SimpleTest.h:17: Error: Expected ('a' == 'A'), found ('a' != 'A')
+SimpleTest.h:18: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In SimpleTest::testAddition:
+SimpleTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In SimpleTest::TestMultiplication:
+SimpleTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+SimpleTest.h:31: Error: Expected (-2 * -2 != 4), found (4)
+In SimpleTest::testComparison:
+SimpleTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In SimpleTest::testTheWorldIsCrazy:
+SimpleTest.h:42: Error: Expected (true == false), found (true != false)
+In SimpleTest::test_Failure:
+SimpleTest.h:47: Error: Test failed: Not implemented
+SimpleTest.h:48: Error: Test failed: 1569779912
+In SimpleTest::test_TS_WARN_macro:
+SimpleTest.h:53: Warning: Just a friendly warning
+SimpleTest.h:54: Warning: Warnings don't abort the test
+.
+In TestFunky::testPets:
+TraitsTest.h:59: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat"))
+TraitsTest.h:61: Error: Expected (cat != gato), found (Pet("cat"))
+TraitsTest.h:64: Error: Expected (String("Hello") == String("World!")), found ("Hello" != "World!")
+Failed 12 of 14 tests
+Success rate: 14%
+Error level = 12
diff --git a/tools/cxxtest/test/factor.out b/tools/cxxtest/test/factor.out
new file mode 100644 (file)
index 0000000..260bd6f
--- /dev/null
@@ -0,0 +1,72 @@
+Running 2 :) tests
+In Factor::test_Some_numbers:
+Factor.h:30: Warning: 53 :)
+Factor.h:33: Warning: 0
+Factor.h:33: Warning: 1
+Factor.h:33: Warning: 2 :|
+Factor.h:33: Warning: 3 :|
+Factor.h:33: Warning: 4 = 2^2
+Factor.h:33: Warning: 5 :|
+Factor.h:33: Warning: 6 = 2 * 3
+Factor.h:33: Warning: 7 :|
+Factor.h:33: Warning: 8 = 2^3
+Factor.h:33: Warning: 9 = 3^2
+Factor.h:33: Warning: 10 = 2 * 5
+Factor.h:33: Warning: 11 :|
+Factor.h:33: Warning: 12 = 2^2 * 3
+Factor.h:33: Warning: 13 :|
+Factor.h:33: Warning: 14 = 2 * 7
+Factor.h:33: Warning: 15 = 3 * 5
+Factor.h:33: Warning: 16 = 2^4
+Factor.h:33: Warning: 17 :|
+Factor.h:33: Warning: 18 = 2 * 3^2
+Factor.h:33: Warning: 19 :|
+Factor.h:33: Warning: 20 = 2^2 * 5
+Factor.h:33: Warning: 21 = 3 * 7
+Factor.h:33: Warning: 22 = 2 * 11
+Factor.h:33: Warning: 23 :|
+Factor.h:33: Warning: 24 = 2^3 * 3
+Factor.h:33: Warning: 25 = 5^2
+Factor.h:33: Warning: 26 = 2 * 13
+Factor.h:33: Warning: 27 = 3^3
+Factor.h:33: Warning: 28 = 2^2 * 7
+Factor.h:33: Warning: 29 :|
+Factor.h:33: Warning: 30 = 2 * 3 * 5
+Factor.h:33: Warning: 31 :|
+Factor.h:32: Error: Expected (n != 32), found (32)
+Factor.h:33: Warning: 32 = 2^5
+Factor.h:33: Warning: 33 = 3 * 11
+Factor.h:33: Warning: 34 = 2 * 17
+Factor.h:33: Warning: 35 = 5 * 7
+Factor.h:33: Warning: 36 = 2^2 * 3^2
+Factor.h:33: Warning: 37 :(
+Factor.h:33: Warning: 38 = 2 * 19
+Factor.h:33: Warning: 39 = 3 * 13
+Factor.h:33: Warning: 40 = 2^3 * 5
+Factor.h:33: Warning: 41 :(
+Factor.h:33: Warning: 42 = 2 * 3 * 7
+Factor.h:33: Warning: 43 :(
+Factor.h:33: Warning: 44 = 2^2 * 11
+Factor.h:33: Warning: 45 = 3^2 * 5
+Factor.h:33: Warning: 46 = 2 * 23
+Factor.h:33: Warning: 47 :(
+Factor.h:33: Warning: 48 = 2^4 * 3
+Factor.h:33: Warning: 49 = 7^2
+Factor.h:33: Warning: 50 = 2 * 5^2
+Factor.h:33: Warning: 51 = 3 * 17
+Factor.h:33: Warning: 52 = 2^2 * 13
+Factor.h:33: Warning: 53 :(
+Factor.h:33: Warning: 54 = 2 * 3^3
+Factor.h:33: Warning: 55 = 5 * 11
+Factor.h:33: Warning: 56 = 2^3 * 7
+Factor.h:33: Warning: 57 = 3 * 19
+Factor.h:33: Warning: 58 = 2 * 29
+Factor.h:33: Warning: 59 :(
+Factor.h:33: Warning: 60 = 2^2 * 3 * 5
+Factor.h:33: Warning: 61 :(
+Factor.h:33: Warning: 62 = 2 * 31
+Factor.h:33: Warning: 63 = 3^2 * 7
+.
+Failed 1 of 2 :( tests
+Success rate: 50%
+Error level = 1
diff --git a/tools/cxxtest/test/fake/.cvsignore b/tools/cxxtest/test/fake/.cvsignore
new file mode 100644 (file)
index 0000000..782a42d
--- /dev/null
@@ -0,0 +1 @@
+*.cpp *_runner*
\ No newline at end of file
diff --git a/tools/cxxtest/test/fake/X11/Xlib.h b/tools/cxxtest/test/fake/X11/Xlib.h
new file mode 100644 (file)
index 0000000..05eddd1
--- /dev/null
@@ -0,0 +1,46 @@
+// Fake Xlib.h
+
+struct Display {};
+typedef int Window, Colormap, GC;
+typedef const char *XID;
+struct XFontStruct { int ascent, descent; };
+struct Screen {};
+struct XColor { int pixel; };
+
+enum { Success, ExposureMask };
+
+inline Display *XOpenDisplay(void *) { return 0; }
+inline Colormap DefaultColormap( Display *, int ) { return 0; }
+inline void XParseColor( Display *, Colormap, const char *, XColor * ) {}
+inline int XAllocColor( Display *, Colormap, XColor *) { return 0; }
+inline Window XCreateSimpleWindow( Display *, Window, int, int, int, int, int, int, int ) { return 0; }
+inline Window RootWindow( Display *, int ) { return 0; }
+inline GC XCreateGC( Display *, Window, int, int ) { return 0; }
+inline XID XLoadFont( Display *, const char * ) { return 0; }
+inline int XSetFont( Display *, GC, XID ) { return 0; }
+inline XID XGContextFromGC( GC ) { return 0; }
+inline XFontStruct *XQueryFont( Display *, const char * ) { return 0; }
+inline int XFreeFontInfo( char **, XFontStruct *, int ) { return 0; }
+inline int XSelectInput( Display *, Window, int ) { return 0; }
+inline int XMapWindow( Display *, Window ) { return 0; }
+inline Screen *XDefaultScreenOfDisplay( Display * ) { return 0; }
+inline int WidthOfScreen( Screen * ) { return 0; }    
+inline int HeightOfScreen( Screen * ) { return 0; }
+inline int XMoveResizeWindow( Display *, Window, int, int, int, int ) { return 0; }
+
+struct XEvent {};
+inline int XCheckMaskEvent( Display *, int, XEvent * ) { return 0; }
+inline int XSetStandardProperties( Display *, Window, const char *, int, int, int, int, int ) { return 0; }
+
+struct XWindowAttributes { int width, height; };
+inline int XGetWindowAttributes( Display *, Window, XWindowAttributes * ) { return 0; }
+inline int XSetForeground( Display *, GC, unsigned long ) { return 0; }
+inline int XSetBackground( Display *, GC, unsigned long ) { return 0; }
+inline int XFillRectangle( Display *, Window, GC, int, int, int, int ) { return 0; }
+inline int XDrawLine( Display *, Window, GC, int, int, int, int ) { return 0; }
+inline int XDrawString( Display *, Window, GC, int, int, const char *, int ) { return 0; }
+inline int XFlush( Display * ) { return 0; }
+inline int XFreeGC( Display *, GC ) { return 0; }
+inline int XDestroyWindow( Display *, Window ) { return 0; }
+inline int XCloseDisplay( Display * ) { return 0; }
+inline int XTextWidth( XFontStruct *, const char *, int ) { return 0; }
diff --git a/tools/cxxtest/test/fake/X11/Xutil.h b/tools/cxxtest/test/fake/X11/Xutil.h
new file mode 100644 (file)
index 0000000..b2da513
--- /dev/null
@@ -0,0 +1 @@
+// Fake Xutil.h
diff --git a/tools/cxxtest/test/fake/commctrl.h b/tools/cxxtest/test/fake/commctrl.h
new file mode 100644 (file)
index 0000000..b07e267
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __FAKE__COMMCTRL_H__
+#define __FAKE__COMMCTRL_H__
+
+#include <windows.h>
+
+#define PROGRESS_CLASS TEXT("PROGRESS_CLASS")
+#define STATUSCLASSNAME TEXT("STATUSCLASSNAME")
+
+enum { PBM_SETRANGE32, PBM_SETRANGE, PBM_SETPOS, PBM_SETSTEP, PBM_STEPIT, PBM_SETBARCOLOR,
+       SB_SETTEXTA, SB_SETPARTS, BS_AUTOCHECKBOX, BM_SETCHECK, BST_UNCHECKED, BM_GETCHECK,
+       BST_CHECKED, PBS_SMOOTH };
+
+#define ICC_BAR_CLASSES 1
+#define ICC_PROGRESS_CLASS 2
+
+struct INITCOMMONCONTROLSEX
+{
+    DWORD dwSize;
+    DWORD dwICC;
+};
+
+inline void InitCommonControls() {}
+inline int InitCommonControlsEx(INITCOMMONCONTROLSEX *) { return 0; }
+
+#endif // __FAKE__COMMCTRL_H__
diff --git a/tools/cxxtest/test/fake/qapplication.h b/tools/cxxtest/test/fake/qapplication.h
new file mode 100644 (file)
index 0000000..f49d677
--- /dev/null
@@ -0,0 +1,14 @@
+// fake QApplication
+
+class QWidget;
+
+class QApplication
+{
+public:
+    QApplication( int &, char ** ) {}
+    void exec() {}
+    void setMainWidget( void * ) {}
+    void processEvents() {}
+    static QWidget *desktop() { return 0; }
+    void *activeWindow() { return 0; }
+};
diff --git a/tools/cxxtest/test/fake/qglobal.h b/tools/cxxtest/test/fake/qglobal.h
new file mode 100644 (file)
index 0000000..7ae8e67
--- /dev/null
@@ -0,0 +1,2 @@
+// fake qglobal.h
+#define QT_VERSION 0x030000
diff --git a/tools/cxxtest/test/fake/qlabel.h b/tools/cxxtest/test/fake/qlabel.h
new file mode 100644 (file)
index 0000000..478709d
--- /dev/null
@@ -0,0 +1,10 @@
+// fake QLabel
+#include <qstring.h>
+#include <qwidget.h>
+
+class QLabel
+{
+public:
+    QLabel( void * ) {}
+    void setText( const QString & ) {}
+};
diff --git a/tools/cxxtest/test/fake/qlayout.h b/tools/cxxtest/test/fake/qlayout.h
new file mode 100644 (file)
index 0000000..05eb0df
--- /dev/null
@@ -0,0 +1,8 @@
+// fake qlayout.h
+
+class QVBoxLayout
+{
+public:
+    QVBoxLayout( void * ) {}
+    void addWidget( void * ) {}
+};
diff --git a/tools/cxxtest/test/fake/qmessagebox.h b/tools/cxxtest/test/fake/qmessagebox.h
new file mode 100644 (file)
index 0000000..bf24a00
--- /dev/null
@@ -0,0 +1,8 @@
+// fake qmessagebox.h
+
+class QMessageBox
+{
+public:
+    enum Icon { Information, Warning, Critical };
+    static void *standardIcon( Icon ) { return 0; }
+};
diff --git a/tools/cxxtest/test/fake/qpixmap.h b/tools/cxxtest/test/fake/qpixmap.h
new file mode 100644 (file)
index 0000000..fae33d0
--- /dev/null
@@ -0,0 +1,2 @@
+// fake qpixmap.h
+
diff --git a/tools/cxxtest/test/fake/qprogressbar.h b/tools/cxxtest/test/fake/qprogressbar.h
new file mode 100644 (file)
index 0000000..9da6104
--- /dev/null
@@ -0,0 +1,29 @@
+// fake qprogressbar.h
+
+class QColorGroup
+{
+public:
+    enum { Highlight };
+};
+
+class QColor
+{
+public:
+    QColor( int, int, int ) {}
+};
+
+class QPalette
+{
+public:
+    void setColor( int, const QColor & ) {}
+};
+
+class QProgressBar
+{
+public:
+    QProgressBar( int, void * ) {}
+    void setProgress( int )  {}
+    int progress()  { return 0; }
+    QPalette palette() { return QPalette(); }
+    void setPalette( const QPalette & ) {}
+};
diff --git a/tools/cxxtest/test/fake/qstatusbar.h b/tools/cxxtest/test/fake/qstatusbar.h
new file mode 100644 (file)
index 0000000..b1efdc2
--- /dev/null
@@ -0,0 +1,10 @@
+// fake qstatusbar.h
+
+class QStatusBar
+{
+public:
+    QStatusBar( void * ) {}
+    void setProgress()  {}
+    void addWidget( void *, int ) {}
+    void removeWidget( void * ) {}
+};
diff --git a/tools/cxxtest/test/fake/qstring.h b/tools/cxxtest/test/fake/qstring.h
new file mode 100644 (file)
index 0000000..09e8205
--- /dev/null
@@ -0,0 +1,17 @@
+// fake qstring.h
+#ifndef __FAKE__QSTRING_H
+#define __FAKE__QSTRING_H
+
+class QString
+{
+public:
+    QString() {}
+    QString( const char * ) {}
+    bool operator==( const QString & ) { return false; }
+
+    static QString number( int ) { return QString(); }
+};
+
+inline QString operator+( const QString &, const QString & ) { return QString(); }
+
+#endif // __FAKE__QSTRING_H
diff --git a/tools/cxxtest/test/fake/qwidget.h b/tools/cxxtest/test/fake/qwidget.h
new file mode 100644 (file)
index 0000000..c8752ef
--- /dev/null
@@ -0,0 +1,23 @@
+// fake qwidget.h
+#ifndef __FAKE__QWIDGET_H
+#define __FAKE__QWIDGET_H
+
+class QString;
+
+class QWidget
+{
+public:
+    bool isMinimized() { return false; }
+    void close( bool ) {}
+    void showMinimized() {}
+    void showNormal() {}
+    void setCaption( const QString & ) {}
+    void setIcon( void * ) {}
+    int x() { return 0; }
+    int y() { return 0; }
+    int width() { return 0; }
+    int height() { return 0; }
+    void setGeometry( int, int, int, int ) {}
+};
+
+#endif // __FAKE__QWIDGET_H
diff --git a/tools/cxxtest/test/fake/windows.h b/tools/cxxtest/test/fake/windows.h
new file mode 100644 (file)
index 0000000..1b6bf68
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef __FAKE__WINDOWS_H__
+#define __FAKE__WINDOWS_H__
+
+#include <stdio.h>
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long DWORD, ULONG, LRESULT, LPARAM, WPARAM;
+
+typedef int BOOL;
+enum { FALSE, TRUE };
+
+typedef struct _HANDLE {} *HANDLE;
+typedef struct _HBRUSH {} *HBRUSH;
+typedef struct _HCURSOR {} *HCURSOR;
+typedef struct _HEAP {} *HEAP;
+typedef struct _HICON {} *HICON;
+typedef struct _HINSTANCE {} *HINSTANCE;
+typedef struct _HMENU {} *HMENU;
+typedef struct _HMODULE {} *HMODULE;
+typedef struct _HWND {} *HWND;
+
+enum { INFINITE, CS_HREDRAW, CS_VREDRAW, COLOR_WINDOW, GWL_USERDATA, HWND_TOP, SPI_GETWORKAREA,
+       WS_CHILD, WS_VISIBLE, SM_CYCAPTION, SM_CYFRAME, SM_CXSCREEN, SM_CYSCREEN,
+       SW_SHOWNORMAL, SW_MINIMIZE, WM_SIZE, WM_SETICON, ICON_BIG, WS_OVERLAPPEDWINDOW,
+       WM_CREATE, WM_TIMER, WM_CLOSE, WM_DESTROY, WM_QUIT };
+
+typedef void *LPVOID;
+
+#ifdef UNICODE
+typedef wchar_t TCHAR;
+#define TEXT(x) L##x
+#else
+typedef char TCHAR;
+#define TEXT(x) x
+#endif
+
+typedef const TCHAR *LPCTSTR;
+
+typedef char *LPSTR;
+typedef const char *LPCSTR;
+#define IDI_INFORMATION TEXT("IDI_INFORMATION")
+#define IDI_WARNING TEXT("IDI_WARNING")
+#define IDI_ERROR TEXT("IDI_ERROR")
+
+typedef void (*LPPROC)( void );
+
+#define WINAPI
+#define CALLBACK
+
+struct WNDCLASSEX
+{
+    int cbSize;
+    int style;
+    LRESULT CALLBACK (*lpfnWndProc)( HWND, UINT, WPARAM, LPARAM );
+    int cbClsExtra;
+    int cbWndExtra;
+    HINSTANCE hInstance;
+    HICON hIcon;
+    HCURSOR hCursor;
+    HBRUSH hbrBackground;
+    LPCTSTR lpszMenuName;
+    LPCTSTR lpszClassName;
+    HICON hIconSm;
+};
+
+struct RECT
+{
+    LONG left, right, top, bottom;
+};
+
+struct MSG
+{
+};
+
+typedef struct 
+{
+    LPVOID lpCreateParams;
+} CREATESTRUCT, *LPCREATESTRUCT;
+
+inline HANDLE CreateEvent( LPVOID, BOOL, BOOL, LPVOID ) { return 0; }
+inline HANDLE CreateThread( LPVOID, int, DWORD WINAPI (*)( LPVOID ), LPVOID, int, LPVOID ) { return 0; }
+inline int WaitForSingleObject( HANDLE, int ) { return 0; }
+inline int RegisterClassEx( WNDCLASSEX * ) { return 0; }
+inline int SetWindowLong( HWND, int, LONG ) { return 0; }
+inline LPARAM MAKELPARAM( unsigned short, unsigned short ) { return 0; }
+inline HWND CreateWindow( LPCTSTR, LPVOID, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID ) { return 0; }
+inline LRESULT SendMessage( HWND, UINT, WPARAM, LPARAM ) { return 0; }
+inline LONG GetSystemMetrics( int ) { return 0; }
+inline int SetWindowPos( HWND, int, LONG, LONG, LONG, LONG, int ) { return 0; }
+inline int SystemParametersInfo( int, int, LPVOID, int ) { return 0; }
+inline int ShowWindow( HWND, int ) { return 0; }
+inline int UpdateWindow( HWND ) { return 0; }
+inline int SetEvent( HANDLE ) { return 0; }
+inline BOOL GetMessage( MSG *, LPVOID, int, int ) { return FALSE; }
+inline int DispatchMessage( MSG * ) { return 0; }
+inline int GetClientRect( HWND, RECT * ) { return 0; }
+inline HICON LoadIcon( HINSTANCE, LPCTSTR ) { return 0; }
+inline unsigned lstrlenA( LPCSTR ) { return 0; }
+inline int lstrcmpA( LPCSTR, LPCSTR ) { return 0; }
+inline int lstrcpyA( LPSTR, LPCSTR ) { return 0; }
+inline int lstrcatA( LPSTR, LPCSTR ) { return 0; }
+#define wsprintfA sprintf
+inline int SetWindowTextA( HWND, LPCSTR ) { return 0; }
+inline LPVOID HeapAlloc( HEAP, int, ULONG ) { return 0; }
+inline HEAP GetProcessHeap() { return 0; }
+inline int HeapFree( HEAP, int, LPVOID ) { return 0; }
+inline int DestroyWindow( HWND ) { return 0; }
+inline LONG GetWindowLong( HWND, int ) { return 0; }
+inline LRESULT CALLBACK DefWindowProc( HWND, UINT, WPARAM, LPARAM ) { return 0; }
+inline HMODULE LoadLibraryA( LPCSTR ) { return 0; }
+inline LPPROC GetProcAddress( HMODULE, LPCSTR ) { return 0; }
+inline int SetTimer( HWND, unsigned, unsigned, unsigned ) { return 0; }
+inline int KillTimer( HWND, unsigned ) { return 0; }
+inline DWORD GetTickCount() { return 0; }
+inline int ExitProcess( int ) { return 0; }
+inline bool IsIconic( HWND ) { return 0; }
+inline HWND GetForegroundWindow() { return 0; }
+
+#endif // __FAKE__WINDOWS_H__
diff --git a/tools/cxxtest/test/gfsuf.out b/tools/cxxtest/test/gfsuf.out
new file mode 100644 (file)
index 0000000..b10a9db
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In Suite::testOne:
+GfSetUpFails.h:24: Error: Test failed: Error in GlobalFixture::setUp()
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/gfsut.out b/tools/cxxtest/test/gfsut.out
new file mode 100644 (file)
index 0000000..703083c
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In Suite::testOne:
+GfSetUpThrows.h:24: Error: Test failed: Error in GlobalFixture::setUp()
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/gftdf.out b/tools/cxxtest/test/gftdf.out
new file mode 100644 (file)
index 0000000..e6ff594
--- /dev/null
@@ -0,0 +1,9 @@
+Running 2 tests
+In Suite::testOne:
+GfTearDownFails.h:24: Error: Test failed: Error in GlobalFixture::tearDown()
+In Suite::testTwo:
+GfTearDownFails.h:25: Warning: Testing should go on!
+GfTearDownFails.h:25: Error: Test failed: Error in GlobalFixture::tearDown()
+Failed 2 of 2 tests
+Success rate: 0%
+Error level = 2
diff --git a/tools/cxxtest/test/gftdt.out b/tools/cxxtest/test/gftdt.out
new file mode 100644 (file)
index 0000000..15b009b
--- /dev/null
@@ -0,0 +1,9 @@
+Running 2 tests
+In Suite::testOne:
+GfTearDownThrows.h:24: Error: Test failed: Error in GlobalFixture::tearDown()
+In Suite::testTwo:
+GfTearDownThrows.h:25: Warning: Testing should go on!
+GfTearDownThrows.h:25: Error: Test failed: Error in GlobalFixture::tearDown()
+Failed 2 of 2 tests
+Success rate: 0%
+Error level = 2
diff --git a/tools/cxxtest/test/gfxs.out b/tools/cxxtest/test/gfxs.out
new file mode 100644 (file)
index 0000000..77a56b5
--- /dev/null
@@ -0,0 +1,2 @@
+Running 6 tests<world><test></test>.<test></test>.<test></test>.<test></test>.<test></test>.<test></test>.</world>OK!
+Error level = 0
diff --git a/tools/cxxtest/test/good.out b/tools/cxxtest/test/good.out
new file mode 100644 (file)
index 0000000..7b8cb27
--- /dev/null
@@ -0,0 +1,2 @@
+Running 18 tests..................OK!
+Error level = 0
diff --git a/tools/cxxtest/test/gui.out b/tools/cxxtest/test/gui.out
new file mode 100644 (file)
index 0000000..74edb6f
--- /dev/null
@@ -0,0 +1,15 @@
+{Start 7 tests} Running 7 tests {GreenYellowRed::test_Start_green()} . {GreenYellowRed::test_Green_again()}
+In GreenYellowRed::test_Green_again:
+GreenYellowRed.h:26: Trace: Still green
+. {GreenYellowRed::test_Now_yellow()}  {Yellow}
+In GreenYellowRed::test_Now_yellow:
+GreenYellowRed.h:32: Warning: Yellow
+. {GreenYellowRed::test_Cannot_go_back()} . {GreenYellowRed::test_Finally_red()}  {Red}
+In GreenYellowRed::test_Finally_red:
+GreenYellowRed.h:43: Error: Test failed: Red
+{GreenYellowRed::test_Cannot_go_back_to_yellow()} In GreenYellowRed::test_Cannot_go_back_to_yellow:
+GreenYellowRed.h:49: Warning: Yellow?
+. {GreenYellowRed::test_Cannot_go_back_to_green()} . {Stop}
+Failed 1 of 7 tests
+Success rate: 85%
+Error level = 1
diff --git a/tools/cxxtest/test/gui_paren.out b/tools/cxxtest/test/gui_paren.out
new file mode 100644 (file)
index 0000000..c83a73d
--- /dev/null
@@ -0,0 +1,15 @@
+{Start 7 tests} Running 7 tests {GreenYellowRed::test_Start_green()} . {GreenYellowRed::test_Green_again()}
+In GreenYellowRed::test_Green_again:
+test/../sample/gui/GreenYellowRed.h(26): Trace: Still green
+. {GreenYellowRed::test_Now_yellow()}  {Yellow}
+In GreenYellowRed::test_Now_yellow:
+test/../sample/gui/GreenYellowRed.h(32): Warning: Yellow
+. {GreenYellowRed::test_Cannot_go_back()} . {GreenYellowRed::test_Finally_red()}  {Red}
+In GreenYellowRed::test_Finally_red:
+test/../sample/gui/GreenYellowRed.h(43): Error: Test failed: Red
+{GreenYellowRed::test_Cannot_go_back_to_yellow()} In GreenYellowRed::test_Cannot_go_back_to_yellow:
+test/../sample/gui/GreenYellowRed.h(49): Warning: Yellow?
+. {GreenYellowRed::test_Cannot_go_back_to_green()} . {Stop}
+Failed 1 of 7 tests
+Success rate: 85%
+Error level = 1
diff --git a/tools/cxxtest/test/include.out b/tools/cxxtest/test/include.out
new file mode 100644 (file)
index 0000000..43893b9
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In IncludesTest::testTraits:
+IncludeTest.h:12: Warning: (void *)
+IncludeTest.h:13: Warning: (long *)
+.OK!
+Error level = 0
diff --git a/tools/cxxtest/test/infinite.out b/tools/cxxtest/test/infinite.out
new file mode 100644 (file)
index 0000000..9215892
--- /dev/null
@@ -0,0 +1,11 @@
+Running 3 tests
+In TestNonFinite::testNaN:
+TestNonFinite.h:17: Error: Expected (nan == nan), found (nan != nan)
+TestNonFinite.h:18: Error: Expected (nan == zero), found (nan != 0.0000)
+In TestNonFinite::testPlusInf:
+TestNonFinite.h:23: Error: Expected (3.0 == plus_inf), found (3.0000 != inf)
+In TestNonFinite::testMinusInf:
+TestNonFinite.h:28: Error: Expected (1.0/3.0 == minus_inf), found (0.3333 != -inf)
+Failed 3 of 3 tests
+Success rate: 0%
+Error level = 3
diff --git a/tools/cxxtest/test/inheritance.out b/tools/cxxtest/test/inheritance.out
new file mode 100644 (file)
index 0000000..b99c4f1
--- /dev/null
@@ -0,0 +1,44 @@
+Running 14 tests
+In InheritedTests1::testEquality:
+InheritedTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+InheritedTest.h:17: Error: Expected ('a' == 'A'), found ('a' != 'A')
+InheritedTest.h:18: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In InheritedTests1::testAddition:
+InheritedTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In InheritedTests1::TestMultiplication:
+InheritedTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+InheritedTest.h:31: Error: Expected (-2 * -2 != 4), found (4)
+In InheritedTests1::testComparison:
+InheritedTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In InheritedTests1::testTheWorldIsCrazy:
+InheritedTest.h:42: Error: Expected (true == false), found (true != false)
+In InheritedTests1::test_Failure:
+InheritedTest.h:47: Error: Test failed: Not implemented
+InheritedTest.h:48: Error: Test failed: 1569779912
+In InheritedTests1::test_TS_WARN_macro:
+InheritedTest.h:53: Warning: Just a friendly warning
+InheritedTest.h:54: Warning: Warnings don't abort the test
+.
+In InheritedTests2::testEquality:
+InheritedTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+InheritedTest.h:17: Error: Expected ('a' == 'A'), found ('a' != 'A')
+InheritedTest.h:18: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In InheritedTests2::testAddition:
+InheritedTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In InheritedTests2::TestMultiplication:
+InheritedTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+InheritedTest.h:31: Error: Expected (-2 * -2 != 4), found (4)
+In InheritedTests2::testComparison:
+InheritedTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In InheritedTests2::testTheWorldIsCrazy:
+InheritedTest.h:42: Error: Expected (true == false), found (true != false)
+In InheritedTests2::test_Failure:
+InheritedTest.h:47: Error: Test failed: Not implemented
+InheritedTest.h:48: Error: Test failed: 1569779912
+In InheritedTests2::test_TS_WARN_macro:
+InheritedTest.h:53: Warning: Just a friendly warning
+InheritedTest.h:54: Warning: Warnings don't abort the test
+.
+Failed 12 of 14 tests
+Success rate: 14%
+Error level = 12
diff --git a/tools/cxxtest/test/int64.cpp b/tools/cxxtest/test/int64.cpp
new file mode 100644 (file)
index 0000000..c529f72
--- /dev/null
@@ -0,0 +1,8 @@
+//
+// This program is used to check if the compiler supports __int64
+//
+int main()
+{
+    __int64 ll = 0;
+    return (int)ll;
+}
diff --git a/tools/cxxtest/test/int64.out b/tools/cxxtest/test/int64.out
new file mode 100644 (file)
index 0000000..920a838
--- /dev/null
@@ -0,0 +1,8 @@
+Running 1 test
+In Int64::testInt64:
+Int64.h:12: Error: Expected ((__int64)1 == (__int64)2), found (1 != 2)
+Int64.h:13: Error: Expected ((__int64)3 != (__int64)3), found (3)
+Int64.h:14: Error: Expected ((__int64)5 < (__int64)4), found (5 >= 4)
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/longlong.cpp b/tools/cxxtest/test/longlong.cpp
new file mode 100644 (file)
index 0000000..a744e04
--- /dev/null
@@ -0,0 +1,8 @@
+//
+// This program is used to check if the compiler supports "long long"
+//
+int main()
+{
+    long long ll = 0;
+    return (int)ll;
+}
diff --git a/tools/cxxtest/test/longlong.out b/tools/cxxtest/test/longlong.out
new file mode 100644 (file)
index 0000000..f834eec
--- /dev/null
@@ -0,0 +1,8 @@
+Running 1 test
+In LongLongTest::testLongLong:
+LongLong.h:12: Error: Expected ((long long)1 == (long long)2), found (1 != 2)
+LongLong.h:13: Error: Expected ((long long)3 != (long long)3), found (3)
+LongLong.h:14: Error: Expected ((long long)5 < (long long)4), found (5 >= 4)
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/main.cpp b/tools/cxxtest/test/main.cpp
new file mode 100644 (file)
index 0000000..afb6aa2
--- /dev/null
@@ -0,0 +1,33 @@
+#include <cxxtest/TestRunner.h>
+#include <cxxtest/TestListener.h>
+#include <stdio.h>
+
+//
+// This test runner printer some statistics at the end of the run.
+// Note that it uses <stdio.h> and not <iostream> for compatibility
+// with older compilers.
+//
+
+using namespace CxxTest;
+
+class SummaryPrinter : public CxxTest::TestListener
+{
+public:
+    void run()
+    {
+        CxxTest::TestRunner::runAllTests( *this );
+    }
+    
+    void leaveWorld( const CxxTest::WorldDescription &wd )
+    {
+        printf( "Number of suites: %u\n", wd.numSuites() );
+        printf( "Number of tests: %u\n", wd.numTotalTests() );
+        printf( "Number of failed tests: %u\n", TestTracker::tracker().failedTests() );
+    }
+};
+
+int main()
+{
+    SummaryPrinter().run();
+    return 0;
+}
diff --git a/tools/cxxtest/test/max.out b/tools/cxxtest/test/max.out
new file mode 100644 (file)
index 0000000..8a4b98f
--- /dev/null
@@ -0,0 +1,56 @@
+Running 10 tests
+In DynamicMax::test_Max_size_from_define:
+DynamicMax.h:19: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+In DynamicMax::test_Set_max_size:
+DynamicMax.h:25: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 ... }
+In DynamicMax::test_Revert_to_max_size_from_define:
+DynamicMax.h:30: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+In DynamicMax::test_Set_max_size_to_zero__dumps_all:
+DynamicMax.h:36: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SetUpAffectsAllTests::test_Use_12_in_this_test:
+DynamicMax.h:58: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 ... }
+In SetUpAffectsAllTests::test_Use_12_in_this_test_too:
+DynamicMax.h:63: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 ... }
+In SameData::testAssertSameData:
+SameData.h:23: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+In SameData::testAssertMessageSameData:
+SameData.h:28: Error: Test failed: Not same data
+SameData.h:28: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+In SameData::testSafeAssertSameData:
+SameData.h:33: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+In SameData::testSafeAssertMessageSameData:
+SameData.h:38: Error: Test failed: Not same data
+SameData.h:38: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 ... }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC ... }
+Failed 10 of 10 tests
+Success rate: 0%
+Error level = 10
diff --git a/tools/cxxtest/test/normal.out b/tools/cxxtest/test/normal.out
new file mode 100644 (file)
index 0000000..bd5ac1e
--- /dev/null
@@ -0,0 +1,204 @@
+Running 35 tests
+In LessThanEquals::testLessThanEquals:
+LessThanEquals.h:16: Error: Expected (1 <= 0), found (1 > 0)
+LessThanEquals.h:17: Error: Test failed: 1 <=? 0
+LessThanEquals.h:17: Error: Expected (1 <= 0), found (1 > 0)
+LessThanEquals.h:19: Error: Expected (1 < 0), found (1 >= 0)
+LessThanEquals.h:20: Error: Test failed: 1 <=? 0
+LessThanEquals.h:20: Error: Expected (1 <= 0), found (1 > 0)
+In Relation::testPredicate:
+Relation.h:19: Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+Relation.h:20: Error: Test failed: 1 <? 0
+Relation.h:20: Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+Relation.h:22: Warning: 1
+Relation.h:24: Warning: 1
+In Relation::testRelation:
+Relation.h:29: Error: Expected MyLess<int>( 2, 1 ), found !MyLess<int>( 2, 1 )
+Relation.h:30: Error: Test failed: 2 <? 1
+Relation.h:30: Error: Expected MyLess<int>( 2, 1 ), found !MyLess<int>( 2, 1 )
+Relation.h:32: Warning: 1
+Relation.h:34: Warning: 1
+In DefaultTraits::testSmallDefaultTraits:
+DefaultTraits.h:21: Error: Test failed: { 00 01 02 03 04 05 06 07  }
+In DefaultTraits::testBigDefaultTraits:
+DefaultTraits.h:35: Error: Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... }
+In DoubleCall::testAssertEqualsWithSideEffects:
+DoubleCall.h:21: Error: Expected (increment() == 3), found (1 != 3)
+In DoubleCall::testAssertDiffersWithSideEffects:
+DoubleCall.h:26: Error: Expected (increment() != 1), found (1)
+In DoubleCall::testAssertDeltaWithSideEffects:
+DoubleCall.h:31: Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000)
+In SameData::testAssertSameData:
+SameData.h:23: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testAssertMessageSameData:
+SameData.h:28: Error: Test failed: Not same data
+SameData.h:28: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testSafeAssertSameData:
+SameData.h:33: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+In SameData::testSafeAssertMessageSameData:
+SameData.h:38: Error: Test failed: Not same data
+SameData.h:38: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+.
+In SameFiles::testAssertFileShorter:
+SameFiles.h:18: Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42)
+=     }
+=  };
+=
+<
+
+In SameFiles::testAssertFileLonger:
+SameFiles.h:23: Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42)
+=     }
+=  };
+=
+>
+
+In SameFiles::testAssertMessageSameFiles:
+SameFiles.h:28: Error: Test failed: Not same files
+SameFiles.h:28: Error: Files 'SameFiles.h' and 'SameData.h' differ at line 4
+= #include <cxxtest/TestSuite.h>
+=
+= //
+< // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+> // This test suite demonstrates TS_ASSERT_SAME_//
+
+.
+In SameFiles::testSafeAssertMessageSameFiles:
+SameFiles.h:38: Error: Test failed: Not same files
+SameFiles.h:38: Error: Files 'SameFiles.h' and 'SameData.h' differ at line 4
+= #include <cxxtest/TestSuite.h>
+=
+= //
+< // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+> // This test suite demonstrates TS_ASSERT_SAME_//
+
+In TestMessageMacros::testMessageMacros:
+Tsm.h:15: Error: Test failed: String
+Tsm.h:15: Error: Assertion failed: false
+Tsm.h:16: Error: Test failed: 42
+Tsm.h:16: Error: Assertion failed: false
+Tsm.h:17: Error: Test failed: String
+Tsm.h:17: Error: Expected (2 + 2 == 5), found (4 != 5)
+Tsm.h:18: Error: Test failed: 42
+Tsm.h:18: Error: Expected (2 + 2 == 5), found (4 != 5)
+Tsm.h:19: Error: Test failed: String
+Tsm.h:19: Error: Expected 1 (1) bytes to be equal at (&x) and (&y), found:
+{ 78 }
+differs from
+{ 79 }
+Tsm.h:20: Error: Test failed: 42
+Tsm.h:20: Error: Expected 1 (1) bytes to be equal at (&x) and (&y), found:
+{ 78 }
+differs from
+{ 79 }
+Tsm.h:21: Error: Test failed: String
+Tsm.h:21: Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Tsm.h:22: Error: Test failed: 42
+Tsm.h:22: Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Tsm.h:23: Error: Test failed: String
+Tsm.h:23: Error: Expected (0 != 0), found (0)
+Tsm.h:24: Error: Test failed: 42
+Tsm.h:24: Error: Expected (0 != 0), found (0)
+Tsm.h:25: Error: Test failed: String
+Tsm.h:25: Error: Expected (2 < 1), found (2 >= 1)
+Tsm.h:26: Error: Test failed: 42
+Tsm.h:26: Error: Expected (2 < 1), found (2 >= 1)
+Tsm.h:27: Error: Test failed: String
+Tsm.h:27: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:28: Error: Test failed: 42
+Tsm.h:28: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:29: Error: Test failed: String
+Tsm.h:29: Error: Expected (throwNothing()) to throw (...) but it didn't throw
+Tsm.h:30: Error: Test failed: 42
+Tsm.h:30: Error: Expected (throwNothing()) to throw (...) but it didn't throw
+Tsm.h:31: Error: Test failed: String
+Tsm.h:31: Error: Expected (throwInteger( n )) not to throw, but it did
+Tsm.h:32: Error: Test failed: 42
+Tsm.h:32: Error: Expected (throwInteger( n )) not to throw, but it did
+Tsm.h:33: Error: Test failed: String
+Tsm.h:33: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:34: Error: Test failed: 42
+Tsm.h:34: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:35: Error: Test failed: String
+Tsm.h:35: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:36: Error: Test failed: 42
+Tsm.h:36: Error: Expected (throwNothing()) to throw (int) but it didn't throw
+Tsm.h:37: Error: Test failed: String
+Tsm.h:37: Error: Expected (i == 43), found (42 != 43)
+Tsm.h:38: Error: Test failed: 42
+Tsm.h:38: Error: Expected (i == 43), found (42 != 43)
+In TraitsTest::testIntegerTraits:
+TraitsTest.h:13: Error: Test failed: 1
+TraitsTest.h:14: Error: Test failed: '\x0F'
+TraitsTest.h:15: Error: Test failed: -12
+TraitsTest.h:16: Error: Test failed: 34
+TraitsTest.h:17: Error: Test failed: -123
+TraitsTest.h:18: Error: Test failed: 456
+TraitsTest.h:19: Error: Test failed: -12345
+TraitsTest.h:20: Error: Test failed: 67890
+In TraitsTest::testFloatingPointTraits:
+TraitsTest.h:25: Error: Test failed: 0.1234
+TraitsTest.h:26: Error: Test failed: 0.1234
+In TraitsTest::testBoolTraits:
+TraitsTest.h:31: Error: Test failed: true
+TraitsTest.h:32: Error: Test failed: false
+In TraitsTest::testCharTraits:
+TraitsTest.h:37: Error: Test failed: 'A'
+TraitsTest.h:38: Error: Test failed: '\x04'
+TraitsTest.h:39: Error: Test failed: '\x1B'
+TraitsTest.h:40: Error: Test failed: '\0'
+TraitsTest.h:41: Error: Test failed: '\r'
+TraitsTest.h:42: Error: Test failed: '\n'
+TraitsTest.h:43: Error: Test failed: '\b'
+TraitsTest.h:44: Error: Test failed: '\t'
+TraitsTest.h:45: Error: Test failed: '\a'
+TraitsTest.h:46: Error: Test failed: '\xFB'
+In TraitsTest::testStringTraits:
+TraitsTest.h:51: Error: Test failed: (char *) is displayed as-is
+
+In TraitsTest::testStdStringTraits:
+TraitsTest.h:57: Error: Test failed: "std::string is displayed with \"\""
+TraitsTest.h:58: Error: Test failed: "Escapes\rAre\rTranslated"
+TraitsTest.h:59: Error: Test failed: "As are unprintable chars: \x124Vx"
+..
+In MockTest::test_Unimplemented:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+MockTest.h:129: Error: Expected (T::one() == 1), found (0 != 1)
+.
+In MockTest::test_Mock_traits:
+MockTest.h:40: Error: Test failed: T::getOpaque( int i ) called with no T::Base_getOpaque object
+MockTest.h:143: Error: Expected (T::getOpaque( 3 ).value == 72), found (42 != 72)
+In MockTest::test_Override:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+MockTest.h:157: Error: Expected (T::one() == 1), found (0 != 1)
+.
+In MockTest::test_Unimplemented_supply:
+MockTest.h:42: Error: Test failed: T::supplyOne( void ) called with no T::Base_supplyOne object
+MockTest.h:168: Error: Expected (supplyOne() == 1), found (0 != 1)
+.
+In SameZero::test_TS_ASSERT_SAME_DATA_passed_zero:
+SameZero.h:20: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found:
+{ 00 01 02 03 }
+differs from
+(null)
+SameZero.h:21: Error: Expected sizeof(data) (4) bytes to be equal at (0) and (data), found:
+(null)
+differs from
+{ 00 01 02 03 }
+Failed 28 of 35 tests
+Success rate: 20%
+Error level = 28
diff --git a/tools/cxxtest/test/normal.xml b/tools/cxxtest/test/normal.xml
new file mode 100644 (file)
index 0000000..b09a2c1
--- /dev/null
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite name="cxxtest"  tests="35" errors="0" failures="28" time="0" >
+<testcase classname="LessThanEquals" name="testLessThanEquals" line="11">
+<failure file="test/LessThanEquals.h" line="16" type="failedAssertLessThanEquals" >Error: Expected (1 &lt;= 0), found (1 &gt; 0)
+Test failed: 1 &lt;=? 0
+Error: Expected (1 &lt;= 0), found (1 &gt; 0)
+Error: Expected (1 &lt; 0), found (1 &gt;= 0)
+Test failed: 1 &lt;=? 0
+Error: Expected (1 &lt;= 0), found (1 &gt; 0)</failure>
+<system-out >
+In LessThanEquals::testLessThanEquals:
+LessThanEquals.h:16: Error: Expected (1 &lt;= 0), found (1 &gt; 0)
+LessThanEquals.h:17: Error: Test failed: 1 &lt;=? 0
+LessThanEquals.h:17: Error: Expected (1 &lt;= 0), found (1 &gt; 0)
+LessThanEquals.h:19: Error: Expected (1 &lt; 0), found (1 &gt;= 0)
+LessThanEquals.h:20: Error: Test failed: 1 &lt;=? 0
+LessThanEquals.h:20: Error: Expected (1 &lt;= 0), found (1 &gt; 0)
+</system-out>
+</testcase>
+<testcase classname="Relation" name="testPredicate" line="17">
+<failure file="test/Relation.h" line="19" type="failedAssertPredicate" >Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+Test failed: 1 &lt;? 0
+Error: Expected MyNegative( 1 ), found !MyNegative( 1 )</failure>
+<warning line="22" >1</warning>
+<warning line="24" >1</warning>
+<system-out >In Relation::testPredicate:
+Relation.h:19: Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+Relation.h:20: Error: Test failed: 1 &lt;? 0
+Relation.h:20: Error: Expected MyNegative( 1 ), found !MyNegative( 1 )
+Relation.h:22: Warning: 1
+Relation.h:24: Warning: 1
+</system-out>
+</testcase>
+<testcase classname="Relation" name="testRelation" line="27">
+<failure file="test/Relation.h" line="29" type="failedAssertRelation" >Error: Expected MyLess&lt;int&gt;( 2, 1 ), found !MyLess&lt;int&gt;( 2, 1 )
+Test failed: 2 &lt;? 1
+Error: Expected MyLess&lt;int&gt;( 2, 1 ), found !MyLess&lt;int&gt;( 2, 1 )</failure>
+<warning line="32" >1</warning>
+<warning line="34" >1</warning>
+<system-out >In Relation::testRelation:
+Relation.h:29: Error: Expected MyLess&lt;int&gt;( 2, 1 ), found !MyLess&lt;int&gt;( 2, 1 )
+Relation.h:30: Error: Test failed: 2 &lt;? 1
+Relation.h:30: Error: Expected MyLess&lt;int&gt;( 2, 1 ), found !MyLess&lt;int&gt;( 2, 1 )
+Relation.h:32: Warning: 1
+Relation.h:34: Warning: 1
+</system-out>
+</testcase>
+<testcase classname="DefaultTraits" name="testSmallDefaultTraits" line="16">
+<failure file="test/DefaultTraits.h" line="21" type="failure" >Test failed: { 00 01 02 03 04 05 06 07  }</failure>
+<system-out >In DefaultTraits::testSmallDefaultTraits:
+DefaultTraits.h:21: Error: Test failed: { 00 01 02 03 04 05 06 07  }
+</system-out>
+</testcase>
+<testcase classname="DefaultTraits" name="testBigDefaultTraits" line="30">
+<failure file="test/DefaultTraits.h" line="35" type="failure" >Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... }</failure>
+<system-out >In DefaultTraits::testBigDefaultTraits:
+DefaultTraits.h:35: Error: Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... }
+</system-out>
+</testcase>
+<testcase classname="DoubleCall" name="testAssertEqualsWithSideEffects" line="19">
+<failure file="test/DoubleCall.h" line="21" type="failedAssertEquals" >Error: Expected (increment() == 3), found (1 != 3)</failure>
+<system-out >In DoubleCall::testAssertEqualsWithSideEffects:
+DoubleCall.h:21: Error: Expected (increment() == 3), found (1 != 3)
+</system-out>
+</testcase>
+<testcase classname="DoubleCall" name="testAssertDiffersWithSideEffects" line="24">
+<failure file="test/DoubleCall.h" line="26" type="failedAssertDiffers" >Error: Expected (increment() != 1), found (1)</failure>
+<system-out >In DoubleCall::testAssertDiffersWithSideEffects:
+DoubleCall.h:26: Error: Expected (increment() != 1), found (1)
+</system-out>
+</testcase>
+<testcase classname="DoubleCall" name="testAssertDeltaWithSideEffects" line="29">
+<failure file="test/DoubleCall.h" line="31" type="failedAssertDelta" >Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000)</failure>
+<system-out >In DoubleCall::testAssertDeltaWithSideEffects:
+DoubleCall.h:31: Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000)
+</system-out>
+</testcase>
+<testcase classname="SameData" name="testAssertSameData" line="21">
+<failure file="test/SameData.h" line="23" type="failedAssertSameData" >Error: Expected DATA_SIZE (24)  bytes to be equal at (x) and (y), found</failure>
+<system-out >In SameData::testAssertSameData:
+SameData.h:23: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+</system-out>
+</testcase>
+<testcase classname="SameData" name="testAssertMessageSameData" line="26">
+<failure file="test/SameData.h" line="28" type="failure" >Test failed: Not same data
+Error: Expected DATA_SIZE (24)  bytes to be equal at (x) and (y), found</failure>
+<system-out >In SameData::testAssertMessageSameData:
+SameData.h:28: Error: Test failed: Not same data
+SameData.h:28: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+</system-out>
+</testcase>
+<testcase classname="SameData" name="testSafeAssertSameData" line="31">
+<failure file="test/SameData.h" line="33" type="failedAssertSameData" >Error: Expected DATA_SIZE (24)  bytes to be equal at (x) and (y), found</failure>
+<system-out >In SameData::testSafeAssertSameData:
+SameData.h:33: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+</system-out>
+</testcase>
+<testcase classname="SameData" name="testSafeAssertMessageSameData" line="36">
+<failure file="test/SameData.h" line="38" type="failure" >Test failed: Not same data
+Error: Expected DATA_SIZE (24)  bytes to be equal at (x) and (y), found</failure>
+<system-out >In SameData::testSafeAssertMessageSameData:
+SameData.h:38: Error: Test failed: Not same data
+SameData.h:38: Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found:
+{ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 }
+differs from
+{ FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 }
+</system-out>
+</testcase>
+<testcase classname="SameFiles" name="testAssertFiles" line="11" />
+<testcase classname="SameFiles" name="testAssertFileShorter" line="16">
+<failure file="test/SameFiles.h" line="18" type="failedAssertSameFiles" >Error: File &apos;SameFiles.h&apos; ended before file &apos;SameFilesLonger.h&apos; (line 42)
+=     }
+=  };
+=
+&lt;
+</failure>
+<system-out >
+In SameFiles::testAssertFileShorter:
+SameFiles.h:18: Error: File &apos;SameFiles.h&apos; ended before file &apos;SameFilesLonger.h&apos; (line 42)
+=     }
+=  };
+=
+&lt;
+
+</system-out>
+</testcase>
+<testcase classname="SameFiles" name="testAssertFileLonger" line="21">
+<failure file="test/SameFiles.h" line="23" type="failedAssertSameFiles" >Error: File &apos;SameFiles.h&apos; ended before file &apos;SameFilesLonger.h&apos; (line 42)
+=     }
+=  };
+=
+&gt;
+</failure>
+<system-out >In SameFiles::testAssertFileLonger:
+SameFiles.h:23: Error: File &apos;SameFiles.h&apos; ended before file &apos;SameFilesLonger.h&apos; (line 42)
+=     }
+=  };
+=
+&gt;
+
+</system-out>
+</testcase>
+<testcase classname="SameFiles" name="testAssertMessageSameFiles" line="26">
+<failure file="test/SameFiles.h" line="28" type="failure" >Test failed: Not same files
+Error: Files &apos;SameFiles.h&apos; and &apos;SameData.h&apos; differ at line 4
+= #include &lt;cxxtest/TestSuite.h&gt;
+=
+= //
+&lt; // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+&gt; // This test suite demonstrates TS_ASSERT_SAME_//
+</failure>
+<system-out >In SameFiles::testAssertMessageSameFiles:
+SameFiles.h:28: Error: Test failed: Not same files
+SameFiles.h:28: Error: Files &apos;SameFiles.h&apos; and &apos;SameData.h&apos; differ at line 4
+= #include &lt;cxxtest/TestSuite.h&gt;
+=
+= //
+&lt; // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+&gt; // This test suite demonstrates TS_ASSERT_SAME_//
+
+</system-out>
+</testcase>
+<testcase classname="SameFiles" name="testSafeAssertSameFiles" line="31" />
+<testcase classname="SameFiles" name="testSafeAssertMessageSameFiles" line="36">
+<failure file="test/SameFiles.h" line="38" type="failure" >Test failed: Not same files
+Error: Files &apos;SameFiles.h&apos; and &apos;SameData.h&apos; differ at line 4
+= #include &lt;cxxtest/TestSuite.h&gt;
+=
+= //
+&lt; // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+&gt; // This test suite demonstrates TS_ASSERT_SAME_//
+</failure>
+<system-out >
+In SameFiles::testSafeAssertMessageSameFiles:
+SameFiles.h:38: Error: Test failed: Not same files
+SameFiles.h:38: Error: Files &apos;SameFiles.h&apos; and &apos;SameData.h&apos; differ at line 4
+= #include &lt;cxxtest/TestSuite.h&gt;
+=
+= //
+&lt; // This test suite demonstrates TS_ASSERT_SAME_ATA
+
+&gt; // This test suite demonstrates TS_ASSERT_SAME_//
+
+</system-out>
+</testcase>
+<testcase classname="TestMessageMacros" name="testMessageMacros" line="10">
+<failure file="test/Tsm.h" line="15" type="failure" >Test failed: String
+Assertion failed: false
+Test failed: 42
+Assertion failed: false
+Test failed: String
+Error: Expected (2 + 2 == 5), found (4 != 5)
+Test failed: 42
+Error: Expected (2 + 2 == 5), found (4 != 5)
+Test failed: String
+Error: Expected 1 (1)  bytes to be equal at (&amp;x) and (&amp;y), found
+Test failed: 42
+Error: Expected 1 (1)  bytes to be equal at (&amp;x) and (&amp;y), found
+Test failed: String
+Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Test failed: 42
+Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Test failed: String
+Error: Expected (0 != 0), found (0)
+Test failed: 42
+Error: Expected (0 != 0), found (0)
+Test failed: String
+Error: Expected (2 &lt; 1), found (2 &gt;= 1)
+Test failed: 42
+Error: Expected (2 &lt; 1), found (2 &gt;= 1)
+Test failed: String
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: 42
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: String
+Error: Expected (throwNothing()) to throw (...) but it didn&apos;t throw
+Test failed: 42
+Error: Expected (throwNothing()) to throw (...) but it didn&apos;t throw
+Test failed: String
+Error: Expected (throwInteger( n )) not to throw, but it did
+Test failed: 42
+Error: Expected (throwInteger( n )) not to throw, but it did
+Test failed: String
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: 42
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: String
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: 42
+Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Test failed: String
+Error: Expected (i == 43), found (42 != 43)
+Test failed: 42
+Error: Expected (i == 43), found (42 != 43)</failure>
+<system-out >In TestMessageMacros::testMessageMacros:
+Tsm.h:15: Error: Test failed: String
+Tsm.h:15: Error: Assertion failed: false
+Tsm.h:16: Error: Test failed: 42
+Tsm.h:16: Error: Assertion failed: false
+Tsm.h:17: Error: Test failed: String
+Tsm.h:17: Error: Expected (2 + 2 == 5), found (4 != 5)
+Tsm.h:18: Error: Test failed: 42
+Tsm.h:18: Error: Expected (2 + 2 == 5), found (4 != 5)
+Tsm.h:19: Error: Test failed: String
+Tsm.h:19: Error: Expected 1 (1) bytes to be equal at (&amp;x) and (&amp;y), found:
+{ 78 }
+differs from
+{ 79 }
+Tsm.h:20: Error: Test failed: 42
+Tsm.h:20: Error: Expected 1 (1) bytes to be equal at (&amp;x) and (&amp;y), found:
+{ 78 }
+differs from
+{ 79 }
+Tsm.h:21: Error: Test failed: String
+Tsm.h:21: Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Tsm.h:22: Error: Test failed: 42
+Tsm.h:22: Error: Expected (1.0 == 2.0) up to 0.5 (0.5000), found (1.0000 != 2.0000)
+Tsm.h:23: Error: Test failed: String
+Tsm.h:23: Error: Expected (0 != 0), found (0)
+Tsm.h:24: Error: Test failed: 42
+Tsm.h:24: Error: Expected (0 != 0), found (0)
+Tsm.h:25: Error: Test failed: String
+Tsm.h:25: Error: Expected (2 &lt; 1), found (2 &gt;= 1)
+Tsm.h:26: Error: Test failed: 42
+Tsm.h:26: Error: Expected (2 &lt; 1), found (2 &gt;= 1)
+Tsm.h:27: Error: Test failed: String
+Tsm.h:27: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:28: Error: Test failed: 42
+Tsm.h:28: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:29: Error: Test failed: String
+Tsm.h:29: Error: Expected (throwNothing()) to throw (...) but it didn&apos;t throw
+Tsm.h:30: Error: Test failed: 42
+Tsm.h:30: Error: Expected (throwNothing()) to throw (...) but it didn&apos;t throw
+Tsm.h:31: Error: Test failed: String
+Tsm.h:31: Error: Expected (throwInteger( n )) not to throw, but it did
+Tsm.h:32: Error: Test failed: 42
+Tsm.h:32: Error: Expected (throwInteger( n )) not to throw, but it did
+Tsm.h:33: Error: Test failed: String
+Tsm.h:33: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:34: Error: Test failed: 42
+Tsm.h:34: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:35: Error: Test failed: String
+Tsm.h:35: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:36: Error: Test failed: 42
+Tsm.h:36: Error: Expected (throwNothing()) to throw (int) but it didn&apos;t throw
+Tsm.h:37: Error: Test failed: String
+Tsm.h:37: Error: Expected (i == 43), found (42 != 43)
+Tsm.h:38: Error: Test failed: 42
+Tsm.h:38: Error: Expected (i == 43), found (42 != 43)
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testIntegerTraits" line="11">
+<failure file="test/TraitsTest.h" line="13" type="failure" >Test failed: 1
+Test failed: &apos;\x0F&apos;
+Test failed: -12
+Test failed: 34
+Test failed: -123
+Test failed: 456
+Test failed: -12345
+Test failed: 67890</failure>
+<system-out >In TraitsTest::testIntegerTraits:
+TraitsTest.h:13: Error: Test failed: 1
+TraitsTest.h:14: Error: Test failed: &apos;\x0F&apos;
+TraitsTest.h:15: Error: Test failed: -12
+TraitsTest.h:16: Error: Test failed: 34
+TraitsTest.h:17: Error: Test failed: -123
+TraitsTest.h:18: Error: Test failed: 456
+TraitsTest.h:19: Error: Test failed: -12345
+TraitsTest.h:20: Error: Test failed: 67890
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testFloatingPointTraits" line="23">
+<failure file="test/TraitsTest.h" line="25" type="failure" >Test failed: 0.1234
+Test failed: 0.1234</failure>
+<system-out >In TraitsTest::testFloatingPointTraits:
+TraitsTest.h:25: Error: Test failed: 0.1234
+TraitsTest.h:26: Error: Test failed: 0.1234
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testBoolTraits" line="29">
+<failure file="test/TraitsTest.h" line="31" type="failure" >Test failed: true
+Test failed: false</failure>
+<system-out >In TraitsTest::testBoolTraits:
+TraitsTest.h:31: Error: Test failed: true
+TraitsTest.h:32: Error: Test failed: false
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testCharTraits" line="35">
+<failure file="test/TraitsTest.h" line="37" type="failure" >Test failed: &apos;A&apos;
+Test failed: &apos;\x04&apos;
+Test failed: &apos;\x1B&apos;
+Test failed: &apos;\0&apos;
+Test failed: &apos;\r&apos;
+Test failed: &apos;\n&apos;
+Test failed: &apos;\b&apos;
+Test failed: &apos;\t&apos;
+Test failed: &apos;\a&apos;
+Test failed: &apos;\xFB&apos;</failure>
+<system-out >In TraitsTest::testCharTraits:
+TraitsTest.h:37: Error: Test failed: &apos;A&apos;
+TraitsTest.h:38: Error: Test failed: &apos;\x04&apos;
+TraitsTest.h:39: Error: Test failed: &apos;\x1B&apos;
+TraitsTest.h:40: Error: Test failed: &apos;\0&apos;
+TraitsTest.h:41: Error: Test failed: &apos;\r&apos;
+TraitsTest.h:42: Error: Test failed: &apos;\n&apos;
+TraitsTest.h:43: Error: Test failed: &apos;\b&apos;
+TraitsTest.h:44: Error: Test failed: &apos;\t&apos;
+TraitsTest.h:45: Error: Test failed: &apos;\a&apos;
+TraitsTest.h:46: Error: Test failed: &apos;\xFB&apos;
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testStringTraits" line="49">
+<failure file="test/TraitsTest.h" line="51" type="failure" >Test failed: (char *) is displayed as-is
+</failure>
+<system-out >In TraitsTest::testStringTraits:
+TraitsTest.h:51: Error: Test failed: (char *) is displayed as-is
+
+</system-out>
+</testcase>
+<testcase classname="TraitsTest" name="testStdStringTraits" line="54">
+<failure file="test/TraitsTest.h" line="57" type="failure" >Test failed: &quot;std::string is displayed with \&quot;\&quot;&quot;
+Test failed: &quot;Escapes\rAre\rTranslated&quot;
+Test failed: &quot;As are unprintable chars: \x124Vx&quot;</failure>
+<system-out >In TraitsTest::testStdStringTraits:
+TraitsTest.h:57: Error: Test failed: &quot;std::string is displayed with \&quot;\&quot;&quot;
+TraitsTest.h:58: Error: Test failed: &quot;Escapes\rAre\rTranslated&quot;
+TraitsTest.h:59: Error: Test failed: &quot;As are unprintable chars: \x124Vx&quot;
+</system-out>
+</testcase>
+<testcase classname="MockTest" name="test_Mock" line="115" />
+<testcase classname="MockTest" name="test_Real" line="121" />
+<testcase classname="MockTest" name="test_Unimplemented" line="127">
+<failure file="test/MockTest.h" line="33" type="failure" >Test failed: T::one( void ) called with no T::Base_one object
+Error: Expected (T::one() == 1), found (0 != 1)</failure>
+<system-out >
+In MockTest::test_Unimplemented:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+MockTest.h:129: Error: Expected (T::one() == 1), found (0 != 1)
+</system-out>
+</testcase>
+<testcase classname="MockTest" name="test_More_complex_mock" line="132" />
+<testcase classname="MockTest" name="test_Mock_traits" line="141">
+<failure file="test/MockTest.h" line="40" type="failure" >Test failed: T::getOpaque( int i ) called with no T::Base_getOpaque object
+Error: Expected (T::getOpaque( 3 ).value == 72), found (42 != 72)</failure>
+<system-out >
+In MockTest::test_Mock_traits:
+MockTest.h:40: Error: Test failed: T::getOpaque( int i ) called with no T::Base_getOpaque object
+MockTest.h:143: Error: Expected (T::getOpaque( 3 ).value == 72), found (42 != 72)
+</system-out>
+</testcase>
+<testcase classname="MockTest" name="test_Override" line="146">
+<failure file="test/MockTest.h" line="33" type="failure" >Test failed: T::one( void ) called with no T::Base_one object
+Error: Expected (T::one() == 1), found (0 != 1)</failure>
+<system-out >In MockTest::test_Override:
+MockTest.h:33: Error: Test failed: T::one( void ) called with no T::Base_one object
+MockTest.h:157: Error: Expected (T::one() == 1), found (0 != 1)
+</system-out>
+</testcase>
+<testcase classname="MockTest" name="test_Supply" line="160" />
+<testcase classname="MockTest" name="test_Unimplemented_supply" line="166">
+<failure file="test/MockTest.h" line="42" type="failure" >Test failed: T::supplyOne( void ) called with no T::Base_supplyOne object
+Error: Expected (supplyOne() == 1), found (0 != 1)</failure>
+<system-out >
+In MockTest::test_Unimplemented_supply:
+MockTest.h:42: Error: Test failed: T::supplyOne( void ) called with no T::Base_supplyOne object
+MockTest.h:168: Error: Expected (supplyOne() == 1), found (0 != 1)
+</system-out>
+</testcase>
+<testcase classname="MockTest" name="test_More_complex_supply" line="171" />
+<testcase classname="SameZero" name="test_TS_ASSERT_SAME_DATA_passed_zero" line="18">
+<failure file="test/SameZero.h" line="20" type="failedAssertSameData" >Error: Expected sizeof(data) (4)  bytes to be equal at (data) and (0), found
+Error: Expected sizeof(data) (4)  bytes to be equal at (0) and (data), found</failure>
+<system-out >
+In SameZero::test_TS_ASSERT_SAME_DATA_passed_zero:
+SameZero.h:20: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found:
+{ 00 01 02 03 }
+differs from
+(null)
+SameZero.h:21: Error: Expected sizeof(data) (4) bytes to be equal at (0) and (data), found:
+(null)
+differs from
+{ 00 01 02 03 }
+</system-out>
+</testcase>
+</testsuite>
diff --git a/tools/cxxtest/test/paren.out b/tools/cxxtest/test/paren.out
new file mode 100644 (file)
index 0000000..c0f966a
--- /dev/null
@@ -0,0 +1,51 @@
+Running 14 tests
+In CreatedTest::test_nothing:
+sample/CreatedTest.h(26): Error: Test failed: Nothing to test
+.
+In EnumTraits::test_Enum_traits:
+sample/EnumTraits.h(32): Error: Test failed: Yes
+sample/EnumTraits.h(33): Error: Test failed: No
+sample/EnumTraits.h(34): Error: Test failed: Maybe
+sample/EnumTraits.h(35): Error: Test failed: DontKnow
+sample/EnumTraits.h(36): Error: Test failed: DontCare
+sample/EnumTraits.h(37): Error: Test failed: (Answer)1000
+In ExceptionTest::testAssertion:
+sample/ExceptionTest.h(20): Error: Expected (throwThis(5)) to throw (const char *) but it threw something else
+sample/ExceptionTest.h(22): Error: Expected (goodFunction(1)) to throw (...) but it didn't throw
+sample/ExceptionTest.h(24): Error: Test failed: Unhandled exception
+sample/ExceptionTest.h(26): Error: Expected (throwThis(-1)) not to throw, but it did
+sample/ExceptionTest.h(31): Error: Test failed: throwThis(3) failed
+In FixtureTest::test_strcpy:
+sample/FixtureTest.h(32): Error: Expected (_buffer[1] == 'E'), found ('e' != 'E')
+In MessageTest::testValues:
+sample/MessageTest.h(24): Error: Test failed: My hovercraft
+sample/MessageTest.h(24): Error: Assertion failed: value != 0
+sample/MessageTest.h(25): Error: Test failed: of eels
+sample/MessageTest.h(25): Error: Expected (value == value * value), found (2 != 4)
+In SimpleTest::testEquality:
+sample/SimpleTest.h(16): Error: Expected (1 == 2), found (1 != 2)
+sample/SimpleTest.h(17): Error: Expected ('a' == 'A'), found ('a' != 'A')
+sample/SimpleTest.h(18): Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In SimpleTest::testAddition:
+sample/SimpleTest.h(24): Error: Expected (2 + 2 == 5), found (4 != 5)
+In SimpleTest::TestMultiplication:
+sample/SimpleTest.h(30): Error: Expected (4 * 4 == 44), found (16 != 44)
+sample/SimpleTest.h(31): Error: Expected (-2 * -2 != 4), found (4)
+In SimpleTest::testComparison:
+sample/SimpleTest.h(37): Error: Expected (-1 < -2), found (-1 >= -2)
+In SimpleTest::testTheWorldIsCrazy:
+sample/SimpleTest.h(42): Error: Expected (true == false), found (true != false)
+In SimpleTest::test_Failure:
+sample/SimpleTest.h(47): Error: Test failed: Not implemented
+sample/SimpleTest.h(48): Error: Test failed: 1569779912
+In SimpleTest::test_TS_WARN_macro:
+sample/SimpleTest.h(53): Warning: Just a friendly warning
+sample/SimpleTest.h(54): Warning: Warnings don't abort the test
+.
+In TestFunky::testPets:
+sample/TraitsTest.h(59): Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat"))
+sample/TraitsTest.h(61): Error: Expected (cat != gato), found (Pet("cat"))
+sample/TraitsTest.h(64): Error: Expected (String("Hello") == String("World!")), found ("Hello" != "World!")
+Failed 12 of 14 tests
+Success rate: 14%
+Error level = 12
diff --git a/tools/cxxtest/test/parts.out b/tools/cxxtest/test/parts.out
new file mode 100644 (file)
index 0000000..fc4be03
--- /dev/null
@@ -0,0 +1,2 @@
+Running 2 tests..OK!
+Error level = 0
diff --git a/tools/cxxtest/test/preamble.out b/tools/cxxtest/test/preamble.out
new file mode 100644 (file)
index 0000000..be2a0de
--- /dev/null
@@ -0,0 +1,67 @@
+Running 14 tests
+In CreatedTest::test_nothing:
+CreatedTest.h:26: Error: Test failed: Nothing to test
+.
+In EnumTraits::test_Enum_traits:
+EnumTraits.h:32: Error: Test failed: Yes
+In ExceptionTest::testAssertion:
+ExceptionTest.h:20: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else
+In FixtureTest::test_strcpy:
+FixtureTest.h:32: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E')
+In MessageTest::testValues:
+MessageTest.h:24: Error: Test failed: My hovercraft
+MessageTest.h:24: Error: Assertion failed: value != 0
+In SimpleTest::testEquality:
+SimpleTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+In SimpleTest::testAddition:
+SimpleTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In SimpleTest::TestMultiplication:
+SimpleTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+In SimpleTest::testComparison:
+SimpleTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In SimpleTest::testTheWorldIsCrazy:
+SimpleTest.h:42: Error: Expected (true == false), found (true != false)
+In SimpleTest::test_Failure:
+SimpleTest.h:47: Error: Test failed: Not implemented
+In SimpleTest::test_TS_WARN_macro:
+SimpleTest.h:53: Warning: Just a friendly warning
+SimpleTest.h:54: Warning: Warnings don't abort the test
+.
+In TestFunky::testPets:
+TraitsTest.h:59: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat"))
+Failed 12 of 14 tests
+Success rate: 14%
+Running 14 tests
+In CreatedTest::test_nothing:
+CreatedTest.h:26: Error: Test failed: Nothing to test
+.
+In EnumTraits::test_Enum_traits:
+EnumTraits.h:32: Error: Test failed: Yes
+In ExceptionTest::testAssertion:
+ExceptionTest.h:20: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else
+In FixtureTest::test_strcpy:
+FixtureTest.h:32: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E')
+In MessageTest::testValues:
+MessageTest.h:24: Error: Test failed: My hovercraft
+MessageTest.h:24: Error: Assertion failed: value != 0
+In SimpleTest::testEquality:
+SimpleTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+In SimpleTest::testAddition:
+SimpleTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In SimpleTest::TestMultiplication:
+SimpleTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+In SimpleTest::testComparison:
+SimpleTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In SimpleTest::testTheWorldIsCrazy:
+SimpleTest.h:42: Error: Expected (true == false), found (true != false)
+In SimpleTest::test_Failure:
+SimpleTest.h:47: Error: Test failed: Not implemented
+In SimpleTest::test_TS_WARN_macro:
+SimpleTest.h:53: Warning: Just a friendly warning
+SimpleTest.h:54: Warning: Warnings don't abort the test
+.
+In TestFunky::testPets:
+TraitsTest.h:59: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat"))
+Failed 12 of 14 tests
+Success rate: 14%
+Error level = 24
diff --git a/tools/cxxtest/test/preamble.tpl b/tools/cxxtest/test/preamble.tpl
new file mode 100644 (file)
index 0000000..a15356b
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+
+#define CXXTEST_ABORT_TEST_ON_FAIL
+
+// CxxTest definitions and headers
+<CxxTest preamble>
+
+// Make sure this worked
+#ifndef TS_ASSERT
+#   error The preamble does not work!
+#endif
+
+#include <cxxtest/StdioPrinter.h>
+
+int main()
+{
+    CxxTest::StdioPrinter runner;
+
+    TS_FAIL( "This will not be displayed" );
+    int result = runner.run() + runner.run();
+    TS_FAIL( "This will not be displayed" );
+    
+    return result;
+}
+
+
+// The CxxTest "world"
+<CxxTest world>
+
diff --git a/tools/cxxtest/test/runner.out b/tools/cxxtest/test/runner.out
new file mode 100644 (file)
index 0000000..7225774
--- /dev/null
@@ -0,0 +1 @@
+Error level = 12
diff --git a/tools/cxxtest/test/simple_inheritance.out b/tools/cxxtest/test/simple_inheritance.out
new file mode 100644 (file)
index 0000000..836fae6
--- /dev/null
@@ -0,0 +1,2 @@
+Running 4 tests....OK!
+Error level = 0
diff --git a/tools/cxxtest/test/simple_inheritance2.out b/tools/cxxtest/test/simple_inheritance2.out
new file mode 100644 (file)
index 0000000..fc4be03
--- /dev/null
@@ -0,0 +1,2 @@
+Running 2 tests..OK!
+Error level = 0
diff --git a/tools/cxxtest/test/std.out b/tools/cxxtest/test/std.out
new file mode 100644 (file)
index 0000000..d642556
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In HaveStd::testHaveStd:
+HaveStd.h:13: Error: Expected (something() == "Something"), found ("something" != Something)
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/stl.out b/tools/cxxtest/test/stl.out
new file mode 100644 (file)
index 0000000..274999a
--- /dev/null
@@ -0,0 +1,46 @@
+Running 9 tests
+In StlTraits::test_Pair:
+StlTraits.h:13: Error: Test failed: <3, "Three">
+StlTraits.h:15: Error: Test failed: <"Four", 4.0000>
+In StlTraits::test_Vector:
+StlTraits.h:21: Trace: {}
+StlTraits.h:25: Error: Test failed: { 1, 2, 3 }
+StlTraits.h:28: Trace: {}
+StlTraits.h:32: Error: Test failed: { "One", "Two", "Three" }
+StlTraits.h:35: Trace: {}
+StlTraits.h:39: Error: Test failed: { <1, "One">, <2, "Two">, <3, "Three"> }
+In StlTraits::test_List:
+StlTraits.h:45: Trace: {}
+StlTraits.h:49: Error: Test failed: { 1, 2, 3 }
+StlTraits.h:52: Trace: {}
+StlTraits.h:56: Error: Test failed: { "One", "Two", "Three" }
+StlTraits.h:59: Trace: {}
+StlTraits.h:63: Error: Test failed: { <1, "One">, <2, "Two">, <3, "Three"> }
+In StlTraits::test_Set:
+StlTraits.h:69: Trace: {}
+StlTraits.h:73: Error: Test failed: { 1, 2, 3 }
+StlTraits.h:76: Trace: {}
+StlTraits.h:80: Error: Test failed: { "One", "Three", "Two" }
+StlTraits.h:83: Trace: {}
+StlTraits.h:87: Error: Test failed: { <1, "One">, <2, "Two">, <3, "Three"> }
+In StlTraits::test_Map:
+StlTraits.h:93: Trace: {}
+StlTraits.h:99: Error: Test failed: { <"Humpty", "Dumpty">, <"Jack", "Jill">, <"Ren", "Stimpy"> }
+StlTraits.h:102: Trace: {}
+StlTraits.h:111: Error: Test failed: { <6, { 2, 3 }>, <210, { 2, 3, 5, 7 }> }
+In StlTraits::test_Deque:
+StlTraits.h:117: Trace: {}
+StlTraits.h:122: Error: Test failed: { 4, 3, 2, 1 }
+In StlTraits::test_MultiMap:
+StlTraits.h:128: Trace: {}
+StlTraits.h:132: Error: Test failed: { <"One", 1.0000>, <"Two", 2.0000> }
+In StlTraits::test_MultiSet:
+StlTraits.h:138: Trace: {}
+StlTraits.h:142: Error: Test failed: { 123, 456 }
+In StlTraits::test_Complex:
+StlTraits.h:148: Error: Test failed: (3.1400 + 2.7100 * i)
+StlTraits.h:149: Error: Test failed: (1.0000 * i)
+StlTraits.h:150: Error: Test failed: 1.0000
+Failed 9 of 9 tests
+Success rate: 0%
+Error level = 9
diff --git a/tools/cxxtest/test/stpltpl.cpp b/tools/cxxtest/test/stpltpl.cpp
new file mode 100644 (file)
index 0000000..f541dc5
--- /dev/null
@@ -0,0 +1,6 @@
+#include <cxxtest/Flags.h>
+
+#ifdef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+int main() { return 0; }
+#endif // !_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+
diff --git a/tools/cxxtest/test/suite.out b/tools/cxxtest/test/suite.out
new file mode 100644 (file)
index 0000000..9cf4378
--- /dev/null
@@ -0,0 +1,24 @@
+Running 7 tests
+In SimpleTest::testEquality:
+SimpleTest.h:16: Error: Expected (1 == 2), found (1 != 2)
+SimpleTest.h:17: Error: Expected ('a' == 'A'), found ('a' != 'A')
+SimpleTest.h:18: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50)
+In SimpleTest::testAddition:
+SimpleTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+In SimpleTest::TestMultiplication:
+SimpleTest.h:30: Error: Expected (4 * 4 == 44), found (16 != 44)
+SimpleTest.h:31: Error: Expected (-2 * -2 != 4), found (4)
+In SimpleTest::testComparison:
+SimpleTest.h:37: Error: Expected (-1 < -2), found (-1 >= -2)
+In SimpleTest::testTheWorldIsCrazy:
+SimpleTest.h:42: Error: Expected (true == false), found (true != false)
+In SimpleTest::test_Failure:
+SimpleTest.h:47: Error: Test failed: Not implemented
+SimpleTest.h:48: Error: Test failed: 1569779912
+In SimpleTest::test_TS_WARN_macro:
+SimpleTest.h:53: Warning: Just a friendly warning
+SimpleTest.h:54: Warning: Warnings don't abort the test
+.
+Failed 6 of 7 tests
+Success rate: 14%
+Error level = 6
diff --git a/tools/cxxtest/test/suite_test.out b/tools/cxxtest/test/suite_test.out
new file mode 100644 (file)
index 0000000..b269608
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In SimpleTest::testAddition:
+SimpleTest.h:24: Error: Expected (2 + 2 == 5), found (4 != 5)
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/suwe.out b/tools/cxxtest/test/suwe.out
new file mode 100644 (file)
index 0000000..43a0289
--- /dev/null
@@ -0,0 +1,6 @@
+Running 2 tests
+In <no suite>::<no test>:
+SetUpWorldError.h:12: Error: Test failed: THIS IS BAD
+RealDescriptions.cpp:5: Warning: Error setting up world
+OK!
+Error level = 0
diff --git a/tools/cxxtest/test/suwf.out b/tools/cxxtest/test/suwf.out
new file mode 100644 (file)
index 0000000..aa10abd
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test
+In <no suite>::<no test>:
+RealDescriptions.cpp:5: Warning: Error setting up world
+OK!
+Error level = 0
diff --git a/tools/cxxtest/test/suwt.out b/tools/cxxtest/test/suwt.out
new file mode 100644 (file)
index 0000000..aa10abd
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test
+In <no suite>::<no test>:
+RealDescriptions.cpp:5: Warning: Error setting up world
+OK!
+Error level = 0
diff --git a/tools/cxxtest/test/tdwf.out b/tools/cxxtest/test/tdwf.out
new file mode 100644 (file)
index 0000000..7b68b61
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test.
+In <no suite>::<no test>:
+RealDescriptions.cpp:5: Warning: Error tearing down world
+OK!
+Error level = 0
diff --git a/tools/cxxtest/test/tdwt.out b/tools/cxxtest/test/tdwt.out
new file mode 100644 (file)
index 0000000..7b68b61
--- /dev/null
@@ -0,0 +1,5 @@
+Running 1 test.
+In <no suite>::<no test>:
+RealDescriptions.cpp:5: Warning: Error tearing down world
+OK!
+Error level = 0
diff --git a/tools/cxxtest/test/template.out b/tools/cxxtest/test/template.out
new file mode 100644 (file)
index 0000000..fc4be03
--- /dev/null
@@ -0,0 +1,2 @@
+Running 2 tests..OK!
+Error level = 0
diff --git a/tools/cxxtest/test/test_cxxtest.py b/tools/cxxtest/test/test_cxxtest.py
new file mode 100644 (file)
index 0000000..79c8d56
--- /dev/null
@@ -0,0 +1,704 @@
+import sys
+import os
+import os.path
+import glob
+import difflib
+import subprocess
+import re
+if sys.version_info < (2,7):
+    import unittest2 as unittest
+else:
+    import unittest
+try:
+    import ply
+    ply_available=True
+except:
+    ply_available=False
+
+currdir = os.path.dirname(os.path.abspath(__file__))+os.sep
+sampledir = os.path.dirname(os.path.dirname(currdir))+'/sample'+os.sep
+cxxtestdir = os.path.dirname(os.path.dirname(currdir))+os.sep
+
+compilerre = re.compile("^(?P<path>[^:]+)(?P<rest>:[0-9]+:.*)$")
+dirre      = re.compile("^([^"+os.sep+"]*/)*")
+xmlre      = re.compile("\"(?P<path>[^\"]*/[^\"]*)\"")
+
+# Headers from the cxxtest/sample directory
+samples = ' '.join(file for file in sorted(glob.glob(sampledir+'*.h')))
+guiInputs=currdir+'../sample/gui/GreenYellowRed.h'
+if sys.platform.startswith('win'):
+    target_suffix = '.exe'
+else:
+    target_suffix = ''
+# Create a file with the list of sample files
+OUTPUT = open(currdir+'Samples.txt','w')
+for line in sorted(glob.glob(sampledir+'*.h')):
+    OUTPUT.write(line+'\n')
+OUTPUT.close()
+
+def available(compiler, exe_option):
+    cmd = "cd %s; %s %s %s %s > %s 2>&1" % (currdir, compiler, exe_option, currdir+'anything', currdir+'anything.cpp', currdir+'anything.log')
+    ##print cmd
+    status = subprocess.call(cmd, shell=True)
+    flag = status == 0 and os.path.exists(currdir+'anything')
+    os.remove(currdir+'anything.log')
+    if os.path.exists(currdir+'anything'):
+        os.remove(currdir+'anything')
+    return flag
+
+def remove_absdir(filename):
+    INPUT=open(filename, 'r')
+    lines = [line.strip() for line in INPUT]
+    INPUT.close()
+    OUTPUT=open(filename, 'w')
+    for line in lines:
+        # remove basedir at front of line
+        match = compilerre.match(line) # see if we can remove the basedir
+        if match:
+            parts = match.groupdict()
+            line = dirre.sub("", parts['path']) + parts['rest']
+        OUTPUT.write(line+'\n')
+    OUTPUT.close()
+
+def normalize_line_for_diff(line):
+    # add spaces around {}<>()
+    line = re.sub("[{}<>()]", r" \0 ", line)
+
+    # beginnig and ending whitespace
+    line = line.strip()
+
+    # remove all whitespace
+    # and leave a single space
+    line = ' '.join(line.split())
+
+    # remove spaces around "="
+    line = re.sub(" ?= ?", "=", line)
+
+
+    # remove all absolute path prefixes
+    line = ''.join(line.split(cxxtestdir))
+    # for xml, remove prefixes from everything that looks like a 
+    # file path inside ""
+    line = xmlre.sub(
+            lambda match: '"'+re.sub("^[^/]+/", "", match.group(1))+'"',
+            line
+            )
+    return line
+
+def make_diff_readable(diff):
+    i = 0
+    while i+1 < len(diff):
+        if diff[i][0] == '-' and diff[i+1][0] == '+':
+            l1 = diff[i]
+            l2 = diff[i+1]
+            for j in range(1, min([len(l1), len(l2)])):
+                if l1[j] != l2[j]:
+                    if j > 4:
+                        j = j-2;
+                        l1 = l1[j:]
+                        l2 = l2[j:]
+                        diff[i] = '-(...)' + l1
+                        diff[i+1] = '+(...)' + l2
+                    break
+        i+=1
+
+def file_diff(filename1, filename2):
+    remove_absdir(filename1)
+    remove_absdir(filename2)
+    #
+    INPUT=open(filename1, 'r')
+    lines1 = INPUT.readlines()
+    INPUT.close()
+    #
+    INPUT=open(filename2, 'r')
+    lines2 = INPUT.readlines()
+    INPUT.close()
+    #
+    lines1cmp = [normalize_line_for_diff(line) for line in lines1]
+    lines2cmp = [normalize_line_for_diff(line) for line in lines2]
+    diff = list(difflib.unified_diff(lines2cmp, lines1cmp,
+        fromfile=filename2, tofile=filename1))
+    if diff: make_diff_readable(diff)
+    diff = '\n'.join(diff)
+    return diff
+
+class BaseTestCase(object):
+
+    fog=''
+
+    def setUp(self):
+        self.passed=False
+        self.prefix=''
+        self.py_out=''
+        self.py_cpp=''
+        self.px_pre=''
+        self.px_out=''
+        self.build_log=''
+        self.build_target=''
+
+    def tearDown(self):
+        if not self.passed:
+            return
+        if os.path.exists(self.py_out):
+            os.remove(self.py_out)
+        if os.path.exists(self.py_cpp) and not 'CXXTEST_GCOV_FLAGS' in os.environ:
+            os.remove(self.py_cpp)
+        if os.path.exists(self.px_pre):
+            os.remove(self.px_pre)
+        if os.path.exists(self.px_out):
+            os.remove(self.px_out)
+        if os.path.exists(self.build_log):
+            os.remove(self.build_log)
+        if os.path.exists(self.build_target) and not 'CXXTEST_GCOV_FLAGS' in os.environ:
+            os.remove(self.build_target)
+
+    def check_if_supported(self, filename, msg):
+        target=currdir+'check'+'px'+target_suffix
+        log=currdir+'check'+'_build.log'
+        cmd = "cd %s; %s %s %s %s. %s%s../ %s > %s 2>&1" % (currdir, self.compiler, self.exe_option, target, self.include_option, self.include_option, currdir, filename, log)
+        ##print cmd
+        status = subprocess.call(cmd, shell=True)
+        os.remove(log)
+        if status != 0 or not os.path.exists(target):
+            self.skipTest(msg)
+        os.remove(target)
+
+    def init(self, prefix):
+        #
+        self.prefix = self.__class__.__name__+'_'+prefix
+        self.py_out = currdir+self.prefix+'_py.out'
+        self.py_cpp = currdir+self.prefix+'_py.cpp'
+        self.px_pre = currdir+self.prefix+'_px.pre'
+        self.px_out = currdir+self.prefix+'_px.out'
+        self.build_log = currdir+self.prefix+'_build.log'
+        self.build_target = currdir+self.prefix+'px'+target_suffix
+
+    def check_root(self, prefix='', output=None):
+        self.init(prefix)
+        args = "--have-eh --abort-on-fail --root --error-printer"
+        cmd = "cd %s; %s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (currdir, sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out)
+        #print self.fog, "CMD", cmd
+        status = subprocess.call(cmd, shell=True)
+        self.assertEqual(status, 0, 'Error executing cxxtestgen')
+        #
+        files = [self.py_cpp]
+        for i in [1,2]:
+            args = "--have-eh --abort-on-fail --part Part%s.h" % str(i)
+            file = currdir+self.prefix+'_py%s.cpp' % str(i)
+            files.append(file)
+            cmd = "cd %s; %s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (currdir, sys.executable, currdir, self.fog, file, args, self.py_out)
+            ##print cmd
+            status = subprocess.call(cmd, shell=True)
+            self.assertEqual(status, 0, 'Error executing cxxtestgen')
+        #
+        cmd = "cd %s; %s %s %s %s. %s%s../ %s > %s 2>&1" % (currdir, self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, ' '.join(files), self.build_log)
+        ##print cmd
+        status = subprocess.call(cmd, shell=True)
+        for file in files:
+            if os.path.exists(file):
+                os.remove(file)
+        self.assertEqual(status, 0, 'Error executing command: '+cmd)
+        #
+        status = subprocess.call("cd %s; %s -v > %s 2>&1" % (currdir, self.build_target, self.px_pre), shell=True)
+        OUTPUT = open(self.px_pre,'a')
+        OUTPUT.write('Error level = '+str(status)+'\n')
+        OUTPUT.close()
+        diffstr = file_diff(self.px_pre, currdir+output)
+        if not diffstr == '':
+            self.fail("Unexpected differences in output:\n"+diffstr)
+        #
+        self.passed=True
+
+    def compile(self, prefix='', args=None, compile='', output=None, main=None, failGen=False, run=None, logfile=None, failBuild=False):
+        self.init(prefix)
+        #
+        cmd = "cd %s; %s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (currdir, sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out)
+        #print ("HERE "+cmd)
+        status = subprocess.call(cmd, shell=True)
+        if failGen:
+            if status == 0:
+                self.fail('Expected cxxtestgen to fail.')
+            else:
+                self.passed=True
+                return
+        self.assertEqual(status, 0, 'Error executing command: '+cmd)
+        #
+        if not main is None:
+            # Compile with main
+            cmd = "cd %s; %s %s %s %s. %s%s../ %s main.cpp %s > %s 2>&1" % (currdir, self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, compile, self.py_cpp, self.build_log)
+        else:
+            # Compile without main
+            cmd = "cd %s; %s %s %s %s. %s%s../ %s %s > %s 2>&1" % (currdir, self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, compile, self.py_cpp, self.build_log)
+        status = subprocess.call(cmd, shell=True)
+        if failBuild:
+            if status == 0:
+                self.fail('Expected compiler to fail.')
+            else:
+                self.passed=True
+                return
+        else:
+            self.assertEqual(status, 0, 'Error executing command: '+cmd)
+        #
+        if compile == '' and not output is None:
+            if run is None:
+                cmd = "cd %s; %s -v > %s 2>&1" % (currdir, self.build_target, self.px_pre)
+            else:
+                cmd = run % (self.build_target, self.px_pre)
+            status = subprocess.call(cmd, shell=True)
+            #print "HERE-status",status
+            OUTPUT = open(self.px_pre,'a')
+            OUTPUT.write('Error level = '+str(status)+'\n')
+            OUTPUT.close()
+            if logfile is None:
+                diffstr = file_diff(self.px_pre, currdir+output)
+            else:
+                diffstr = file_diff(currdir+logfile, currdir+output)
+            if not diffstr == '':
+                self.fail("Unexpected differences in output:\n"+diffstr)
+            if not logfile is None:
+                os.remove(currdir+logfile)
+        #
+        if compile == '' and output is None and os.path.exists(self.py_cpp):
+            self.fail("Output cpp file %s should not have been generated." % self.py_cpp)
+        #
+        self.passed=True
+
+    #
+    # Tests for cxxtestgen
+    #
+
+    def test_root_or_part(self):
+        """Root/Part"""
+        self.check_root(prefix='root_or_part', output="parts.out")
+
+    def test_root_plus_part(self):
+        """Root + Part"""
+        self.compile(prefix='root_plus_part', args="--error-printer --root --part "+samples, output="error.out")
+
+    def test_wildcard(self):
+        """Wildcard input"""
+        self.compile(prefix='wildcard', args='../sample/*.h', main=True, output="wildcard.out")
+
+    def test_stdio_printer(self):
+        """Stdio printer"""
+        self.compile(prefix='stdio_printer', args="--runner=StdioPrinter "+samples, output="error.out")
+
+    def test_paren_printer(self):
+        """Paren printer"""
+        self.compile(prefix='paren_printer', args="--runner=ParenPrinter "+samples, output="paren.out")
+
+    def test_yn_runner(self):
+        """Yes/No runner"""
+        self.compile(prefix='yn_runner', args="--runner=YesNoRunner "+samples, output="runner.out")
+
+    def test_no_static_init(self):
+        """No static init"""
+        self.compile(prefix='no_static_init', args="--error-printer --no-static-init "+samples, output="error.out")
+
+    def test_samples_file(self):
+        """Samples file"""
+        self.compile(prefix='samples_file', args="--error-printer --headers Samples.txt", output="error.out")
+
+    def test_have_std(self):
+        """Have Std"""
+        self.compile(prefix='have_std', args="--runner=StdioPrinter --have-std HaveStd.h", output="std.out")
+
+    def test_comments(self):
+        """Comments"""
+        self.compile(prefix='comments', args="--error-printer Comments.h", output="comments.out")
+
+    def test_longlong(self):
+        """Long long"""
+        self.check_if_supported('longlong.cpp', "Long long is not supported by this compiler")
+        self.compile(prefix='longlong', args="--error-printer --longlong='long long' LongLong.h", output="longlong.out")
+
+    def test_int64(self):
+        """Int64"""
+        self.check_if_supported('int64.cpp', "64-bit integers are not supported by this compiler")
+        self.compile(prefix='int64', args="--error-printer --longlong=__int64 Int64.h", output="int64.out")
+
+    def test_include(self):
+        """Include"""
+        self.compile(prefix='include', args="--include=VoidTraits.h --include=LongTraits.h --error-printer IncludeTest.h", output="include.out")
+
+    #
+    # Template file tests
+    #
+
+    def test_preamble(self):
+        """Preamble"""
+        self.compile(prefix='preamble', args="--template=preamble.tpl "+samples, output="preamble.out")
+
+    def test_activate_all(self):
+        """Activate all"""
+        self.compile(prefix='activate_all', args="--template=activate.tpl "+samples, output="error.out")
+
+    def test_only_suite(self):
+        """Only Suite"""
+        self.compile(prefix='only_suite', args="--template=%s../sample/only.tpl %s" % (currdir, samples), run="%s SimpleTest > %s 2>&1", output="suite.out")
+
+    def test_only_test(self):
+        """Only Test"""
+        self.compile(prefix='only_test', args="--template=%s../sample/only.tpl %s" % (currdir, samples), run="%s SimpleTest testAddition > %s 2>&1", output="suite_test.out")
+
+    def test_have_std_tpl(self):
+        """Have Std - Template"""
+        self.compile(prefix='have_std_tpl', args="--template=HaveStd.tpl HaveStd.h", output="std.out")
+
+    def test_exceptions_tpl(self):
+        """Exceptions - Template"""
+        self.compile(prefix='exceptions_tpl', args="--template=HaveEH.tpl "+self.ehNormals, output="eh_normals.out")
+
+    #
+    # Test cases which do not require exception handling
+    #
+
+    def test_no_errors(self):
+        """No errors"""
+        self.compile(prefix='no_errors', args="--error-printer GoodSuite.h", output="good.out")
+
+    def test_infinite_values(self):
+        """Infinite values"""
+        self.compile(prefix='infinite_values', args="--error-printer --have-std TestNonFinite.h", output="infinite.out")
+
+    def test_max_dump_size(self):
+        """Max dump size"""
+        self.compile(prefix='max_dump_size', args="--error-printer --include=MaxDump.h DynamicMax.h SameData.h", output='max.out')
+
+    def test_wide_char(self):
+        """Wide char"""
+        self.check_if_supported('wchar.cpp', "The file wchar.cpp is not supported.")
+        self.compile(prefix='wide_char', args="--error-printer WideCharTest.h", output="wchar.out")
+
+    #def test_factor(self):
+        #"""Factor"""
+        #self.compile(prefix='factor', args="--error-printer --factor Factor.h", output="factor.out")
+
+    def test_user_traits(self):
+        """User traits"""
+        self.compile(prefix='user_traits', args="--template=UserTraits.tpl UserTraits.h", output='user.out')
+
+    normals = " ".join(currdir+file for file in ["LessThanEquals.h","Relation.h","DefaultTraits.h","DoubleCall.h","SameData.h","SameFiles.h","Tsm.h","TraitsTest.h","MockTest.h","SameZero.h"])
+
+    def test_normal_behavior_xunit(self):
+        """Normal Behavior with XUnit Output"""
+        self.compile(prefix='normal_behavior_xunit', args="--xunit-printer "+self.normals, logfile='TEST-cxxtest.xml', output="normal.xml")
+
+    def test_normal_behavior(self):
+        """Normal Behavior"""
+        self.compile(prefix='normal_behavior', args="--error-printer "+self.normals, output="normal.out")
+
+    def test_normal_plus_abort(self):
+        """Normal + Abort"""
+        self.compile(prefix='normal_plus_abort', args="--error-printer --have-eh --abort-on-fail "+self.normals, output="abort.out")
+
+    def test_stl_traits(self):
+        """STL Traits"""
+        self.check_if_supported('stpltpl.cpp', "The file stpltpl.cpp is not supported.")
+        self.compile(prefix='stl_traits', args="--error-printer StlTraits.h", output="stl.out")
+
+    #
+    # Test cases which do require exception handling
+    #
+    def test_throw_wo_std(self):
+        """Throw w/o Std"""
+        self.compile(prefix='test_throw_wo_std', args="--template=ThrowNoStd.tpl ThrowNoStd.h", output='throw.out')
+
+    ehNormals = "Exceptions.h DynamicAbort.h"
+
+    def test_exceptions(self):
+        """Exceptions"""
+        self.compile(prefix='exceptions', args="--error-printer --have-eh "+self.ehNormals, output="eh_normals.out")
+
+    def test_exceptions_plus_abort(self):
+        """Exceptions plus abort"""
+        self.compile(prefix='exceptions', args="--error-printer --abort-on-fail --have-eh DynamicAbort.h DeepAbort.h ThrowsAssert.h", output="eh_plus_abort.out")
+
+    def test_default_abort(self):
+        """Default abort"""
+        self.compile(prefix='default_abort', args="--error-printer --include=DefaultAbort.h "+self.ehNormals+ " DeepAbort.h ThrowsAssert.h", output="default_abort.out")
+
+    def test_default_no_abort(self):
+        """Default no abort"""
+        self.compile(prefix='default_no_abort', args="--error-printer "+self.ehNormals+" DeepAbort.h ThrowsAssert.h", output="default_abort.out")
+
+    #
+    # Global Fixtures
+    #
+
+    def test_global_fixtures(self):
+        """Global fixtures"""
+        self.compile(prefix='global_fixtures', args="--error-printer GlobalFixtures.h WorldFixtures.h", output="gfxs.out")
+
+    def test_gf_suw_fails(self):
+        """GF:SUW fails"""
+        self.compile(prefix='gf_suw_fails', args="--error-printer SetUpWorldFails.h", output="suwf.out")
+
+    def test_gf_suw_error(self):
+        """GF:SUW error"""
+        self.compile(prefix='gf_suw_error', args="--error-printer SetUpWorldError.h", output="suwe.out")
+
+    def test_gf_suw_throws(self):
+        """GF:SUW throws"""
+        self.compile(prefix='gf_suw_throws', args="--error-printer SetUpWorldThrows.h", output="suwt.out")
+
+    def test_gf_su_fails(self):
+        """GF:SU fails"""
+        self.compile(prefix='gf_su_fails', args="--error-printer GfSetUpFails.h", output="gfsuf.out")
+
+    def test_gf_su_throws(self):
+        """GF:SU throws"""
+        self.compile(prefix='gf_su_throws', args="--error-printer GfSetUpThrows.h", output="gfsut.out")
+
+    def test_gf_td_fails(self):
+        """GF:TD fails"""
+        self.compile(prefix='gf_td_fails', args="--error-printer GfTearDownFails.h", output="gftdf.out")
+
+    def test_gf_td_throws(self):
+        """GF:TD throws"""
+        self.compile(prefix='gf_td_throws', args="--error-printer GfTearDownThrows.h", output="gftdt.out")
+
+    def test_gf_tdw_fails(self):
+        """GF:TDW fails"""
+        self.compile(prefix='gf_tdw_fails', args="--error-printer TearDownWorldFails.h", output="tdwf.out")
+
+    def test_gf_tdw_throws(self):
+        """GF:TDW throws"""
+        self.compile(prefix='gf_tdw_throws', args="--error-printer TearDownWorldThrows.h", output="tdwt.out")
+
+    #
+    # GUI
+    #
+
+    def test_gui(self):
+        """GUI"""
+        self.compile(prefix='gui', args='--gui=DummyGui %s' % guiInputs, output ="gui.out")
+
+    def test_gui_runner(self):
+        """GUI + runner"""
+        self.compile(prefix='gui_runner', args="--gui=DummyGui --runner=ParenPrinter %s" % guiInputs, output="gui_paren.out")
+
+    def test_qt_gui(self):
+        """QT GUI"""
+        self.compile(prefix='qt_gui', args="--gui=QtGui GoodSuite.h", compile=self.qtFlags)
+
+    def test_win32_gui(self):
+        """Win32 GUI"""
+        self.compile(prefix='win32_gui', args="--gui=Win32Gui GoodSuite.h", compile=self.w32Flags)
+
+    def test_win32_unicode(self):
+        """Win32 Unicode"""
+        self.compile(prefix='win32_unicode', args="--gui=Win32Gui GoodSuite.h", compile=self.w32Flags+' -DUNICODE')
+
+    def test_x11_gui(self):
+        """X11 GUI"""
+        self.check_if_supported('wchar.cpp', "Cannot compile wchar.cpp")
+        self.compile(prefix='x11_gui', args="--gui=X11Gui GoodSuite.h", compile=self.x11Flags)
+
+
+    #
+    # Tests for when the compiler doesn't support exceptions
+    #
+
+    def test_no_exceptions(self):
+        """No exceptions"""
+        if self.no_eh_option is None:
+            self.skipTest("This compiler does not have an exception handling option")
+        self.compile(prefix='no_exceptions', args='--runner=StdioPrinter NoEh.h', output="no_eh.out", compile=self.no_eh_option)
+
+    def test_force_no_eh(self):
+        """Force no EH"""
+        if self.no_eh_option is None:
+            self.skipTest("This compiler does not have an exception handling option")
+        self.compile(prefix="force_no_eh", args="--runner=StdioPrinter --no-eh ForceNoEh.h", output="no_eh.out", compile=self.no_eh_option)
+
+    #
+    # Invalid input to cxxtestgen
+    #
+
+    def test_no_tests(self):
+        """No tests"""
+        self.compile(prefix='no_tests', args='EmptySuite.h', failGen=True)
+
+    def test_missing_input(self):
+        """Missing input"""
+        self.compile(prefix='missing_input', args='--template=NoSuchFile.h', failGen=True)
+
+    def test_missing_template(self):
+        """Missing template"""
+        self.compile(prefix='missing_template', args='--template=NoSuchFile.h '+samples, failGen=True)
+
+    def test_inheritance(self):
+        """Test relying on inheritance"""
+        self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', output='inheritance_old.out')
+
+    #
+    # Tests that illustrate differences between the different C++ parsers
+    #
+
+    def test_inheritance(self):
+        """Test relying on inheritance"""
+        if self.fog == '':
+            self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', failGen=True)
+        else:
+            self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', output='inheritance.out')
+
+    def test_simple_inheritance(self):
+        """Test relying on simple inheritance"""
+        self.compile(prefix='simple_inheritance', args='--error-printer SimpleInheritedTest.h', output='simple_inheritance.out')
+
+    def test_simple_inheritance2(self):
+        """Test relying on simple inheritance (2)"""
+        if self.fog == '':
+            self.compile(prefix='simple_inheritance2', args='--error-printer SimpleInheritedTest2.h', failGen=True)
+        else:
+            self.compile(prefix='simple_inheritance2', args='--error-printer SimpleInheritedTest2.h', output='simple_inheritance2.out')
+
+    def test_comments2(self):
+        """Comments2"""
+        if self.fog == '':
+            self.compile(prefix='comments2', args="--error-printer Comments2.h", failBuild=True)
+        else:
+            self.compile(prefix='comments2', args="--error-printer Comments2.h", output='comments2.out')
+
+    def test_cpp_template1(self):
+        """C++ Templates"""
+        if self.fog == '':
+            self.compile(prefix='cpp_template1', args="--error-printer CppTemplateTest.h", failGen=True)
+        else:
+            self.compile(prefix='cpp_template1', args="--error-printer CppTemplateTest.h", output='template.out')
+
+    def test_bad1(self):
+        """BadTest1"""
+        if self.fog == '':
+            self.compile(prefix='bad1', args="--error-printer BadTest.h", failGen=True)
+        else:
+            self.compile(prefix='bad1', args="--error-printer BadTest.h", output='bad.out')
+
+
+class TestCpp(BaseTestCase, unittest.TestCase):
+
+    # Compiler specifics
+    exe_option = '-o'
+    include_option = '-I'
+    compiler='c++ -Wall -W -Werror -g'
+    no_eh_option = None
+    qtFlags='-Ifake'
+    x11Flags='-Ifake'
+    w32Flags='-Ifake'
+
+    def run(self, *args, **kwds):
+        if available('c++', '-o'):
+            return unittest.TestCase.run(self, *args, **kwds)
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+    def tearDown(self):
+        BaseTestCase.tearDown(self)
+
+
+class TestCppFOG(TestCpp):
+
+    fog='-f'
+
+    def run(self, *args, **kwds):
+        if ply_available:
+            return TestCpp.run(self, *args, **kwds)
+
+
+class TestGpp(BaseTestCase, unittest.TestCase):
+
+    # Compiler specifics
+    exe_option = '-o'
+    include_option = '-I'
+    compiler='g++ -g -ansi -pedantic -Wmissing-declarations -Werror -Wall -W -Wshadow -Woverloaded-virtual -Wnon-virtual-dtor -Wreorder -Wsign-promo %s' % os.environ.get('CXXTEST_GCOV_FLAGS','')
+    no_eh_option = '-fno-exceptions'
+    qtFlags='-Ifake'
+    x11Flags='-Ifake'
+    w32Flags='-Ifake'
+
+    def run(self, *args, **kwds):
+        if available('g++', '-o'):
+            return unittest.TestCase.run(self, *args, **kwds)
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+    def tearDown(self):
+        BaseTestCase.tearDown(self)
+
+
+class TestGppFOG(TestGpp):
+
+    fog='-f'
+
+    def run(self, *args, **kwds):
+        if ply_available:
+            return TestGpp.run(self, *args, **kwds)
+
+
+class TestClang(BaseTestCase, unittest.TestCase):
+
+    # Compiler specifics
+    exe_option = '-o'
+    include_option = '-I'
+    compiler='clang++ -v -g -Wall -W -Wshadow -Woverloaded-virtual -Wnon-virtual-dtor -Wreorder -Wsign-promo'
+    no_eh_option = '-fno-exceptions'
+    qtFlags='-Ifake'
+    x11Flags='-Ifake'
+    w32Flags='-Ifake'
+
+    def run(self, *args, **kwds):
+        if available('clang++', '-o'):
+            return unittest.TestCase.run(self, *args, **kwds)
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+    def tearDown(self):
+        BaseTestCase.tearDown(self)
+
+
+class TestClangFOG(TestClang):
+
+    fog='-f'
+
+    def run(self, *args, **kwds):
+        if ply_available:
+            return TestClang.run(self, *args, **kwds)
+
+
+class TestCL(BaseTestCase, unittest.TestCase):
+
+    # Compiler specifics
+    exe_option = '-o'
+    include_option = '-I'
+    compiler='cl -nologo -GX -W4 -WX'
+    no_eh_option = '-GX-'
+    qtFlags='-Ifake'
+    x11Flags='-Ifake'
+    w32Flags='-Ifake'
+
+    def run(self, *args, **kwds):
+        if available('cl', '-o'):
+            return unittest.TestCase.run(self, *args, **kwds)
+
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+    def tearDown(self):
+        BaseTestCase.tearDown(self)
+
+
+class TestCLFOG(TestCL):
+
+    fog='-f'
+
+    def run(self, *args, **kwds):
+        if ply_available:
+            return TestCL.run(self, *args, **kwds)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/cxxtest/test/test_doc.py b/tools/cxxtest/test/test_doc.py
new file mode 100644 (file)
index 0000000..c927c7b
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Import and execute the Python test driver for the user guide examples
+#
+
+# Imports
+try:
+    import pyutilib.th as unittest
+    pyutilib_available=True
+except:
+    pyutilib_available=False
+import os
+from os.path import dirname, abspath, abspath, basename
+import sys
+
+if pyutilib_available:
+    currdir = dirname(abspath(__file__))+os.sep
+    datadir = os.sep.join([dirname(dirname(abspath(__file__))),'doc','examples'])+os.sep
+
+    os.chdir(datadir)
+    sys.path.insert(0, datadir)
+
+    from test_examples import *
+
+# Execute the tests
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/cxxtest/test/throw.out b/tools/cxxtest/test/throw.out
new file mode 100644 (file)
index 0000000..41d8c73
--- /dev/null
@@ -0,0 +1,2 @@
+Running 1 test.OK!
+Error level = 0
diff --git a/tools/cxxtest/test/tpltpl.cpp b/tools/cxxtest/test/tpltpl.cpp
new file mode 100644 (file)
index 0000000..29ffd25
--- /dev/null
@@ -0,0 +1,10 @@
+#include <cxxtest/Flags.h>
+
+#ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+template<class T> class X {} x;
+template<class T, class U> class Pair {} p;
+template<class T, class U> class X< Pair<T, U> > {} xp;
+
+int main() { return 0; }
+#endif // !_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION
+
diff --git a/tools/cxxtest/test/unit/LinkedList_test.t.h b/tools/cxxtest/test/unit/LinkedList_test.t.h
new file mode 100644 (file)
index 0000000..995f317
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef LINKEDLIST_TEST_H
+#define LINKEDLIST_TEST_H
+
+#include <cxxtest/LinkedList.h>
+
+class TestLink : public CxxTest::Link
+{
+    public:
+    bool setUp() { return true; }
+    bool tearDown() { return true; }
+};
+
+#include <cxxtest/TestSuite.h>
+class LinkedList_test : public CxxTest::TestSuite
+{
+public:
+    void test_initialize()
+    {
+        CxxTest::List list;
+        list.initialize();
+        TS_ASSERT_EQUALS((CxxTest::Link*)0, list.head());
+        TS_ASSERT_EQUALS((CxxTest::Link*)0, list.tail());
+        TS_ASSERT_EQUALS(0, list.size());
+        TS_ASSERT(list.empty());
+    }
+
+    void test_attach()
+    {
+        CxxTest::List list;
+        TestLink link;
+
+        list.initialize();
+        link.attach(list);
+
+        TS_ASSERT_EQUALS(1, list.size());
+        TS_ASSERT_EQUALS((CxxTest::Link*)&link, list.head());
+        TS_ASSERT_EQUALS((CxxTest::Link*)&link, list.tail());
+    }
+
+    void test_detach()
+    {
+        CxxTest::List list;
+        TestLink link;
+
+        list.initialize();
+        link.attach(list);
+        link.detach(list);
+
+        TS_ASSERT_EQUALS((CxxTest::Link*)0, list.head());
+        TS_ASSERT_EQUALS((CxxTest::Link*)0, list.tail());
+        TS_ASSERT_EQUALS(0, list.size());
+        TS_ASSERT(list.empty());
+    }
+};
+
+
+#endif // __SIMPLETEST_H
diff --git a/tools/cxxtest/test/unit/SConstruct b/tools/cxxtest/test/unit/SConstruct
new file mode 100644 (file)
index 0000000..aaba221
--- /dev/null
@@ -0,0 +1,12 @@
+CxxTestBuilder_path = '../../build_tools/SCons/cxxtest.py'
+CxxTest_dir = '../..'
+
+# First a little python magic to pull in CxxTestBuilder
+import imp
+cxxtest = imp.load_source('cxxtest', CxxTestBuilder_path)
+env = Environment()
+cxxtest.generate(env, CXXTEST_INSTALL_DIR=CxxTest_dir)
+
+for test in env.Glob('*.t.h'):
+  env.CxxTest(test)
+
diff --git a/tools/cxxtest/test/user.out b/tools/cxxtest/test/user.out
new file mode 100644 (file)
index 0000000..f883261
--- /dev/null
@@ -0,0 +1,6 @@
+Running 1 test
+In TestUserTraits::testUserTraits:
+UserTraits.h:34: Error: Test failed: 0x7F
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/wchar.cpp b/tools/cxxtest/test/wchar.cpp
new file mode 100644 (file)
index 0000000..ef2b1db
--- /dev/null
@@ -0,0 +1,11 @@
+//
+// This program is used to check if the compiler supports basic_string<wchar_t>
+//
+#include <string>
+
+int main()
+{
+    std::basic_string<wchar_t> s(L"s");
+    return 0;
+}
+
diff --git a/tools/cxxtest/test/wchar.out b/tools/cxxtest/test/wchar.out
new file mode 100644 (file)
index 0000000..b82b812
--- /dev/null
@@ -0,0 +1,7 @@
+Running 1 test
+In WideCharTest::testWideStringTraits:
+WideCharTest.h:14: Error: Test failed: L"std::wstring is displayed with L\"\""
+WideCharTest.h:16: Error: Test failed: L"\x1234\x5678"
+Failed 1 of 1 test
+Success rate: 0%
+Error level = 1
diff --git a/tools/cxxtest/test/wildcard.out b/tools/cxxtest/test/wildcard.out
new file mode 100644 (file)
index 0000000..680c1b1
--- /dev/null
@@ -0,0 +1,4 @@
+Number of suites: 8
+Number of tests: 14
+Number of failed tests: 12
+Error level = 0
diff --git a/tools/rake_utils/buildconfig.rb b/tools/rake_utils/buildconfig.rb
new file mode 100644 (file)
index 0000000..6abfe57
--- /dev/null
@@ -0,0 +1,44 @@
+require "#{File.expand_path(File.dirname(__FILE__))}/plainconfig"
+require 'rake'
+require 'rake/clean'
+
+class BuildConfig < PlainConfig
+       def initialize(config)
+               super(config)
+
+               # Register output directories
+               register_directory("#{@settings[:output_dir]}/bin")
+               register_directory("#{@settings[:output_dir]}/obj")
+               register_directory("#{@settings[:output_dir]}/test")
+
+               # set output name
+               @settings[:bin_name] = "#{@settings[:output_dir]}/bin/#{@settings[:name]}#{get_bin_extension()}"
+               CLEAN.include(@settings[:bin_name])
+
+               # Create object file list
+               @settings[:object_source_lookup] = {}
+               @settings[:object_files] = []
+               @settings[:source_files].each{ |f|
+                       obj_file = @settings[:output_dir] + '/obj/' + File.basename(f).ext('o')
+                       CLEAN.include(obj_file)
+                       @settings[:object_files].push( obj_file )
+                       @settings[:object_source_lookup][obj_file] = f
+               }
+       end
+
+       def binary_name()
+               return @settings[:bin_name]
+       end
+       
+       def objects()
+               return @settings[:object_files]
+       end
+
+       def source_from_obj(obj)
+               return @settings[:object_source_lookup][obj]
+       end
+
+       def obj_src_lookup()
+               return lambda{|obj| @settings[:object_source_lookup][obj]}
+       end
+end
diff --git a/tools/rake_utils/plainconfig.rb b/tools/rake_utils/plainconfig.rb
new file mode 100644 (file)
index 0000000..aeebaaa
--- /dev/null
@@ -0,0 +1,96 @@
+require 'pp'
+
+class PlainConfig
+       def initialize(config)
+               @settings = defaults()
+               @settings.merge!(config)
+               
+               # Process Source paths
+               @settings[:source_files] = make_file_list( @settings[:source_files] )
+               
+               # Process Include paths
+               @settings[:include_dirs] = make_file_list( @settings[:include_dirs] )
+               @settings[:include_dirs] = make_option_list( '-I', @settings[:include_dirs] )
+
+               # Process compiler options
+               @settings[:compiler_options] = make_option_list('',@settings[:compiler_options])
+
+               # Process linker options
+               @settings[:linker_options] = make_option_list('',@settings[:linker_options])
+
+               # Process preprocessor defines
+               @settings[:preprocessor_defines] = make_option_list('-D',@settings[:preprocessor_defines])
+       end
+
+       def defaults()
+               return {
+                       :name => 'binary',
+                       :output_dir => 'build',
+
+                       :compiler_bin => 'c++',
+                       :compiler_options => ['-c'],
+                       :preprocessor_defines => [],
+                       
+                       :linker_bin => 'c++',
+                       :linker_options => [],
+       
+                       :source_files => [ 'source/*.c*' ],
+                       :include_dirs => [ 'source/**/' ],              
+                       :directories => []
+               }
+       end
+
+       def to_s
+               pp @settings
+       end
+       
+       def get_bin_extension()
+               if ENV['OS'] == 'Windows_NT' then 
+                       return '.exe'
+               else 
+                       return ''
+               end
+       end
+
+       def make_option_list(prefix,list)
+               if list != nil then
+                       return list.collect{|opt| "#{prefix}#{opt} "}
+               else
+                       return list
+               end
+       end
+       
+       def make_file_list(patt_list)
+               file_list = []
+               patt_list.each {|f|
+                       file_list.concat( FileList[f] )
+               }
+               return file_list
+       end
+
+       def register_directory(dir_name)
+               @settings[:directories].push(dir_name)
+               directory dir_name
+               CLOBBER.include(dir_name)
+       end
+
+       def directories()
+               return @settings[:directories]
+       end
+
+       def compile(input,output)
+               config = @settings
+               sh "#{config[:compiler_bin]} #{config[:compiler_options]} #{config[:preprocessor_defines]} #{config[:include_dirs]} -o #{output} #{input}"
+       end
+
+       def link(*args)
+               config = @settings
+               if args.size == 2 then
+                       file_list = args[0]
+                       output = args[1]
+                       sh "#{config[:linker_bin]} #{config[:linker_options]} -o #{output} #{file_list.collect{|x| x + ' '}}"
+               else
+                       sh "#{config[:linker_bin]} #{config[:linker_options]} -o #{config[:bin_name]} #{config[:object_files].collect{|x| x + ' '}}"
+               end
+       end
+end
diff --git a/tools/rake_utils/testconfig.rb b/tools/rake_utils/testconfig.rb
new file mode 100644 (file)
index 0000000..2806d37
--- /dev/null
@@ -0,0 +1,82 @@
+require "#{File.expand_path(File.dirname(__FILE__))}/plainconfig"
+require 'rake'
+require 'rake/clean'
+
+class TestConfig < PlainConfig
+       def initialize(config)
+               super(config)
+
+               # Register test output directory
+               register_directory("#{@settings[:output_dir]}/test")
+
+               # Process test paths
+               @settings[:test_files] = make_file_list( @settings[:test_files] )
+
+               # Create source to runner lookup table
+               @settings[:src_test_lookup] = {}
+               @settings[:test_files].each{ |test|
+                       out_dir = "#{@settings[:output_dir]}/test"
+                       runner = "#{out_dir}/#{File.basename(test).ext('')}_runner.cpp"
+                       @settings[:src_test_lookup][runner] = test
+                       @settings[:runners].push( runner.ext(get_bin_extension()) )
+               }
+       end
+
+       def defaults()
+               defs = super()
+               defs.merge!({
+                       :test_gen_bin => 'python tools/cxxtest/bin/cxxtestgen',
+                       :test_gen_options => ['--error-printer'],
+                       :output_dir => 'build',
+                       :test_files => ['tests/source/**.h'],
+                       :include_dirs => [ '.','tests/**/', 'source/**/', 'tools/cxxtest' ],
+                       :runners => []
+               })
+               return defs
+       end
+
+       def directories()
+               dir_list = [ "#{@settings[:output_dir]}/test" ]
+               directory dir_list[0]
+               CLOBBER.include(dir_list[0])
+               return dir_list
+       end
+
+       def runners()
+               return @settings[:runners]
+       end
+
+       def bin_obj_lookup()
+               return lambda{|bin| bin.ext('.o')}
+       end
+
+       def obj_src_lookup()
+               return lambda{|obj| obj.ext('.cpp')}
+       end
+
+       def src_test_lookup()
+               return lambda{|src| @settings[:src_test_lookup][src] }
+       end
+
+       def generate_test_runner(input,output)
+               sh "#{@settings[:test_gen_bin]} #{@settings[:test_gen_options]} -o #{output} #{input}" 
+       end
+
+       def run_all_test_runners()
+               succeeded = true
+               puts ''
+               puts '------------------'
+               puts '    Unit Tests'
+               puts '------------------'
+               puts ''
+               @settings[:runners].each{|runner|
+                       status = system(runner)
+                       succeeded = (succeeded and status)
+                       puts ''
+               }
+               if not succeeded then 
+                       abort('Error: There are unit test failures')
+               end
+       end
+end
+