diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index aa9bb1d8..80bfa6f7 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -23,7 +23,8 @@ set(XLNT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) set(XLNT_INCLUDE_DIR ${XLNT_ROOT_DIR}/include) set(XLNT_SOURCE_DIR ${XLNT_ROOT_DIR}/source) set(THIRD_PARTY_DIR ${XLNT_ROOT_DIR}/third-party) -add_subdirectory(${THIRD_PARTY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/third-party) + +add_subdirectory(${THIRD_PARTY_DIR}/libstudxml ${CMAKE_CURRENT_BINARY_DIR}/third-party/libstudxml) if(COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") @@ -127,12 +128,10 @@ else() endif() endif() -add_dependencies(xlnt xlnt.third-party) - target_link_libraries(xlnt PRIVATE libstudxml) target_include_directories(xlnt PUBLIC ${XLNT_INCLUDE_DIR}) target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}) -target_link_libraries(xlnt PRIVATE ${ZLIB_LIBRARIRES}) +target_link_libraries(xlnt PRIVATE ${ZLIB_LIBRARIES}) target_include_directories(xlnt PRIVATE ${ZLIB_INCLUDE_DIR}) target_link_libraries(xlnt PRIVATE ${CRYPTOPP_LIBRARIES}) target_include_directories(xlnt PRIVATE ${CRYPTOPP_INCLUDE_DIR}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c5ded567..5b0d34eb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,10 @@ if(COVERAGE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov --coverage") endif() +set(CXXTEST_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../third-party/cxxtest) +set(CXXTEST_INCLUDE_DIR ${CXXTEST_ROOT_DIR}) +set(CXXTEST_PYTHON_TESTGEN_EXECUTABLE ${CXXTEST_ROOT_DIR}/bin/cxxtestgen) + add_executable(xlnt.test ${TEST_HELPERS} ${TESTS} ${RUNNER}) target_link_libraries(xlnt.test PRIVATE xlnt @@ -76,7 +80,6 @@ else() endif() find_package(PythonInterp REQUIRED) -set(CXXTEST_PYTHON_TESTGEN_EXECUTABLE ${CMAKE_BINARY_DIR}/source/third-party/cxxtest/cxxtest-download-prefix/src/cxxtest-download/bin/cxxtestgen) add_custom_command(OUTPUT ${RUNNER} COMMAND ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE} --runner=ErrorPrinter -o ${RUNNER} ${TESTS} diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt deleted file mode 100644 index 464c7362..00000000 --- a/third-party/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -cmake_minimum_required(VERSION 3.2) -project(xlnt.third-party) - -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libstudxml) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cxxtest) - -add_custom_target(xlnt.third-party - DEPENDS libstudxml cxxtest-download) diff --git a/third-party/cxxtest/CMakeLists.txt b/third-party/cxxtest/CMakeLists.txt index 6f50bdf1..71102442 100644 --- a/third-party/cxxtest/CMakeLists.txt +++ b/third-party/cxxtest/CMakeLists.txt @@ -3,13 +3,3 @@ project(cxxtest) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) - -include(ExternalProject) -ExternalProject_Add(cxxtest-download - GIT_REPOSITORY https://github.com/CxxTest/cxxtest - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "") - -set(CXXTEST_ROOT_DIR ${CMAKE_CURRENT_BINARY_DIR}/cxxtest-download-prefix/src/cxxtest-download) -set(CXXTEST_INCLUDE_DIR ${CXXTEST_ROOT_DIR}) diff --git a/third-party/cxxtest/COPYING b/third-party/cxxtest/COPYING new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/third-party/cxxtest/COPYING @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU 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 as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/third-party/cxxtest/README b/third-party/cxxtest/README new file mode 100644 index 00000000..87aea1bf --- /dev/null +++ b/third-party/cxxtest/README @@ -0,0 +1,44 @@ +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 can be downloaded from http://cxxtest.com. + + +A Simple Example +---------------- + +1. Create a test suite header file: + +MyTestSuite.h: + + #include + + 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 tests.cpp + # ./main + Running cxxtest tests (1 test).OK! + diff --git a/third-party/cxxtest/Versions b/third-party/cxxtest/Versions new file mode 100644 index 00000000..89fe0761 --- /dev/null +++ b/third-party/cxxtest/Versions @@ -0,0 +1,192 @@ + +CxxTest Releases +---------------- + +* Version 4.4 (2014-06-03) + - Fixed compilation error on Windows (MSVC) in XmlFormatter.h (#86) + - Fix to ensure that tearDown() is called (#89) + - Add option run test with a user defined command in scons (#91) + - Use a Python path relative to the cxxtestgen script (#88) + - Add defensive guard in ErrorFormatter.h (#96) + - Fixed bug with "None" appearing in CXXTEST_CPPATH (#99) + - Added CXXTEST_LIBPATH to properly use shared libraries (#100) + - Added guards when XmlFormatter.h data is not initialize (#87) + +* Version 4.3 (2013-07-05) + - Changes to assess code coverage of the cxxtestgen command + - Standardizing C++ file formats (using astyle) + - Bug fixes that led to the test runner hanging + - Adding special assertions for floating point values + - Added date to XML output + - Added support for comparison of C strings + +* Version 4.2.1 (2013-03-22) + - Fixing documentation of LGPL version + +* Version 4.2 (2013-03-16) + - Changes to support test fixtures in namespaces + - Adding logic to support test skipping + - Change to create self-contained HTML documentation + - Fixed inheritance issue in GlobalFixture (#69) + - Update LGPL version + - Changes to try/catch to avoid ambiguities withn catching std::exception (#53) + - Fixed TS_ASSERT_DELTA to work on integer types (#65) + - Changed output format to print world-name (#70) + +* Version 4.1 (2012-11-30) + - Added absolute paths to resolve bug when relative path links are provided. + - Bug fix when files contain unicode characters + - Fix for --no-static-init: Changed how non-static tests are created + - Updated user guide to include SCons build system + - Closing out Tigris and SourceForge tickets + - Added valgrind tests. + +* 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. + - The <> and <> macros have the same behavior now. + - CxxTest runners now have a command-line interface that facilitates interactive 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/third-party/cxxtest/admin/announcement b/third-party/cxxtest/admin/announcement new file mode 100644 index 00000000..65b4d039 --- /dev/null +++ b/third-party/cxxtest/admin/announcement @@ -0,0 +1,19 @@ +We are pleased to announce the updated release of CxxTest 4.4. 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. + +This release includes a variety of bug fixes: + + - Fixed compilation error on Windows (MSVC) in XmlFormatter.h (#86) + - Fix to ensure that tearDown() is called (#89) + - Add option run test with a user defined command in scons (#91) + - Use a Python path relative to the cxxtestgen script (#88) + - Add defensive guard in ErrorFormatter.h (#96) + - Fixed bug with "None" appearing in CXXTEST_CPPATH (#99) + - Added CXXTEST_LIBPATH to properly use shared libraries (#100) + - Added guards when XmlFormatter.h data is not initialize (#87) + +See the CxxTest Home Page (http://cxxtest.com) for documentation and download instructions. + +Enjoy! + + CxxTest Developer Team + cxxtest-developers@googlegroups.com diff --git a/third-party/cxxtest/admin/cloudbees_cxxtest b/third-party/cxxtest/admin/cloudbees_cxxtest new file mode 100644 index 00000000..49a21499 --- /dev/null +++ b/third-party/cxxtest/admin/cloudbees_cxxtest @@ -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 --verbosity=2 --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/third-party/cxxtest/admin/cxxtest.spec b/third-party/cxxtest/admin/cxxtest.spec new file mode 100644 index 00000000..b25f135a --- /dev/null +++ b/third-party/cxxtest/admin/cxxtest.spec @@ -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/third-party/cxxtest/admin/jenkins_cxxtest b/third-party/cxxtest/admin/jenkins_cxxtest new file mode 100755 index 00000000..552924cf --- /dev/null +++ b/third-party/cxxtest/admin/jenkins_cxxtest @@ -0,0 +1,85 @@ +#!/bin/bash + +if test -z "$WORKSPACE"; then + echo "ERROR: \$WORKSPACE not defined" + exit 1 +fi +export PATH="$WORKSPACE/vpython/bin:$PATH" + +if test -n "$1"; then + PYTHON="$1" +else + PYTHON=python +fi + +echo +echo "Building on `hostname`:" +echo +echo " Workspace: ${WORKSPACE}" +echo +echo " Package: ${PACKAGE}" +echo +echo " Environment:" +/usr/bin/env 2>&1 | sort | sed 's/^/ /' +echo +echo " Python:" +${PYTHON} -c 'import sys; sys.stdout.write(sys.version+"\n")' 2>&1 \ + | sed 's/^/ /' +PYTHON_VER=`${PYTHON} -c 'import sys; sys.stdout.write(str(sys.version_info[0]))'` +echo +# The following executables are required (missing app yields build failure) +for app in gcc; do +which $app || exit 1 +echo " $app:" +$app --version 2>&1 | grep -v '^$' | sed 's/^/ /' || exit 1 +echo +done + + +# Setup virtual Python environment +\rm -Rf vpython +tmp=2.6 +if [ "yes" = "$(echo | awk "($PYTHON_VER < $tmp) { print \"yes\"; }")" ]; then + "$PYTHON" "$WORKSPACE"/cxxtest/admin/virtualenv_1.7.py "$WORKSPACE"/vpython || exit 1 +else + "$PYTHON" "$WORKSPACE"/cxxtest/admin/virtualenv.py "$WORKSPACE"/vpython || exit 1 +fi +vpython/bin/easy_install nose +if test "$PYTHON_VER" -gt 2; then + vpython/bin/easy_install unittest2py3k + #vpython/bin/pip install unittest2py3k +else + vpython/bin/easy_install unittest2 +fi +vpython/bin/easy_install ply +vpython/bin/easy_install ordereddict +vpython/bin/easy_install gcovr +vpython/bin/easy_install coverage +vpython/bin/easy_install pyutilib.th +cd "$WORKSPACE"/cxxtest/python +"$WORKSPACE"/vpython/bin/python setup.py develop + +# Cleanup test directories +cd "$WORKSPACE"/cxxtest/test +make clean +cd "$WORKSPACE"/cxxtest/doc +make clean +cd "$WORKSPACE" + +# Run tests +export CXXTEST_GCOV_FLAGS='-fprofile-arcs -ftest-coverage' +vpython/bin/nosetests --verbosity=2 -w "$WORKSPACE"/cxxtest \ + --with-coverage --with-xunit --xunit-file="$WORKSPACE"/TEST-cxxtest.xml \ + || echo "(INFO) nosetests returned non-zero return code" + +# Generate Python code coverage +vpython/bin/coverage xml --omit="$WORKSPACE/vpython/lib/*,$WORKSPACE/cxxtest/test/*,$WORKSPACE/cxxtest/doc/examples/*" -o $WORKSPACE/cxxtest/test/coverage.xml + +# Generate C++ code coverage +cd "$WORKSPACE"/cxxtest +"$WORKSPACE"/vpython/bin/gcovr -v -d -r "$WORKSPACE"/cxxtest \ + -x -o "$WORKSPACE"/cxxtest/coverage.xml \ + --gcov-filter '.*#test#(\.\.|\^)#cxxtest#.*gcov' + +echo "DONE" + diff --git a/third-party/cxxtest/admin/virtualenv.py b/third-party/cxxtest/admin/virtualenv.py new file mode 100755 index 00000000..ccb6eec9 --- /dev/null +++ b/third-party/cxxtest/admin/virtualenv.py @@ -0,0 +1,2581 @@ +#!/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. +__version__ = "1.9.1" # following best practices +virtualenv_version = __version__ # legacy, again + +import base64 +import sys +import os +import codecs +import optparse +import re +import shutil +import logging +import tempfile +import zlib +import errno +import glob +import distutils.sysconfig +from distutils.util import strtobool +import struct +import subprocess + +if sys.version_info < (2, 5): + print('ERROR: %s' % sys.exc_info()[1]) + print('ERROR: this script requires Python 2.5 or greater.') + sys.exit(101) + +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') +is_cygwin = (sys.platform == 'cygwin') +is_darwin = (sys.platform == 'darwin') +abiflags = getattr(sys, 'abiflags', '') + +user_dir = os.path.expanduser('~') +if is_win: + 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', 'tokenize', 'token', + 'functools', 'heapq', 'bisect', 'weakref', + 'reprlib']) + if minver >= 2: + REQUIRED_FILES[-1] = 'config-%s' % majver + if minver == 3: + import sysconfig + platdir = sysconfig.get_config_var('PLATDIR') + REQUIRED_FILES.append(platdir) + # 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", + "imp", + "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.ERROR, 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') and not is_win: + 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.encode("utf-8"): + 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 reversed(dirs): + files = glob.glob(os.path.join(dir, filename)) + if files and os.path.isfile(files[0]): + return True, files[0] + return False, 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: + egg_path = 'setuptools-*-py%s.egg' % sys.version[:3] + found, egg_path = _find_file(egg_path, search_dirs) + project_name = 'setuptools' + bootstrap_script = EZ_SETUP_PY + tgz_path = None + else: + # Look for a distribute egg (these are not distributed by default, + # but can be made available by the user) + egg_path = 'distribute-*-py%s.egg' % sys.version[:3] + found, egg_path = _find_file(egg_path, search_dirs) + project_name = 'distribute' + if found: + tgz_path = None + bootstrap_script = DISTRIBUTE_FROM_EGG_PY + else: + # Fall back to sdist + # NB: egg_path is not None iff tgz_path is None + # iff bootstrap_script is a generic setup script accepting + # the standard arguments. + egg_path = None + tgz_path = 'distribute-*.tar.gz' + found, tgz_path = _find_file(tgz_path, search_dirs) + bootstrap_script = DISTRIBUTE_SETUP_PY + + 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 and egg_path: + cmd.append('--always-unzip') + env = {} + remove_from_env = ['__PYVENV_LAUNCHER__'] + if logger.stdout_level_matches(logger.DEBUG) and egg_path: + cmd.append('-v') + + old_chdir = os.getcwd() + if egg_path is not None and os.path.exists(egg_path): + logger.info('Using existing %s egg: %s' % (project_name, egg_path)) + cmd.append(egg_path) + if os.environ.get('PYTHONPATH'): + env['PYTHONPATH'] = egg_path + os.path.pathsep + os.environ['PYTHONPATH'] + else: + env['PYTHONPATH'] = egg_path + elif tgz_path is not None and os.path.exists(tgz_path): + # Found a tgz source dist, let's chdir + logger.info('Using existing %s egg: %s' % (project_name, tgz_path)) + os.chdir(os.path.dirname(tgz_path)) + # 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') + elif 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, + egg_path or tgz_path, + search_dirs)) + sys.exit(1) + elif egg_path: + logger.info('No %s egg found; downloading' % project_name) + cmd.extend(['--always-copy', '-U', project_name]) + else: + logger.info('No %s tgz found; downloading' % 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 tgz_path is not None and os.path.exists(tgz_path): + # the current working dir is hostile, let's copy the + # tarball to a temp dir + target = os.path.join(cwd, os.path.split(tgz_path)[-1]) + shutil.copy(tgz_path, 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 cwd is not None: + shutil.rmtree(cwd) + 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 is_win: + easy_install_script = 'easy_install-script.py' + # There's two subtle issues here when invoking easy_install. + # 1. On unix-like systems the easy_install script can *only* be executed + # directly if its full filesystem path is no longer than 78 characters. + # 2. A work around to [1] is to use the `python path/to/easy_install foo` + # pattern, but that breaks if the path contains non-ASCII characters, as + # you can't put the file encoding declaration before the shebang line. + # The solution is to use Python's -x flag to skip the first line of the + # script (and any ASCII decoding errors that may have occurred in that line) + cmd = [py_executable, '-x', join(os.path.dirname(py_executable), easy_install_script), filename] + # jython and pypy don't yet support -x + if is_jython or is_pypy: + cmd.remove('-x') + 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 == 'store_false': + val = not strtobool(val) + elif option.action in ('store_true', '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.set_defaults(system_site_packages=False) + parser.add_option( + '--no-site-packages', + dest='system_site_packages', + action='store_false', + help="Don't give access to the global site-packages dir to the " + "virtual environment (default)") + + 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', '--use-distribute', # the second option is for legacy reasons here. Hi Kenneth! + dest='use_distribute', + action='store_true', + help='Use Distribute instead of Setuptools. Set environ variable ' + 'VIRTUALENV_DISTRIBUTE to make it the default ') + + parser.add_option( + '--no-setuptools', + dest='no_setuptools', + action='store_true', + help='Do not install distribute/setuptools (or pip) ' + 'in the new virtualenv.') + + parser.add_option( + '--no-pip', + dest='no_pip', + action='store_true', + help='Do not install pip in the new virtualenv.') + + parser.add_option( + '--setuptools', + dest='use_distribute', + action='store_false', + help='Use Setuptools instead of Distribute. Set environ variable ' + 'VIRTUALENV_SETUPTOOLS to make it the default ') + + # Set this to True to use distribute by default, even in Python 2. + parser.set_defaults(use_distribute=False) + + 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 --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 + + 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, + no_setuptools=options.no_setuptools, + no_pip=options.no_pip) + 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, + no_setuptools=False, no_pip=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) + + if not no_setuptools: + if 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) + + if not no_pip: + install_pip(py_executable, search_dirs=search_dirs, never_download=never_download) + + install_activate(home_dir, bin_dir, prompt) + +def is_executable_file(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +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 is_win: + # 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: + import ctypes + GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW + size = max(len(home_dir)+1, 256) + buf = ctypes.create_unicode_buffer(size) + try: + u = unicode + except NameError: + u = str + ret = GetShortPathName(u(home_dir), buf, size) + if not ret: + print('Error: the path "%s" has a space in it' % home_dir) + print('We could not determine the short pathname for it.') + print('Exiting.') + sys.exit(3) + home_dir = str(buf.value) + lib_dir = join(home_dir, 'Lib') + inc_dir = join(home_dir, 'Include') + bin_dir = join(home_dir, 'Scripts') + if 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') + elif not is_win: + lib_dir = join(home_dir, 'lib', py_version) + multiarch_exec = '/usr/bin/multiarch-platform' + if is_executable_file(multiarch_exec): + # In Mageia (2) and Mandriva distros the include dir must be like: + # virtualenv/include/multiarch-x86_64-linux/python2.7 + # instead of being virtualenv/include/python2.7 + p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + # stdout.strip is needed to remove newline character + inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags) + else: + 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 is_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"), + # Python 2.6 no-frameworks + os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"), + # System Python 2.7 on OSX Mountain Lion + os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"))) + + if hasattr(sys, 'real_prefix'): + prefixes.append(sys.real_prefix) + if hasattr(sys, 'base_prefix'): + prefixes.append(sys.base_prefix) + prefixes = list(map(os.path.expanduser, prefixes)) + prefixes = list(map(os.path.abspath, prefixes)) + # Check longer prefixes first so we don't split in the middle of a filename + prefixes = sorted(prefixes, key=len, reverse=True) + filename = os.path.abspath(filename) + for src_prefix in prefixes: + if filename.startswith(src_prefix): + _, relpath = filename.split(src_prefix, 1) + if src_prefix != os.sep: # sys.prefix == "/" + 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 + # If we are running under -p, we need to remove the current + # directory from sys.path temporarily here, so that we + # definitely get the modules from the site directory of + # the interpreter we are running under, not the one + # virtualenv.py is installed under (which might lead to py2/py3 + # incompatibility issues) + _prev_sys_path = sys.path + if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): + sys.path = sys.path[1:] + try: + 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() + # special-case custom readline.so on OS X, but not for pypy: + if modname == 'readline' and sys.platform == 'darwin' and not ( + is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))): + dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so') + else: + 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]) + finally: + sys.path = _prev_sys_path + + +def subst_path(prefix_path, prefix, home_dir): + prefix_path = os.path.normpath(prefix_path) + prefix = os.path.normpath(prefix) + home_dir = os.path.normpath(home_dir) + if not prefix_path.startswith(prefix): + logger.warn('Path not in prefix %r %r', prefix_path, prefix) + return + return prefix_path.replace(prefix, home_dir, 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 + elif hasattr(sys, 'base_prefix'): + logger.notify('Using base prefix %r' % sys.base_prefix) + prefix = sys.base_prefix + else: + prefix = sys.prefix + mkdir(lib_dir) + fix_lib64(lib_dir) + stdlib_dirs = [os.path.dirname(os.__file__)] + if is_win: + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) + elif is_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, '') + + 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) + + platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1) + if platinc_dir != stdinc_dir: + platinc_dest = distutils.sysconfig.get_python_inc( + plat_specific=1, prefix=home_dir) + if platinc_dir == platinc_dest: + # Do platinc_dest manually due to a CPython bug; + # not http://bugs.python.org/issue3386 but a close cousin + platinc_dest = subst_path(platinc_dir, prefix, home_dir) + if platinc_dest: + # PyPy's stdinc_dir and prefix are relative to the original binary + # (traversing virtualenvs), whereas the platinc_dir is relative to + # the inner virtualenv and ignores the prefix argument. + # This seems more evolved than designed. + copyfile(platinc_dir, platinc_dest) + + # pypy never uses exec_prefix, just ignore it + if sys.exec_prefix != prefix and not is_pypy: + if is_win: + 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: + # OS X framework builds cause validation to break + # https://github.com/pypa/virtualenv/issues/322 + if os.environ.get('__PYVENV_LAUNCHER__'): + os.unsetenv('__PYVENV_LAUNCHER__') + 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) + pcbuild_dir = os.path.dirname(sys.executable) + pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth') + if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')): + logger.notify('Detected python running from build directory %s', pcbuild_dir) + logger.notify('Writing .pth file linking to build directory for *.pyd files') + writefile(pyd_pth, pcbuild_dir) + else: + pcbuild_dir = None + if os.path.exists(pyd_pth): + logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth) + os.unlink(pyd_pth) + + if sys.executable != py_executable: + ## FIXME: could I just hard link? + executable = sys.executable + shutil.copyfile(executable, py_executable) + make_exe(py_executable) + if is_win or is_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')) + python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe') + python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe') + if os.path.exists(python_d): + logger.info('Also created python_d.exe') + shutil.copyfile(python_d, python_d_dest) + elif os.path.exists(python_d_dest): + logger.info('Removed python_d.exe as it is no longer at the source') + os.unlink(python_d_dest) + # we need to copy the DLL to enforce that windows will load the correct one. + # may not exist if we are cygwin. + py_executable_dll = 'python%s%s.dll' % ( + sys.version_info[0], sys.version_info[1]) + py_executable_dll_d = 'python%s%s_d.dll' % ( + sys.version_info[0], sys.version_info[1]) + pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) + pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) + pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) + if os.path.exists(pythondll): + logger.info('Also created %s' % py_executable_dll) + shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) + if os.path.exists(pythondll_d): + logger.info('Also created %s' % py_executable_dll_d) + shutil.copyfile(pythondll_d, pythondll_d_dest) + elif os.path.exists(pythondll_d_dest): + logger.info('Removed %s as the source does not exist' % pythondll_d_dest) + os.unlink(pythondll_d_dest) + if is_pypy: + # make a symlink python --> pypy-c + python_executable = os.path.join(os.path.dirname(py_executable), 'python') + if sys.platform in ('win32', 'cygwin'): + python_executable += '.exe' + logger.info('Also created executable %s' % python_executable) + copyfile(py_executable, python_executable) + + if is_win: + for name in 'libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', 'libeay32.dll', 'ssleay32.dll', 'sqlite.dll': + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(bin_dir, name)) + + 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 '.framework' in prefix: + 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') + if 'EPD' in prefix: + logger.debug('EPD framework detected') + original_python = os.path.join(prefix, 'bin/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: + mach_o_change(py_executable, + os.path.join(prefix, 'Python'), + '@executable_path/../.Python') + except: + e = sys.exc_info()[1] + logger.warn("Could not call mach_o_change: %s. " + "Trying to call install_name_tool instead." % e) + 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 + + if not is_win: + # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist + py_exe_version_major = 'python%s' % sys.version_info[0] + py_exe_version_major_minor = 'python%s.%s' % ( + sys.version_info[0], sys.version_info[1]) + py_exe_no_version = 'python' + required_symlinks = [ py_exe_no_version, py_exe_version_major, + py_exe_version_major_minor ] + + py_executable_base = os.path.basename(py_executable) + + if py_executable_base in required_symlinks: + # Don't try to symlink to yourself. + required_symlinks.remove(py_executable_base) + + for pth in required_symlinks: + full_pth = join(bin_dir, pth) + if os.path.exists(full_pth): + os.unlink(full_pth) + os.symlink(py_executable_base, full_pth) + + if is_win 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 + # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks + cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' + 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] + 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 is_win: + logger.fatal( + 'Note: some Windows users have reported this error when they ' + 'installed Python for "Only this user" or have multiple ' + 'versions of Python installed. Copying the appropriate ' + 'PythonXX.dll to the virtualenv Scripts/ directory may fix ' + 'this problem.') + 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 + + fix_local_scheme(home_dir) + + if site_packages: + if os.path.exists(site_packages_filename): + logger.info('Deleting %s' % site_packages_filename) + os.unlink(site_packages_filename) + + return py_executable + + +def install_activate(home_dir, bin_dir, prompt=None): + home_dir = os.path.abspath(home_dir) + if is_win or is_jython and os._name == 'nt': + files = { + 'activate.bat': ACTIVATE_BAT, + 'deactivate.bat': DEACTIVATE_BAT, + 'activate.ps1': ACTIVATE_PS, + } + + # MSYS needs paths of the form /c/path/to/file + drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) + home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) + + # Run-time conditional enables (basic) Cygwin compatibility + home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % + (home_dir, home_dir_msys)) + files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_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 + 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.mkdir(local_path) + for subdir_name in os.listdir(home_dir): + if subdir_name == 'local': + continue + os.symlink(os.path.abspath(os.path.join(home_dir, subdir_name)), \ + os.path.join(local_path, subdir_name)) + +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) + top_level = os.path.dirname(lib_parent) + lib_dir = os.path.join(top_level, 'lib') + lib64_link = os.path.join(top_level, 'lib64') + assert os.path.basename(lib_parent) == 'lib', ( + "Unexpected parent dir: %r" % lib_parent) + if os.path.lexists(lib64_link): + return + os.symlink('lib', lib64_link) + +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] + if is_win: + 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') + try: + try: + lines = f.read().decode('utf-8').splitlines() + except UnicodeDecodeError: + # This is probably a binary program instead + # of a script, so just ignore it. + continue + finally: + 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) + script = relative_script([new_shebang] + lines[1:]) + f = open(filename, 'wb') + f.write('\n'.join(script).encode('utf-8')) + f.close() + +def relative_script(lines): + "Return a script that'll work in a relocatable environment." + activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this" + # Find the last future statement in the script. If we insert the activation + # line before a future statement, Python will raise a SyntaxError. + activate_at = None + for idx, line in reversed(list(enumerate(lines))): + if line.split()[:3] == ['from', '__future__', 'import']: + activate_at = idx + 1 + break + if activate_at is None: + # Activate after the shebang. + activate_at = 1 + return lines[:activate_at] + ['', activate, ''] + lines[activate_at:] + +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.readline().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.5'`` then the + script will start with ``#!/usr/bin/env python2.5`` 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 = codecs.open(filename, 'r', encoding='utf-8') + 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(""" +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 +""") + +##file ez_setup.py +EZ_SETUP_PY = convert(""" +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 +qL7+C1AkCcw= +""") + +##file distribute_from_egg.py +DISTRIBUTE_FROM_EGG_PY = convert(""" +eJw9j8tqAzEMRfcG/4MgmxQyptkGusonZBmGoGTUGYFfWPKE6dfXTkM3gqt7rh47OKP3NMF3SQFW +LlrRU1zhybpAxoKBlIqcrNnBdRjQP3GTocYfzmNrrCPQPN9iwzpxSQfQhWBi0cL3qtRtYIG/4Mv0 +KApY5hooqrOGQ05FQTaxptF9Fnx16Rq0XofjaE1XGXVxHIWK7j8P8EY/rHndLqQ1a0pe3COFgHFy +hLLdWkDbi/DeEpCjNb3u/zccT2Ob8gtnwVyI +""") + +##file distribute_setup.py +DISTRIBUTE_SETUP_PY = convert(""" +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 +""") + +##file activate.sh +ACTIVATE_SH = convert(""" +eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+ +nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI +BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D +M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m +k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU +abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws +MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD +BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7 +2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ +4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN +l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz +N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS +Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1 +D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG ++n8O9H8f5vsGOWXsL1+1k3g= +""") + +##file activate.fish +ACTIVATE_FISH = convert(""" +eJyVVWFv2jAQ/c6vuBoqQVWC9nVSNVGVCaS2VC2rNLWVZZILWAs2s52wVvvxsyEJDrjbmgpK7PP5 +3bt3d22YLbmGlGcIq1wbmCPkGhPYcLMEEsGciwGLDS+YwSjlekngLFVyBe73GXSXxqw/DwbuTS8x +yyKpFr1WG15lDjETQhpQuQBuIOEKY5O9tlppLqxHKSDByjVAPwEy+mXtCq5MzjIUBTCRgEKTKwFG +gpBqxTLYXgN2myspVigMaYF92tZSowGZJf4mFExxNs9Qb614CgZtmH0BpEOn11f0cXI/+za8pnfD +2ZjA1sg9zlV/8QvcMhxbNu0QwgYokn/d+n02nt6Opzcjcnx1vXcIoN74O4ymWQXmHURfJw9jenc/ +vbmb0enj6P5+cuVhqlKm3S0u2XRtRbA2QQAhV7VhBF0rsgUX9Ur1rBUXJgVSy8O751k8mzY5OrKH +RW3eaQhYGTr8hrXO59ALhxQ83mCsDLAid3T72CCSdJhaFE+fXgicXAARUiR2WeVO37gH3oYHzFKo +9k7CaPZ1UeNwH1tWuXA4uFKYYcEa8vaKqXl7q1UpygMPhFLvlVKyNzsSM3S2km7UBOl4xweUXk5u +6e3wZmQ9leY1XE/Ili670tr9g/5POBBpGIJXCCF79L1siarl/dbESa8mD8PL61GpzqpzuMS7tqeB +1YkALrRBloBMbR9yLcVx7frQAgUqR7NZIuzkEu110gbNit1enNs82Rx5utq7Z3prU78HFRgulqNC +OTwbqJa9vkJFclQgZSjbKeBgSsUtCtt9D8OwAbIVJuewQdfvQRaoFE9wd1TmCuRG7OgJ1bVXGHc7 +z5WDL/WW36v2oi37CyVBak61+yPBA9C1qqGxzKQqZ0oPuocU9hpud0PIp8sDHkXR1HKkNlzjuUWA +a0enFUyzOWZA4yXGP+ZMI3Tdt2OuqU/SO4q64526cPE0A7ZyW2PMbWZiZ5HamIZ2RcCKLXhcDl2b +vXL+eccQoRzem80mekPDEiyiWK4GWqZmwxQOmPM0eIfgp1P9cqrBsewR2p/DPMtt+pfcYM+Ls2uh +hALufTAdmGl8B1H3VPd2af8fQAc4PgqjlIBL9cGQqNpXaAwe3LrtVn8AkZTUxg== +""") + +##file activate.csh +ACTIVATE_CSH = convert(""" +eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc +ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw +tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D +r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW +VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs +cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V +tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g +QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k +TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa +n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H +37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD +""") + +##file activate.bat +ACTIVATE_BAT = convert(""" +eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT +PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt +r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X +0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw== +""") + +##file deactivate.bat +DEACTIVATE_BAT = convert(""" +eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho +cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx +EchHtwsohN1bILUgw61c/Vy4AJYPYm4= +""") + +##file activate.ps1 +ACTIVATE_PS = convert(""" +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 +QastYw== +""") + +##file distutils-init.py +DISTUTILS_INIT = convert(""" +eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E +UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB +C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss +aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT +0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9 +oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE +NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c +f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8 +p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk +vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw +hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh +cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw +buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ +5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh +gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC +1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL +MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6 +84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK +0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO +kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG +qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h +kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9 +GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ= +""") + +##file distutils.cfg +DISTUTILS_CFG = convert(""" +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= +""") + +##file activate_this.py +ACTIVATE_THIS = convert(""" +eJyNU01v2zAMvetXEB4K21jmDOstQA4dMGCHbeihlyEIDMWmG62yJEiKE//7kXKdpN2KzYBt8euR +fKSyLPs8wiEo8wh4wqZTGou4V6Hm0wJa1cSiTkJdr8+GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe +5a3p0cRKiAe2NtLADikftnDco0ko/SFEVgEZ8aRC5GLux7i3BpSJ6J1H+i7A2CjiHq9z7JRZuuQq +siwTIvpxJYCeuWaBpwZdhB+yxy/eWz+ZvVSU8C4E9FFZkyxFsvCT/ZzL8gcz9aXVE14Yyp2M+2W0 +y7n5mp0qN+avKXvbsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCZN9UzlJr+/e/iab8WfqsmPI6pWeUPd +FrMsd4H/55poeO9n54COhUs+sZNEzNtg/wanpjpuqHJaxs76HtZryI/K3H7KJ/KDIhqcbJ7kI4ar +XL+sMgXnX0D+Te2Iy5xdP8yueSlQB/x/ED2BTAtyE3K4SYUN6AMNfbO63f4lBW3bUJPbTL+mjSxS +PyRfJkZRgj+VbFv+EzHFi5pKwUEepa4JslMnwkowSRCXI+m5XvEOvtuBrxHdhLalG0JofYBok6qj +YdN2dEngUlbC4PG60M1WEN0piu7Nq7on0mgyyUw3iV1etLo6r/81biWdQ9MWHFaePWZYaq+nmp+t +s3az+sj7eA0jfgPfeoN1 +""") + +MH_MAGIC = 0xfeedface +MH_CIGAM = 0xcefaedfe +MH_MAGIC_64 = 0xfeedfacf +MH_CIGAM_64 = 0xcffaedfe +FAT_MAGIC = 0xcafebabe +BIG_ENDIAN = '>' +LITTLE_ENDIAN = '<' +LC_LOAD_DYLIB = 0xc +maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') + + +class fileview(object): + """ + A proxy for file-like objects that exposes a given view of a file. + Modified from macholib. + """ + + def __init__(self, fileobj, start=0, size=maxint): + if isinstance(fileobj, fileview): + self._fileobj = fileobj._fileobj + else: + self._fileobj = fileobj + self._start = start + self._end = start + size + self._pos = 0 + + def __repr__(self): + return '' % ( + self._start, self._end, self._fileobj) + + def tell(self): + return self._pos + + def _checkwindow(self, seekto, op): + if not (self._start <= seekto <= self._end): + raise IOError("%s to offset %d is outside window [%d, %d]" % ( + op, seekto, self._start, self._end)) + + def seek(self, offset, whence=0): + seekto = offset + if whence == os.SEEK_SET: + seekto += self._start + elif whence == os.SEEK_CUR: + seekto += self._start + self._pos + elif whence == os.SEEK_END: + seekto += self._end + else: + raise IOError("Invalid whence argument to seek: %r" % (whence,)) + self._checkwindow(seekto, 'seek') + self._fileobj.seek(seekto) + self._pos = seekto - self._start + + def write(self, bytes): + here = self._start + self._pos + self._checkwindow(here, 'write') + self._checkwindow(here + len(bytes), 'write') + self._fileobj.seek(here, os.SEEK_SET) + self._fileobj.write(bytes) + self._pos += len(bytes) + + def read(self, size=maxint): + assert size >= 0 + here = self._start + self._pos + self._checkwindow(here, 'read') + size = min(size, self._end - here) + self._fileobj.seek(here, os.SEEK_SET) + bytes = self._fileobj.read(size) + self._pos += len(bytes) + return bytes + + +def read_data(file, endian, num=1): + """ + Read a given number of 32-bits unsigned integers from the given file + with the given endianness. + """ + res = struct.unpack(endian + 'L' * num, file.read(num * 4)) + if len(res) == 1: + return res[0] + return res + + +def mach_o_change(path, what, value): + """ + Replace a given name (what) in any LC_LOAD_DYLIB command found in + the given binary with a new name (value), provided it's shorter. + """ + + def do_macho(file, bits, endian): + # Read Mach-O header (the magic number is assumed read by the caller) + cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6) + # 64-bits header has one more field. + if bits == 64: + read_data(file, endian) + # The header is followed by ncmds commands + for n in range(ncmds): + where = file.tell() + # Read command header + cmd, cmdsize = read_data(file, endian, 2) + if cmd == LC_LOAD_DYLIB: + # The first data field in LC_LOAD_DYLIB commands is the + # offset of the name, starting from the beginning of the + # command. + name_offset = read_data(file, endian) + file.seek(where + name_offset, os.SEEK_SET) + # Read the NUL terminated string + load = file.read(cmdsize - name_offset).decode() + load = load[:load.index('\0')] + # If the string is what is being replaced, overwrite it. + if load == what: + file.seek(where + name_offset, os.SEEK_SET) + file.write(value.encode() + '\0'.encode()) + # Seek to the next command + file.seek(where + cmdsize, os.SEEK_SET) + + def do_file(file, offset=0, size=maxint): + file = fileview(file, offset, size) + # Read magic number + magic = read_data(file, BIG_ENDIAN) + if magic == FAT_MAGIC: + # Fat binaries contain nfat_arch Mach-O binaries + nfat_arch = read_data(file, BIG_ENDIAN) + for n in range(nfat_arch): + # Read arch header + cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5) + do_file(file, offset, size) + elif magic == MH_MAGIC: + do_macho(file, 32, BIG_ENDIAN) + elif magic == MH_CIGAM: + do_macho(file, 32, LITTLE_ENDIAN) + elif magic == MH_MAGIC_64: + do_macho(file, 64, BIG_ENDIAN) + elif magic == MH_CIGAM_64: + do_macho(file, 64, LITTLE_ENDIAN) + + assert(len(what) >= len(value)) + do_file(open(path, 'r+b')) + + +if __name__ == '__main__': + main() + +## TODO: +## Copy python.exe.manifest +## Monkeypatch distutils.sysconfig diff --git a/third-party/cxxtest/admin/virtualenv_1.7.py b/third-party/cxxtest/admin/virtualenv_1.7.py new file mode 100755 index 00000000..5b4951db --- /dev/null +++ b/third-party/cxxtest/admin/virtualenv_1.7.py @@ -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(""" +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 +""") + +##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(""" +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 +""") + +##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/third-party/cxxtest/bin/cxxtestgen b/third-party/cxxtest/bin/cxxtestgen new file mode 100755 index 00000000..e001cfa8 --- /dev/null +++ b/third-party/cxxtest/bin/cxxtestgen @@ -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/third-party/cxxtest/bin/cxxtestgen.bat b/third-party/cxxtest/bin/cxxtestgen.bat new file mode 100644 index 00000000..95d7d140 --- /dev/null +++ b/third-party/cxxtest/bin/cxxtestgen.bat @@ -0,0 +1,3 @@ +@echo off +rem Just run the python script +python %0 %* diff --git a/third-party/cxxtest/build_tools/SCons/AUTHORS b/third-party/cxxtest/build_tools/SCons/AUTHORS new file mode 100644 index 00000000..1f3e7e44 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/AUTHORS @@ -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/third-party/cxxtest/build_tools/SCons/cxxtest.py b/third-party/cxxtest/build_tools/SCons/cxxtest.py new file mode 100644 index 00000000..a66856c4 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/cxxtest.py @@ -0,0 +1,400 @@ +# coding=UTF-8 +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- +# +# == Preamble == +# Authors of this script are in the Authors file in the same directory as this +# script. +# +# Maintainer: Gašper Ažman +# +# 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 +from SCons.Util import PrependPath, unique, uniquer +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 prepend_ld_library_path(env, overrides, **kwargs): + """Prepend LD_LIBRARY_PATH with LIBPATH to run successfully programs that + were linked against local shared libraries.""" + # make it unique but preserve order ... + libpath = uniquer(Split(kwargs.get('CXXTEST_LIBPATH', [])) + + Split(env.get( 'CXXTEST_LIBPATH', []))) + if len(libpath) > 0: + libpath = env.arg2nodes(libpath, env.fs.Dir) + platform = env.get('PLATFORM','') + if platform == 'win32': + var = 'PATH' + else: + var = 'LD_LIBRARY_PATH' + eenv = overrides.get('ENV', env['ENV'].copy()) + canonicalize = lambda p : p.abspath + eenv[var] = PrependPath(eenv.get(var,''), libpath, os.pathsep, 1, canonicalize) + overrides['ENV'] = eenv + return overrides + +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) + testCommand = multiget([kwargs, env, os.environ], 'CXXTEST_COMMAND') + if testCommand: + testCommand = testCommand.replace('%t', test[0].abspath) + else: + testCommand = test[0].abspath + if multiget([kwargs, env, os.environ], 'CXXTEST_SKIP_ERRORS', False): + runner = env.Action(testCommand, exitstatfunc=lambda x:0) + else: + runner = env.Action(testCommand) + overrides = prepend_ld_library_path(env, {}, **kwargs) + cxxtest_target = multiget([kwargs, env], 'CXXTEST_TARGET') + env.Alias(cxxtest_target, test, runner, **overrides) + env.AlwaysBuild(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] + foundpaths = [] + for p in searchpaths: + if os.path.exists(os.path.join(p, 'cxxtest', searchfile)): + foundpaths.append(p) + return foundpaths + +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_COMMAND - the command that will be executed to run the test, + %t will be replace with the test executable. + Can be used for example for MPI or valgrind tests. + Default: %t + 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_LIBPATH - If your test is linked to shared libraries which are + outside of standard directories. This is used as LIBPATH + when compiling the test program and to modify + LD_LIBRARY_PATH (or PATH on win32) when running the + program. + 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'] = unique( + Split(kwargs.get('CPPPATH', [])) + + Split(env.get( 'CPPPATH', [])) + + Split(kwargs.get('CXXTEST_CPPPATH', [])) + + Split(env.get( 'CXXTEST_CPPPATH', [])) + ) + kwargs['LIBPATH'] = unique( + Split(kwargs.get('LIBPATH', [])) + + Split(env.get( 'LIBPATH', [])) + + Split(kwargs.get('CXXTEST_LIBPATH', [])) + + Split(env.get( 'CXXTEST_LIBPATH', [])) + ) + + 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/third-party/cxxtest/build_tools/SCons/test/default_env/README b/third-party/cxxtest/build_tools/SCons/test/default_env/README new file mode 100644 index 00000000..d8c8b69a --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/default_env/README @@ -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/third-party/cxxtest/build_tools/SCons/test/default_env/SConstruct b/third-party/cxxtest/build_tools/SCons/test/default_env/SConstruct new file mode 100644 index 00000000..637992ee --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/default_env/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/default_env/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/default_env/TestDef.py new file mode 100644 index 00000000..c951f102 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/default_env/TestDef.py @@ -0,0 +1,17 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +expect_success = True +type = 'scons' +links = { + 'cxxtest': '../../../../', + 'src' : '../../../../test/' + } + + diff --git a/third-party/cxxtest/build_tools/SCons/test/empty_source_list/README b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/README new file mode 100644 index 00000000..419901bb --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/README @@ -0,0 +1,2 @@ +Tests if cxxtest behaves correctly if no sources are given. +by: Gašper Ažman diff --git a/third-party/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct new file mode 100644 index 00000000..9f1dda96 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/SConstruct @@ -0,0 +1,4 @@ +env = Environment(toolpath=['../../'],tools=['default','cxxtest']) + +env.CxxTest('test_bar') +env.CxxTest('test_foo') diff --git a/third-party/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp new file mode 100644 index 00000000..3a6f7574 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/requirement.hpp @@ -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/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h new file mode 100644 index 00000000..4cd1adad --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_bar.t.h @@ -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 +#include "requirement.hpp" + +class TestBar : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h new file mode 100644 index 00000000..2850447c --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/empty_source_list/test_foo.t.h @@ -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 + +class TestFoo : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/eprouvette.py b/third-party/cxxtest/build_tools/SCons/test/eprouvette.py new file mode 100755 index 00000000..c1e6550b --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/eprouvette.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# vim: fileencoding=utf-8 +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 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/third-party/cxxtest/build_tools/SCons/test/expanding_#/README b/third-party/cxxtest/build_tools/SCons/test/expanding_#/README new file mode 100644 index 00000000..eac1c926 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/expanding_#/README @@ -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/third-party/cxxtest/build_tools/SCons/test/expanding_#/SConstruct b/third-party/cxxtest/build_tools/SCons/test/expanding_#/SConstruct new file mode 100644 index 00000000..bae8789b --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/expanding_#/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py new file mode 100644 index 00000000..1ec6c2cc --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/expanding_#/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'src' : '../../../../test'} diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing/README b/third-party/cxxtest/build_tools/SCons/test/globbing/README new file mode 100644 index 00000000..a83d021f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/README @@ -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/third-party/cxxtest/build_tools/SCons/test/globbing/SConstruct b/third-party/cxxtest/build_tools/SCons/test/globbing/SConstruct new file mode 100644 index 00000000..f647182c --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/SConstruct @@ -0,0 +1,3 @@ +env = Environment(toolpath=['../../'],tools=['default','cxxtest']) + +env.CxxTest('joint_tests',[Glob('src/*.t.h'), 'src/requirement.cpp']) diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/globbing/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp b/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp new file mode 100644 index 00000000..45d60ad7 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.cpp @@ -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/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.h b/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.h new file mode 100644 index 00000000..9bb94370 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/src/requirement.h @@ -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/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h b/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h new file mode 100644 index 00000000..76e594df --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_bar.t.h @@ -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 +#include "requirement.h" + +class TestBar : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h b/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h new file mode 100644 index 00000000..418a3ca0 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing/src/test_foo.t.h @@ -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 + +class TestFoo : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/README b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/README new file mode 100644 index 00000000..188908b6 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/README @@ -0,0 +1,2 @@ +Test for various things cxxtest failed to do, but now does. +by: Edmundo López B. diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct new file mode 100644 index 00000000..fdfd3bd4 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc new file mode 100644 index 00000000..e18191d5 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.cc @@ -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 + +int +Hello::foo(int x, int y) + { + return x + y; + } diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh new file mode 100644 index 00000000..72299954 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hello.hh @@ -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/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h new file mode 100644 index 00000000..e90f26b2 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/hellotest.t.h @@ -0,0 +1,23 @@ +/** + * \file + * The test file. + */ +/**************************************************** + * Author: Edmundo LOPEZ + * email: lopezed5@etu.unige.ch + * + * **************************************************/ + +#include +#include + + +class helloTestSuite : public CxxTest::TestSuite + { + public: + void testFoo() + { + Hello h; + TS_ASSERT_EQUALS (h.foo(2,2), 4); + } + }; diff --git a/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp new file mode 100644 index 00000000..21f1938f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/globbing_edmundo/main.cpp @@ -0,0 +1,18 @@ +/** + * \file + * Main function comes here. + */ +/**************************************************** + * Author: Edmundo LOPEZ + * email: lopezed5@etu.unige.ch + * + * **************************************************/ + +#include +#include + +int main (int argc, char *argv[]) + { + Hello h; + std::cout << h.foo(2,3) << std::endl; + } diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/README b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/README new file mode 100644 index 00000000..64905b91 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/README @@ -0,0 +1,3 @@ +Tests: + - if CXXTEST_CXXFLAGS_REMOVE and CXXTEST_CCFLAGS_REMOVE flags work, + - if CCFLAGS and CXXFLAGS vars work. diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct new file mode 100644 index 00000000..d946c33f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h new file mode 100644 index 00000000..e7377bb2 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/not-with-pedantic.h @@ -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 + +class TestPedantic : public CxxTest::TestSuite +{ +public: + void testPedanticPresent() { + TS_ASSERT(true); + int f = (true)?:5; + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h new file mode 100644 index 00000000..4f6615e6 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CCFLAGS/src/only_with_ansi.t.h @@ -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 + +class TestAnsi : public CxxTest::TestSuite +{ +public: + void testAnsiPresent() { +#ifdef __STRICT_ANSI__ + TS_ASSERT(true); +#else + TS_ASSERT(false); +#endif + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README new file mode 100644 index 00000000..07a99470 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/README @@ -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/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct new file mode 100644 index 00000000..aefb4393 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h new file mode 100644 index 00000000..2b92cd69 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/include_CXXFLAGS/src/not-with-pedantic.h @@ -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 + +class TestPedantic : public CxxTest::TestSuite +{ +public: + void testPedanticPresent() { + int f = (true)?:5; + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/README b/third-party/cxxtest/build_tools/SCons/test/libpath/README new file mode 100644 index 00000000..4eefa741 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/README @@ -0,0 +1,2 @@ +Test whether we can run program that depends on (shared) libraries that we know +but they are outside of standard load path. diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/SConstruct b/third-party/cxxtest/build_tools/SCons/test/libpath/SConstruct new file mode 100644 index 00000000..b89e2b89 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/SConstruct @@ -0,0 +1,3 @@ +env = Environment(toolpath=['../../'],tools=['default','cxxtest']) + +SConscript(['src/SConscript', 'test/SConscript'], exports = ['env']) diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/libpath/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/src/SConscript b/third-party/cxxtest/build_tools/SCons/test/libpath/src/SConscript new file mode 100644 index 00000000..889aa8ad --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/src/SConscript @@ -0,0 +1,3 @@ +Import('env') + +env.SharedLibrary('foo', 'foo.cpp') diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/src/foo.cpp b/third-party/cxxtest/build_tools/SCons/test/libpath/src/foo.cpp new file mode 100644 index 00000000..e05eb7e6 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/src/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 0; +} diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/test/SConscript b/third-party/cxxtest/build_tools/SCons/test/libpath/test/SConscript new file mode 100644 index 00000000..476e11d0 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/test/SConscript @@ -0,0 +1,2 @@ +Import('env') +env.CxxTest('test.t.h', LIBS = ['foo'], CXXTEST_LIBPATH = ['../src']) diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath/test/test.t.h b/third-party/cxxtest/build_tools/SCons/test/libpath/test/test.t.h new file mode 100644 index 00000000..eb505f14 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath/test/test.t.h @@ -0,0 +1,12 @@ +// test/test.t.h +#include + +extern int foo(); +class FooTestSuite1 : public CxxTest::TestSuite +{ +public: + void testFoo(void) + { + TS_ASSERT_EQUALS(foo(), 0); + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/README b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/README new file mode 100644 index 00000000..756e57cf --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/README @@ -0,0 +1,3 @@ +Test whether we can run program that depends on (shared) libraries that we know +but they are outside of standard load path. Test whether multiple test runners +do not alter each other. diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/SConstruct b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/SConstruct new file mode 100644 index 00000000..98288e9b --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/SConstruct @@ -0,0 +1,3 @@ +env = Environment(toolpath=['../../'],tools=['default','cxxtest']) + +SConscript(['src1/SConscript', 'src2/SConscript', 'test/SConscript'], exports = ['env']) diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/SConscript b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/SConscript new file mode 100644 index 00000000..889aa8ad --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/SConscript @@ -0,0 +1,3 @@ +Import('env') + +env.SharedLibrary('foo', 'foo.cpp') diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/foo.cpp b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/foo.cpp new file mode 100644 index 00000000..e05eb7e6 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src1/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 0; +} diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/SConscript b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/SConscript new file mode 100644 index 00000000..591773fa --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/SConscript @@ -0,0 +1,3 @@ +Import('env') + +env.SharedLibrary('bar', 'bar.cpp') diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/bar.cpp b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/bar.cpp new file mode 100644 index 00000000..01eedf70 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/src2/bar.cpp @@ -0,0 +1,4 @@ +int bar() +{ + return 0; +} diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/SConscript b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/SConscript new file mode 100644 index 00000000..502196ac --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/SConscript @@ -0,0 +1,5 @@ +Import('env') +env.CxxTest('test1.t.h', LIBS = ['foo'], CXXTEST_LIBPATH = ['../src1'], CXXTEST_TARGET = 'check-1') +env.CxxTest('test2.t.h', LIBS = ['bar'], CXXTEST_LIBPATH = ['../src2'], CXXTEST_TARGET = 'check-2') +env.Alias('check', ['check-1', 'check-2']) +env.AlwaysBuild('check') diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test1.t.h b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test1.t.h new file mode 100644 index 00000000..eb505f14 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test1.t.h @@ -0,0 +1,12 @@ +// test/test.t.h +#include + +extern int foo(); +class FooTestSuite1 : public CxxTest::TestSuite +{ +public: + void testFoo(void) + { + TS_ASSERT_EQUALS(foo(), 0); + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test2.t.h b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test2.t.h new file mode 100644 index 00000000..7378ba49 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/libpath_multitarget/test/test2.t.h @@ -0,0 +1,12 @@ +// test/test.t.h +#include + +extern int bar(); +class BarTestSuite1 : public CxxTest::TestSuite +{ +public: + void testBar(void) + { + TS_ASSERT_EQUALS(bar(), 0); + } +}; diff --git a/third-party/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct new file mode 100644 index 00000000..435b9cb3 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp new file mode 100644 index 00000000..45d60ad7 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.cpp @@ -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/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h new file mode 100644 index 00000000..9bb94370 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/requirement.h @@ -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/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h new file mode 100644 index 00000000..76e594df --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_bar.t.h @@ -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 +#include "requirement.h" + +class TestBar : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h new file mode 100644 index 00000000..418a3ca0 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/multifile_tests/src/test_foo.t.h @@ -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 + +class TestFoo : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct new file mode 100644 index 00000000..d457e55e --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/need_cpppath/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/TestDef.py new file mode 100644 index 00000000..e69de29b diff --git a/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h new file mode 100644 index 00000000..3c08c391 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppath.t.h @@ -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 + +class CppPathTest : public CxxTest::TestSuite +{ +public: + void test_i_need_me_exists() { + TS_ASSERT(i_need_me() == 0); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h new file mode 100644 index 00000000..93d3b039 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/need_cpppath/src/cpppathdir/include.h @@ -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/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct b/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct new file mode 100644 index 00000000..9b811621 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py new file mode 100644 index 00000000..b76a14cb --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/nonstandard_cxxtest_dir/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'src' : '../../../../test/'} diff --git a/third-party/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct new file mode 100644 index 00000000..d87118ff --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/printer_propagation/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/TestDef.py new file mode 100644 index 00000000..e69de29b diff --git a/third-party/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h new file mode 100644 index 00000000..6ceac42a --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/cxxtest/CrazyRunner.h @@ -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/third-party/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h new file mode 100644 index 00000000..ac8c8295 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/printer_propagation/src/failtest.t.h @@ -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 + +class CppPathTest : public CxxTest::TestSuite +{ +public: + void test_i_will_fail() { + TS_ASSERT(false); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/recursive_sources/README b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/README new file mode 100644 index 00000000..e1e6b749 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/README @@ -0,0 +1,2 @@ +Tests whether we can swallow recursively supplied sources - a list of lists, for +instance. diff --git a/third-party/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct new file mode 100644 index 00000000..5ba85026 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py new file mode 100644 index 00000000..3758853f --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/TestDef.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +links = {'cxxtest' : '../../../../'} diff --git a/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp new file mode 100644 index 00000000..45d60ad7 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.cpp @@ -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/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h new file mode 100644 index 00000000..9bb94370 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/requirement.h @@ -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/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h new file mode 100644 index 00000000..76e594df --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_bar.t.h @@ -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 +#include "requirement.h" + +class TestBar : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h new file mode 100644 index 00000000..418a3ca0 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/recursive_sources/src/test_foo.t.h @@ -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 + +class TestFoo : public CxxTest::TestSuite +{ +public: + void test_foo() { + TS_ASSERT(call_a_requirement()); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct new file mode 100644 index 00000000..4e1e8fee --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/SConstruct @@ -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/third-party/cxxtest/build_tools/SCons/test/string_cpppath/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/TestDef.py new file mode 100644 index 00000000..e69de29b diff --git a/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h new file mode 100644 index 00000000..3c08c391 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppath.t.h @@ -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 + +class CppPathTest : public CxxTest::TestSuite +{ +public: + void test_i_need_me_exists() { + TS_ASSERT(i_need_me() == 0); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h new file mode 100644 index 00000000..93d3b039 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/string_cpppath/src/cpppathdir/include.h @@ -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/third-party/cxxtest/build_tools/SCons/test/target_syntax/SConstruct b/third-party/cxxtest/build_tools/SCons/test/target_syntax/SConstruct new file mode 100644 index 00000000..7a600bba --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/target_syntax/SConstruct @@ -0,0 +1,9 @@ + +env = Environment( + toolpath=['../../'], + tools=['default','cxxtest'], + CXXTEST_INSTALL_DIR = '../../../../', + CPPPATH = ['src/cpppathdir/'] + ) + +env.CxxTest('src/cpppath') diff --git a/third-party/cxxtest/build_tools/SCons/test/target_syntax/TestDef.py b/third-party/cxxtest/build_tools/SCons/test/target_syntax/TestDef.py new file mode 100644 index 00000000..e69de29b diff --git a/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h b/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h new file mode 100644 index 00000000..3c08c391 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppath.t.h @@ -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 + +class CppPathTest : public CxxTest::TestSuite +{ +public: + void test_i_need_me_exists() { + TS_ASSERT(i_need_me() == 0); + } +}; + +#endif diff --git a/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h b/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h new file mode 100644 index 00000000..93d3b039 --- /dev/null +++ b/third-party/cxxtest/build_tools/SCons/test/target_syntax/src/cpppathdir/include.h @@ -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/third-party/cxxtest/build_tools/cmake/CxxTest.cmake b/third-party/cxxtest/build_tools/cmake/CxxTest.cmake new file mode 100644 index 00000000..6ed3652f --- /dev/null +++ b/third-party/cxxtest/build_tools/cmake/CxxTest.cmake @@ -0,0 +1,17 @@ + +include("${CMAKE_CURRENT_LIST_DIR}/FindCxxTest.cmake") + +function(cxx_test target source) + get_filename_component(CPP_FILE_NAME ${source} NAME) + string(REGEX REPLACE "h$|hpp$" "cpp" CPP_FILE_NAME ${CPP_FILE_NAME}) + message(${CPP_FILE_NAME}) + set(CPP_FULL_NAME "${CMAKE_CURRENT_BINARY_DIR}/${CPP_FILE_NAME}") + add_custom_command( + OUTPUT "${CPP_FULL_NAME}" + COMMAND ${CXXTESTGEN} --runner=ErrorPrinter --output "${CPP_FULL_NAME}" "${source}" + DEPENDS "${source}" + ) + add_executable(${target} ${CPP_FULL_NAME}) + set_target_properties(${target} PROPERTIES COMPILE_FLAGS "-Wno-effc++") + add_test(${target} ${RUNTIME_OUTPUT_DIRECTORY}/${target}) +endfunction(cxx_test) diff --git a/third-party/cxxtest/build_tools/cmake/FindCxxTest.cmake b/third-party/cxxtest/build_tools/cmake/FindCxxTest.cmake new file mode 100644 index 00000000..e1e4404c --- /dev/null +++ b/third-party/cxxtest/build_tools/cmake/FindCxxTest.cmake @@ -0,0 +1,36 @@ +IF (DEFINED FIND_CXXTEST_CMAKE_INCLUDED) + RETURN() +ENDIF (DEFINED FIND_CXXTEST_CMAKE_INCLUDED) +SET(FIND_CXXTEST_CMAKE_INCLUDED true) + +FIND_PROGRAM(CXXTESTGEN + NAMES cxxtestgen + PATHS "${CXXTEST_PATH}/bin" + "${PROJECT_SOURCE_DIR}/cxxtest/bin" + "${PROJECT_SOURCE_DIR}/lib/cxxtest/bin" + "${PROJECT_BINARY_DIR}/cxxtest/bin" + "${PROJECT_BINARY_DIR}/lib/cxxtest/bin" + /usr/bin + /bin + ) + +FIND_PATH(CXXTEST_INCLUDES + NAMES "cxxtest/TestSuite.h" + PATHS "${CXXTEST_PATH}" + "${PROJECT_SOURCE_DIR}/cxxtest/" + "${PROJECT_SOURCE_DIR}/lib/cxxtest/" + ) + +IF(NOT CXXTESTGEN) + MESSAGE(FATAL_ERROR "Unable to find 'cxxtestgen'") + SET(CXXTEST_FOUND false) +ELSEIF(NOT CXXTEST_INCLUDES) + SET(CXXTEST_FOUND false) +ELSE(NOT CXXTESTGEN) + SET(CXXTEST_FOUND true) + SET(CXXTEST_ROOT ${CXXTEST_INCLUDES}) +ENDIF(NOT CXXTESTGEN) + +SET(CXXTEST_CMAKE_MODULES_PATH "${CMAKE_CURRENT_LIST_DIR}") +INCLUDE("${CXXTEST_CMAKE_MODULES_PATH}/CxxTest.cmake") + diff --git a/third-party/cxxtest/cxxtest b/third-party/cxxtest/cxxtest new file mode 160000 index 00000000..191adddb --- /dev/null +++ b/third-party/cxxtest/cxxtest @@ -0,0 +1 @@ +Subproject commit 191adddb3876ab389c0c856e1c03874bf70f8ee4 diff --git a/third-party/cxxtest/doc/Makefile b/third-party/cxxtest/doc/Makefile new file mode 100644 index 00000000..f3e890f1 --- /dev/null +++ b/third-party/cxxtest/doc/Makefile @@ -0,0 +1,40 @@ +.PHONY: all anchors outputs clean manpages + +export XML_CATALOG_FILES = catalog.xml +PY = python +XSLTPROC_OPTS := --stringparam toc.section.depth 2 --stringparam generate.section.toc.level 1 +DBLATEX_OPTS := -P latex.output.revhistory=0 -P doc.collab.show=1 -P toc.section.depth=2 +A2X_OPTS := -a toc -a icons -L -d article -v --xsltproc-opts "$(XSLTPROC_OPTS)" --dblatex-opts "$(DBLATEX_OPTS)" + +%.html: %.txt anchors outputs + asciidoc -a data-uri -v -b html -d article -n -a toc2 -a icons $< + +# Ignore errors (dblatex may not be installed) +%.pdf: %.txt anchors outputs + - a2x -f pdf $(A2X_OPTS) $< + +# Ignore errors +%.epub: %.txt anchors outputs + - a2x -f epub $(A2X_OPTS) $< + +all: guide.html guide.pdf guide.epub + +manpages: + cd man; ./create_manpage; + cd man; asciidoc -v -d manpage ./cxxtestgen.1.txt + +html: guide.html + +pdf: guide.pdf + +epub: guide.epub + +anchors: guide.txt + $(PY) include_anchors.py $< + +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/third-party/cxxtest/doc/README.txt b/third-party/cxxtest/doc/README.txt new file mode 100644 index 00000000..75254456 --- /dev/null +++ b/third-party/cxxtest/doc/README.txt @@ -0,0 +1,43 @@ +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. + + +MANPAGES + +The command + + make manpages + +creates CxxTest man pages in the doc/man directory. + diff --git a/third-party/cxxtest/doc/catalog.xml b/third-party/cxxtest/doc/catalog.xml new file mode 100644 index 00000000..fde98a7f --- /dev/null +++ b/third-party/cxxtest/doc/catalog.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/third-party/cxxtest/doc/epub/README b/third-party/cxxtest/doc/epub/README new file mode 100644 index 00000000..5e2587a1 --- /dev/null +++ b/third-party/cxxtest/doc/epub/README @@ -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: + * + * , , , with text/XML + @filerefs + * + * in lists (generic XHTML rendering inability) + * (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 and
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/third-party/cxxtest/doc/epub/bin/dbtoepub b/third-party/cxxtest/doc/epub/bin/dbtoepub new file mode 100755 index 00000000..9976f816 --- /dev/null +++ b/third-party/cxxtest/doc/epub/bin/dbtoepub @@ -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 and
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/third-party/cxxtest/doc/epub/bin/lib/docbook.rb b/third-party/cxxtest/doc/epub/bin/lib/docbook.rb new file mode 100755 index 00000000..14110d60 --- /dev/null +++ b/third-party/cxxtest/doc/epub/bin/lib/docbook.rb @@ -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/third-party/cxxtest/doc/epub/bin/xslt/obfuscate.xsl b/third-party/cxxtest/doc/epub/bin/xslt/obfuscate.xsl new file mode 100644 index 00000000..4ea4cd55 --- /dev/null +++ b/third-party/cxxtest/doc/epub/bin/xslt/obfuscate.xsl @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/third-party/cxxtest/doc/epub/docbook.xsl b/third-party/cxxtest/doc/epub/docbook.xsl new file mode 100644 index 00000000..753fcd00 --- /dev/null +++ b/third-party/cxxtest/doc/epub/docbook.xsl @@ -0,0 +1,1690 @@ + + + + + + + + + + 1 + 2 + + book toc,title + + + + + 4 + + + + + + + + + + + + + + + ncxtoc + htmltoc + + + + + + 0 + + + + + + + + .png + + + + + + + + + + + + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + + + + + + + + + + + + + + Note + + + namesp. cut + + + stripped namespace before processing + + + + + + + Note + + + namesp. cut + + + processing stripped document + + + + + + + + + + + ID ' + + ' not found in document. + + + + + + + + + Formatting from + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + urn: + + : + + + + + urn:isbn: + + + + urn:issn: + + + + + + + + + + + + + _ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2.0 + + + + + + + + + + + + + + + + + + + + + + cover + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + application/oebps-package+xml + + + + + + + + + + + + + + + + + + + + + + + + + 2005-1 + + + + + + cover + + + + + + + dtb:uid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + : + + + + + + + + : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + © + + + + + + + + + + + + + + + + cover + Cover + + + + + + + + + + + toc + Table of Contents + + + + + + + + + + + + + + + + + + + + + + yes + + no + + + + + + + + + + yes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + application/x-dtbncx+xml + + + + + + + application/xhtml+xml + + + + + + + + + + + text/css + css + + + + + + + + + + + application/xhtml+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/gif + + + image/gif + + + image/png + + + image/png + + + image/jpeg + + + image/jpeg + + + image/jpeg + + + image/jpeg + + + image/svg+xml + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WARNING: mediaobjectco almost certainly will not render as expected in .epub! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + application/xhtml+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (missing alt) + + + + + + + + + + + + + + text-align: + + middle + + + + + + + + + + + + + + + + + + + + + + 1 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + 1 + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No insertfile extension available. + + + + + + + + No insertfile extension available. Use a different processor (with extensions) or turn on $use.extensions and $textinsert.extension (see docs for more). + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cover + + text/css + + img { max-width: 100%; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -toc + + + + + + + + + + + + + + + + + + + + + + + + font/opentype + + + + WARNING: OpenType fonts should be supplied! ( + + ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + + + + + + + + + + clear: both + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + 1 + + + + + + + 1 + 2 + 3 + 4 + 5 + + + + + + + + + + + + + + + + + + + + + + + + 6 + 5 + 4 + 3 + 2 + 1 + + + + + title + + + + + + + + + + + + + diff --git a/third-party/cxxtest/doc/examples/Assertions.h b/third-party/cxxtest/doc/examples/Assertions.h new file mode 100644 index 00000000..14be035c --- /dev/null +++ b/third-party/cxxtest/doc/examples/Assertions.h @@ -0,0 +1,193 @@ +// Assertions.h +#include + +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 + +// @assertIsNan: + void test_assert_is_nan(void) + { + TS_ASSERT_IS_NAN( 0.0/0.0 ); + } +// @:assertIsNan + +// @assertIsInfinite: + void test_assert_is_infinite(void) + { + TS_ASSERT_IS_INFINITE( 1.0/0.0 ); + } +// @:assertIsInfinite + +// @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, 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 + +// @assertThrowsIsNan: + void throws_nan(void) + { + raise 0.0/0.0; + } + + void test_assert_throws_is_nan(void) + { + TS_ASSERT_THROWS_IS_NAN(self.throws_nan(), const Error & e, e.what()); + } +// @:assertThrowsIsNan + +// @assertThrowsIsInfinite: + void throws_infinite(void) + { + raise 1.0/0.0; + } + + void test_assert_throws_is_infinite(void) + { + TS_ASSERT_THROWS_IS_INFINITE(self.throws_infinite(), const Error & e, e.what()); + } +// @:assertThrowsIsInfinite + +// @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 + +// @skip: + void test_skip(void) + { + TS_SKIP("This test has been skipped."); + } +// @:skip + +// @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/third-party/cxxtest/doc/examples/BadTestSuite1.h b/third-party/cxxtest/doc/examples/BadTestSuite1.h new file mode 100644 index 00000000..21cd8fc6 --- /dev/null +++ b/third-party/cxxtest/doc/examples/BadTestSuite1.h @@ -0,0 +1,19 @@ +// BadTestSuite1.h +#include + +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/third-party/cxxtest/doc/examples/GetGlobals.sh b/third-party/cxxtest/doc/examples/GetGlobals.sh new file mode 100644 index 00000000..27d59f84 --- /dev/null +++ b/third-party/cxxtest/doc/examples/GetGlobals.sh @@ -0,0 +1,4 @@ +if [[ "x$CXXTEST" -eq "x" ]] +then + CXXTEST="../../" +fi diff --git a/third-party/cxxtest/doc/examples/MockTestSuite.h b/third-party/cxxtest/doc/examples/MockTestSuite.h new file mode 100644 index 00000000..5de32498 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MockTestSuite.h @@ -0,0 +1,26 @@ +// MockTestSuite.h +#include +#include + +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/third-party/cxxtest/doc/examples/MyClass.h b/third-party/cxxtest/doc/examples/MyClass.h new file mode 100644 index 00000000..6cad25de --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyClass.h @@ -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 +#include + +namespace CxxTest +{ +CXXTEST_TEMPLATE_INSTANTIATION +class ValueTraits +{ + 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/third-party/cxxtest/doc/examples/MyTestSuite1.h b/third-party/cxxtest/doc/examples/MyTestSuite1.h new file mode 100644 index 00000000..f437d112 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite1.h @@ -0,0 +1,12 @@ +// MyTestSuite1.h +#include + +class MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; diff --git a/third-party/cxxtest/doc/examples/MyTestSuite10.h b/third-party/cxxtest/doc/examples/MyTestSuite10.h new file mode 100644 index 00000000..d3681fc9 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite10.h @@ -0,0 +1,20 @@ +// MyTestSuite10.h +#include +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite11.h b/third-party/cxxtest/doc/examples/MyTestSuite11.h new file mode 100644 index 00000000..2d0083e8 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite11.h @@ -0,0 +1,20 @@ +// MyTestSuite11.h +#include +#include + +class MyTestSuite11 : public CxxTest::TestSuite +{ +public: + void test_le() + { + TMyClass x(1), y(2); + TS_ASSERT_LESS_THAN(x, y); + } + + void test_eq() + { + TMyClass x(1), y(2); + TS_ASSERT_EQUALS(x, y); + } +}; + diff --git a/third-party/cxxtest/doc/examples/MyTestSuite12.h b/third-party/cxxtest/doc/examples/MyTestSuite12.h new file mode 100644 index 00000000..aae9ac24 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite12.h @@ -0,0 +1,24 @@ +// MyTestSuite12.h +#include + +class MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; + + +#ifndef CXXTEST_RUNNING +#include + +int main(int argc, char *argv[]) +{ + + std::cout << "Non-CxxTest stuff is happening now." << std::endl; + +} +#endif diff --git a/third-party/cxxtest/doc/examples/MyTestSuite2.h b/third-party/cxxtest/doc/examples/MyTestSuite2.h new file mode 100644 index 00000000..b5def59b --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite2.h @@ -0,0 +1,19 @@ +// MyTestSuite2.h +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite3.h b/third-party/cxxtest/doc/examples/MyTestSuite3.h new file mode 100644 index 00000000..2505ab63 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite3.h @@ -0,0 +1,32 @@ +// MyTestSuite3.h +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite4.h b/third-party/cxxtest/doc/examples/MyTestSuite4.h new file mode 100644 index 00000000..89236ee9 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite4.h @@ -0,0 +1,14 @@ +// MyTestSuite4.h +#include + +class MyTestSuite4 + : +public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; diff --git a/third-party/cxxtest/doc/examples/MyTestSuite5.h b/third-party/cxxtest/doc/examples/MyTestSuite5.h new file mode 100644 index 00000000..788c2ec8 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite5.h @@ -0,0 +1,35 @@ +// MyTestSuite5.h +#include +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite6.h b/third-party/cxxtest/doc/examples/MyTestSuite6.h new file mode 100644 index 00000000..6cafb457 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite6.h @@ -0,0 +1,24 @@ +// MyTestSuite6.h +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite7.h b/third-party/cxxtest/doc/examples/MyTestSuite7.h new file mode 100644 index 00000000..0fd38ac0 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite7.h @@ -0,0 +1,36 @@ +// MyTestSuite7.h +#include +#include + +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/third-party/cxxtest/doc/examples/MyTestSuite8.h b/third-party/cxxtest/doc/examples/MyTestSuite8.h new file mode 100644 index 00000000..6a457dc6 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite8.h @@ -0,0 +1,71 @@ +// MyTestSuite8.h +#include +#include +#include + +// +// 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/third-party/cxxtest/doc/examples/MyTestSuite9.h b/third-party/cxxtest/doc/examples/MyTestSuite9.h new file mode 100644 index 00000000..040f3828 --- /dev/null +++ b/third-party/cxxtest/doc/examples/MyTestSuite9.h @@ -0,0 +1,34 @@ +// MyTestSuite9.h +#include + +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/third-party/cxxtest/doc/examples/Namespace1.h b/third-party/cxxtest/doc/examples/Namespace1.h new file mode 100644 index 00000000..a0e4f44d --- /dev/null +++ b/third-party/cxxtest/doc/examples/Namespace1.h @@ -0,0 +1,39 @@ +// Namespace1.h +#include + +namespace foo +{ +namespace bar +{ + +class MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; + +} +} + + +namespace FOO +{ +namespace BAR +{ + +class MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; + +} +} diff --git a/third-party/cxxtest/doc/examples/Namespace2.h b/third-party/cxxtest/doc/examples/Namespace2.h new file mode 100644 index 00000000..ee1bfec5 --- /dev/null +++ b/third-party/cxxtest/doc/examples/Namespace2.h @@ -0,0 +1,28 @@ +// Namespace2.h +#include + +namespace foo { namespace bar { class MyTestSuite1; } } + +class foo::bar::MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; + + +namespace FOO { namespace BAR { class MyTestSuite1; } } + +class MyTestSuite1 : public CxxTest::TestSuite +{ +public: + void testAddition(void) + { + TS_ASSERT(1 + 1 > 1); + TS_ASSERT_EQUALS(1 + 1, 2); + } +}; + diff --git a/third-party/cxxtest/doc/examples/TMyClass.h b/third-party/cxxtest/doc/examples/TMyClass.h new file mode 100644 index 00000000..e4772498 --- /dev/null +++ b/third-party/cxxtest/doc/examples/TMyClass.h @@ -0,0 +1,43 @@ +// TMyClass.h + +template +class TMyClass +{ +public: + + T value; + + TMyClass(const T& value_) : value(value_) {} + + // CxxTest requires a copy constructor + TMyClass(const TMyClass& other) : value(other.value) {} + + // This is required if you want to use TS_ASSERT_EQUALS + bool operator==(const TMyClass& other) const { return value == other.value; } + + // If you want to use TS_ASSERT_LESS_THAN + bool operator<(const TMyClass& other) const { return value < other.value; } +}; + +#ifdef CXXTEST_RUNNING +// This declaration is only activated when building a CxxTest test suite +#include +#include +#include + +namespace CxxTest +{ +template +class ValueTraits< TMyClass > +{ +public: + std::ostringstream _s; + + ValueTraits(const TMyClass& t) { _s << typeid(t).name() << "( " << t.value << " )"; } + + ValueTraits(const ValueTraits< TMyClass >& value) { _s << value._s.rdbuf(); } + + const char *asString() const { return _s.str().c_str(); } +}; +}; +#endif // CXXTEST_RUNNING diff --git a/third-party/cxxtest/doc/examples/buildRunner.log b/third-party/cxxtest/doc/examples/buildRunner.log new file mode 100644 index 00000000..653dfd09 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner.log @@ -0,0 +1 @@ +Running cxxtest tests (1 test).OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner.sh b/third-party/cxxtest/doc/examples/buildRunner.sh new file mode 100755 index 00000000..f82d77f8 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner.sh @@ -0,0 +1,18 @@ +#!/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 > buildRunner.log +# @run: +./runner +# @:run +\rm -f runner runner.cpp diff --git a/third-party/cxxtest/doc/examples/buildRunner.txt b/third-party/cxxtest/doc/examples/buildRunner.txt new file mode 100644 index 00000000..653dfd09 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner.txt @@ -0,0 +1 @@ +Running cxxtest tests (1 test).OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner10.sh b/third-party/cxxtest/doc/examples/buildRunner10.sh new file mode 100755 index 00000000..eab85287 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner10.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner10.txt b/third-party/cxxtest/doc/examples/buildRunner10.txt new file mode 100644 index 00000000..0d6601ae --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner10.txt @@ -0,0 +1,7 @@ +Starting test runner +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% +Stopping test runner diff --git a/third-party/cxxtest/doc/examples/buildRunner11.sh b/third-party/cxxtest/doc/examples/buildRunner11.sh new file mode 100755 index 00000000..dd354f9d --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner11.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner11.txt b/third-party/cxxtest/doc/examples/buildRunner11.txt new file mode 100644 index 00000000..8c58f7cd --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner11.txt @@ -0,0 +1,2 @@ +Parsing file MyTestSuite3.h done. +Running cxxtest tests (1 test).OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner12.sh b/third-party/cxxtest/doc/examples/buildRunner12.sh new file mode 100755 index 00000000..3c4278eb --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner12.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner12.txt b/third-party/cxxtest/doc/examples/buildRunner12.txt new file mode 100644 index 00000000..5f6cafd0 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner12.txt @@ -0,0 +1,2 @@ +Parsing file MyTestSuite4.h done. +Running cxxtest tests (1 test).OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner13.sh b/third-party/cxxtest/doc/examples/buildRunner13.sh new file mode 100755 index 00000000..ae3e5bab --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner13.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner14.sh b/third-party/cxxtest/doc/examples/buildRunner14.sh new file mode 100755 index 00000000..215b2ce8 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner14.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner14.txt b/third-party/cxxtest/doc/examples/buildRunner14.txt new file mode 100644 index 00000000..9785efdd --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner14.txt @@ -0,0 +1 @@ +Running cxxtest tests (2 tests)..OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner15.sh b/third-party/cxxtest/doc/examples/buildRunner15.sh new file mode 100755 index 00000000..20c0ce06 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner15.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner15.txt b/third-party/cxxtest/doc/examples/buildRunner15.txt new file mode 100644 index 00000000..1103fe19 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner15.txt @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In MyTestSuite6::: +MyTestSuite6.h:8: Error: Test failed: createSuite() failed +MyTestSuite6.h:8: Error: Assertion failed: suite() != 0 +Failed 1 and Skipped 0 of 1 test +Success rate: 0% diff --git a/third-party/cxxtest/doc/examples/buildRunner16.sh b/third-party/cxxtest/doc/examples/buildRunner16.sh new file mode 100755 index 00000000..ba420e67 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner16.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner16.txt b/third-party/cxxtest/doc/examples/buildRunner16.txt new file mode 100644 index 00000000..653dfd09 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner16.txt @@ -0,0 +1 @@ +Running cxxtest tests (1 test).OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner17.sh b/third-party/cxxtest/doc/examples/buildRunner17.sh new file mode 100755 index 00000000..649da617 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner17.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner17.txt b/third-party/cxxtest/doc/examples/buildRunner17.txt new file mode 100644 index 00000000..3440276e --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner17.txt @@ -0,0 +1,9 @@ +Running cxxtest tests (1 test) +In MyTestSuite7::testCompareData: +MyTestSuite7.h:28: Error: Expected (x == y), found ({ 12 12 12 } != { F6 F6 F6 }) +MyTestSuite7.h:33: Error: Expected sizeof(z) (3) bytes to be equal at (&z) and (&w), found: + { 12 12 12 } + differs from + { F6 F6 F6 } +Failed 1 and Skipped 0 of 1 test +Success rate: 0% diff --git a/third-party/cxxtest/doc/examples/buildRunner18.sh b/third-party/cxxtest/doc/examples/buildRunner18.sh new file mode 100755 index 00000000..d34b9133 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner18.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner18.txt b/third-party/cxxtest/doc/examples/buildRunner18.txt new file mode 100644 index 00000000..d10e665a --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner18.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests)Starting a test suite +Starting a test suite +..Finishing a test suite +Finishing a test suite +OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner19.sh b/third-party/cxxtest/doc/examples/buildRunner19.sh new file mode 100755 index 00000000..64402fc0 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner19.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner19.txt b/third-party/cxxtest/doc/examples/buildRunner19.txt new file mode 100644 index 00000000..9da0e25e --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner19.txt @@ -0,0 +1,10 @@ +Running cxxtest tests (1 test) +In EnumTraits::test_Enum_traits: +MyTestSuite9.h:27: Error: Test failed: Yes +MyTestSuite9.h:28: Error: Test failed: No +MyTestSuite9.h:29: Error: Test failed: Maybe +MyTestSuite9.h:30: Error: Test failed: DontKnow +MyTestSuite9.h:31: Error: Test failed: DontCare +MyTestSuite9.h:32: Error: Test failed: (Answer)1000 +Failed 1 and Skipped 0 of 1 test +Success rate: 0% diff --git a/third-party/cxxtest/doc/examples/buildRunner2.log b/third-party/cxxtest/doc/examples/buildRunner2.log new file mode 100644 index 00000000..0c8b4a26 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner2.log @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner2.sh b/third-party/cxxtest/doc/examples/buildRunner2.sh new file mode 100755 index 00000000..623d806b --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner2.sh @@ -0,0 +1,16 @@ +#!/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 > buildRunner2.log +cat buildRunner2.log +\rm -f runner runner.cpp diff --git a/third-party/cxxtest/doc/examples/buildRunner2.txt b/third-party/cxxtest/doc/examples/buildRunner2.txt new file mode 100644 index 00000000..c0467088 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner2.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner20.sh b/third-party/cxxtest/doc/examples/buildRunner20.sh new file mode 100755 index 00000000..55c4794d --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner20.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner20.txt b/third-party/cxxtest/doc/examples/buildRunner20.txt new file mode 100644 index 00000000..e5531593 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner20.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite10::test_eq: +MyTestSuite10.h:17: Error: Expected (x == y), found (MyClass( 1 ) != MyClass( 2 )) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner21.sh b/third-party/cxxtest/doc/examples/buildRunner21.sh new file mode 100755 index 00000000..a9f1dafc --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner21.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner21.txt b/third-party/cxxtest/doc/examples/buildRunner21.txt new file mode 100644 index 00000000..1f8d72bb --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner21.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite11::test_eq: +MyTestSuite11.h:17: Error: Expected (x == y), found (8TMyClassIiE( 1 ) != 8TMyClassIiE( 1 )) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner22.sh b/third-party/cxxtest/doc/examples/buildRunner22.sh new file mode 100755 index 00000000..fc5d4aa0 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner22.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +. GetGlobals.sh +export PATH=$CXXTEST/bin:$PATH + +# @main: +cxxtestgen --fog --error-printer -o runner.cpp Namespace1.h +# @:main + +# @compile: +g++ -o runner -I$CXXTEST -I. runner.cpp +# @:compile + +./runner +#\rm -f runner runner.cpp + diff --git a/third-party/cxxtest/doc/examples/buildRunner22.txt b/third-party/cxxtest/doc/examples/buildRunner22.txt new file mode 100644 index 00000000..78d8f488 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner22.txt @@ -0,0 +1,2 @@ +Parsing file Namespace1.h done. +Running cxxtest tests (2 tests)..OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner23.sh b/third-party/cxxtest/doc/examples/buildRunner23.sh new file mode 100755 index 00000000..af0e3055 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner23.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +. GetGlobals.sh +export PATH=$CXXTEST/bin:$PATH + +# @main: +cxxtestgen --error-printer -o runner.cpp Namespace2.h +# @:main + +# @compile: +g++ -o runner -I$CXXTEST -I. runner.cpp +# @:compile + +./runner +\rm -f runner runner.cpp + diff --git a/third-party/cxxtest/doc/examples/buildRunner23.txt b/third-party/cxxtest/doc/examples/buildRunner23.txt new file mode 100644 index 00000000..9785efdd --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner23.txt @@ -0,0 +1 @@ +Running cxxtest tests (2 tests)..OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner24.sh b/third-party/cxxtest/doc/examples/buildRunner24.sh new file mode 100755 index 00000000..8cb11b15 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner24.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +. GetGlobals.sh +export PATH=$CXXTEST/bin:$PATH + +# @main: +cxxtestgen --fog --error-printer -o runner.cpp Namespace2.h +# @:main + +# @compile: +g++ -o runner -I$CXXTEST -I. runner.cpp +# @:compile + +./runner +\rm -f runner runner.cpp + diff --git a/third-party/cxxtest/doc/examples/buildRunner24.txt b/third-party/cxxtest/doc/examples/buildRunner24.txt new file mode 100644 index 00000000..fac84af3 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner24.txt @@ -0,0 +1,2 @@ +Parsing file Namespace2.h done. +Running cxxtest tests (2 tests)..OK! diff --git a/third-party/cxxtest/doc/examples/buildRunner25.sh b/third-party/cxxtest/doc/examples/buildRunner25.sh new file mode 100755 index 00000000..30cde5de --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner25.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +. GetGlobals.sh +export PATH=$CXXTEST/bin:$PATH + +# @main: +cxxtestgen --error-printer -o runner.cpp MyTestSuite12.h +# @:main + +# @compile: +g++ -o runner -I$CXXTEST runner.cpp +# @:compile + +./runner > buildRunner.log +# @run: +./runner +# @:run +\rm -f runner runner.cpp + + +cp MyTestSuite12.h runner2.cpp +g++ -o runner2 -I$CXXTEST runner2.cpp +./runner2 +\rm -f runner2 runner2.cpp diff --git a/third-party/cxxtest/doc/examples/buildRunner25.txt b/third-party/cxxtest/doc/examples/buildRunner25.txt new file mode 100644 index 00000000..31c75a4f --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner25.txt @@ -0,0 +1,2 @@ +Running cxxtest tests (1 test).OK! +Non-CxxTest stuff is happening now. diff --git a/third-party/cxxtest/doc/examples/buildRunner3.sh b/third-party/cxxtest/doc/examples/buildRunner3.sh new file mode 100755 index 00000000..f5f5c695 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner3.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner3.txt b/third-party/cxxtest/doc/examples/buildRunner3.txt new file mode 100644 index 00000000..1362f9f3 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner3.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +MyTestSuite2.h(16): Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner4.sh b/third-party/cxxtest/doc/examples/buildRunner4.sh new file mode 100755 index 00000000..44a6d535 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner4.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner4.txt b/third-party/cxxtest/doc/examples/buildRunner4.txt new file mode 100644 index 00000000..c0467088 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner4.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner5.sh b/third-party/cxxtest/doc/examples/buildRunner5.sh new file mode 100755 index 00000000..f3c5db0f --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner5.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner5.txt b/third-party/cxxtest/doc/examples/buildRunner5.txt new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner5.txt @@ -0,0 +1 @@ +1 diff --git a/third-party/cxxtest/doc/examples/buildRunner6.sh b/third-party/cxxtest/doc/examples/buildRunner6.sh new file mode 100755 index 00000000..3fd180cc --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner6.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner6.txt b/third-party/cxxtest/doc/examples/buildRunner6.txt new file mode 100644 index 00000000..bad004d8 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner6.txt @@ -0,0 +1,7 @@ + + + + + Error: Expected (2 * 2 == 5), found (4 != 5) + + diff --git a/third-party/cxxtest/doc/examples/buildRunner7.sh b/third-party/cxxtest/doc/examples/buildRunner7.sh new file mode 100755 index 00000000..12a25d0a --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner7.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner7.txt b/third-party/cxxtest/doc/examples/buildRunner7.txt new file mode 100644 index 00000000..c0467088 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner7.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/buildRunner8.sh b/third-party/cxxtest/doc/examples/buildRunner8.sh new file mode 100755 index 00000000..6ecd7968 --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner8.sh @@ -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/third-party/cxxtest/doc/examples/buildRunner9.sh b/third-party/cxxtest/doc/examples/buildRunner9.sh new file mode 100755 index 00000000..3c77bcce --- /dev/null +++ b/third-party/cxxtest/doc/examples/buildRunner9.sh @@ -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/third-party/cxxtest/doc/examples/cxxtestgen.out b/third-party/cxxtest/doc/examples/cxxtestgen.out new file mode 100644 index 00000000..b0cd5098 --- /dev/null +++ b/third-party/cxxtest/doc/examples/cxxtestgen.out @@ -0,0 +1,46 @@ +Usage: cxxtestgen [options] [ ...] + +The 'cxxtestgen' command processes C++ header files to perform test discovery, +and then it creates files for the 'CxxTest' test runner. + +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-.xml, where 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 (disabled) diff --git a/third-party/cxxtest/doc/examples/rand_example.cpp b/third-party/cxxtest/doc/examples/rand_example.cpp new file mode 100644 index 00000000..01f92201 --- /dev/null +++ b/third-party/cxxtest/doc/examples/rand_example.cpp @@ -0,0 +1,7 @@ +// rand_example.cpp +#include + +int generateRandomNumber() +{ + return T::time(NULL) * 3; +} diff --git a/third-party/cxxtest/doc/examples/runner10.tpl b/third-party/cxxtest/doc/examples/runner10.tpl new file mode 100644 index 00000000..4d3ebb77 --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner10.tpl @@ -0,0 +1,14 @@ +#define CXXTEST_HAVE_EH +#define CXXTEST_ABORT_TEST_ON_FAIL +#include + +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" + diff --git a/third-party/cxxtest/doc/examples/runner13.MyTestSuite2.txt b/third-party/cxxtest/doc/examples/runner13.MyTestSuite2.txt new file mode 100644 index 00000000..0c8b4a26 --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner13.MyTestSuite2.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (2 tests). +In MyTestSuite2::testMultiplication: +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 2 tests +Success rate: 50% diff --git a/third-party/cxxtest/doc/examples/runner13.help.txt b/third-party/cxxtest/doc/examples/runner13.help.txt new file mode 100644 index 00000000..41a61969 --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner13.help.txt @@ -0,0 +1,6 @@ +./runner +./runner +./runner -h +./runner --help +./runner --help-tests +./runner -v Enable tracing output. diff --git a/third-party/cxxtest/doc/examples/runner13.helpTests.txt b/third-party/cxxtest/doc/examples/runner13.helpTests.txt new file mode 100644 index 00000000..872cce9f --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner13.helpTests.txt @@ -0,0 +1,6 @@ +Suite/Test Names +--------------------------------------------------------------------------- +MyTestSuite1 testAddition +MyTestSuite2 testAddition +MyTestSuite2 testMultiplication +MyTestSuite4 testAddition diff --git a/third-party/cxxtest/doc/examples/runner13.testMultiplication.txt b/third-party/cxxtest/doc/examples/runner13.testMultiplication.txt new file mode 100644 index 00000000..1f18f7e6 --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner13.testMultiplication.txt @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test) +In MyTestSuite2::testMultiplication: +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 1 test +Success rate: 0% diff --git a/third-party/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt b/third-party/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt new file mode 100644 index 00000000..92549ab0 --- /dev/null +++ b/third-party/cxxtest/doc/examples/runner13.testMultiplicationVerbose.txt @@ -0,0 +1,7 @@ +Running cxxtest tests (1 test) +In MyTestSuite2::testMultiplication: +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:15: Trace: Starting multiplication test +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:16: Error: Expected (2 * 2 == 5), found (4 != 5) +/Users/wehart/home/mac/src/cxxtest/doc/examples/MyTestSuite2.h:17: Trace: Finishing multiplication test +Failed 1 and Skipped 0 of 1 test +Success rate: 0% diff --git a/third-party/cxxtest/doc/examples/test_examples.py b/third-party/cxxtest/doc/examples/test_examples.py new file mode 100644 index 00000000..059b9115 --- /dev/null +++ b/third-party/cxxtest/doc/examples/test_examples.py @@ -0,0 +1,68 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +# Imports +import pyutilib.th as unittest +import glob +import os +from os.path import dirname, abspath, basename +import sys +import re + +currdir = dirname(abspath(__file__))+os.sep +datadir = currdir + +compilerre = re.compile("^(?P[^:]+)(?P:.*)$") +dirre = re.compile("^([^%s]*/)*" % re.escape(os.sep)) +xmlre = re.compile("\"(?P[^\"]*/[^\"]*)\"") +datere = re.compile("date=\"[^\"]*\"") +failure = re.compile("^(?P.+)file=\"(?P[^\"]+)\"(?P.*)$") + +#print "FOO", dirre +def filter(line): + # for xml, remove prefixes from everything that looks like a + # file path inside "" + line = xmlre.sub( + lambda match: '"'+re.sub("^[^/]+/", "", match.group(1))+'"', + line + ) + # Remove date info + line = datere.sub( lambda match: 'date=""', line) + + if 'Running' in line: + return False + if "IGNORE" in line: + return True + pathmatch = compilerre.match(line) # see if we can remove the basedir + failmatch = failure.match(line) # see if we can remove the basedir + #print "HERE", pathmatch, failmatch + if failmatch: + parts = failmatch.groupdict() + #print "X", parts + line = "%s file=\"%s\" %s" % (parts['prefix'], dirre.sub("", parts['path']), parts['suffix']) + elif pathmatch: + parts = pathmatch.groupdict() + #print "Y", parts + line = dirre.sub("", parts['path']) + parts['rest'] + return 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/third-party/cxxtest/doc/examples/time_mock.cpp b/third-party/cxxtest/doc/examples/time_mock.cpp new file mode 100644 index 00000000..38d9bd48 --- /dev/null +++ b/third-party/cxxtest/doc/examples/time_mock.cpp @@ -0,0 +1,3 @@ +// time_mock.cpp +#define CXXTEST_MOCK_TEST_SOURCE_FILE +#include diff --git a/third-party/cxxtest/doc/examples/time_mock.h b/third-party/cxxtest/doc/examples/time_mock.h new file mode 100644 index 00000000..a637ca2f --- /dev/null +++ b/third-party/cxxtest/doc/examples/time_mock.h @@ -0,0 +1,8 @@ +// time_mock.h +#include +#include + +CXXTEST_MOCK_GLOBAL(time_t, /* Return type */ + time, /* Name of the function */ + (time_t *t), /* Prototype */ + (t) /* Argument list */); diff --git a/third-party/cxxtest/doc/examples/time_real.cpp b/third-party/cxxtest/doc/examples/time_real.cpp new file mode 100644 index 00000000..8503f797 --- /dev/null +++ b/third-party/cxxtest/doc/examples/time_real.cpp @@ -0,0 +1,3 @@ +// time_real.cpp +#define CXXTEST_MOCK_REAL_SOURCE_FILE +#include diff --git a/third-party/cxxtest/doc/guide.txt b/third-party/cxxtest/doc/guide.txt new file mode 100644 index 00000000..7eb1e1a7 --- /dev/null +++ b/third-party/cxxtest/doc/guide.txt @@ -0,0 +1,1841 @@ +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.4, which is an incremental release that includes +a variety of bug fixes and minor enhancements. + +: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/guide.html[HTML], +http://cxxtest.com/guide.pdf[PDF], and +http://cxxtest.com/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/licenses/lgpl.html[GNU Lesser General Public] +license. + +The CxxTest User Guide provides the following documentation: + + - <>: Some simple examples that illustrate how to use CxxTest + - <>: The test assertions supported by CxxTest + - <>: Documentation for the +cxxtestgen+ command + - <>: Discussion of command line options for test runners + - <>: Advanced features of CxxTest + - <>: Customizing data traits for error messages + - <>: How to test with mock global functions + - <>: How to install CxxTest + - <>: 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_compile.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/.buildRunner_run.sh[] +---- +which generates the following output: +---- +include::examples/buildRunner.log[] +---- + + +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/buildRunner2.log[] +---- + + +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. +<> provides examples that illustrate the use of these test assertions. + +[options="header"] +|==================================================================================== +| Macro | Description +| <> | 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+ +| <> | Verify that +x+ is NaN +| <> | Verify that +x+ is infinite +| 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 +| <> | 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 +| xref:ts_assert_throws_is_nan[+TS_ASSERT_THROWS_IS_NAN(expr,arg,x)+] | Verify type and value of what +expr+ throws +| xref:ts_assert_throws_is_infinite[+TS_ASSERT_THROWS_IS_INFINITE(expr,arg,x)+] | Verify type and value of what +expr+ throws +| <> | Verify that +expr+ doesn't throw anything +| <> | Fail unconditionally +| <> | Skip this test +| <> | Print +message+ as an informational 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/buildRunner2.log[] +---- + +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-.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 ++, 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 + found in the template file. If this +behavior is not what you need, use the directive ++ +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 to 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. + + +Test Classes Nested in Namespaces +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some contexts, it is appropriate to nest test classes in namespaces. +This allows the same class name to be used without creating conflicts +in the test runner. The default test discovery mechanism can only do +this by declaring the namespaces with the class name, and then declaring the +class with the explicit namespace prefix. For example: +[source,{cpp}] +----- +include::examples/Namespace2.h[] +---- +However, the default test discovery mechanism cannot recognize the more typical +declaration of test classes within nested namespaces: +[source,{cpp}] +----- +include::examples/Namespace1.h[] +---- +The FOG parser can discover tests nested within arbitrary namespaces, and unique +names are used within the test runner to distinguish the test classes in different namespaces. + + + +[[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+. + +Finally, CxxTest defines the +CXXTEST_RUNNING+ preprocessor macro. +This can be used in a test header file to define code that is +executed when the header is not used in a test runner. For example: +[source,{cpp}] +----- +include::examples/MyTestSuite12.h[] +---- +Note that test suites derived from +CxxTest::TestSuite+ class cannot +easily be built outside of the test runner. + + + +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[] +----- + +Note that test assertions cannot be used in within the +setUp()+ +or +tearDown()+ methods. The scope of these methods is outside any +test case, so an assertion failure does not have a clear semantics. +Similarly, test assertions cannot be used in +world setup and teardown or in +createSuite()+ or +destroySuite()+ methods for for +dynamicly created test suites (see below). + + +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 <> +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 +<> to `Data` objects. However, +the <> 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 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 <> +and <>. 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.3, though future releases will not support +Python 2.4. Note that this script has only been tested with the +CPython implementation. CxxTest 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.4 release is an incremental release that was driven +by a variety of bug fixes and minor enhancements. The CxxTest 4.0 +release reflected major changes in the management and focus of +CxxTest: + + - 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 <> 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 contributed to the CxxTest 4.x releases: + +* GaÅ¡per Ažman +* Andrey Batyiev +* Olivier Charloton +* Dave Elcock +* Kevin Fitch +* William Hart +* Allan Odgaard +* Lionel Orry +* John Siirola +* Jon Schlueter +* Andrei Korostelev +* Sebastian Rettenberger +* Piotr Kasprzyk +* Gluttton +* Pawel Tomulik + +The CxxTest documentation is generated using +http://www.methods.co.nz/asciidoc/[AsciiDoc]. + +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_is_nan]] TS_ASSERT_IS_NAN:: + This test assertion verifies that the argument is NaN: +[source,{cpp}] +---- +include::examples/.Assertions_assertIsNan.h[] +---- + +[[ts_assert_is_infinite]] TS_ASSERT_IS_INFINITE:: + This test assertion verifies that the argument is infinite: +[source,{cpp}] +---- +include::examples/.Assertions_assertIsInfinite.h[] +---- + +[[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 <>, 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 <>, <>, <> and <>. +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 <>, +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:: +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_is_nan]] TS_ASSERT_THROWS_IS_NAN:: +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 a value that are asserted to be NaN after the exception is thrown: +[source,{cpp}] +---- +include::examples/.Assertions_assertThrowsIsNan.h[] +---- + +[[ts_assert_throws_is_infinite]] TS_ASSERT_THROWS_IS_INFINITE:: +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 a value that are asserted to be infinite after the exception is thrown: +[source,{cpp}] +---- +include::examples/.Assertions_assertThrowsIsInfinite.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_skip]] TS_SKIP:: +This function causes the current test to be skipped with an associated warning message: +[source,{cpp}] +---- +include::examples/.Assertions_skip.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 (except for the SCons ones) are not actively maintained and +tested. Please send suggestions to the CxxTest developers for updating this +documentation. + +[[scons]] +SCons +~~~~~ + +CxxTest provides built-in support for the SCons build system. This part +documents this feature. + +[[scons_installation]] +Installation +^^^^^^^^^^^^ + +The script is located at +build_tools/SCons/cxxtest.py+. +You need SCons to be able to find this file, so do one of the following: + +- add the file to your project site_tools directory (default: +#/site_scons/site_tools/+) +- link the file to your project site_tools directory +- add +build_tools/SCons/cxxtest.py+ to your SCons toolpath. + +[NOTE] +'#' means the project root, using the SCons convention of marking it that way. + +Preparing the tests for use with the builder +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This builder assumes that tests have a different suffix than other files in your +project (by default: +.t.h+, configure via 'CXXTEST_SUFFIX'). This isn't a bad +idea to begin with, since test "header files" are not really header files in the +traditional sense. This is how it separates files it should run through +cxxtestgen from the ones it should not. + +[NOTE] +Test header files' filenames should end with +.t.h+. + +Compiling and Running the Tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, you build and run the tests by issuing the following command: + +.Building and running the tests in the shell +=================== +[source,bash] +scons check +=================== + +Of course, the actual name of the target is configurable (+CXXTEST_TARGET+). + +Using the Builder +^^^^^^^^^^^^^^^^^ + +This section describes what you do in your SConstruct file in order to be able +to use the builder. + +First, you must tell the environment that you want to use the 'cxxtest' tool and +how it should set itself up. + +The easiest way to set the environment up is to pray the defaults are ok. +The builder does some autodetection and tries its best to figure everything out. +In the event this works, setting up the environment is as easy as telling SCons +it should use the 'cxxtest' tool. + +.Configuring the environment if defaults are ok +=================== +[source,python] +env = Environment(tools = ['default', 'cxxtest']) +=================== + +If this doesn't work, the builder tries its best to tell you what went wrong. In +most cases, it just wasn't able to find where you installed cxxtest. You can fix +this like so (assuming you have CxxTest in +#/extern_libs/cxxtest/+): + +.Configuring the environment: telling the builder where CxxTest is installed +=================== +[source,python] +env = Environment(tools = [ + 'default', + ('cxxtest', {'CXXTEST_INSTALL_DIR' : '#/extern_libs/cxxtest/'}) + ]) +=================== + +[NOTE] +If you want to pass other options to the builder, just append them to the +dictionary. + +It is advisable to pass most options to the builder at creation time, although +the 'CxxTest' call can also accept most of them if you need to do some weird +thing with a particular test. + +You can use the builder the same way you would the 'Program' builder. + +.Setting up tests with SCons and the cxxtest builder +=================== +[source,python] +--------------------------------------------------------------------------- +# ... set up the environment as above, with your favorite options +# and then tell the builder to build some tests +env.CxxTest('my_test_suite', source='mytests.t.h') #<1> +env.CxxTest('the_other_suite', ['test_header.t.h', '../utilities.cpp']) #<2> +env.CxxTest('the_third_suite', + ['testsuite1.t.h', 'testsuite2.t.h', + 'testsuite3.t.h', 'required_libs.cpp']) #<3> +env.CxxTest('the_fourth_suite', + ['reginold_never_checks_for_warnings.t.h'], + CXXFLAGS='-Wall -Wextra -Weffc++ -pedantic') #<4> +--------------------------------------------------------------------------- + +<1> Normal, 1-source file tests +<2> This is how a single testsuite needing implementations is compilied +<3> If you want multiple testsuites in a single runner, this is how it's done +<4> unrecognised options are passed through to the Program builder unchanged + +=================== + +Configuration Options +^^^^^^^^^^^^^^^^^^^^^ + +===== +CXXTEST_RUNNER+ + +Default: "ErrorPrinter". + +This is what is passed to the +--runner+ option of +cxxtestgen+. See the section +about runners to see what the other options are. + +===== +CXXTEST_OPTS+ + +Default: empty. + +Any other commandline options to pass to +cxxtestgen+. + +Do not pass +--runner+, +--error-printer+ and friends, and +--root+ or +--part+ +here. + +===== +CXXTEST_SUFFIX+ + +Default: ".t.h" + +The suffix test suite files have. Should be different from other header files. +If you never mean to pass any header files that are not test suites to the +builder, you can set this to ".h" and use plain ".h" files. + +===== +CXXTEST_TARGET+ + +Default: "check" + +This is the target that scons tests are added to in order to run them. If you +want something else, this is the place. + +===== +CXXTEST_INSTALL_DIR+ + +Default: autodetect + +If cxxtest isn't found automatically, you need to set this. Normal SCons path +expansion rules apply. + +===== +CXXTEST_CPPPATH+ + +Default: autodetect + +If you don't want to clutter your normal +CPPPATH+ with CxxTest headers and this +isn't autodetected even after you set +CXXTEST_INSTALL_DIR+, then set this. + +===== +CXXTEST+ + +Default: autodetect + +If +cxxtestgen+ isn't found even after you set +CXXTEST_INSTALL_DIR+, then set +this to the path of the +cxxtestgen+ script. + +===== +CXXTEST_SKIP_ERRORS+ + +Default: False + +When running tests with +scons check+, if you want to continue even if tests +fail, set this to True. + +===== +CXXTEST_PYTHON+ + +Default: the same python interpreter that is running scons. + +If you want to use a particular python interpreter to run +cxxtestgen+, set its +path here. + +===== +CXXTEST_CXXFLAGS_REMOVE+ + +Default: a list of flags with which no test compiles. Changes as we fix bugs. + +Do you want your tests to compile without some flags and don't want gymnastics +to get them out for tests only? This is the way. Just add them to here and they +will be stripped. (This is a list, by the way, not a string.) + +===== +CXXTEST_CCFLAGS_REMOVE+ + +Same as above, but for +CCFLAGS+. + +===== +CXXTEST_CXXTESTGEN_SCRIPT_NAME+ + +If you are crazy and have changed the name of the cxxtestgen executable and want +autodetection to work otherwise, set this to the new name. + + +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 + $(CXX) -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 <>. +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: ft=asciidoc diff --git a/third-party/cxxtest/doc/images/icons/README b/third-party/cxxtest/doc/images/icons/README new file mode 100644 index 00000000..f12b2a73 --- /dev/null +++ b/third-party/cxxtest/doc/images/icons/README @@ -0,0 +1,5 @@ +Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook +icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency +from the Jimmac icons to get round MS IE and FOP PNG incompatibilies. + +Stuart Rackham diff --git a/third-party/cxxtest/doc/images/icons/callouts/1.png b/third-party/cxxtest/doc/images/icons/callouts/1.png new file mode 100644 index 00000000..7d473430 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/1.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/10.png b/third-party/cxxtest/doc/images/icons/callouts/10.png new file mode 100644 index 00000000..997bbc82 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/10.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/11.png b/third-party/cxxtest/doc/images/icons/callouts/11.png new file mode 100644 index 00000000..ce47dac3 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/11.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/12.png b/third-party/cxxtest/doc/images/icons/callouts/12.png new file mode 100644 index 00000000..31daf4e2 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/12.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/13.png b/third-party/cxxtest/doc/images/icons/callouts/13.png new file mode 100644 index 00000000..14021a89 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/13.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/14.png b/third-party/cxxtest/doc/images/icons/callouts/14.png new file mode 100644 index 00000000..64014b75 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/14.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/15.png b/third-party/cxxtest/doc/images/icons/callouts/15.png new file mode 100644 index 00000000..0d65765f Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/15.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/2.png b/third-party/cxxtest/doc/images/icons/callouts/2.png new file mode 100644 index 00000000..5d09341b Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/2.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/3.png b/third-party/cxxtest/doc/images/icons/callouts/3.png new file mode 100644 index 00000000..ef7b7004 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/3.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/4.png b/third-party/cxxtest/doc/images/icons/callouts/4.png new file mode 100644 index 00000000..adb8364e Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/4.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/5.png b/third-party/cxxtest/doc/images/icons/callouts/5.png new file mode 100644 index 00000000..4d7eb460 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/5.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/6.png b/third-party/cxxtest/doc/images/icons/callouts/6.png new file mode 100644 index 00000000..0ba694af Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/6.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/7.png b/third-party/cxxtest/doc/images/icons/callouts/7.png new file mode 100644 index 00000000..472e96f8 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/7.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/8.png b/third-party/cxxtest/doc/images/icons/callouts/8.png new file mode 100644 index 00000000..5e60973c Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/8.png differ diff --git a/third-party/cxxtest/doc/images/icons/callouts/9.png b/third-party/cxxtest/doc/images/icons/callouts/9.png new file mode 100644 index 00000000..a0676d26 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/callouts/9.png differ diff --git a/third-party/cxxtest/doc/images/icons/caution.png b/third-party/cxxtest/doc/images/icons/caution.png new file mode 100644 index 00000000..9a8c515a Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/caution.png differ diff --git a/third-party/cxxtest/doc/images/icons/example.png b/third-party/cxxtest/doc/images/icons/example.png new file mode 100644 index 00000000..1199e864 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/example.png differ diff --git a/third-party/cxxtest/doc/images/icons/home.png b/third-party/cxxtest/doc/images/icons/home.png new file mode 100644 index 00000000..37a5231b Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/home.png differ diff --git a/third-party/cxxtest/doc/images/icons/important.png b/third-party/cxxtest/doc/images/icons/important.png new file mode 100644 index 00000000..be685cc4 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/important.png differ diff --git a/third-party/cxxtest/doc/images/icons/next.png b/third-party/cxxtest/doc/images/icons/next.png new file mode 100644 index 00000000..64e126bd Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/next.png differ diff --git a/third-party/cxxtest/doc/images/icons/note.png b/third-party/cxxtest/doc/images/icons/note.png new file mode 100644 index 00000000..7c1f3e2f Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/note.png differ diff --git a/third-party/cxxtest/doc/images/icons/prev.png b/third-party/cxxtest/doc/images/icons/prev.png new file mode 100644 index 00000000..3e8f12fe Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/prev.png differ diff --git a/third-party/cxxtest/doc/images/icons/tip.png b/third-party/cxxtest/doc/images/icons/tip.png new file mode 100644 index 00000000..f087c73b Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/tip.png differ diff --git a/third-party/cxxtest/doc/images/icons/up.png b/third-party/cxxtest/doc/images/icons/up.png new file mode 100644 index 00000000..2db1ce62 Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/up.png differ diff --git a/third-party/cxxtest/doc/images/icons/warning.png b/third-party/cxxtest/doc/images/icons/warning.png new file mode 100644 index 00000000..d41edb9a Binary files /dev/null and b/third-party/cxxtest/doc/images/icons/warning.png differ diff --git a/third-party/cxxtest/doc/include_anchors.py b/third-party/cxxtest/doc/include_anchors.py new file mode 100644 index 00000000..8279cadc --- /dev/null +++ b/third-party/cxxtest/doc/include_anchors.py @@ -0,0 +1,90 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 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/third-party/cxxtest/python/README.txt b/third-party/cxxtest/python/README.txt new file mode 100644 index 00000000..1cd84b90 --- /dev/null +++ b/third-party/cxxtest/python/README.txt @@ -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/third-party/cxxtest/python/convert.py b/third-party/cxxtest/python/convert.py new file mode 100644 index 00000000..b7265156 --- /dev/null +++ b/third-party/cxxtest/python/convert.py @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- +# +# 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/third-party/cxxtest/python/cxxtest/.gitignore b/third-party/cxxtest/python/cxxtest/.gitignore new file mode 100644 index 00000000..0d20b648 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/third-party/cxxtest/python/cxxtest/__init__.py b/third-party/cxxtest/python/cxxtest/__init__.py new file mode 100644 index 00000000..669f8bbf --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/__init__.py @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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.com/ + +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.com" + +from cxxtest.cxxtestgen import * diff --git a/third-party/cxxtest/python/cxxtest/__release__.py b/third-party/cxxtest/python/cxxtest/__release__.py new file mode 100644 index 00000000..1369c60c --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/__release__.py @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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.4' +__date__ = "2014-06-03" diff --git a/third-party/cxxtest/python/cxxtest/cxx_parser.py b/third-party/cxxtest/python/cxxtest/cxx_parser.py new file mode 100644 index 00000000..b9761b32 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/cxx_parser.py @@ -0,0 +1,2204 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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(); +# +# 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: #pragma: no cover + from ordereddict import OrderedDict + +# global data +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): + # + # Reset global data + # + global lexer + lexer = None + global scope_lineno + scope_lineno = 0 + global indentifier_lineno + identifier_lineno = {} + global _parse_info + _parse_info=None + global _parsedata + _parsedata=None + global noExceptionLogic + noExceptionLogic = True + # + 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 + # + lexer = lex.lex() + # + # Initialize parse object + # + _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 + # + 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__': #pragma: no cover + # + # 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/third-party/cxxtest/python/cxxtest/cxxtest_fog.py b/third-party/cxxtest/python/cxxtest/cxxtest_fog.py new file mode 100644 index 00000000..a157b683 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/cxxtest_fog.py @@ -0,0 +1,99 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 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 + if key.startswith('::'): + fullname = key[2:] + else: + fullname = key + suite = { + 'fullname' : fullname, + 'name' : name, + 'file' : file, + 'cfile' : cstr(file), + 'line' : str(parse_info.index[key].lineno), + 'generated' : 0, + 'object' : 'suite_%s' % fullname.replace('::','_'), + 'dobject' : 'suiteDescription_%s' % fullname.replace('::','_'), + 'tlist' : 'Tests_%s' % fullname.replace('::','_'), + '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['fullname'].replace('::','_'), tname), + 'object' : 'testDescription_suite_%s_%s' % (suite['fullname'].replace('::','_'), 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/third-party/cxxtest/python/cxxtest/cxxtest_misc.py b/third-party/cxxtest/python/cxxtest/cxxtest_misc.py new file mode 100755 index 00000000..c9d337e2 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/cxxtest_misc.py @@ -0,0 +1,78 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 +import os + +def abort( problem ): + '''Print error message and exit''' + sys.stderr.write( '\n' ) + sys.stderr.write( problem ) + sys.stderr.write( '\n\n' ) + sys.exit(2) + +if sys.version_info < (2,6): #pragma: no cover + def resolve_symlinks(orig_path): + drive,tmp = os.path.splitdrive(os.path.normpath(orig_path)) + if not drive: + drive = os.path.sep + parts = tmp.split(os.path.sep) + actual_path = [drive] + while parts: + actual_path.append(parts.pop(0)) + if not os.path.islink(os.path.join(*actual_path)): + continue + actual_path[-1] = os.readlink(os.path.join(*actual_path)) + tmp_drive, tmp_path = os.path.splitdrive( + dereference_path(os.path.join(*actual_path)) ) + if tmp_drive: + drive = tmp_drive + actual_path = [drive] + tmp_path.split(os.path.sep) + return os.path.join(*actual_path) + + def relpath(path, start=None): + """Return a relative version of a path. + (provides compatibility with Python < 2.6)""" + # Some notes on implementation: + # - We rely on resolve_symlinks to correctly resolve any symbolic + # links that may be present in the paths + # - The explicit handling od the drive name is critical for proper + # function on Windows (because os.path.join('c:','foo') yields + # "c:foo"!). + if not start: + start = os.getcwd() + ref_drive, ref_path = os.path.splitdrive( + resolve_symlinks(os.path.abspath(start)) ) + if not ref_drive: + ref_drive = os.path.sep + start = [ref_drive] + ref_path.split(os.path.sep) + while '' in start: + start.remove('') + + pth_drive, pth_path = os.path.splitdrive( + resolve_symlinks(os.path.abspath(path)) ) + if not pth_drive: + pth_drive = os.path.sep + path = [pth_drive] + pth_path.split(os.path.sep) + while '' in path: + path.remove('') + + i = 0 + max = min(len(path), len(start)) + while i < max and path[i] == start[i]: + i += 1 + + if i < 2: + return os.path.join(*path) + else: + rel = ['..']*(len(start)-i) + path[i:] + if rel: + return os.path.join(*rel) + else: + return '.' diff --git a/third-party/cxxtest/python/cxxtest/cxxtest_parser.py b/third-party/cxxtest/python/cxxtest/cxxtest_parser.py new file mode 100644 index 00000000..d7c8f205 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/cxxtest_parser.py @@ -0,0 +1,254 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 +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''' + # + # Reset global data + # + global options + options=_options + global suites + suites = [] + global suite + suite = None + global inBlock + inBlock = 0 + # + for file in files: + scanInputFile(file) + 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: + try: + line = file.readline() + except UnicodeDecodeError: + sys.stderr.write("Could not decode unicode character at %s:%s\n" % (fileName, lineNo + 1)); + raise + 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 = { 'fullname' : name, + '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/third-party/cxxtest/python/cxxtest/cxxtestgen.py b/third-party/cxxtest/python/cxxtest/cxxtestgen.py new file mode 100644 index 00000000..99437cd8 --- /dev/null +++ b/third-party/cxxtest/python/cxxtest/cxxtestgen.py @@ -0,0 +1,630 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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', 'create_manpage'] + +import __release__ +import os +import sys +import re +import glob +from optparse import OptionParser +import cxxtest_parser +from string import Template + +try: + import cxxtest_fog + imported_fog=True +except ImportError: + imported_fog=False + +from cxxtest_misc import abort + +try: + from os.path import relpath +except ImportError: + from cxxtest_misc import relpath + +# Global data is initialized by main() +options = [] +suites = [] +wrotePreamble = 0 +wroteWorld = 0 +lastIncluded = '' + + +def main(args=sys.argv, catch=False): + '''The main program''' + # + # Reset global state + # + global wrotePreamble + wrotePreamble=0 + global wroteWorld + wroteWorld=0 + global lastIncluded + lastIncluded = '' + global suites + suites = [] + global options + options = [] + # + try: + 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() + except SystemExit: + if not catch: + raise + +def create_parser(asciidoc=False): + parser = OptionParser("cxxtestgen [options] [ ...]") + if asciidoc: + parser.description="The cxxtestgen command processes C++ header files to perform test discovery, and then it creates files for the CxxTest test runner." + else: + parser.description="The 'cxxtestgen' command processes C++ header files to perform test discovery, and then it creates files for the 'CxxTest' test runner." + + 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-.xml, where 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 + ) + return parser + +def parseCommandline(args): + '''Analyze command line arguments''' + global imported_fog + global options + + parser = create_parser() + (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+\s*$" ) +world_re = re.compile( r"^\s*\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 \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 \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + if options.runner: + output.write( "#include \n" % options.runner ) + if options.gui: + output.write( "#include \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 " % (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 ) + else: + output.write( ' %s tmp;\n' % tester_t ) + output.write( ' CxxTest::RealWorldDescription::_worldName = "%s";\n' % options.world ) + 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 not options.noStaticInit: + 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 options.outputFileName: + dirname = os.path.split(options.outputFileName)[0] + tfile = relpath(file, dirname) + if os.path.exists(tfile): + if tfile == lastIncluded: return + output.writelines( [ '#include "', tfile, '"\n\n' ] ) + lastIncluded = tfile + return + # + # Use an absolute path if the relative path failed + # + tfile = os.path.abspath(file) + if os.path.exists(tfile): + if tfile == lastIncluded: return + output.writelines( [ '#include "', tfile, '"\n\n' ] ) + lastIncluded = tfile + return + +def generateSuite( output, suite ): + '''Write a suite declared with CXXTEST_SUITE()''' + output.write( 'class %s : public CxxTest::TestSuite {\n' % suite['fullname'] ) + 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['fullname'], suite['object']) ) + else: + output.write( 'static %s* %s = 0;\n\n' % (suite['fullname'], suite['object']) ) + +def writeSuiteObject( output, suite ): + '''Create static suite object for non-dynamic suites''' + output.writelines( [ "static ", suite['fullname'], " ", 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''' + if not options.noStaticInit: + output.write( 'static class %s : public CxxTest::RealTestDescription {\n' % test['class'] ) + else: + output.write( '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']) ) + else: + if isDynamic(suite): + output.write( ' %s(%s* _%s) : %s(_%s) { }\n' % + (test['class'], suite['fullname'], suite['object'], suite['object'], suite['object']) ) + output.write( ' %s* %s;\n' % (suite['fullname'], suite['object']) ) + else: + output.write( ' %s(%s& _%s) : %s(_%s) { }\n' % + (test['class'], suite['fullname'], suite['object'], suite['object'], suite['object']) ) + output.write( ' %s& %s;\n' % (suite['fullname'], suite['object']) ) + output.write( ' void runTest() { %s }\n' % runBody( suite, test ) ) + # + if not options.noStaticInit: + output.write( '} %s;\n\n' % test['object'] ) + else: + output.write( '};\n\n' ) + +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['fullname'], suite['dobject']) ) + if not options.noStaticInit: + output.write( '( %s, %s, "%s", %s, %s, %s, %s )' % + (suite['cfile'], suite['line'], suite['fullname'], 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['fullname'], suite['object'], suite['tlist']) ) + output.write( ';\n\n' ) + +def writeRoot(output): + '''Write static members of CxxTest classes''' + output.write( '#include \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: + #print "HERE", suite + writeTestList( output, suite ) + output.write( ' %s.initialize();\n' % suite['tlist'] ) + #writeSuiteObject( output, suite ) + if isDynamic(suite): + writeSuitePointer( output, suite ) + output.write( ' %s = 0;\n' % suite['object']) + else: + writeSuiteObject( output, suite ) + output.write( ' static ') + writeSuiteDescription( output, suite ) + if isDynamic(suite): + #output.write( ' %s = %s.suite();\n' % (suite['object'],suite['dobject']) ) + output.write( ' %s.initialize( %s, %s, "%s", %s, %s, %s, %s );\n' % + (suite['dobject'], suite['cfile'], suite['line'], suite['fullname'], + suite['tlist'], suite['object'], suite['create'], suite['destroy']) ) + output.write( ' %s.setUp();\n' % suite['dobject']) + else: + output.write( ' %s.initialize( %s, %s, "%s", %s, %s );\n' % + (suite['dobject'], suite['cfile'], suite['line'], suite['fullname'], + suite['object'], suite['tlist']) ) + + for test in suite['tests']: + output.write( ' static %s %s(%s);\n' % + (test['class'], test['object'], suite['object']) ) + 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' ) + +man_template=Template("""CXXTESTGEN(1) +============= +:doctype: manpage + + +NAME +---- +cxxtestgen - performs test discovery to create a CxxTest test runner + + +SYNOPSIS +-------- +${usage} + + +DESCRIPTION +----------- +${description} + + +OPTIONS +------- +${options} + + +EXIT STATUS +----------- +*0*:: + Success + +*1*:: + Failure (syntax or usage error; configuration error; document + processing failure; unexpected error). + + +BUGS +---- +See the CxxTest Home Page for the link to the CxxTest ticket repository. + + +AUTHOR +------ +CxxTest was originally written by Erez Volk. Many people have +contributed to it. + + +RESOURCES +--------- +Home page: + +CxxTest User Guide: + + + +COPYING +------- +Copyright (c) 2008 Sandia Corporation. This software is distributed +under the Lesser GNU General Public License (LGPL) v3 +""") + +def create_manpage(): + """Write ASCIIDOC manpage file""" + parser = create_parser(asciidoc=True) + # + usage = parser.usage + description = parser.description + options="" + for opt in parser.option_list: + opts = opt._short_opts + opt._long_opts + optstr = '*' + ', '.join(opts) + '*' + if not opt.metavar is None: + optstr += "='%s'" % opt.metavar + optstr += '::\n' + options += optstr + # + options += opt.help + options += '\n\n' + # + OUTPUT = open('cxxtestgen.1.txt','w') + OUTPUT.write( man_template.substitute(usage=usage, description=description, options=options) ) + OUTPUT.close() + + diff --git a/third-party/cxxtest/python/python3/cxxtest/__init__.py b/third-party/cxxtest/python/python3/cxxtest/__init__.py new file mode 100644 index 00000000..669f8bbf --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/__init__.py @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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.com/ + +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.com" + +from cxxtest.cxxtestgen import * diff --git a/third-party/cxxtest/python/python3/cxxtest/__release__.py b/third-party/cxxtest/python/python3/cxxtest/__release__.py new file mode 100644 index 00000000..1369c60c --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/__release__.py @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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.4' +__date__ = "2014-06-03" diff --git a/third-party/cxxtest/python/python3/cxxtest/cxx_parser.py b/third-party/cxxtest/python/python3/cxxtest/cxx_parser.py new file mode 100644 index 00000000..c3b7561e --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/cxx_parser.py @@ -0,0 +1,2204 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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(); +# +# 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: #pragma: no cover + from ordereddict import OrderedDict + +# global data +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): + # + # Reset global data + # + global lexer + lexer = None + global scope_lineno + scope_lineno = 0 + global indentifier_lineno + identifier_lineno = {} + global _parse_info + _parse_info=None + global _parsedata + _parsedata=None + global noExceptionLogic + noExceptionLogic = True + # + 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 + # + lexer = lex.lex() + # + # Initialize parse object + # + _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 + # + 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__': #pragma: no cover + # + # 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/third-party/cxxtest/python/python3/cxxtest/cxxtest_fog.py b/third-party/cxxtest/python/python3/cxxtest/cxxtest_fog.py new file mode 100644 index 00000000..45dc9406 --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/cxxtest_fog.py @@ -0,0 +1,99 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 .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 + if key.startswith('::'): + fullname = key[2:] + else: + fullname = key + suite = { + 'fullname' : fullname, + 'name' : name, + 'file' : file, + 'cfile' : cstr(file), + 'line' : str(parse_info.index[key].lineno), + 'generated' : 0, + 'object' : 'suite_%s' % fullname.replace('::','_'), + 'dobject' : 'suiteDescription_%s' % fullname.replace('::','_'), + 'tlist' : 'Tests_%s' % fullname.replace('::','_'), + '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['fullname'].replace('::','_'), tname), + 'object' : 'testDescription_suite_%s_%s' % (suite['fullname'].replace('::','_'), 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/third-party/cxxtest/python/python3/cxxtest/cxxtest_misc.py b/third-party/cxxtest/python/python3/cxxtest/cxxtest_misc.py new file mode 100644 index 00000000..c9d337e2 --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/cxxtest_misc.py @@ -0,0 +1,78 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 +import os + +def abort( problem ): + '''Print error message and exit''' + sys.stderr.write( '\n' ) + sys.stderr.write( problem ) + sys.stderr.write( '\n\n' ) + sys.exit(2) + +if sys.version_info < (2,6): #pragma: no cover + def resolve_symlinks(orig_path): + drive,tmp = os.path.splitdrive(os.path.normpath(orig_path)) + if not drive: + drive = os.path.sep + parts = tmp.split(os.path.sep) + actual_path = [drive] + while parts: + actual_path.append(parts.pop(0)) + if not os.path.islink(os.path.join(*actual_path)): + continue + actual_path[-1] = os.readlink(os.path.join(*actual_path)) + tmp_drive, tmp_path = os.path.splitdrive( + dereference_path(os.path.join(*actual_path)) ) + if tmp_drive: + drive = tmp_drive + actual_path = [drive] + tmp_path.split(os.path.sep) + return os.path.join(*actual_path) + + def relpath(path, start=None): + """Return a relative version of a path. + (provides compatibility with Python < 2.6)""" + # Some notes on implementation: + # - We rely on resolve_symlinks to correctly resolve any symbolic + # links that may be present in the paths + # - The explicit handling od the drive name is critical for proper + # function on Windows (because os.path.join('c:','foo') yields + # "c:foo"!). + if not start: + start = os.getcwd() + ref_drive, ref_path = os.path.splitdrive( + resolve_symlinks(os.path.abspath(start)) ) + if not ref_drive: + ref_drive = os.path.sep + start = [ref_drive] + ref_path.split(os.path.sep) + while '' in start: + start.remove('') + + pth_drive, pth_path = os.path.splitdrive( + resolve_symlinks(os.path.abspath(path)) ) + if not pth_drive: + pth_drive = os.path.sep + path = [pth_drive] + pth_path.split(os.path.sep) + while '' in path: + path.remove('') + + i = 0 + max = min(len(path), len(start)) + while i < max and path[i] == start[i]: + i += 1 + + if i < 2: + return os.path.join(*path) + else: + rel = ['..']*(len(start)-i) + path[i:] + if rel: + return os.path.join(*rel) + else: + return '.' diff --git a/third-party/cxxtest/python/python3/cxxtest/cxxtest_parser.py b/third-party/cxxtest/python/python3/cxxtest/cxxtest_parser.py new file mode 100644 index 00000000..a4313a61 --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/cxxtest_parser.py @@ -0,0 +1,254 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 +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''' + # + # Reset global data + # + global options + options=_options + global suites + suites = [] + global suite + suite = None + global inBlock + inBlock = 0 + # + for file in files: + scanInputFile(file) + 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: + try: + line = file.readline() + except UnicodeDecodeError: + sys.stderr.write("Could not decode unicode character at %s:%s\n" % (fileName, lineNo + 1)); + raise + 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 = { 'fullname' : name, + '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/third-party/cxxtest/python/python3/cxxtest/cxxtestgen.py b/third-party/cxxtest/python/python3/cxxtest/cxxtestgen.py new file mode 100644 index 00000000..8a5b84c4 --- /dev/null +++ b/third-party/cxxtest/python/python3/cxxtest/cxxtestgen.py @@ -0,0 +1,630 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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', 'create_manpage'] + +from . import __release__ +import os +import sys +import re +import glob +from optparse import OptionParser +from . import cxxtest_parser +from string import Template + +try: + from . import cxxtest_fog + imported_fog=True +except ImportError: + imported_fog=False + +from .cxxtest_misc import abort + +try: + from os.path import relpath +except ImportError: + from .cxxtest_misc import relpath + +# Global data is initialized by main() +options = [] +suites = [] +wrotePreamble = 0 +wroteWorld = 0 +lastIncluded = '' + + +def main(args=sys.argv, catch=False): + '''The main program''' + # + # Reset global state + # + global wrotePreamble + wrotePreamble=0 + global wroteWorld + wroteWorld=0 + global lastIncluded + lastIncluded = '' + global suites + suites = [] + global options + options = [] + # + try: + 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() + except SystemExit: + if not catch: + raise + +def create_parser(asciidoc=False): + parser = OptionParser("cxxtestgen [options] [ ...]") + if asciidoc: + parser.description="The cxxtestgen command processes C++ header files to perform test discovery, and then it creates files for the CxxTest test runner." + else: + parser.description="The 'cxxtestgen' command processes C++ header files to perform test discovery, and then it creates files for the 'CxxTest' test runner." + + 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-.xml, where 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 + ) + return parser + +def parseCommandline(args): + '''Analyze command line arguments''' + global imported_fog + global options + + parser = create_parser() + (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+\s*$" ) +world_re = re.compile( r"^\s*\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 \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 \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + output.write( "#include \n" ) + if options.runner: + output.write( "#include \n" % options.runner ) + if options.gui: + output.write( "#include \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 " % (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 ) + else: + output.write( ' %s tmp;\n' % tester_t ) + output.write( ' CxxTest::RealWorldDescription::_worldName = "%s";\n' % options.world ) + 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 not options.noStaticInit: + 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 options.outputFileName: + dirname = os.path.split(options.outputFileName)[0] + tfile = relpath(file, dirname) + if os.path.exists(tfile): + if tfile == lastIncluded: return + output.writelines( [ '#include "', tfile, '"\n\n' ] ) + lastIncluded = tfile + return + # + # Use an absolute path if the relative path failed + # + tfile = os.path.abspath(file) + if os.path.exists(tfile): + if tfile == lastIncluded: return + output.writelines( [ '#include "', tfile, '"\n\n' ] ) + lastIncluded = tfile + return + +def generateSuite( output, suite ): + '''Write a suite declared with CXXTEST_SUITE()''' + output.write( 'class %s : public CxxTest::TestSuite {\n' % suite['fullname'] ) + 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['fullname'], suite['object']) ) + else: + output.write( 'static %s* %s = 0;\n\n' % (suite['fullname'], suite['object']) ) + +def writeSuiteObject( output, suite ): + '''Create static suite object for non-dynamic suites''' + output.writelines( [ "static ", suite['fullname'], " ", 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''' + if not options.noStaticInit: + output.write( 'static class %s : public CxxTest::RealTestDescription {\n' % test['class'] ) + else: + output.write( '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']) ) + else: + if isDynamic(suite): + output.write( ' %s(%s* _%s) : %s(_%s) { }\n' % + (test['class'], suite['fullname'], suite['object'], suite['object'], suite['object']) ) + output.write( ' %s* %s;\n' % (suite['fullname'], suite['object']) ) + else: + output.write( ' %s(%s& _%s) : %s(_%s) { }\n' % + (test['class'], suite['fullname'], suite['object'], suite['object'], suite['object']) ) + output.write( ' %s& %s;\n' % (suite['fullname'], suite['object']) ) + output.write( ' void runTest() { %s }\n' % runBody( suite, test ) ) + # + if not options.noStaticInit: + output.write( '} %s;\n\n' % test['object'] ) + else: + output.write( '};\n\n' ) + +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['fullname'], suite['dobject']) ) + if not options.noStaticInit: + output.write( '( %s, %s, "%s", %s, %s, %s, %s )' % + (suite['cfile'], suite['line'], suite['fullname'], 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['fullname'], suite['object'], suite['tlist']) ) + output.write( ';\n\n' ) + +def writeRoot(output): + '''Write static members of CxxTest classes''' + output.write( '#include \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: + #print "HERE", suite + writeTestList( output, suite ) + output.write( ' %s.initialize();\n' % suite['tlist'] ) + #writeSuiteObject( output, suite ) + if isDynamic(suite): + writeSuitePointer( output, suite ) + output.write( ' %s = 0;\n' % suite['object']) + else: + writeSuiteObject( output, suite ) + output.write( ' static ') + writeSuiteDescription( output, suite ) + if isDynamic(suite): + #output.write( ' %s = %s.suite();\n' % (suite['object'],suite['dobject']) ) + output.write( ' %s.initialize( %s, %s, "%s", %s, %s, %s, %s );\n' % + (suite['dobject'], suite['cfile'], suite['line'], suite['fullname'], + suite['tlist'], suite['object'], suite['create'], suite['destroy']) ) + output.write( ' %s.setUp();\n' % suite['dobject']) + else: + output.write( ' %s.initialize( %s, %s, "%s", %s, %s );\n' % + (suite['dobject'], suite['cfile'], suite['line'], suite['fullname'], + suite['object'], suite['tlist']) ) + + for test in suite['tests']: + output.write( ' static %s %s(%s);\n' % + (test['class'], test['object'], suite['object']) ) + 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' ) + +man_template=Template("""CXXTESTGEN(1) +============= +:doctype: manpage + + +NAME +---- +cxxtestgen - performs test discovery to create a CxxTest test runner + + +SYNOPSIS +-------- +${usage} + + +DESCRIPTION +----------- +${description} + + +OPTIONS +------- +${options} + + +EXIT STATUS +----------- +*0*:: + Success + +*1*:: + Failure (syntax or usage error; configuration error; document + processing failure; unexpected error). + + +BUGS +---- +See the CxxTest Home Page for the link to the CxxTest ticket repository. + + +AUTHOR +------ +CxxTest was originally written by Erez Volk. Many people have +contributed to it. + + +RESOURCES +--------- +Home page: + +CxxTest User Guide: + + + +COPYING +------- +Copyright (c) 2008 Sandia Corporation. This software is distributed +under the Lesser GNU General Public License (LGPL) v3 +""") + +def create_manpage(): + """Write ASCIIDOC manpage file""" + parser = create_parser(asciidoc=True) + # + usage = parser.usage + description = parser.description + options="" + for opt in parser.option_list: + opts = opt._short_opts + opt._long_opts + optstr = '*' + ', '.join(opts) + '*' + if not opt.metavar is None: + optstr += "='%s'" % opt.metavar + optstr += '::\n' + options += optstr + # + options += opt.help + options += '\n\n' + # + OUTPUT = open('cxxtestgen.1.txt','w') + OUTPUT.write( man_template.substitute(usage=usage, description=description, options=options) ) + OUTPUT.close() + + diff --git a/third-party/cxxtest/python/python3/scripts/cxxtestgen b/third-party/cxxtest/python/python3/scripts/cxxtestgen new file mode 100644 index 00000000..74090ec7 --- /dev/null +++ b/third-party/cxxtest/python/python3/scripts/cxxtestgen @@ -0,0 +1,5 @@ +#! python + +import cxxtest.cxxtestgen + +cxxtest.cxxtestgen.main() diff --git a/third-party/cxxtest/python/scripts/cxxtestgen b/third-party/cxxtest/python/scripts/cxxtestgen new file mode 100755 index 00000000..4fb2d796 --- /dev/null +++ b/third-party/cxxtest/python/scripts/cxxtestgen @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +import sys +import os.path + +try: + import cxxtest.cxxtestgen +except ImportError: + currdir = os.path.dirname(os.path.abspath(__file__)) + + if sys.version_info < (3,0): + sys.path.append( os.path.abspath( os.path.sep.join([currdir, '..']) ) ) + else: + sys.path.append( os.path.abspath( os.path.sep.join([currdir, '..', python3]) ) ) + + import cxxtest.cxxtestgen + +cxxtest.cxxtestgen.main() diff --git a/third-party/cxxtest/python/setup.py b/third-party/cxxtest/python/setup.py new file mode 100644 index 00000000..7fc9168c --- /dev/null +++ b/third-party/cxxtest/python/setup.py @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +""" +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/third-party/cxxtest/sample/.cvsignore b/third-party/cxxtest/sample/.cvsignore new file mode 100644 index 00000000..087c5dc6 --- /dev/null +++ b/third-party/cxxtest/sample/.cvsignore @@ -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/third-party/cxxtest/sample/Construct b/third-party/cxxtest/sample/Construct new file mode 100644 index 00000000..60902254 --- /dev/null +++ b/third-party/cxxtest/sample/Construct @@ -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/third-party/cxxtest/sample/CreatedTest.h b/third-party/cxxtest/sample/CreatedTest.h new file mode 100644 index 00000000..d1518634 --- /dev/null +++ b/third-party/cxxtest/sample/CreatedTest.h @@ -0,0 +1,29 @@ +#ifndef __CREATEDTEST_H +#define __CREATEDTEST_H + +#include +#include +#include + +// +// 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/third-party/cxxtest/sample/DeltaTest.h b/third-party/cxxtest/sample/DeltaTest.h new file mode 100644 index 00000000..2820c016 --- /dev/null +++ b/third-party/cxxtest/sample/DeltaTest.h @@ -0,0 +1,30 @@ +#ifndef __DELTATEST_H +#define __DELTATEST_H + +#include +#include + +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); + } + + void testInt() { + unsigned a = 0; + unsigned b = 0; + TS_ASSERT_DELTA(a, b, 10); + } +}; + +#endif // __DELTATEST_H diff --git a/third-party/cxxtest/sample/EnumTraits.h b/third-party/cxxtest/sample/EnumTraits.h new file mode 100644 index 00000000..f17bf3f2 --- /dev/null +++ b/third-party/cxxtest/sample/EnumTraits.h @@ -0,0 +1,37 @@ +// +// This is a test of CxxTest's ValueTraits for enumerations. +// +#include + +// +// 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/third-party/cxxtest/sample/ExceptionTest.h b/third-party/cxxtest/sample/ExceptionTest.h new file mode 100644 index 00000000..ccb41aab --- /dev/null +++ b/third-party/cxxtest/sample/ExceptionTest.h @@ -0,0 +1,49 @@ +#ifndef __EXCEPTIONTEST_H +#define __EXCEPTIONTEST_H + +#include + +// +// 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)); + // This assert fails, since throwThis() throws (Number) + TS_ASSERT_THROWS(throwThis(3), std::exception&); + // 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/third-party/cxxtest/sample/FixtureTest.h b/third-party/cxxtest/sample/FixtureTest.h new file mode 100644 index 00000000..2a350963 --- /dev/null +++ b/third-party/cxxtest/sample/FixtureTest.h @@ -0,0 +1,33 @@ +#ifndef __FIXTURETEST_H +#define __FIXTURETEST_H + +#include +#include + +// +// 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/third-party/cxxtest/sample/Makefile.PL b/third-party/cxxtest/sample/Makefile.PL new file mode 100755 index 00000000..d29afcc6 --- /dev/null +++ b/third-party/cxxtest/sample/Makefile.PL @@ -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/third-party/cxxtest/sample/Makefile.bcc32 b/third-party/cxxtest/sample/Makefile.bcc32 new file mode 100644 index 00000000..3bd5303b --- /dev/null +++ b/third-party/cxxtest/sample/Makefile.bcc32 @@ -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/third-party/cxxtest/sample/Makefile.msvc b/third-party/cxxtest/sample/Makefile.msvc new file mode 100644 index 00000000..2374f802 --- /dev/null +++ b/third-party/cxxtest/sample/Makefile.msvc @@ -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/third-party/cxxtest/sample/Makefile.unix b/third-party/cxxtest/sample/Makefile.unix new file mode 100644 index 00000000..ad87b3bc --- /dev/null +++ b/third-party/cxxtest/sample/Makefile.unix @@ -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/third-party/cxxtest/sample/MessageTest.h b/third-party/cxxtest/sample/MessageTest.h new file mode 100644 index 00000000..d981d35b --- /dev/null +++ b/third-party/cxxtest/sample/MessageTest.h @@ -0,0 +1,27 @@ +#ifndef __MESSAGETEST_H +#define __MESSAGETEST_H + +#include + +// +// 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/third-party/cxxtest/sample/SCons/SConstruct b/third-party/cxxtest/sample/SCons/SConstruct new file mode 100644 index 00000000..cb394084 --- /dev/null +++ b/third-party/cxxtest/sample/SCons/SConstruct @@ -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/third-party/cxxtest/sample/SCons/include/stack.h b/third-party/cxxtest/sample/SCons/include/stack.h new file mode 100644 index 00000000..e73420b9 --- /dev/null +++ b/third-party/cxxtest/sample/SCons/include/stack.h @@ -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/third-party/cxxtest/sample/SCons/src/stack.c b/third-party/cxxtest/sample/SCons/src/stack.c new file mode 100644 index 00000000..960f8cfb --- /dev/null +++ b/third-party/cxxtest/sample/SCons/src/stack.c @@ -0,0 +1,48 @@ +#include + +#include + +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/third-party/cxxtest/sample/SCons/tests/stack_test.h b/third-party/cxxtest/sample/SCons/tests/stack_test.h new file mode 100644 index 00000000..24fd6b52 --- /dev/null +++ b/third-party/cxxtest/sample/SCons/tests/stack_test.h @@ -0,0 +1,71 @@ +#ifndef STACK_TEST_H +#define STACK_TEST_H + +#include +#include + +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/third-party/cxxtest/sample/SimpleTest.h b/third-party/cxxtest/sample/SimpleTest.h new file mode 100644 index 00000000..159b534e --- /dev/null +++ b/third-party/cxxtest/sample/SimpleTest.h @@ -0,0 +1,58 @@ +#ifndef __SIMPLETEST_H +#define __SIMPLETEST_H + +#include + +// +// 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); + const char* tmp = "foo"; + TS_ASSERT_EQUALS("foo", tmp); + } + + 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_SKIP_macro() { + TS_SKIP("Simply skip this test"); + TS_WARN("Skipping will abort the test"); + } + + 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/third-party/cxxtest/sample/TraitsTest.h b/third-party/cxxtest/sample/TraitsTest.h new file mode 100644 index 00000000..ed5a499d --- /dev/null +++ b/third-party/cxxtest/sample/TraitsTest.h @@ -0,0 +1,63 @@ +#ifndef __TRAITSTEST_H +#define __TRAITSTEST_H + +// +// This example shows how to use TS_ASSERT_EQUALS for your own classes +// +#include +#include + +// +// Define your class with operator== +// +#include +#include + +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 and ValueTraits, but some do. +// +namespace CxxTest { +CXXTEST_TEMPLATE_INSTANTIATION +class ValueTraits { + 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/third-party/cxxtest/sample/aborter.tpl b/third-party/cxxtest/sample/aborter.tpl new file mode 100644 index 00000000..14fc50d2 --- /dev/null +++ b/third-party/cxxtest/sample/aborter.tpl @@ -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 + +int main() +{ + return CxxTest::ErrorPrinter().run(); +} + +// The CxxTest "world" + + diff --git a/third-party/cxxtest/sample/file_printer.tpl b/third-party/cxxtest/sample/file_printer.tpl new file mode 100644 index 00000000..a9627d6d --- /dev/null +++ b/third-party/cxxtest/sample/file_printer.tpl @@ -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 +#include + +int main( int argc, char *argv[] ) +{ + if ( argc != 2 ) { + fprintf( stderr, "Usage: %s \n", argv[0] ); + return -1; + } + + return CxxTest::StdioPrinter( fopen( argv[1], "w" ) ).run(); +} + +// The CxxTest "world" + + diff --git a/third-party/cxxtest/sample/gui/GreenYellowRed.h b/third-party/cxxtest/sample/gui/GreenYellowRed.h new file mode 100644 index 00000000..1d1baf1f --- /dev/null +++ b/third-party/cxxtest/sample/gui/GreenYellowRed.h @@ -0,0 +1,57 @@ +#include + +#ifdef _WIN32 +# include +# 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/third-party/cxxtest/sample/mock/Dice.cpp b/third-party/cxxtest/sample/mock/Dice.cpp new file mode 100644 index 00000000..d3f29390 --- /dev/null +++ b/third-party/cxxtest/sample/mock/Dice.cpp @@ -0,0 +1,14 @@ +#include +#include "Dice.h" + +Dice::Dice() +{ + T::srand(T::time(0)); +} + +unsigned Dice::roll() +{ + return (T::rand() % 6) + 1; +} + + diff --git a/third-party/cxxtest/sample/mock/Dice.h b/third-party/cxxtest/sample/mock/Dice.h new file mode 100644 index 00000000..3a393ef2 --- /dev/null +++ b/third-party/cxxtest/sample/mock/Dice.h @@ -0,0 +1,13 @@ +#ifndef __DICE_H +#define __DICE_H + +class Dice +{ +public: + Dice(); + + unsigned roll(); +}; + +#endif // __DICE_H + diff --git a/third-party/cxxtest/sample/mock/Makefile b/third-party/cxxtest/sample/mock/Makefile new file mode 100644 index 00000000..4f40ad28 --- /dev/null +++ b/third-party/cxxtest/sample/mock/Makefile @@ -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/third-party/cxxtest/sample/mock/MockStdlib.h b/third-party/cxxtest/sample/mock/MockStdlib.h new file mode 100644 index 00000000..9398c440 --- /dev/null +++ b/third-party/cxxtest/sample/mock/MockStdlib.h @@ -0,0 +1,33 @@ +#include + +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/third-party/cxxtest/sample/mock/T/stdlib.h b/third-party/cxxtest/sample/mock/T/stdlib.h new file mode 100644 index 00000000..30306ba2 --- /dev/null +++ b/third-party/cxxtest/sample/mock/T/stdlib.h @@ -0,0 +1,13 @@ +#ifndef __T__STDLIB_H +#define __T__STDLIB_H + +#include +#include + +#include + +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/third-party/cxxtest/sample/mock/TestDice.h b/third-party/cxxtest/sample/mock/TestDice.h new file mode 100644 index 00000000..6247607c --- /dev/null +++ b/third-party/cxxtest/sample/mock/TestDice.h @@ -0,0 +1,62 @@ +#include +#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/third-party/cxxtest/sample/mock/mock_stdlib.cpp b/third-party/cxxtest/sample/mock/mock_stdlib.cpp new file mode 100644 index 00000000..148a044d --- /dev/null +++ b/third-party/cxxtest/sample/mock/mock_stdlib.cpp @@ -0,0 +1,2 @@ +#define CXXTEST_MOCK_TEST_SOURCE_FILE +#include diff --git a/third-party/cxxtest/sample/mock/real_stdlib.cpp b/third-party/cxxtest/sample/mock/real_stdlib.cpp new file mode 100644 index 00000000..db02f3a1 --- /dev/null +++ b/third-party/cxxtest/sample/mock/real_stdlib.cpp @@ -0,0 +1,2 @@ +#define CXXTEST_MOCK_REAL_SOURCE_FILE +#include diff --git a/third-party/cxxtest/sample/mock/roll.cpp b/third-party/cxxtest/sample/mock/roll.cpp new file mode 100644 index 00000000..53dd5378 --- /dev/null +++ b/third-party/cxxtest/sample/mock/roll.cpp @@ -0,0 +1,11 @@ +#include +#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/third-party/cxxtest/sample/msvc/CxxTest_1_Run.dsp b/third-party/cxxtest/sample/msvc/CxxTest_1_Run.dsp new file mode 100644 index 00000000..6bc00e7f --- /dev/null +++ b/third-party/cxxtest/sample/msvc/CxxTest_1_Run.dsp @@ -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/third-party/cxxtest/sample/msvc/CxxTest_2_Build.dsp b/third-party/cxxtest/sample/msvc/CxxTest_2_Build.dsp new file mode 100644 index 00000000..04727fd3 --- /dev/null +++ b/third-party/cxxtest/sample/msvc/CxxTest_2_Build.dsp @@ -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/third-party/cxxtest/sample/msvc/CxxTest_3_Generate.dsp b/third-party/cxxtest/sample/msvc/CxxTest_3_Generate.dsp new file mode 100644 index 00000000..5bbad94c --- /dev/null +++ b/third-party/cxxtest/sample/msvc/CxxTest_3_Generate.dsp @@ -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/third-party/cxxtest/sample/msvc/CxxTest_Workspace.dsw b/third-party/cxxtest/sample/msvc/CxxTest_Workspace.dsw new file mode 100644 index 00000000..5dbf8419 --- /dev/null +++ b/third-party/cxxtest/sample/msvc/CxxTest_Workspace.dsw @@ -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/third-party/cxxtest/sample/msvc/FixFiles.bat b/third-party/cxxtest/sample/msvc/FixFiles.bat new file mode 100644 index 00000000..498d98ad --- /dev/null +++ b/third-party/cxxtest/sample/msvc/FixFiles.bat @@ -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 \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/g; + $data =~ s//$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 = + +# Where the CxxTest distribution is unpacked +CXXTESTDIR = + +# 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 "" /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 +'; + +main(); + +__END__ +:endofperl + +rem +rem Local Variables: +rem compile-command: "perl FixFiles.bat" +rem End: +rem diff --git a/third-party/cxxtest/sample/msvc/Makefile b/third-party/cxxtest/sample/msvc/Makefile new file mode 100644 index 00000000..8dd66ca2 --- /dev/null +++ b/third-party/cxxtest/sample/msvc/Makefile @@ -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/third-party/cxxtest/sample/msvc/ReadMe.txt b/third-party/cxxtest/sample/msvc/ReadMe.txt new file mode 100644 index 00000000..9be51e83 --- /dev/null +++ b/third-party/cxxtest/sample/msvc/ReadMe.txt @@ -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/third-party/cxxtest/sample/only.tpl b/third-party/cxxtest/sample/only.tpl new file mode 100644 index 00000000..b2a7277c --- /dev/null +++ b/third-party/cxxtest/sample/only.tpl @@ -0,0 +1,33 @@ +// -*- C++ -*- +#include +#include + +int main( int argc, char *argv[] ) +{ + if ( argc < 2 || argc > 3 ) { + fprintf( stderr, "Usage: only []\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" + + diff --git a/third-party/cxxtest/sample/parts/.cvsignore b/third-party/cxxtest/sample/parts/.cvsignore new file mode 100644 index 00000000..6e091710 --- /dev/null +++ b/third-party/cxxtest/sample/parts/.cvsignore @@ -0,0 +1 @@ +*.cpp *.o runner \ No newline at end of file diff --git a/third-party/cxxtest/sample/parts/Makefile.unix b/third-party/cxxtest/sample/parts/Makefile.unix new file mode 100644 index 00000000..1b78a960 --- /dev/null +++ b/third-party/cxxtest/sample/parts/Makefile.unix @@ -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/third-party/cxxtest/sample/winddk/Makefile b/third-party/cxxtest/sample/winddk/Makefile new file mode 100644 index 00000000..8bf25333 --- /dev/null +++ b/third-party/cxxtest/sample/winddk/Makefile @@ -0,0 +1,2 @@ +# Standard DDK Makefile +!include $(NTMAKEENV)\makefile.def diff --git a/third-party/cxxtest/sample/winddk/Makefile.inc b/third-party/cxxtest/sample/winddk/Makefile.inc new file mode 100644 index 00000000..3d564363 --- /dev/null +++ b/third-party/cxxtest/sample/winddk/Makefile.inc @@ -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/third-party/cxxtest/sample/winddk/RunTests.tpl b/third-party/cxxtest/sample/winddk/RunTests.tpl new file mode 100644 index 00000000..917f14b4 --- /dev/null +++ b/third-party/cxxtest/sample/winddk/RunTests.tpl @@ -0,0 +1,13 @@ +// -*- C++ -*- + +// +// The DDK doesn't handle too well +// +#include + +int __cdecl main() +{ + return CxxTest::StdioPrinter().run(); +} + + diff --git a/third-party/cxxtest/sample/winddk/SOURCES b/third-party/cxxtest/sample/winddk/SOURCES new file mode 100644 index 00000000..dae01488 --- /dev/null +++ b/third-party/cxxtest/sample/winddk/SOURCES @@ -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/third-party/cxxtest/sample/yes_no_runner.cpp b/third-party/cxxtest/sample/yes_no_runner.cpp new file mode 100644 index 00000000..f9d1c2de --- /dev/null +++ b/third-party/cxxtest/sample/yes_no_runner.cpp @@ -0,0 +1,10 @@ +// +// A sample program that uses class YesNoRunner to run all the tests +// and find out if all pass. +// + +#include + +int main() { + return CxxTest::YesNoRunner().run(); +} diff --git a/third-party/cxxtest/test/.cvsignore b/third-party/cxxtest/test/.cvsignore new file mode 100644 index 00000000..e56da81f --- /dev/null +++ b/third-party/cxxtest/test/.cvsignore @@ -0,0 +1 @@ +*pl.cpp *py.cpp *pl.out *py.out *px *px.exe *px.out *build.log *root.cpp diff --git a/third-party/cxxtest/test/AborterNoThrow.h b/third-party/cxxtest/test/AborterNoThrow.h new file mode 100644 index 00000000..b2905e49 --- /dev/null +++ b/third-party/cxxtest/test/AborterNoThrow.h @@ -0,0 +1,19 @@ +#include + +// +// 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/third-party/cxxtest/test/BadTest.h b/third-party/cxxtest/test/BadTest.h new file mode 100644 index 00000000..251e27ec --- /dev/null +++ b/third-party/cxxtest/test/BadTest.h @@ -0,0 +1,55 @@ +#include + +// +// 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/third-party/cxxtest/test/Comments.h b/third-party/cxxtest/test/Comments.h new file mode 100644 index 00000000..e674d4c0 --- /dev/null +++ b/third-party/cxxtest/test/Comments.h @@ -0,0 +1,24 @@ +#include + +// +// 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/third-party/cxxtest/test/Comments2.h b/third-party/cxxtest/test/Comments2.h new file mode 100644 index 00000000..9cb5bf44 --- /dev/null +++ b/third-party/cxxtest/test/Comments2.h @@ -0,0 +1,21 @@ +#include + +// +// 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/third-party/cxxtest/test/CppTemplateTest.h b/third-party/cxxtest/test/CppTemplateTest.h new file mode 100644 index 00000000..21d80fef --- /dev/null +++ b/third-party/cxxtest/test/CppTemplateTest.h @@ -0,0 +1,39 @@ +#include + +template +class Tests +{ +public: + + CXXTEST_STD(list)* cache; + + void setUp() + { + this->cache = new CXXTEST_STD(list)(); + } + + void tearDown() + { + delete this->cache; + } + + 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, public CxxTest::TestSuite +{ +public: + + void setUp() { Tests::setUp(); } + void tearDown() { Tests::tearDown(); } +}; diff --git a/third-party/cxxtest/test/DeepAbort.h b/third-party/cxxtest/test/DeepAbort.h new file mode 100644 index 00000000..cd832e2b --- /dev/null +++ b/third-party/cxxtest/test/DeepAbort.h @@ -0,0 +1,84 @@ +#include + +// +// 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/third-party/cxxtest/test/DefaultAbort.h b/third-party/cxxtest/test/DefaultAbort.h new file mode 100644 index 00000000..7902ef67 --- /dev/null +++ b/third-party/cxxtest/test/DefaultAbort.h @@ -0,0 +1,3 @@ +#define CXXTEST_HAVE_EH +#define CXXTEST_ABORT_TEST_ON_FAIL +#define CXXTEST_DEFAULT_ABORT false diff --git a/third-party/cxxtest/test/DefaultTraits.h b/third-party/cxxtest/test/DefaultTraits.h new file mode 100644 index 00000000..eead6698 --- /dev/null +++ b/third-party/cxxtest/test/DefaultTraits.h @@ -0,0 +1,41 @@ +#include + +// +// 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/third-party/cxxtest/test/DoubleCall.h b/third-party/cxxtest/test/DoubleCall.h new file mode 100644 index 00000000..65256b1c --- /dev/null +++ b/third-party/cxxtest/test/DoubleCall.h @@ -0,0 +1,38 @@ +#include + +// +// 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/third-party/cxxtest/test/DynamicAbort.h b/third-party/cxxtest/test/DynamicAbort.h new file mode 100644 index 00000000..c6f8270b --- /dev/null +++ b/third-party/cxxtest/test/DynamicAbort.h @@ -0,0 +1,52 @@ +#include + +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/third-party/cxxtest/test/DynamicMax.h b/third-party/cxxtest/test/DynamicMax.h new file mode 100644 index 00000000..cb934e85 --- /dev/null +++ b/third-party/cxxtest/test/DynamicMax.h @@ -0,0 +1,67 @@ +#include + +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/third-party/cxxtest/test/EmptySuite.h b/third-party/cxxtest/test/EmptySuite.h new file mode 100644 index 00000000..c4421d92 --- /dev/null +++ b/third-party/cxxtest/test/EmptySuite.h @@ -0,0 +1,16 @@ +#include + +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/third-party/cxxtest/test/Exceptions.h b/third-party/cxxtest/test/Exceptions.h new file mode 100644 index 00000000..b9cddb36 --- /dev/null +++ b/third-party/cxxtest/test/Exceptions.h @@ -0,0 +1,70 @@ +#include + +// +// 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 *suite) { delete suite; 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/third-party/cxxtest/test/Factor.h b/third-party/cxxtest/test/Factor.h new file mode 100644 index 00000000..1af08acc --- /dev/null +++ b/third-party/cxxtest/test/Factor.h @@ -0,0 +1,69 @@ +// +// This file is used to test WorldDescription::strTotalTests() +// + +#include +#include + +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/third-party/cxxtest/test/ForceNoEh.h b/third-party/cxxtest/test/ForceNoEh.h new file mode 100644 index 00000000..e46470ea --- /dev/null +++ b/third-party/cxxtest/test/ForceNoEh.h @@ -0,0 +1,16 @@ +#include + +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/third-party/cxxtest/test/GfSetUpFails.h b/third-party/cxxtest/test/GfSetUpFails.h new file mode 100644 index 00000000..912aab66 --- /dev/null +++ b/third-party/cxxtest/test/GfSetUpFails.h @@ -0,0 +1,28 @@ +// +// This file tests what happens when GlobalFixture::setUp() fails +// + +#include +#include +#include + +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/third-party/cxxtest/test/GfSetUpThrows.h b/third-party/cxxtest/test/GfSetUpThrows.h new file mode 100644 index 00000000..6e83d528 --- /dev/null +++ b/third-party/cxxtest/test/GfSetUpThrows.h @@ -0,0 +1,28 @@ +// +// This file tests what happens when GlobalFixture::setUp() throws +// + +#include +#include +#include + +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/third-party/cxxtest/test/GfTearDownFails.h b/third-party/cxxtest/test/GfTearDownFails.h new file mode 100644 index 00000000..797ea93b --- /dev/null +++ b/third-party/cxxtest/test/GfTearDownFails.h @@ -0,0 +1,26 @@ +// +// This file tests what happens when GlobalFixture::tearDown() fails +// + +#include +#include +#include + +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/third-party/cxxtest/test/GfTearDownThrows.h b/third-party/cxxtest/test/GfTearDownThrows.h new file mode 100644 index 00000000..40d4847a --- /dev/null +++ b/third-party/cxxtest/test/GfTearDownThrows.h @@ -0,0 +1,26 @@ +// +// This file tests what happens when GlobalFixture::tearDown() throws +// + +#include +#include +#include + +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/third-party/cxxtest/test/GlobalFixtures.h b/third-party/cxxtest/test/GlobalFixtures.h new file mode 100644 index 00000000..72c07893 --- /dev/null +++ b/third-party/cxxtest/test/GlobalFixtures.h @@ -0,0 +1,72 @@ +// +// This file tests CxxTest global fixtures +// + +#include +#include + +// +// 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/third-party/cxxtest/test/GoodSuite.h b/third-party/cxxtest/test/GoodSuite.h new file mode 100644 index 00000000..251492b9 --- /dev/null +++ b/third-party/cxxtest/test/GoodSuite.h @@ -0,0 +1,114 @@ +#include +#include + +// +// 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/third-party/cxxtest/test/GuiWait.h b/third-party/cxxtest/test/GuiWait.h new file mode 100644 index 00000000..a0b871c2 --- /dev/null +++ b/third-party/cxxtest/test/GuiWait.h @@ -0,0 +1,6 @@ +#ifndef __GUI_WAIT_H +#define __GUI_WAIT_H + +#define CXXTEST_SAMPLE_GUI_WAIT() + +#endif // __GUI_WAIT_H diff --git a/third-party/cxxtest/test/HaveEH.tpl b/third-party/cxxtest/test/HaveEH.tpl new file mode 100644 index 00000000..7e01a1d3 --- /dev/null +++ b/third-party/cxxtest/test/HaveEH.tpl @@ -0,0 +1,10 @@ +#define CXXTEST_HAVE_EH +#include + +int main( int argc, char *argv[] ) { + CxxTest::ErrorPrinter tmp; + return CxxTest::Main( tmp, argc, argv ); +} + +// The CxxTest "world" + diff --git a/third-party/cxxtest/test/HaveStd.h b/third-party/cxxtest/test/HaveStd.h new file mode 100644 index 00000000..621a481a --- /dev/null +++ b/third-party/cxxtest/test/HaveStd.h @@ -0,0 +1,15 @@ +#include + +// +// 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/third-party/cxxtest/test/HaveStd.tpl b/third-party/cxxtest/test/HaveStd.tpl new file mode 100644 index 00000000..63743a26 --- /dev/null +++ b/third-party/cxxtest/test/HaveStd.tpl @@ -0,0 +1,10 @@ +#define CXXTEST_HAVE_STD +#include + +int main( int argc, char *argv[] ) { + CxxTest::ErrorPrinter tmp; + return CxxTest::Main( tmp, argc, argv ); +} + +// The CxxTest "world" + diff --git a/third-party/cxxtest/test/IncludeTest.h b/third-party/cxxtest/test/IncludeTest.h new file mode 100644 index 00000000..9deb6c9e --- /dev/null +++ b/third-party/cxxtest/test/IncludeTest.h @@ -0,0 +1,15 @@ +#include + +// +// 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/third-party/cxxtest/test/InheritedTest.h b/third-party/cxxtest/test/InheritedTest.h new file mode 100644 index 00000000..f4209d59 --- /dev/null +++ b/third-party/cxxtest/test/InheritedTest.h @@ -0,0 +1,65 @@ +#ifndef __INHERITANCETEST_H +#define __INHERITANCETEST_H + +#include + +// +// 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/third-party/cxxtest/test/Int64.h b/third-party/cxxtest/test/Int64.h new file mode 100644 index 00000000..737c5b29 --- /dev/null +++ b/third-party/cxxtest/test/Int64.h @@ -0,0 +1,16 @@ +#include + +// +// 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/third-party/cxxtest/test/LessThanEquals.h b/third-party/cxxtest/test/LessThanEquals.h new file mode 100644 index 00000000..494f7e99 --- /dev/null +++ b/third-party/cxxtest/test/LessThanEquals.h @@ -0,0 +1,22 @@ +#include + +// +// 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/third-party/cxxtest/test/LongLong.h b/third-party/cxxtest/test/LongLong.h new file mode 100644 index 00000000..8d52052b --- /dev/null +++ b/third-party/cxxtest/test/LongLong.h @@ -0,0 +1,16 @@ +#include + +// +// 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/third-party/cxxtest/test/LongTraits.h b/third-party/cxxtest/test/LongTraits.h new file mode 100644 index 00000000..89c0479e --- /dev/null +++ b/third-party/cxxtest/test/LongTraits.h @@ -0,0 +1,16 @@ +// +// This include file is used to test the --include option +// + +#include + +namespace CxxTest +{ +CXXTEST_TEMPLATE_INSTANTIATION +class ValueTraits +{ +public: + ValueTraits(long *) {} + const char *asString() { return "(long *)"; } +}; +} diff --git a/third-party/cxxtest/test/Makefile b/third-party/cxxtest/test/Makefile new file mode 100644 index 00000000..21990073 --- /dev/null +++ b/third-party/cxxtest/test/Makefile @@ -0,0 +1,11 @@ +# +# Some convenient ways of running the self tests +# + +all: + lpython test_cxxtest.py + +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/third-party/cxxtest/test/MaxDump.h b/third-party/cxxtest/test/MaxDump.h new file mode 100644 index 00000000..4c332892 --- /dev/null +++ b/third-party/cxxtest/test/MaxDump.h @@ -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/third-party/cxxtest/test/MockTest.h b/third-party/cxxtest/test/MockTest.h new file mode 100644 index 00000000..b54f7cc2 --- /dev/null +++ b/third-party/cxxtest/test/MockTest.h @@ -0,0 +1,182 @@ +// +// This is a test of CxxTest's Mock framework (not a mock test). +// +#include + +// +// 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_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/third-party/cxxtest/test/Namespace1.h b/third-party/cxxtest/test/Namespace1.h new file mode 100644 index 00000000..9250b8aa --- /dev/null +++ b/third-party/cxxtest/test/Namespace1.h @@ -0,0 +1,72 @@ +#ifndef __NAMESPACE1_H +#define __NAMESPACE1_H + +#include + +// +// A simple test suite: Just inherit CxxTest::TestSuite and write tests! +// + +namespace foo { +namespace bar { + +class Tests : 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"); + } +}; + +} +} + +namespace FOO { +namespace BAR { + +class Tests : 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); + } +}; + +} +} + +#endif // __NAMESPACE1_H diff --git a/third-party/cxxtest/test/Namespace2.h b/third-party/cxxtest/test/Namespace2.h new file mode 100644 index 00000000..b6953a72 --- /dev/null +++ b/third-party/cxxtest/test/Namespace2.h @@ -0,0 +1,68 @@ +#ifndef __NAMESPACE2_H +#define __NAMESPACE2_H + +#include + +// +// A simple test suite: Just inherit CxxTest::TestSuite and write tests! +// + +// Declare Tests in the appropriate namespace +namespace foo { namespace bar { class Tests; } } + +// Use explicit namespace declaration +class foo::bar::Tests : 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"); + } +}; + +// Declare Tests in the appropriate namespace +namespace FOO { namespace BAR { class Tests; } } + +// Use explicit namespace declaration +class FOO::BAR::Tests : 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); + } +}; + +#endif // __NAMESPACE2_H diff --git a/third-party/cxxtest/test/NoEh.h b/third-party/cxxtest/test/NoEh.h new file mode 100644 index 00000000..247b1c8e --- /dev/null +++ b/third-party/cxxtest/test/NoEh.h @@ -0,0 +1,11 @@ +#include + +class NoEh : public CxxTest::TestSuite +{ +public: + void testCxxTestCanCompileWithoutExceptionHandling() + { + TS_ASSERT_EQUALS(1, 2); + TS_ASSERT_EQUALS(2, 3); + } +}; diff --git a/third-party/cxxtest/test/Part1.h b/third-party/cxxtest/test/Part1.h new file mode 100644 index 00000000..1a5d73ba --- /dev/null +++ b/third-party/cxxtest/test/Part1.h @@ -0,0 +1,18 @@ +#include + +// +// 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/third-party/cxxtest/test/Part2.h b/third-party/cxxtest/test/Part2.h new file mode 100644 index 00000000..475795ca --- /dev/null +++ b/third-party/cxxtest/test/Part2.h @@ -0,0 +1,18 @@ +#include + +// +// 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/third-party/cxxtest/test/Relation.h b/third-party/cxxtest/test/Relation.h new file mode 100644 index 00000000..fef937cd --- /dev/null +++ b/third-party/cxxtest/test/Relation.h @@ -0,0 +1,41 @@ +#include + +struct MyNegative +{ + bool operator()(const int &i) const { return i < 0; } +}; + +template +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 , 2, 1); + TSM_ASSERT_RELATION("2 , 2, 1); + try { ETS_ASSERT_RELATION(MyLess, throwInt(1), throwInt(1)); } + catch (int i) { TS_WARN(i); } + try { ETSM_ASSERT_RELATION("2 , throwInt(1), throwInt(1)); } + catch (int i) { TS_WARN(i); } + } + + int throwInt(int i) + { + throw i; + } +}; diff --git a/third-party/cxxtest/test/SameData.h b/third-party/cxxtest/test/SameData.h new file mode 100644 index 00000000..03b05c7d --- /dev/null +++ b/third-party/cxxtest/test/SameData.h @@ -0,0 +1,41 @@ +#include + +// +// 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/third-party/cxxtest/test/SameFiles.h b/third-party/cxxtest/test/SameFiles.h new file mode 100644 index 00000000..7e6c93c1 --- /dev/null +++ b/third-party/cxxtest/test/SameFiles.h @@ -0,0 +1,41 @@ +#include + +// +// 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/third-party/cxxtest/test/SameFilesLonger.h b/third-party/cxxtest/test/SameFilesLonger.h new file mode 100644 index 00000000..3115e0e5 --- /dev/null +++ b/third-party/cxxtest/test/SameFilesLonger.h @@ -0,0 +1,42 @@ +#include + +// +// 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/third-party/cxxtest/test/SameZero.h b/third-party/cxxtest/test/SameZero.h new file mode 100644 index 00000000..78cbf970 --- /dev/null +++ b/third-party/cxxtest/test/SameZero.h @@ -0,0 +1,28 @@ +#include + +// +// 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/third-party/cxxtest/test/SetUpWorldError.h b/third-party/cxxtest/test/SetUpWorldError.h new file mode 100644 index 00000000..653e201b --- /dev/null +++ b/third-party/cxxtest/test/SetUpWorldError.h @@ -0,0 +1,34 @@ +// +// This file tests what happens when setUpWorld() fails +// + +#include +#include +#include + +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/third-party/cxxtest/test/SetUpWorldFails.h b/third-party/cxxtest/test/SetUpWorldFails.h new file mode 100644 index 00000000..29d9ff4c --- /dev/null +++ b/third-party/cxxtest/test/SetUpWorldFails.h @@ -0,0 +1,28 @@ +// +// This file tests what happens when setUpWorld() fails +// + +#include +#include +#include + +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/third-party/cxxtest/test/SetUpWorldThrows.h b/third-party/cxxtest/test/SetUpWorldThrows.h new file mode 100644 index 00000000..85c226de --- /dev/null +++ b/third-party/cxxtest/test/SetUpWorldThrows.h @@ -0,0 +1,28 @@ +// +// This file tests what happens when setUpWorld() throws an exception +// + +#include +#include +#include + +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/third-party/cxxtest/test/SimpleInheritedTest.h b/third-party/cxxtest/test/SimpleInheritedTest.h new file mode 100644 index 00000000..e61a980c --- /dev/null +++ b/third-party/cxxtest/test/SimpleInheritedTest.h @@ -0,0 +1,36 @@ +#include + +class Tests : public CxxTest::TestSuite +{ +public: + + CXXTEST_STD(list)* cache; + + void setUp() + { + this->cache = new CXXTEST_STD(list)(); + } + + void tearDown() + { delete this->cache; } + + 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/third-party/cxxtest/test/SimpleInheritedTest2.h b/third-party/cxxtest/test/SimpleInheritedTest2.h new file mode 100644 index 00000000..554fc3a2 --- /dev/null +++ b/third-party/cxxtest/test/SimpleInheritedTest2.h @@ -0,0 +1,38 @@ +#include + +class Tests +{ +public: + + CXXTEST_STD(list)* cache; + + void setUp() + { + this->cache = new CXXTEST_STD(list)(); + } + + void tearDown() + { delete this->cache; } + + 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::tearDown();} +}; + diff --git a/third-party/cxxtest/test/Something.h b/third-party/cxxtest/test/Something.h new file mode 100644 index 00000000..4e8b8848 --- /dev/null +++ b/third-party/cxxtest/test/Something.h @@ -0,0 +1,3 @@ +#include + +inline std::string something() { return "something"; } diff --git a/third-party/cxxtest/test/StlTraits.h b/third-party/cxxtest/test/StlTraits.h new file mode 100644 index 00000000..e1e3129f --- /dev/null +++ b/third-party/cxxtest/test/StlTraits.h @@ -0,0 +1,152 @@ +#include + +class StlTraits : public CxxTest::TestSuite +{ +public: + typedef CXXTEST_STD(string) String; + typedef CXXTEST_STD(pair) IntString; + typedef CXXTEST_STD(pair) 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) v; + TS_TRACE(v); + v.push_back(1); + v.push_back(2); + v.push_back(3); + TS_FAIL(v); + + CXXTEST_STD(vector) w; + TS_TRACE(w); + w.push_back("One"); + w.push_back("Two"); + w.push_back("Three"); + TS_FAIL(w); + + CXXTEST_STD(vector) 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) v; + TS_TRACE(v); + v.push_back(1); + v.push_back(2); + v.push_back(3); + TS_FAIL(v); + + CXXTEST_STD(list) w; + TS_TRACE(w); + w.push_back("One"); + w.push_back("Two"); + w.push_back("Three"); + TS_FAIL(w); + + CXXTEST_STD(list) 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) v; + TS_TRACE(v); + v.insert(1); + v.insert(2); + v.insert(3); + TS_FAIL(v); + + CXXTEST_STD(set) w; + TS_TRACE(w); + w.insert("One"); + w.insert("Two"); + w.insert("Three"); + TS_FAIL(w); + + CXXTEST_STD(set) 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) m; + TS_TRACE(m); + + m["Jack"] = "Jill"; + m["Humpty"] = "Dumpty"; + m["Ren"] = "Stimpy"; + + TS_FAIL(m); + + CXXTEST_STD(map)< unsigned, CXXTEST_STD(list) > 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) 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) 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) ms; + TS_TRACE(ms); + + ms.insert(123); + ms.insert(456); + TS_FAIL(ms); + } + + void test_Complex() + { + typedef CXXTEST_STD(complex) 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/third-party/cxxtest/test/TearDownWorldFails.h b/third-party/cxxtest/test/TearDownWorldFails.h new file mode 100644 index 00000000..c1cb8606 --- /dev/null +++ b/third-party/cxxtest/test/TearDownWorldFails.h @@ -0,0 +1,25 @@ +// +// This file tests what happens when GlobalFixture::tearDownWorld() fails +// + +#include +#include +#include + +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/third-party/cxxtest/test/TearDownWorldThrows.h b/third-party/cxxtest/test/TearDownWorldThrows.h new file mode 100644 index 00000000..fa634590 --- /dev/null +++ b/third-party/cxxtest/test/TearDownWorldThrows.h @@ -0,0 +1,25 @@ +// +// This file tests what happens when GlobalFixture::tearDownWorld() throws +// + +#include +#include +#include + +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/third-party/cxxtest/test/TestNonFinite.h b/third-party/cxxtest/test/TestNonFinite.h new file mode 100644 index 00000000..0f96482b --- /dev/null +++ b/third-party/cxxtest/test/TestNonFinite.h @@ -0,0 +1,33 @@ +#include + +// 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/third-party/cxxtest/test/ThrowNoStd.h b/third-party/cxxtest/test/ThrowNoStd.h new file mode 100644 index 00000000..fe53c245 --- /dev/null +++ b/third-party/cxxtest/test/ThrowNoStd.h @@ -0,0 +1,10 @@ +#include + +class ThrowNoStd : public CxxTest::TestSuite +{ +public: + void testThrowNoStd() + { + TS_ASSERT_THROWS( { throw 1; }, int); + } +}; diff --git a/third-party/cxxtest/test/ThrowNoStd.tpl b/third-party/cxxtest/test/ThrowNoStd.tpl new file mode 100644 index 00000000..0df329bb --- /dev/null +++ b/third-party/cxxtest/test/ThrowNoStd.tpl @@ -0,0 +1,10 @@ +#define CXXTEST_ABORT_TEST_ON_FAIL +#include + +int main() +{ + return CxxTest::ErrorPrinter().run(); +} + +// The CxxTest "world" + diff --git a/third-party/cxxtest/test/ThrowsAssert.h b/third-party/cxxtest/test/ThrowsAssert.h new file mode 100644 index 00000000..36e78239 --- /dev/null +++ b/third-party/cxxtest/test/ThrowsAssert.h @@ -0,0 +1,101 @@ +#include + +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/third-party/cxxtest/test/TraitsTest.h b/third-party/cxxtest/test/TraitsTest.h new file mode 100644 index 00000000..16d65f6e --- /dev/null +++ b/third-party/cxxtest/test/TraitsTest.h @@ -0,0 +1,61 @@ +#define CXXTEST_HAVE_STD +#include + +// +// 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/third-party/cxxtest/test/Tsm.h b/third-party/cxxtest/test/Tsm.h new file mode 100644 index 00000000..0a5c7601 --- /dev/null +++ b/third-party/cxxtest/test/Tsm.h @@ -0,0 +1,53 @@ +#include + +// +// 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/third-party/cxxtest/test/UserTraits.h b/third-party/cxxtest/test/UserTraits.h new file mode 100644 index 00000000..6b34d520 --- /dev/null +++ b/third-party/cxxtest/test/UserTraits.h @@ -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 which converts to hex notation +// +#include +#include + +namespace CxxTest +{ +CXXTEST_TEMPLATE_INSTANTIATION +class ValueTraits +{ + 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/third-party/cxxtest/test/UserTraits.tpl b/third-party/cxxtest/test/UserTraits.tpl new file mode 100644 index 00000000..9a694789 --- /dev/null +++ b/third-party/cxxtest/test/UserTraits.tpl @@ -0,0 +1,20 @@ +// -*- C++ -*- +// See UserTraits.h + +#define CXXTEST_USER_VALUE_TRAITS +#include + +int main() +{ + return CxxTest::ErrorPrinter().run(); +} + +// The CxxTest "world" + + + +// +// Local Variables: +// compile-command: "perl test.pl" +// End: +// diff --git a/third-party/cxxtest/test/VoidTraits.h b/third-party/cxxtest/test/VoidTraits.h new file mode 100644 index 00000000..6f0002c8 --- /dev/null +++ b/third-party/cxxtest/test/VoidTraits.h @@ -0,0 +1,20 @@ +// +// This include file is used to test the --include option +// + +#ifdef CXXTEST_RUNNING + +#include + +namespace CxxTest +{ +CXXTEST_TEMPLATE_INSTANTIATION +class ValueTraits +{ +public: + ValueTraits(void *) {} + const char *asString(void) { return "(void *)"; } +}; +} + +#endif diff --git a/third-party/cxxtest/test/WideCharTest.h b/third-party/cxxtest/test/WideCharTest.h new file mode 100644 index 00000000..ddef0ee0 --- /dev/null +++ b/third-party/cxxtest/test/WideCharTest.h @@ -0,0 +1,18 @@ +#define CXXTEST_HAVE_STD +#include +#include + +// +// 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(L"std::wstring is displayed with L\"\"")); + wchar_t array[] = { (wchar_t)0x1234, (wchar_t)0x5678 }; + TS_FAIL(std::basic_string(array, 2)); + } +}; diff --git a/third-party/cxxtest/test/WorldFixtures.h b/third-party/cxxtest/test/WorldFixtures.h new file mode 100644 index 00000000..c50963ce --- /dev/null +++ b/third-party/cxxtest/test/WorldFixtures.h @@ -0,0 +1,40 @@ +// +// This file tests CxxTest global fixtures setUpWorld()/tearDownWorld() +// + +#include +#include +#include + +class PrintingFixture : public CxxTest::GlobalFixture +{ +public: + bool setUpWorld() { printf(""); return true; } + bool tearDownWorld() { printf(""); return true; } + bool setUp() { printf(""); return true; } + bool tearDown() { printf(""); 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/third-party/cxxtest/test/__init__.py b/third-party/cxxtest/test/__init__.py new file mode 100644 index 00000000..6e4575df --- /dev/null +++ b/third-party/cxxtest/test/__init__.py @@ -0,0 +1,10 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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. +#------------------------------------------------------------------------- + +# Dummy __init__ file for nosetests diff --git a/third-party/cxxtest/test/abort.out b/third-party/cxxtest/test/abort.out new file mode 100644 index 00000000..f6c37323 --- /dev/null +++ b/third-party/cxxtest/test/abort.out @@ -0,0 +1,111 @@ +Running cxxtest tests (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( 2, 1 ), found !MyLess( 2, 1 ) +In DefaultTraits::testSmallDefaultTraits: +DefaultTraits.h:23: Error: Test failed: { 00 01 02 03 04 05 06 07 } +In DefaultTraits::testBigDefaultTraits: +DefaultTraits.h:39: 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:24: 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:29: Error: Test failed: Not same data +SameData.h:29: 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:34: 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:39: Error: Test failed: Not same data +SameData.h:39: 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 += += // +< // 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 += += // +< // 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:22: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found: +{ 00 01 02 03 } +differs from +(null) +Failed 28 and Skipped 0 of 35 tests +Success rate: 20% +Error level = 28 diff --git a/third-party/cxxtest/test/activate.tpl b/third-party/cxxtest/test/activate.tpl new file mode 100644 index 00000000..25dc7731 --- /dev/null +++ b/third-party/cxxtest/test/activate.tpl @@ -0,0 +1,19 @@ +// -*- C++ -*- +# include +# include + +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" + + diff --git a/third-party/cxxtest/test/anything.cpp b/third-party/cxxtest/test/anything.cpp new file mode 100644 index 00000000..e2329403 --- /dev/null +++ b/third-party/cxxtest/test/anything.cpp @@ -0,0 +1,6 @@ +// This simple source file is just used to verify that the compiler works + +int main() +{ + return 0; +} diff --git a/third-party/cxxtest/test/bad.out b/third-party/cxxtest/test/bad.out new file mode 100644 index 00000000..df3063bb --- /dev/null +++ b/third-party/cxxtest/test/bad.out @@ -0,0 +1,24 @@ +Running cxxtest tests (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 and Skipped 0 of 7 tests +Success rate: 14% +Error level = 6 diff --git a/third-party/cxxtest/test/comments.out b/third-party/cxxtest/test/comments.out new file mode 100644 index 00000000..b59d199e --- /dev/null +++ b/third-party/cxxtest/test/comments.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test) +In Comments::test_Something: +Comments.h:12: Warning: Something +.OK! +Error level = 0 diff --git a/third-party/cxxtest/test/comments2.out b/third-party/cxxtest/test/comments2.out new file mode 100644 index 00000000..46465109 --- /dev/null +++ b/third-party/cxxtest/test/comments2.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test) +In Comments::test_Something: +Comments2.h:12: Warning: Something +.OK! +Error level = 0 diff --git a/third-party/cxxtest/test/cxxtest/DummyGui.h b/third-party/cxxtest/test/cxxtest/DummyGui.h new file mode 100644 index 00000000..1f948f98 --- /dev/null +++ b/third-party/cxxtest/test/cxxtest/DummyGui.h @@ -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 +#include +#include + +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/third-party/cxxtest/test/default_abort.out b/third-party/cxxtest/test/default_abort.out new file mode 100644 index 00000000..7f2019c6 --- /dev/null +++ b/third-party/cxxtest/test/default_abort.out @@ -0,0 +1,120 @@ +Running cxxtest tests (32 tests) +In NullCreate::: +Exceptions.h:10: Error: Test failed: createSuite() failed +Exceptions.h:10: Error: Assertion failed: suite() != 0 +In ThrowCreate::: +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::: +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 and Skipped 0 of 32 tests +Success rate: 3% +Error level = 31 diff --git a/third-party/cxxtest/test/eh_normals.out b/third-party/cxxtest/test/eh_normals.out new file mode 100644 index 00000000..70f484af --- /dev/null +++ b/third-party/cxxtest/test/eh_normals.out @@ -0,0 +1,44 @@ +Running cxxtest tests (13 tests) +In NullCreate::: +Exceptions.h:10: Error: Test failed: createSuite() failed +Exceptions.h:10: Error: Assertion failed: suite() != 0 +In ThrowCreate::: +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::: +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 and Skipped 0 of 13 tests +Success rate: 7% +Error level = 12 diff --git a/third-party/cxxtest/test/eh_plus_abort.out b/third-party/cxxtest/test/eh_plus_abort.out new file mode 100644 index 00000000..b0ea9794 --- /dev/null +++ b/third-party/cxxtest/test/eh_plus_abort.out @@ -0,0 +1,63 @@ +Running cxxtest tests (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 and Skipped 0 of 25 tests +Success rate: 0% +Error level = 25 diff --git a/third-party/cxxtest/test/error.out b/third-party/cxxtest/test/error.out new file mode 100644 index 00000000..a8042e42 --- /dev/null +++ b/third-party/cxxtest/test/error.out @@ -0,0 +1,55 @@ +Running cxxtest tests (16 tests) +In CreatedTest::test_nothing: +CreatedTest.h:24: Error: Test failed: Nothing to test +.. +In EnumTraits::test_Enum_traits: +EnumTraits.h:30: Error: Test failed: Yes +EnumTraits.h:31: Error: Test failed: No +EnumTraits.h:32: Error: Test failed: Maybe +EnumTraits.h:33: Error: Test failed: DontKnow +EnumTraits.h:34: Error: Test failed: DontCare +EnumTraits.h:35: Error: Test failed: (Answer)1000 +In ExceptionTest::testAssertion: +ExceptionTest.h:18: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else +ExceptionTest.h:20: Error: Expected (goodFunction(1)) to throw (...) but it didn't throw +ExceptionTest.h:22: Error: Test failed: Unhandled exception +ExceptionTest.h:24: Error: Expected (throwThis(-1)) not to throw, but it did +ExceptionTest.h:26: Error: Expected (throwThis(3)) to throw (std::exception&) but it threw something else +ExceptionTest.h:31: Error: Test failed: throwThis(3) failed +In FixtureTest::test_strcpy: +FixtureTest.h:28: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E') +In MessageTest::testValues: +MessageTest.h:21: Error: Test failed: My hovercraft +MessageTest.h:21: Error: Assertion failed: value != 0 +MessageTest.h:22: Error: Test failed: of eels +MessageTest.h:22: Error: Expected (value == value * value), found (2 != 4) +In SimpleTest::testEquality: +SimpleTest.h:14: Error: Expected (1 == 2), found (1 != 2) +SimpleTest.h:15: Error: Expected ('a' == 'A'), found ('a' != 'A') +SimpleTest.h:16: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50) +In SimpleTest::testAddition: +SimpleTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5) +In SimpleTest::TestMultiplication: +SimpleTest.h:28: Error: Expected (4 * 4 == 44), found (16 != 44) +SimpleTest.h:29: Error: Expected (-2 * -2 != 4), found (4) +In SimpleTest::testComparison: +SimpleTest.h:34: Error: Expected (-1 < -2), found (-1 >= -2) +In SimpleTest::testTheWorldIsCrazy: +SimpleTest.h:38: Error: Expected (true == false), found (true != false) +In SimpleTest::test_Failure: +SimpleTest.h:42: Error: Test failed: Not implemented +SimpleTest.h:43: Error: Test failed: 1569779912 +In SimpleTest::test_TS_SKIP_macro: +SimpleTest.h:47: Warning: Test skipped: Simply skip this test +s +In SimpleTest::test_TS_WARN_macro: +SimpleTest.h:52: Warning: Just a friendly warning +SimpleTest.h:53: Warning: Warnings don't abort the test +. +In TestFunky::testPets: +TraitsTest.h:53: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat")) +TraitsTest.h:55: Error: Expected (cat != gato), found (Pet("cat")) +TraitsTest.h:58: Error: Expected (String("Hello") == String("World!")), found ("Hello" != "World!") +Failed 12 and Skipped 1 of 16 tests +Success rate: 20% +Error level = 12 diff --git a/third-party/cxxtest/test/factor.out b/third-party/cxxtest/test/factor.out new file mode 100644 index 00000000..53d6a26c --- /dev/null +++ b/third-party/cxxtest/test/factor.out @@ -0,0 +1,72 @@ +Running cxxtest tests (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/third-party/cxxtest/test/fake/.cvsignore b/third-party/cxxtest/test/fake/.cvsignore new file mode 100644 index 00000000..782a42d2 --- /dev/null +++ b/third-party/cxxtest/test/fake/.cvsignore @@ -0,0 +1 @@ +*.cpp *_runner* \ No newline at end of file diff --git a/third-party/cxxtest/test/fake/X11/Xlib.h b/third-party/cxxtest/test/fake/X11/Xlib.h new file mode 100644 index 00000000..05eddd10 --- /dev/null +++ b/third-party/cxxtest/test/fake/X11/Xlib.h @@ -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/third-party/cxxtest/test/fake/X11/Xutil.h b/third-party/cxxtest/test/fake/X11/Xutil.h new file mode 100644 index 00000000..b2da5139 --- /dev/null +++ b/third-party/cxxtest/test/fake/X11/Xutil.h @@ -0,0 +1 @@ +// Fake Xutil.h diff --git a/third-party/cxxtest/test/fake/commctrl.h b/third-party/cxxtest/test/fake/commctrl.h new file mode 100644 index 00000000..baf3d3d1 --- /dev/null +++ b/third-party/cxxtest/test/fake/commctrl.h @@ -0,0 +1,26 @@ +#ifndef __FAKE__COMMCTRL_H__ +#define __FAKE__COMMCTRL_H__ + +#include + +#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/third-party/cxxtest/test/fake/qapplication.h b/third-party/cxxtest/test/fake/qapplication.h new file mode 100644 index 00000000..e04b9a9b --- /dev/null +++ b/third-party/cxxtest/test/fake/qapplication.h @@ -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/third-party/cxxtest/test/fake/qglobal.h b/third-party/cxxtest/test/fake/qglobal.h new file mode 100644 index 00000000..7ae8e675 --- /dev/null +++ b/third-party/cxxtest/test/fake/qglobal.h @@ -0,0 +1,2 @@ +// fake qglobal.h +#define QT_VERSION 0x030000 diff --git a/third-party/cxxtest/test/fake/qlabel.h b/third-party/cxxtest/test/fake/qlabel.h new file mode 100644 index 00000000..01afd9a8 --- /dev/null +++ b/third-party/cxxtest/test/fake/qlabel.h @@ -0,0 +1,10 @@ +// fake QLabel +#include +#include + +class QLabel +{ +public: + QLabel(void *) {} + void setText(const QString &) {} +}; diff --git a/third-party/cxxtest/test/fake/qlayout.h b/third-party/cxxtest/test/fake/qlayout.h new file mode 100644 index 00000000..e406cde6 --- /dev/null +++ b/third-party/cxxtest/test/fake/qlayout.h @@ -0,0 +1,8 @@ +// fake qlayout.h + +class QVBoxLayout +{ +public: + QVBoxLayout(void *) {} + void addWidget(void *) {} +}; diff --git a/third-party/cxxtest/test/fake/qmessagebox.h b/third-party/cxxtest/test/fake/qmessagebox.h new file mode 100644 index 00000000..d809f33b --- /dev/null +++ b/third-party/cxxtest/test/fake/qmessagebox.h @@ -0,0 +1,8 @@ +// fake qmessagebox.h + +class QMessageBox +{ +public: + enum Icon { Information, Warning, Critical }; + static void *standardIcon(Icon) { return 0; } +}; diff --git a/third-party/cxxtest/test/fake/qpixmap.h b/third-party/cxxtest/test/fake/qpixmap.h new file mode 100644 index 00000000..fae33d0e --- /dev/null +++ b/third-party/cxxtest/test/fake/qpixmap.h @@ -0,0 +1,2 @@ +// fake qpixmap.h + diff --git a/third-party/cxxtest/test/fake/qprogressbar.h b/third-party/cxxtest/test/fake/qprogressbar.h new file mode 100644 index 00000000..d5ca0335 --- /dev/null +++ b/third-party/cxxtest/test/fake/qprogressbar.h @@ -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/third-party/cxxtest/test/fake/qstatusbar.h b/third-party/cxxtest/test/fake/qstatusbar.h new file mode 100644 index 00000000..a7e6e5ae --- /dev/null +++ b/third-party/cxxtest/test/fake/qstatusbar.h @@ -0,0 +1,10 @@ +// fake qstatusbar.h + +class QStatusBar +{ +public: + QStatusBar(void *) {} + void setProgress() {} + void addWidget(void *, int) {} + void removeWidget(void *) {} +}; diff --git a/third-party/cxxtest/test/fake/qstring.h b/third-party/cxxtest/test/fake/qstring.h new file mode 100644 index 00000000..8176b596 --- /dev/null +++ b/third-party/cxxtest/test/fake/qstring.h @@ -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/third-party/cxxtest/test/fake/qwidget.h b/third-party/cxxtest/test/fake/qwidget.h new file mode 100644 index 00000000..1d4c1cdb --- /dev/null +++ b/third-party/cxxtest/test/fake/qwidget.h @@ -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/third-party/cxxtest/test/fake/windows.h b/third-party/cxxtest/test/fake/windows.h new file mode 100644 index 00000000..a7d9749b --- /dev/null +++ b/third-party/cxxtest/test/fake/windows.h @@ -0,0 +1,123 @@ +#ifndef __FAKE__WINDOWS_H__ +#define __FAKE__WINDOWS_H__ + +#include + +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/third-party/cxxtest/test/gfsuf.out b/third-party/cxxtest/test/gfsuf.out new file mode 100644 index 00000000..9f014e93 --- /dev/null +++ b/third-party/cxxtest/test/gfsuf.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In Suite::testOne: +GfSetUpFails.h:24: Error: Test failed: Error in GlobalFixture::setUp() +Failed 1 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/gfsut.out b/third-party/cxxtest/test/gfsut.out new file mode 100644 index 00000000..4ab5e45e --- /dev/null +++ b/third-party/cxxtest/test/gfsut.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In Suite::testOne: +GfSetUpThrows.h:24: Error: Test failed: Error in GlobalFixture::setUp() +Failed 1 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/gftdf.out b/third-party/cxxtest/test/gftdf.out new file mode 100644 index 00000000..9201142e --- /dev/null +++ b/third-party/cxxtest/test/gftdf.out @@ -0,0 +1,9 @@ +Running cxxtest tests (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 and Skipped 0 of 2 tests +Success rate: 0% +Error level = 2 diff --git a/third-party/cxxtest/test/gftdt.out b/third-party/cxxtest/test/gftdt.out new file mode 100644 index 00000000..f0664624 --- /dev/null +++ b/third-party/cxxtest/test/gftdt.out @@ -0,0 +1,9 @@ +Running cxxtest tests (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 and Skipped 0 of 2 tests +Success rate: 0% +Error level = 2 diff --git a/third-party/cxxtest/test/gfxs.out b/third-party/cxxtest/test/gfxs.out new file mode 100644 index 00000000..d1d342b7 --- /dev/null +++ b/third-party/cxxtest/test/gfxs.out @@ -0,0 +1,2 @@ +Running cxxtest tests (6 tests)......OK! +Error level = 0 diff --git a/third-party/cxxtest/test/good.out b/third-party/cxxtest/test/good.out new file mode 100644 index 00000000..9a97d314 --- /dev/null +++ b/third-party/cxxtest/test/good.out @@ -0,0 +1,2 @@ +Running cxxtest tests (18 tests)..................OK! +Error level = 0 diff --git a/third-party/cxxtest/test/gui.out b/third-party/cxxtest/test/gui.out new file mode 100644 index 00000000..497ab4f4 --- /dev/null +++ b/third-party/cxxtest/test/gui.out @@ -0,0 +1,15 @@ +{Start 7 tests} Running cxxtest tests (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 and Skipped 0 of 7 tests +Success rate: 85% +Error level = 1 diff --git a/third-party/cxxtest/test/gui_paren.out b/third-party/cxxtest/test/gui_paren.out new file mode 100644 index 00000000..e0eaefbb --- /dev/null +++ b/third-party/cxxtest/test/gui_paren.out @@ -0,0 +1,15 @@ +{Start 7 tests} Running cxxtest tests (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 and Skipped 0 of 7 tests +Success rate: 85% +Error level = 1 diff --git a/third-party/cxxtest/test/include.out b/third-party/cxxtest/test/include.out new file mode 100644 index 00000000..a0495cc3 --- /dev/null +++ b/third-party/cxxtest/test/include.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In IncludesTest::testTraits: +IncludeTest.h:12: Warning: (void *) +IncludeTest.h:13: Warning: (long *) +.OK! +Error level = 0 diff --git a/third-party/cxxtest/test/infinite.out b/third-party/cxxtest/test/infinite.out new file mode 100644 index 00000000..841a8707 --- /dev/null +++ b/third-party/cxxtest/test/infinite.out @@ -0,0 +1,11 @@ +Running cxxtest tests (3 tests) +In TestNonFinite::testNaN: +TestNonFinite.h:18: Error: Expected (nan == nan), found (nan != nan) +TestNonFinite.h:19: Error: Expected (nan == zero), found (nan != 0.0000) +In TestNonFinite::testPlusInf: +TestNonFinite.h:25: Error: Expected (3.0 == plus_inf), found (3.0000 != inf) +In TestNonFinite::testMinusInf: +TestNonFinite.h:31: Error: Expected (1.0 / 3.0 == minus_inf), found (0.3333 != -inf) +Failed 3 and Skipped 0 of 3 tests +Success rate: 0% +Error level = 3 diff --git a/third-party/cxxtest/test/inheritance.out b/third-party/cxxtest/test/inheritance.out new file mode 100644 index 00000000..e2ac9bdc --- /dev/null +++ b/third-party/cxxtest/test/inheritance.out @@ -0,0 +1,44 @@ +Running cxxtest tests (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 and Skipped 0 of 14 tests +Success rate: 14% +Error level = 12 diff --git a/third-party/cxxtest/test/int64.cpp b/third-party/cxxtest/test/int64.cpp new file mode 100644 index 00000000..c529f729 --- /dev/null +++ b/third-party/cxxtest/test/int64.cpp @@ -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/third-party/cxxtest/test/int64.out b/third-party/cxxtest/test/int64.out new file mode 100644 index 00000000..cf50f426 --- /dev/null +++ b/third-party/cxxtest/test/int64.out @@ -0,0 +1,8 @@ +Running cxxtest tests (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/third-party/cxxtest/test/longlong.cpp b/third-party/cxxtest/test/longlong.cpp new file mode 100644 index 00000000..a744e046 --- /dev/null +++ b/third-party/cxxtest/test/longlong.cpp @@ -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/third-party/cxxtest/test/longlong.out b/third-party/cxxtest/test/longlong.out new file mode 100644 index 00000000..61874ef1 --- /dev/null +++ b/third-party/cxxtest/test/longlong.out @@ -0,0 +1,8 @@ +Running cxxtest tests (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 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/main.cpp b/third-party/cxxtest/test/main.cpp new file mode 100644 index 00000000..0e7b0f7e --- /dev/null +++ b/third-party/cxxtest/test/main.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +// +// This test runner printer some statistics at the end of the run. +// Note that it uses and not 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()); + printf("Number of skipped tests: %u\n", TestTracker::tracker().skippedTests()); + } +}; + +int main() +{ + SummaryPrinter().run(); + return 0; +} diff --git a/third-party/cxxtest/test/max.out b/third-party/cxxtest/test/max.out new file mode 100644 index 00000000..c425e5ec --- /dev/null +++ b/third-party/cxxtest/test/max.out @@ -0,0 +1,56 @@ +Running cxxtest tests (10 tests) +In DynamicMax::test_Max_size_from_define: +DynamicMax.h:20: 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:26: 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:31: 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:37: 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:60: 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:65: 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:24: 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:29: Error: Test failed: Not same data +SameData.h:29: 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:34: 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:39: Error: Test failed: Not same data +SameData.h:39: 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 and Skipped 0 of 10 tests +Success rate: 0% +Error level = 10 diff --git a/third-party/cxxtest/test/namespace.out b/third-party/cxxtest/test/namespace.out new file mode 100644 index 00000000..74e425dd --- /dev/null +++ b/third-party/cxxtest/test/namespace.out @@ -0,0 +1,5 @@ +Number of suites: 2 +Number of tests: 8 +Number of failed tests: 7 +Number of skipped tests: 0 +Error level = 0 diff --git a/third-party/cxxtest/test/normal.out b/third-party/cxxtest/test/normal.out new file mode 100644 index 00000000..31542e68 --- /dev/null +++ b/third-party/cxxtest/test/normal.out @@ -0,0 +1,204 @@ +Running cxxtest tests (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 ( 2, 1 ), found !MyLess( 2, 1 ) +Relation.h:30: Error: Test failed: 2 ( 2, 1 ), found !MyLess( 2, 1 ) +Relation.h:32: Warning: 1 +Relation.h:34: Warning: 1 +In DefaultTraits::testSmallDefaultTraits: +DefaultTraits.h:23: Error: Test failed: { 00 01 02 03 04 05 06 07 } +In DefaultTraits::testBigDefaultTraits: +DefaultTraits.h:39: 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:24: 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:29: Error: Test failed: Not same data +SameData.h:29: 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:34: 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:39: Error: Test failed: Not same data +SameData.h:39: 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 += += // +< // 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 += += // +< // 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:22: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found: +{ 00 01 02 03 } +differs from +(null) +SameZero.h:23: Error: Expected sizeof(data) (4) bytes to be equal at (0) and (data), found: +(null) +differs from +{ 00 01 02 03 } +Failed 28 and Skipped 0 of 35 tests +Success rate: 20% +Error level = 28 diff --git a/third-party/cxxtest/test/normal.xml b/third-party/cxxtest/test/normal.xml new file mode 100644 index 00000000..48bb64f8 --- /dev/null +++ b/third-party/cxxtest/test/normal.xml @@ -0,0 +1,437 @@ + + + +LessThanEquals.h" line="16" type="failedAssertLessThanEquals" >Error: Expected (1 <= 0), found (1 > 0) +Test failed: 1 <=? 0 +Error: Expected (1 <= 0), found (1 > 0) +Error: Expected (1 < 0), found (1 >= 0) +Test failed: 1 <=? 0 +Error: Expected (1 <= 0), found (1 > 0) + +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) + + + +Relation.h" line="19" type="failedAssertPredicate" >Error: Expected MyNegative( 1 ), found !MyNegative( 1 ) +Test failed: 1 <? 0 +Error: Expected MyNegative( 1 ), found !MyNegative( 1 ) +1 +1 +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 + + + +Relation.h" line="29" type="failedAssertRelation" >Error: Expected MyLess<int>( 2, 1 ), found !MyLess<int>( 2, 1 ) +Test failed: 2 <? 1 +Error: Expected MyLess<int>( 2, 1 ), found !MyLess<int>( 2, 1 ) +1 +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 + + + +DefaultTraits.h" line="23" type="failure" >Test failed: { 00 01 02 03 04 05 06 07 } +In DefaultTraits::testSmallDefaultTraits: +DefaultTraits.h:23: Error: Test failed: { 00 01 02 03 04 05 06 07 } + + + +DefaultTraits.h" line="39" type="failure" >Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... } +In DefaultTraits::testBigDefaultTraits: +DefaultTraits.h:39: Error: Test failed: { 98 99 9A 9B 9C 9D 9E 9F ... } + + + +DoubleCall.h" line="21" type="failedAssertEquals" >Error: Expected (increment() == 3), found (1 != 3) +In DoubleCall::testAssertEqualsWithSideEffects: +DoubleCall.h:21: Error: Expected (increment() == 3), found (1 != 3) + + + +DoubleCall.h" line="26" type="failedAssertDiffers" >Error: Expected (increment() != 1), found (1) +In DoubleCall::testAssertDiffersWithSideEffects: +DoubleCall.h:26: Error: Expected (increment() != 1), found (1) + + + +DoubleCall.h" line="31" type="failedAssertDelta" >Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000) +In DoubleCall::testAssertDeltaWithSideEffects: +DoubleCall.h:31: Error: Expected (increment() == 2.0) up to 0.5 (0.5000), found (1 != 2.0000) + + + +SameData.h" line="24" type="failedAssertSameData" >Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found +In SameData::testAssertSameData: +SameData.h:24: 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 } + + + +SameData.h" line="29" type="failure" >Test failed: Not same data +Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found +In SameData::testAssertMessageSameData: +SameData.h:29: Error: Test failed: Not same data +SameData.h:29: 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 } + + + +SameData.h" line="34" type="failedAssertSameData" >Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found +In SameData::testSafeAssertSameData: +SameData.h:34: 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 } + + + +SameData.h" line="39" type="failure" >Test failed: Not same data +Error: Expected DATA_SIZE (24) bytes to be equal at (x) and (y), found +In SameData::testSafeAssertMessageSameData: +SameData.h:39: Error: Test failed: Not same data +SameData.h:39: 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 } + + + + +SameFiles.h" line="18" type="failedAssertSameFiles" >Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42) += } += }; += +< + + +In SameFiles::testAssertFileShorter: +SameFiles.h:18: Error: File 'SameFiles.h' ended before file 'SameFilesLonger.h' (line 42) += } += }; += +< + + + + +SameFiles.h" line="23" type="failedAssertSameFiles" >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) += } += }; += +> + + + + +SameFiles.h" line="28" type="failure" >Test failed: Not same files +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::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_// + + + + + +SameFiles.h" line="38" type="failure" >Test failed: Not same files +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_// + + + + +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 (&x) and (&y), found +Test failed: 42 +Error: Expected 1 (1) bytes to be equal at (&x) and (&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 < 1), found (2 >= 1) +Test failed: 42 +Error: Expected (2 < 1), found (2 >= 1) +Test failed: String +Error: Expected (throwNothing()) to throw (int) but it didn't throw +Test failed: 42 +Error: Expected (throwNothing()) to throw (int) but it didn't throw +Test failed: String +Error: Expected (throwNothing()) to throw (...) but it didn't throw +Test failed: 42 +Error: Expected (throwNothing()) to throw (...) but it didn'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't throw +Test failed: 42 +Error: Expected (throwNothing()) to throw (int) but it didn't throw +Test failed: String +Error: Expected (throwNothing()) to throw (int) but it didn't throw +Test failed: 42 +Error: Expected (throwNothing()) to throw (int) but it didn't throw +Test failed: String +Error: Expected (i == 43), found (42 != 43) +Test failed: 42 +Error: Expected (i == 43), found (42 != 43) +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) + + + +TraitsTest.h" line="13" type="failure" >Test failed: 1 +Test failed: '\x0F' +Test failed: -12 +Test failed: 34 +Test failed: -123 +Test failed: 456 +Test failed: -12345 +Test failed: 67890 +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 + + + +TraitsTest.h" line="25" type="failure" >Test failed: 0.1234 +Test failed: 0.1234 +In TraitsTest::testFloatingPointTraits: +TraitsTest.h:25: Error: Test failed: 0.1234 +TraitsTest.h:26: Error: Test failed: 0.1234 + + + +TraitsTest.h" line="31" type="failure" >Test failed: true +Test failed: false +In TraitsTest::testBoolTraits: +TraitsTest.h:31: Error: Test failed: true +TraitsTest.h:32: Error: Test failed: false + + + +TraitsTest.h" line="37" type="failure" >Test failed: 'A' +Test failed: '\x04' +Test failed: '\x1B' +Test failed: '\0' +Test failed: '\r' +Test failed: '\n' +Test failed: '\b' +Test failed: '\t' +Test failed: '\a' +Test failed: '\xFB' +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' + + + +TraitsTest.h" line="51" type="failure" >Test failed: (char *) is displayed as-is + +In TraitsTest::testStringTraits: +TraitsTest.h:51: Error: Test failed: (char *) is displayed as-is + + + + +TraitsTest.h" line="57" type="failure" >Test failed: "std::string is displayed with \"\"" +Test failed: "Escapes\rAre\rTranslated" +Test failed: "As are unprintable chars: \x124Vx" +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" + + + + + +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) + +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) + + + + +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) + +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) + + + +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) +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) + + + + +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) + +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) + + + + +SameZero.h" line="22" 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 + +In SameZero::test_TS_ASSERT_SAME_DATA_passed_zero: +SameZero.h:22: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found: +{ 00 01 02 03 } +differs from +(null) +SameZero.h:23: Error: Expected sizeof(data) (4) bytes to be equal at (0) and (data), found: +(null) +differs from +{ 00 01 02 03 } + + + diff --git a/third-party/cxxtest/test/paren.out b/third-party/cxxtest/test/paren.out new file mode 100644 index 00000000..01055459 --- /dev/null +++ b/third-party/cxxtest/test/paren.out @@ -0,0 +1,55 @@ +Running cxxtest tests (16 tests) +In CreatedTest::test_nothing: +CreatedTest.h(24): Error: Test failed: Nothing to test +.. +In EnumTraits::test_Enum_traits: +EnumTraits.h(30): Error: Test failed: Yes +EnumTraits.h(31): Error: Test failed: No +EnumTraits.h(32): Error: Test failed: Maybe +EnumTraits.h(33): Error: Test failed: DontKnow +EnumTraits.h(34): Error: Test failed: DontCare +EnumTraits.h(35): Error: Test failed: (Answer)1000 +In ExceptionTest::testAssertion: +ExceptionTest.h(18): Error: Expected (throwThis(5)) to throw (const char *) but it threw something else +ExceptionTest.h(20): Error: Expected (goodFunction(1)) to throw (...) but it didn't throw +ExceptionTest.h(22): Error: Test failed: Unhandled exception +ExceptionTest.h(24): Error: Expected (throwThis(-1)) not to throw, but it did +ExceptionTest.h(26): Error: Expected (throwThis(3)) to throw (std::exception&) but it threw something else +ExceptionTest.h(31): Error: Test failed: throwThis(3) failed +In FixtureTest::test_strcpy: +FixtureTest.h(28): Error: Expected (_buffer[1] == 'E'), found ('e' != 'E') +In MessageTest::testValues: +MessageTest.h(21): Error: Test failed: My hovercraft +MessageTest.h(21): Error: Assertion failed: value != 0 +MessageTest.h(22): Error: Test failed: of eels +MessageTest.h(22): Error: Expected (value == value * value), found (2 != 4) +In SimpleTest::testEquality: +SimpleTest.h(14): Error: Expected (1 == 2), found (1 != 2) +SimpleTest.h(15): Error: Expected ('a' == 'A'), found ('a' != 'A') +SimpleTest.h(16): Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50) +In SimpleTest::testAddition: +SimpleTest.h(23): Error: Expected (2 + 2 == 5), found (4 != 5) +In SimpleTest::TestMultiplication: +SimpleTest.h(28): Error: Expected (4 * 4 == 44), found (16 != 44) +SimpleTest.h(29): Error: Expected (-2 * -2 != 4), found (4) +In SimpleTest::testComparison: +SimpleTest.h(34): Error: Expected (-1 < -2), found (-1 >= -2) +In SimpleTest::testTheWorldIsCrazy: +SimpleTest.h(38): Error: Expected (true == false), found (true != false) +In SimpleTest::test_Failure: +SimpleTest.h(42): Error: Test failed: Not implemented +SimpleTest.h(43): Error: Test failed: 1569779912 +In SimpleTest::test_TS_SKIP_macro: +SimpleTest.h(47): Warning: Test skipped: Simply skip this test +s +In SimpleTest::test_TS_WARN_macro: +SimpleTest.h(52): Warning: Just a friendly warning +SimpleTest.h(53): Warning: Warnings don't abort the test +. +In TestFunky::testPets: +TraitsTest.h(53): Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat")) +TraitsTest.h(55): Error: Expected (cat != gato), found (Pet("cat")) +TraitsTest.h(58): Error: Expected (String("Hello") == String("World!")), found ("Hello" != "World!") +Failed 12 and Skipped 1 of 16 tests +Success rate: 20% +Error level = 12 diff --git a/third-party/cxxtest/test/parts.out b/third-party/cxxtest/test/parts.out new file mode 100644 index 00000000..a3b38f4b --- /dev/null +++ b/third-party/cxxtest/test/parts.out @@ -0,0 +1,2 @@ +Running cxxtest tests (2 tests)..OK! +Error level = 0 diff --git a/third-party/cxxtest/test/preamble.out b/third-party/cxxtest/test/preamble.out new file mode 100644 index 00000000..4c3f4d11 --- /dev/null +++ b/third-party/cxxtest/test/preamble.out @@ -0,0 +1,73 @@ +Running cxxtest tests (16 tests) +In CreatedTest::test_nothing: +CreatedTest.h:24: Error: Test failed: Nothing to test +.. +In EnumTraits::test_Enum_traits: +EnumTraits.h:30: Error: Test failed: Yes +In ExceptionTest::testAssertion: +ExceptionTest.h:18: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else +In FixtureTest::test_strcpy: +FixtureTest.h:28: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E') +In MessageTest::testValues: +MessageTest.h:21: Error: Test failed: My hovercraft +MessageTest.h:21: Error: Assertion failed: value != 0 +In SimpleTest::testEquality: +SimpleTest.h:14: Error: Expected (1 == 2), found (1 != 2) +In SimpleTest::testAddition: +SimpleTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5) +In SimpleTest::TestMultiplication: +SimpleTest.h:28: Error: Expected (4 * 4 == 44), found (16 != 44) +In SimpleTest::testComparison: +SimpleTest.h:34: Error: Expected (-1 < -2), found (-1 >= -2) +In SimpleTest::testTheWorldIsCrazy: +SimpleTest.h:38: Error: Expected (true == false), found (true != false) +In SimpleTest::test_Failure: +SimpleTest.h:42: Error: Test failed: Not implemented +In SimpleTest::test_TS_SKIP_macro: +SimpleTest.h:47: Warning: Test skipped: Simply skip this test +s +In SimpleTest::test_TS_WARN_macro: +SimpleTest.h:52: Warning: Just a friendly warning +SimpleTest.h:53: Warning: Warnings don't abort the test +. +In TestFunky::testPets: +TraitsTest.h:53: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat")) +Failed 12 and Skipped 1 of 16 tests +Success rate: 20% +Running cxxtest tests (16 tests) +In CreatedTest::test_nothing: +CreatedTest.h:24: Error: Test failed: Nothing to test +.. +In EnumTraits::test_Enum_traits: +EnumTraits.h:30: Error: Test failed: Yes +In ExceptionTest::testAssertion: +ExceptionTest.h:18: Error: Expected (throwThis(5)) to throw (const char *) but it threw something else +In FixtureTest::test_strcpy: +FixtureTest.h:28: Error: Expected (_buffer[1] == 'E'), found ('e' != 'E') +In MessageTest::testValues: +MessageTest.h:21: Error: Test failed: My hovercraft +MessageTest.h:21: Error: Assertion failed: value != 0 +In SimpleTest::testEquality: +SimpleTest.h:14: Error: Expected (1 == 2), found (1 != 2) +In SimpleTest::testAddition: +SimpleTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5) +In SimpleTest::TestMultiplication: +SimpleTest.h:28: Error: Expected (4 * 4 == 44), found (16 != 44) +In SimpleTest::testComparison: +SimpleTest.h:34: Error: Expected (-1 < -2), found (-1 >= -2) +In SimpleTest::testTheWorldIsCrazy: +SimpleTest.h:38: Error: Expected (true == false), found (true != false) +In SimpleTest::test_Failure: +SimpleTest.h:42: Error: Test failed: Not implemented +In SimpleTest::test_TS_SKIP_macro: +SimpleTest.h:47: Warning: Test skipped: Simply skip this test +s +In SimpleTest::test_TS_WARN_macro: +SimpleTest.h:52: Warning: Just a friendly warning +SimpleTest.h:53: Warning: Warnings don't abort the test +. +In TestFunky::testPets: +TraitsTest.h:53: Error: Expected (pet1 == pet2), found (Pet("dog") != Pet("cat")) +Failed 12 and Skipped 1 of 16 tests +Success rate: 20% +Error level = 24 diff --git a/third-party/cxxtest/test/preamble.tpl b/third-party/cxxtest/test/preamble.tpl new file mode 100644 index 00000000..a15356b4 --- /dev/null +++ b/third-party/cxxtest/test/preamble.tpl @@ -0,0 +1,29 @@ +// -*- C++ -*- + +#define CXXTEST_ABORT_TEST_ON_FAIL + +// CxxTest definitions and headers + + +// Make sure this worked +#ifndef TS_ASSERT +# error The preamble does not work! +#endif + +#include + +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" + + diff --git a/third-party/cxxtest/test/runner.out b/third-party/cxxtest/test/runner.out new file mode 100644 index 00000000..72257749 --- /dev/null +++ b/third-party/cxxtest/test/runner.out @@ -0,0 +1 @@ +Error level = 12 diff --git a/third-party/cxxtest/test/simple_inheritance.out b/third-party/cxxtest/test/simple_inheritance.out new file mode 100644 index 00000000..6fe3354c --- /dev/null +++ b/third-party/cxxtest/test/simple_inheritance.out @@ -0,0 +1,2 @@ +Running cxxtest tests (4 tests)....OK! +Error level = 0 diff --git a/third-party/cxxtest/test/simple_inheritance2.out b/third-party/cxxtest/test/simple_inheritance2.out new file mode 100644 index 00000000..a3b38f4b --- /dev/null +++ b/third-party/cxxtest/test/simple_inheritance2.out @@ -0,0 +1,2 @@ +Running cxxtest tests (2 tests)..OK! +Error level = 0 diff --git a/third-party/cxxtest/test/std.out b/third-party/cxxtest/test/std.out new file mode 100644 index 00000000..caa1c4e8 --- /dev/null +++ b/third-party/cxxtest/test/std.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In HaveStd::testHaveStd: +HaveStd.h:13: Error: Expected (something() == "Something"), found ("something" != Something) +Failed 1 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/stl.out b/third-party/cxxtest/test/stl.out new file mode 100644 index 00000000..26da6464 --- /dev/null +++ b/third-party/cxxtest/test/stl.out @@ -0,0 +1,46 @@ +Running cxxtest tests (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 and Skipped 0 of 9 tests +Success rate: 0% +Error level = 9 diff --git a/third-party/cxxtest/test/stpltpl.cpp b/third-party/cxxtest/test/stpltpl.cpp new file mode 100644 index 00000000..f541dc5e --- /dev/null +++ b/third-party/cxxtest/test/stpltpl.cpp @@ -0,0 +1,6 @@ +#include + +#ifdef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION +int main() { return 0; } +#endif // !_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION + diff --git a/third-party/cxxtest/test/suite.out b/third-party/cxxtest/test/suite.out new file mode 100644 index 00000000..11592349 --- /dev/null +++ b/third-party/cxxtest/test/suite.out @@ -0,0 +1,27 @@ +Running cxxtest tests (8 tests) +In SimpleTest::testEquality: +SimpleTest.h:14: Error: Expected (1 == 2), found (1 != 2) +SimpleTest.h:15: Error: Expected ('a' == 'A'), found ('a' != 'A') +SimpleTest.h:16: Error: Expected (1.0 == -12345678900000000000000000000000000000000000000000.1234), found (1.0000 != -1.2345E50) +In SimpleTest::testAddition: +SimpleTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5) +In SimpleTest::TestMultiplication: +SimpleTest.h:28: Error: Expected (4 * 4 == 44), found (16 != 44) +SimpleTest.h:29: Error: Expected (-2 * -2 != 4), found (4) +In SimpleTest::testComparison: +SimpleTest.h:34: Error: Expected (-1 < -2), found (-1 >= -2) +In SimpleTest::testTheWorldIsCrazy: +SimpleTest.h:38: Error: Expected (true == false), found (true != false) +In SimpleTest::test_Failure: +SimpleTest.h:42: Error: Test failed: Not implemented +SimpleTest.h:43: Error: Test failed: 1569779912 +In SimpleTest::test_TS_SKIP_macro: +SimpleTest.h:47: Warning: Test skipped: Simply skip this test +s +In SimpleTest::test_TS_WARN_macro: +SimpleTest.h:52: Warning: Just a friendly warning +SimpleTest.h:53: Warning: Warnings don't abort the test +. +Failed 6 and Skipped 1 of 8 tests +Success rate: 14% +Error level = 6 diff --git a/third-party/cxxtest/test/suite_test.out b/third-party/cxxtest/test/suite_test.out new file mode 100644 index 00000000..2fe8b48b --- /dev/null +++ b/third-party/cxxtest/test/suite_test.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In SimpleTest::testAddition: +SimpleTest.h:23: Error: Expected (2 + 2 == 5), found (4 != 5) +Failed 1 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/suwe.out b/third-party/cxxtest/test/suwe.out new file mode 100644 index 00000000..57d9fca6 --- /dev/null +++ b/third-party/cxxtest/test/suwe.out @@ -0,0 +1,6 @@ +Running cxxtest tests (2 tests) +In ::: +SetUpWorldError.h:12: Error: Test failed: THIS IS BAD +RealDescriptions.cpp:5: Warning: Error setting up world +OK! +Error level = 0 diff --git a/third-party/cxxtest/test/suwf.out b/third-party/cxxtest/test/suwf.out new file mode 100644 index 00000000..fe499477 --- /dev/null +++ b/third-party/cxxtest/test/suwf.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test) +In ::: +RealDescriptions.cpp:5: Warning: Error setting up world +OK! +Error level = 0 diff --git a/third-party/cxxtest/test/suwt.out b/third-party/cxxtest/test/suwt.out new file mode 100644 index 00000000..fe499477 --- /dev/null +++ b/third-party/cxxtest/test/suwt.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test) +In ::: +RealDescriptions.cpp:5: Warning: Error setting up world +OK! +Error level = 0 diff --git a/third-party/cxxtest/test/tdwf.out b/third-party/cxxtest/test/tdwf.out new file mode 100644 index 00000000..2298586b --- /dev/null +++ b/third-party/cxxtest/test/tdwf.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test). +In ::: +RealDescriptions.cpp:5: Warning: Error tearing down world +OK! +Error level = 0 diff --git a/third-party/cxxtest/test/tdwt.out b/third-party/cxxtest/test/tdwt.out new file mode 100644 index 00000000..2298586b --- /dev/null +++ b/third-party/cxxtest/test/tdwt.out @@ -0,0 +1,5 @@ +Running cxxtest tests (1 test). +In ::: +RealDescriptions.cpp:5: Warning: Error tearing down world +OK! +Error level = 0 diff --git a/third-party/cxxtest/test/template.out b/third-party/cxxtest/test/template.out new file mode 100644 index 00000000..a3b38f4b --- /dev/null +++ b/third-party/cxxtest/test/template.out @@ -0,0 +1,2 @@ +Running cxxtest tests (2 tests)..OK! +Error level = 0 diff --git a/third-party/cxxtest/test/test_cxxtest.py b/third-party/cxxtest/test/test_cxxtest.py new file mode 100644 index 00000000..63593ae6 --- /dev/null +++ b/third-party/cxxtest/test/test_cxxtest.py @@ -0,0 +1,944 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 shutil +import time +import sys +import os +import os.path +import glob +import difflib +import subprocess +import re +import string +if sys.version_info < (2,7): + import unittest2 as unittest +else: + import unittest +try: + import ply + ply_available=True +except: + ply_available=False +try: + import cxxtest + cxxtest_available=True + import cxxtest.cxxtestgen +except: + cxxtest_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[^:]+)(?P:.*)$") +dirre = re.compile("^([^%s]*/)*" % re.escape(os.sep)) +xmlre = re.compile("\"(?P[^\"]*/[^\"]*)\"") +datere = re.compile("date=\"[^\"]*\"") + +# 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' + command_separator = ' && ' + cxxtestdir = '/'.join(cxxtestdir.split('\\')) + remove_extra_path_prefixes_on_windows = True +else: + target_suffix = '' + command_separator = '; ' + remove_extra_path_prefixes_on_windows = False + +def find(filename, executable=False, isfile=True, validate=None): + # + # Use the PATH environment if it is defined and not empty + # + if "PATH" in os.environ and os.environ["PATH"] != "": + search_path = os.environ['PATH'].split(os.pathsep) + else: + search_path = os.defpath.split(os.pathsep) + for path in search_path: + test_fname = os.path.join(path, filename) + if os.path.exists(test_fname) \ + and (not isfile or os.path.isfile(test_fname)) \ + and (not executable or os.access(test_fname, os.X_OK)): + return os.path.abspath(test_fname) + return None + +def join_commands(command_one, command_two): + return command_separator.join([command_one, command_two]) + +_available = {} +def available(compiler, exe_option): + if (compiler,exe_option) in _available: + return _available[compiler,exe_option] + cmd = join_commands("cd %s" % currdir, + "%s %s %s %s > %s 2>&1" % (compiler, exe_option, currdir+'anything', currdir+'anything.cpp', currdir+'anything.log')) + print("Testing for compiler "+compiler) + print("Command: "+cmd) + status = subprocess.call(cmd, shell=True) + executable = currdir+'anything'+target_suffix + flag = status == 0 and os.path.exists(executable) + os.remove(currdir+'anything.log') + if os.path.exists(executable): + os.remove(executable) + print("Status: "+str(flag)) + _available[compiler,exe_option] = flag + 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)) + + if remove_extra_path_prefixes_on_windows: + # Take care of inconsistent path prefixes like + # "e:\path\to\cxxtest\test", "E:/path/to/cxxtest/test" etc + # in output. + line = ''.join(line.split(os.path.normcase(cxxtestdir))) + line = ''.join(line.split(os.path.normpath(cxxtestdir))) + # And some extra relative paths left behind + line= re.sub(r'^.*[\\/]([^\\/]+\.(h|cpp))', r'\1', line) + + # for xml, remove prefixes from everything that looks like a + # file path inside "" + line = xmlre.sub( + lambda match: '"'+re.sub("^[^/]+/", "", match.group(1))+'"', + line + ) + # Remove date info + line = datere.sub( lambda match: 'date=""', 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, filtered_reader): + remove_absdir(filename1) + remove_absdir(filename2) + # + INPUT=open(filename1, 'r') + lines1 = list(filtered_reader(INPUT)) + INPUT.close() + # + INPUT=open(filename2, 'r') + lines2 = list(filtered_reader(INPUT)) + INPUT.close() + # + diff = list(difflib.unified_diff(lines2, lines1, + fromfile=filename2, tofile=filename1)) + if diff: + make_diff_readable(diff) + raise Exception("ERROR: \n\n%s\n\n%s\n\n" % (lines1, lines2)) + diff = '\n'.join(diff) + return diff + + +class BaseTestCase(object): + + fog='' + valgrind='' + cxxtest_import=False + + def setUp(self): + sys.stderr.write("("+self.__class__.__name__+") ") + 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 + files = [] + if os.path.exists(self.py_out): + files.append(self.py_out) + if os.path.exists(self.py_cpp) and not 'CXXTEST_GCOV_FLAGS' in os.environ: + files.append(self.py_cpp) + if os.path.exists(self.px_pre): + files.append(self.px_pre) + if os.path.exists(self.px_out): + files.append(self.px_out) + if os.path.exists(self.build_log): + files.append(self.build_log) + if os.path.exists(self.build_target) and not 'CXXTEST_GCOV_FLAGS' in os.environ: + files.append(self.build_target) + for file in files: + try: + os.remove(file) + except: + time.sleep(2) + try: + os.remove(file) + except: + print( "Error removing file '%s'" % file) + + + # This is a "generator" that just reads a file and normalizes the lines + def file_filter(self, file): + for line in file: + yield normalize_line_for_diff(line) + + + def check_if_supported(self, filename, msg): + target=currdir+'check'+'px'+target_suffix + log=currdir+'check'+'_build.log' + cmd = join_commands("cd %s" % currdir, + "%s %s %s %s. %s%s../ %s > %s 2>&1" % (self.compiler, self.exe_option, target, self.include_option, self.include_option, currdir, filename, log)) + 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" + if self.cxxtest_import: + os.chdir(currdir) + cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', self.py_cpp]+re.split('[ ]+',args), True) + else: + cmd = join_commands("cd %s" % currdir, + "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out)) + status = subprocess.call(cmd, shell=True) + self.assertEqual(status, 0, 'Bad return code: %d Error executing cxxtestgen: %s' % (status,cmd)) + # + 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) + if self.cxxtest_import: + os.chdir(currdir) + cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', file]+re.split('[ ]+',args), True) + else: + cmd = join_commands("cd %s" % currdir, + "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, file, args, self.py_out)) + status = subprocess.call(cmd, shell=True) + self.assertEqual(status, 0, 'Bad return code: %d Error executing cxxtestgen: %s' % (status,cmd)) + # + cmd = join_commands("cd %s" % currdir, + "%s %s %s %s. %s%s../ %s > %s 2>&1" % (self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, ' '.join(files), self.build_log)) + status = subprocess.call(cmd, shell=True) + for file in files: + if os.path.exists(file): + os.remove(file) + self.assertEqual(status, 0, 'Bad return code: %d Error executing command: %s' % (status,cmd)) + # + cmd = join_commands("cd %s" % currdir, + "%s %s -v > %s 2>&1" % (self.valgrind, self.build_target, self.px_pre)) + status = subprocess.call(cmd, 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, self.file_filter) + if not diffstr == '': + self.fail("Unexpected differences in output:\n"+diffstr) + if self.valgrind != '': + self.parse_valgrind(self.px_pre) + # + self.passed=True + + def compile(self, prefix='', args=None, compile='', output=None, main=None, failGen=False, run=None, logfile=None, failBuild=False, init=True): + """Run cxxtestgen and compile the code that is generated""" + if init: + self.init(prefix) + # + if self.cxxtest_import: + try: + os.chdir(currdir) + status = cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', self.py_cpp]+re.split('[ ]+',args), True) + except: + status = 1 + else: + cmd = join_commands("cd %s" % currdir, + "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out)) + status = subprocess.call(cmd, shell=True) + if failGen: + if status == 0: + self.fail('Expected cxxtestgen to fail.') + else: + self.passed=True + return + if not self.cxxtest_import: + self.assertEqual(status, 0, 'Bad return code: %d Error executing command: %s' % (status,cmd)) + # + if not main is None: + # Compile with main + cmd = join_commands("cd %s" % currdir, + "%s %s %s %s. %s%s../ %s main.cpp %s > %s 2>&1" % (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 = join_commands("cd %s" % currdir, + "%s %s %s %s. %s%s../ %s %s > %s 2>&1" % (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, 'Bad return code: %d Error executing command: %s' % (status,cmd)) + # + if compile == '' and not output is None: + if run is None: + cmd = join_commands("cd %s" % currdir, + "%s %s -v > %s 2>&1" % (self.valgrind, self.build_target, self.px_pre)) + else: + cmd = run % (self.valgrind, self.build_target, self.px_pre) + status = subprocess.call(cmd, shell=True) + 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, self.file_filter) + else: + diffstr = file_diff(currdir+logfile, currdir+output, self.file_filter) + if not diffstr == '': + self.fail("Unexpected differences in output:\n"+diffstr) + if self.valgrind != '': + self.parse_valgrind(self.px_pre) + 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""" + # 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() + self.compile(prefix='samples_file', args="--error-printer --headers Samples.txt", output="error.out") + os.remove(currdir+'Samples.txt') + + 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 %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 %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") + + def test_normal_behavior_world(self): + """Normal Behavior with World""" + self.compile(prefix='normal_behavior_world', args="--error-printer --world=myworld "+self.normals, output="world.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") + + def test_gf_suw_fails_XML(self): + """GF:SUW fails""" + self.compile(prefix='gf_suw_fails', args="--xunit-printer SetUpWorldFails.h", output="suwf.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_namespace1(self): + """Nested namespace declarations""" + if self.fog == '': + self.compile(prefix='namespace1', args='Namespace1.h', main=True, failBuild=True) + else: + self.compile(prefix='namespace1', args='Namespace1.h', main=True, output="namespace.out") + + def test_namespace2(self): + """Explicit namespace declarations""" + self.compile(prefix='namespace2', args='Namespace2.h', main=True, output="namespace.out") + + 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') + + # + # Testing path manipulation + # + + def test_normal_sympath(self): + """Normal Behavior - symbolic path""" + _files = " ".join(["LessThanEquals.h","Relation.h","DefaultTraits.h","DoubleCall.h","SameData.h","SameFiles.h","Tsm.h","TraitsTest.h","MockTest.h","SameZero.h"]) + prefix = 'normal_sympath' + self.init(prefix=prefix) + try: + os.remove('test_sympath') + except: + pass + try: + shutil.rmtree('../test_sympath') + except: + pass + os.mkdir('../test_sympath') + os.symlink('../test_sympath', 'test_sympath') + self.py_cpp = 'test_sympath/'+prefix+'_py.cpp' + self.compile(prefix=prefix, init=False, args="--error-printer "+_files, output="normal.out") + os.remove('test_sympath') + shutil.rmtree('../test_sympath') + + def test_normal_relpath(self): + """Normal Behavior - relative path""" + _files = " ".join(["LessThanEquals.h","Relation.h","DefaultTraits.h","DoubleCall.h","SameData.h","SameFiles.h","Tsm.h","TraitsTest.h","MockTest.h","SameZero.h"]) + prefix = 'normal_relative' + self.init(prefix=prefix) + try: + shutil.rmtree('../test_relpath') + except: + pass + os.mkdir('../test_relpath') + self.py_cpp = '../test_relpath/'+prefix+'_py.cpp' + self.compile(prefix=prefix, init=False, args="--error-printer "+_files, output="normal.out") + shutil.rmtree('../test_relpath') + + + +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 TestGppPy(TestGpp): + + def run(self, *args, **kwds): + if cxxtest_available: + self.cxxtest_import = True + status = TestGpp.run(self, *args, **kwds) + self.cxxtest_import = False + return status + + +class TestGppFOG(TestGpp): + + fog='-f' + + def run(self, *args, **kwds): + if ply_available: + return TestGpp.run(self, *args, **kwds) + + +class TestGppFOGPy(TestGppFOG): + + def run(self, *args, **kwds): + if cxxtest_available: + self.cxxtest_import = True + status = TestGppFOG.run(self, *args, **kwds) + self.cxxtest_import = False + return status + + +class TestGppValgrind(TestGpp): + + valgrind='valgrind --tool=memcheck --leak-check=yes' + + def file_filter(self, file): + for line in file: + if line.startswith('=='): + continue + # Some *very* old versions of valgrind produce lines like: + # free: in use at exit: 0 bytes in 0 blocks. + # free: 2 allocs, 2 frees, 360 bytes allocated. + if line.startswith('free: '): + continue + yield normalize_line_for_diff(line) + + def run(self, *args, **kwds): + if find('valgrind') is None: + return + return TestGpp.run(self, *args, **kwds) + + def parse_valgrind(self, fname): + # There is a well-known leak on Mac OSX platforms... + if sys.platform == 'darwin': + min_leak = 16 + else: + min_leak = 0 + # + INPUT = open(fname, 'r') + for line in INPUT: + if not line.startswith('=='): + continue + tokens = re.split('[ \t]+', line) + if len(tokens) < 4: + continue + if tokens[1] == 'definitely' and tokens[2] == 'lost:': + if eval(tokens[3]) > min_leak: + self.fail("Valgrind Error: "+ ' '.join(tokens[1:])) + if tokens[1] == 'possibly' and tokens[2] == 'lost:': + if eval(tokens[3]) > min_leak: + self.fail("Valgrind Error: "+ ' '.join(tokens[1:])) + + + +class TestGppFOGValgrind(TestGppValgrind): + + fog='-f' + + def run(self, *args, **kwds): + if ply_available: + return TestGppValgrind.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/third-party/cxxtest/test/test_doc.py b/third-party/cxxtest/test/test_doc.py new file mode 100644 index 00000000..ff6f6484 --- /dev/null +++ b/third-party/cxxtest/test/test_doc.py @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------- +# CxxTest: A lightweight C++ unit testing library. +# Copyright (c) 2008 Sandia Corporation. +# This software is distributed under the LGPL License v3 +# 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 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/third-party/cxxtest/test/throw.out b/third-party/cxxtest/test/throw.out new file mode 100644 index 00000000..15b90414 --- /dev/null +++ b/third-party/cxxtest/test/throw.out @@ -0,0 +1,2 @@ +Running cxxtest tests (1 test).OK! +Error level = 0 diff --git a/third-party/cxxtest/test/tpltpl.cpp b/third-party/cxxtest/test/tpltpl.cpp new file mode 100644 index 00000000..29ffd25f --- /dev/null +++ b/third-party/cxxtest/test/tpltpl.cpp @@ -0,0 +1,10 @@ +#include + +#ifndef _CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION +template class X {} x; +template class Pair {} p; +template class X< Pair > {} xp; + +int main() { return 0; } +#endif // !_CXXTEST_PARTIAL_TEMPLATE_SPECIALIZATION + diff --git a/third-party/cxxtest/test/unit/LinkedList_test.t.h b/third-party/cxxtest/test/unit/LinkedList_test.t.h new file mode 100644 index 00000000..5bb3b687 --- /dev/null +++ b/third-party/cxxtest/test/unit/LinkedList_test.t.h @@ -0,0 +1,57 @@ +#ifndef LINKEDLIST_TEST_H +#define LINKEDLIST_TEST_H + +#include + +class TestLink : public CxxTest::Link +{ +public: + bool setUp() { return true; } + bool tearDown() { return true; } +}; + +#include +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/third-party/cxxtest/test/unit/SConstruct b/third-party/cxxtest/test/unit/SConstruct new file mode 100644 index 00000000..aaba2212 --- /dev/null +++ b/third-party/cxxtest/test/unit/SConstruct @@ -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/third-party/cxxtest/test/user.out b/third-party/cxxtest/test/user.out new file mode 100644 index 00000000..1055222f --- /dev/null +++ b/third-party/cxxtest/test/user.out @@ -0,0 +1,6 @@ +Running cxxtest tests (1 test) +In TestUserTraits::testUserTraits: +UserTraits.h:34: Error: Test failed: 0x7F +Failed 1 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/wchar.cpp b/third-party/cxxtest/test/wchar.cpp new file mode 100644 index 00000000..ef2b1db7 --- /dev/null +++ b/third-party/cxxtest/test/wchar.cpp @@ -0,0 +1,11 @@ +// +// This program is used to check if the compiler supports basic_string +// +#include + +int main() +{ + std::basic_string s(L"s"); + return 0; +} + diff --git a/third-party/cxxtest/test/wchar.out b/third-party/cxxtest/test/wchar.out new file mode 100644 index 00000000..3340f489 --- /dev/null +++ b/third-party/cxxtest/test/wchar.out @@ -0,0 +1,7 @@ +Running cxxtest tests (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 and Skipped 0 of 1 test +Success rate: 0% +Error level = 1 diff --git a/third-party/cxxtest/test/wildcard.out b/third-party/cxxtest/test/wildcard.out new file mode 100644 index 00000000..199376f8 --- /dev/null +++ b/third-party/cxxtest/test/wildcard.out @@ -0,0 +1,5 @@ +Number of suites: 8 +Number of tests: 16 +Number of failed tests: 12 +Number of skipped tests: 1 +Error level = 0 diff --git a/third-party/cxxtest/test/world.out b/third-party/cxxtest/test/world.out new file mode 100644 index 00000000..df1859a8 --- /dev/null +++ b/third-party/cxxtest/test/world.out @@ -0,0 +1,204 @@ +Running myworld tests (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 ( 2, 1 ), found !MyLess( 2, 1 ) +Relation.h:30: Error: Test failed: 2 ( 2, 1 ), found !MyLess( 2, 1 ) +Relation.h:32: Warning: 1 +Relation.h:34: Warning: 1 +In DefaultTraits::testSmallDefaultTraits: +DefaultTraits.h:23: Error: Test failed: { 00 01 02 03 04 05 06 07 } +In DefaultTraits::testBigDefaultTraits: +DefaultTraits.h:39: 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:24: 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:29: Error: Test failed: Not same data +SameData.h:29: 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:34: 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:39: Error: Test failed: Not same data +SameData.h:39: 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 += += // +< // 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 += += // +< // 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:22: Error: Expected sizeof(data) (4) bytes to be equal at (data) and (0), found: +{ 00 01 02 03 } +differs from +(null) +SameZero.h:23: Error: Expected sizeof(data) (4) bytes to be equal at (0) and (data), found: +(null) +differs from +{ 00 01 02 03 } +Failed 28 and Skipped 0 of 35 tests +Success rate: 20% +Error level = 28 diff --git a/third-party/libstudxml/CMakeLists.txt b/third-party/libstudxml/CMakeLists.txt index 65d7da19..4df947a0 100644 --- a/third-party/libstudxml/CMakeLists.txt +++ b/third-party/libstudxml/CMakeLists.txt @@ -25,35 +25,16 @@ set(GENX ${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.c ${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.h) -if(LOCAL_EXPAT OR LOCAL_DEPENDENCIES) - set(EXPAT - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlparse.c - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.c - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.c - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/ascii.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/asciitab.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/config.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat_external.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/iasciitab.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/internal.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/latin1tab.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/nametab.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/utf8tab.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok_impl.h - ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.h) -else() - set(EXPAT "") -endif() - -add_library(libstudxml STATIC ${LIBSTUDXML} ${GENX} ${EXPAT}) -target_compile_definitions(libstudxml PUBLIC LIBSTUDXML_STATIC_LIB=1) -target_include_directories(libstudxml PUBLIC ${LIBSTUDXML_ROOT_DIR}) - find_package(EXPAT REQUIRED) -target_compile_definitions(libstudxml PRIVATE LIBSTUDXML_EXTERNAL_EXPAT=1) -target_link_libraries(libstudxml PRIVATE expat) + +add_library(libstudxml STATIC ${LIBSTUDXML} ${GENX}) +target_compile_definitions(libstudxml + PUBLIC LIBSTUDXML_STATIC_LIB=1 + PUBLIC LIBSTUDXML_EXTERNAL_EXPAT=1) +target_include_directories(libstudxml + PUBLIC ${LIBSTUDXML_ROOT_DIR}) +target_link_libraries(libstudxml + PRIVATE expat) if(NOT STATIC) set_target_properties(libstudxml PROPERTIES POSITION_INDEPENDENT_CODE 1)