diff --git a/.gitmodules b/.gitmodules index d3c2970..58e923a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "docs"] path = docs url = https://github.com/unittest-cpp/unittest-cpp.wiki.git + ignore = dirty \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c573ef9..b4c75c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,26 @@ -cmake_minimum_required(VERSION 2.8.1) -project(UnitTest++) +cmake_minimum_required(VERSION 3.0) +project(UnitTest++ VERSION 2.1.0) -option(UTPP_USE_PLUS_SIGN "Set this to OFF is you with to use '-cpp' instead of '++' in lib/include paths" ON) +option(UTPP_USE_PLUS_SIGN + "Set this to OFF if you wish to use '-cpp' instead of '++' in lib/include paths" + ON) +option(UTPP_INCLUDE_TESTS_IN_BUILD + "Set this to OFF if you do not wish to automatically build or run unit tests as part of the default cmake --build" + ON) +option(UTPP_AMPLIFY_WARNINGS + "Set this to OFF if you wish to use CMake default warning levels; should generally only use to work around support issues for your specific compiler" + ON) -if(MSVC14 OR MSVC12) - # has the support we need +set(LIB_SUFFIX "" CACHE STRING "Identifier to add to end of lib directory name e.g. 64 for lib64") + +if (MSVC) + # CHECK_CXX_COMPILER_FLAG could be used + # but MSVC version is preferred for feature requirements + if (MSVC14 OR MSVC12) + # has the support we need + else() + message(STATUS "The MSVC compiler version does not support UnitTest++ C++11 features.") + endif() else() include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) @@ -14,7 +30,18 @@ else() elseif(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") + endif() +endif() + +# up warning level for project +if (${UTPP_AMPLIFY_WARNINGS}) + # instead of getting compiler specific, we're going to try making an assumption that an existing /W# means + # we are dealing with an MSVC or MSVC-like compiler (e.g. Intel on Windows) + if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") endif() endif() @@ -37,6 +64,8 @@ source_group(${platformDir_} FILES ${platformHeaders_} ${platformSources_}) # create the lib add_library(UnitTest++ STATIC ${headers_} ${sources_} ${platformHeaders_} ${platformSources_}) +add_library(UnitTest++::UnitTest++ ALIAS UnitTest++) + if(${UTPP_USE_PLUS_SIGN}) set_target_properties(UnitTest++ PROPERTIES OUTPUT_NAME UnitTest++) @@ -47,18 +76,25 @@ endif() file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tests/*.cpp tests/*.h) source_group( "" FILES ${TEST_SRCS}) add_executable(TestUnitTest++ ${TEST_SRCS}) -include_directories(.) + if(${UTPP_USE_PLUS_SIGN}) set_target_properties(TestUnitTest++ PROPERTIES OUTPUT_NAME TestUnitTest++) endif() -target_link_libraries(TestUnitTest++ UnitTest++) +target_link_libraries(TestUnitTest++ + PUBLIC + UnitTest++::UnitTest++ + ) # run unit tests as post build step add_custom_command(TARGET TestUnitTest++ - POST_BUILD COMMAND TestUnitTest++ - COMMENT "Running unit tests") + POST_BUILD COMMAND TestUnitTest++ + COMMENT "Running unit tests") + +if(NOT ${UTPP_INCLUDE_TESTS_IN_BUILD}) + set_target_properties(TestUnitTest++ PROPERTIES EXCLUDE_FROM_ALL 1) +endif() # add install targets # need a custom install path? @@ -69,6 +105,41 @@ else() set (UTPP_INSTALL_DESTINATION "include/UnitTestPP") endif() -install(TARGETS UnitTest++ DESTINATION lib) +target_include_directories( UnitTest++ + PUBLIC + $ + $ + ) +set_target_properties(UnitTest++ PROPERTIES DEBUG_POSTFIX "-d") +set_target_properties(TestUnitTest++ PROPERTIES DEBUG_POSTFIX "-d") + +set(config_install_dir_ lib${LIB_SUFFIX}/cmake/${PROJECT_NAME}) +set(targets_export_name_ "${PROJECT_NAME}Targets") +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + cmake/UnitTest++ConfigVersion.cmake + VERSION ${UnitTest++_VERSION} + COMPATIBILITY SameMajorVersion + ) + +install(TARGETS UnitTest++ EXPORT "${targets_export_name_}" DESTINATION lib${LIB_SUFFIX}) install(FILES ${headers_} DESTINATION ${UTPP_INSTALL_DESTINATION}) -install(FILES ${platformHeaders_} DESTINATION ${UTPP_INSTALL_DESTINATION}/${platformDir_}) \ No newline at end of file +install(FILES ${platformHeaders_} DESTINATION ${UTPP_INSTALL_DESTINATION}/${platformDir_}) +install(FILES + cmake/UnitTest++Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cmake/UnitTest++ConfigVersion.cmake + DESTINATION "${config_install_dir_}") +install(EXPORT "${targets_export_name_}" NAMESPACE "UnitTest++::" DESTINATION "${config_install_dir_}") + +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${CMAKE_INSTALL_PREFIX}/bin) +set(libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) +set(includedir ${CMAKE_INSTALL_PREFIX}/include/UnitTest++) +configure_file("UnitTest++.pc.in" "UnitTest++.pc" @ONLY) +if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + set(pkgconfdir ${CMAKE_INSTALL_PREFIX}/libdata/pkgconfig) +else() + set(pkgconfdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig) +endif() +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/UnitTest++.pc" + DESTINATION "${pkgconfdir}") diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index e69de29..0000000 diff --git a/INSTALL b/INSTALL index 6e90e07..6c99c94 100644 --- a/INSTALL +++ b/INSTALL @@ -1,3 +1,9 @@ + +Preamble: If you are installing UnitTest++ from source, or from a +release prior to 1.6.1, you will need to have autotools installed and +run `autoreconf -i; autoconf` prior to following the standard +instructions below. + Installation Instructions ************************* diff --git a/README.md b/README.md index be3573f..6ece10e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ +> ### Maintenance of UnitTest++, recently sporadic, is officially on hiatus until 26 November 2020. Subscribe to https://github.com/unittest-cpp/unittest-cpp/issues/180 for updates. + + [![Build Status](https://travis-ci.org/unittest-cpp/unittest-cpp.svg?branch=master)](https://travis-ci.org/unittest-cpp/unittest-cpp) [![Build status](https://ci.appveyor.com/api/projects/status/ffs2k8dddts5cyok/branch/master?svg=true)](https://ci.appveyor.com/project/pjohnmeyer/unittest-cpp/branch/master) UnitTest++ =========== -UnitTest++ is a lightweight unit testing framework for C++. It was designed to do test-driven development on a wide variety of platforms. Simplicity, portability, speed, and small footprint are all very important aspects of UnitTest++. UnitTest++ is ANSI portable C++ and makes minimal use of advanced library and languages features, which means it should be easily portable to just about any platform. Out of the box, the following platforms are supported: +UnitTest++ is a lightweight unit testing framework for C++. It was designed to do test-driven development on a wide variety of platforms. Simplicity, portability, speed, and small footprint are all very important aspects of UnitTest++. UnitTest++ is mostly standard C++ and makes minimal use of advanced library and language features, which means it should be easily portable to just about any platform. Out of the box, the following platforms are supported: * Windows * Linux @@ -16,7 +19,7 @@ The full documentation for building and using UnitTest++ can be found on the [Gi Pre-requisites --------------- -While there are currently some bundled makefiles and projects, UnitTest++ is primarily built and supported using [CMake](http://cmake.org). +While there are currently some bundled automake files, UnitTest++ is primarily built and supported using [CMake](http://cmake.org). Downloading ------------ @@ -30,17 +33,17 @@ Via svn: svn checkout https://github.com/unittest-cpp/unittest-cpp/trunk unittest-cpp -### Latest release (v1.5.1) ### +### Latest release (v2.0.0) ### Via git: git clone https://github.com/unittest-cpp/unittest-cpp cd unittest-cpp - git checkout v1.5.1 + git checkout v2.0.0 Via svn: - svn checkout https://github.com/unittest-cpp/unittest-cpp/tags/v1.5.1 unittest-cpp + svn checkout https://github.com/unittest-cpp/unittest-cpp/tags/v2.0.0 unittest-cpp License --------- @@ -58,7 +61,7 @@ Contributors * Charles Nicholson (charles.nicholson@gmail.com) @charlesnicholson ### Original Authors: ### -* Noel Llopis (llopis@convexhull.com) +* Noel Llopis (llopis@convexhull.com) * Charles Nicholson (charles.nicholson@gmail.com) ### Contributors not included in github history ### @@ -77,6 +80,16 @@ Contributors Historic release notes ---------------------- +### Version 2.0.0 (2017-01-13) ### +- Change Check method supporting CHECK macro to accept argument by reference +- Introduce long macro forms (e.g. UNITTEST_CHECK); make short forms optional +- Improved Visual Studio 2015 support +- [Full List](https://github.com/unittest-cpp/unittest-cpp/issues?q=milestone%3A2.0.0+) + +### Version 1.6.0 (2016-02-29) ### +- Add REQUIRE macro to end tests early when selected checks fail +- [Full List](https://github.com/unittest-cpp/unittest-cpp/issues?q=milestone%3A1.6.0+) + ### Version 1.5.1 (2016-01-30) ### - pkg-config support - Fix for Visual Studio 2010 compilation issue in 1.5.0 @@ -110,7 +123,7 @@ Historic release notes - Standard streams can be optionally compiled off by defining UNITTEST_USE_CUSTOM_STREAMS in Config.h - Added named test suites -- Added CHECK_ARRAY2D_CLOSE +- Added CHECK_ARRAY2D_CLOSE - Posix library name is libUnitTest++.a now - Floating point numbers are postfixed with 'f' in the failure reports diff --git a/UnitTest++/CheckMacros.h b/UnitTest++/CheckMacros.h index d79d503..898559d 100644 --- a/UnitTest++/CheckMacros.h +++ b/UnitTest++/CheckMacros.h @@ -5,161 +5,181 @@ #include "ExceptionMacros.h" #include "Checks.h" #include "AssertException.h" +#include "RequiredCheckException.h" #include "MemoryOutStream.h" #include "TestDetails.h" #include "CurrentTest.h" #include "ReportAssertImpl.h" -#ifdef CHECK - #error UnitTest++ redefines CHECK -#endif - -#ifdef CHECK_EQUAL - #error UnitTest++ redefines CHECK_EQUAL -#endif - -#ifdef CHECK_CLOSE - #error UnitTest++ redefines CHECK_CLOSE -#endif - -#ifdef CHECK_ARRAY_EQUAL - #error UnitTest++ redefines CHECK_ARRAY_EQUAL -#endif - -#ifdef CHECK_ARRAY_CLOSE - #error UnitTest++ redefines CHECK_ARRAY_CLOSE -#endif - -#ifdef CHECK_ARRAY2D_CLOSE - #error UnitTest++ redefines CHECK_ARRAY2D_CLOSE -#endif - -#define CHECK(value) \ +#define UNITTEST_CHECK(value) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ - ({ \ + UNITTEST_IMPL_TRY \ + ({ \ if (!UnitTest::Check(value)) \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK(" #value ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK(" #value ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ + UNITTEST_IMPL_CATCH_ALL \ ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK(" #value ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END -#define CHECK_EQUAL(expected, actual) \ +#define UNITTEST_CHECK_EQUAL(expected, actual) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ - ({ \ + UNITTEST_IMPL_TRY \ + ({ \ UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK_EQUAL(" #expected ", " #actual ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK_EQUAL(" #expected ", " #actual ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ - ({ \ + UNITTEST_IMPL_CATCH_ALL \ + ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_EQUAL(" #expected ", " #actual ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END -#define CHECK_CLOSE(expected, actual, tolerance) \ +#define UNITTEST_CHECK_CLOSE(expected, actual, tolerance) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ - ({ \ + UNITTEST_IMPL_TRY \ + ({ \ UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK_CLOSE(" #expected ", " #actual ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK_CLOSE(" #expected ", " #actual ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ - ({ \ + UNITTEST_IMPL_CATCH_ALL \ + ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END -#define CHECK_ARRAY_EQUAL(expected, actual, count) \ +#define UNITTEST_CHECK_ARRAY_EQUAL(expected, actual, count) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ + UNITTEST_IMPL_TRY \ ({ \ UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ + UNITTEST_IMPL_CATCH_ALL \ ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END -#define CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \ +#define UNITTEST_CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ + UNITTEST_IMPL_TRY \ ({ \ UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ + UNITTEST_IMPL_CATCH_ALL \ ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END -#define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \ +#define UNITTEST_CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \ UNITTEST_MULTILINE_MACRO_BEGIN \ - UT_TRY \ + UNITTEST_IMPL_TRY \ ({ \ UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_RETHROW (UnitTest::RequiredCheckException) \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ - UnitTest::MemoryOutStream message; \ - message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY2D_CLOSE(" #expected ", " #actual ")"; \ + UnitTest::MemoryOutStream UnitTest_message; \ + UnitTest_message << "Unhandled exception (" << e.what() << ") in CHECK_ARRAY2D_CLOSE(" #expected ", " #actual ")"; \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ - message.GetText()); \ + UnitTest_message.GetText()); \ }) \ - UT_CATCH_ALL \ + UNITTEST_IMPL_CATCH_ALL \ ({ \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_ARRAY2D_CLOSE(" #expected ", " #actual ")"); \ }) \ UNITTEST_MULTILINE_MACRO_END +#ifndef UNITTEST_DISABLE_SHORT_MACROS + #ifdef CHECK + #error CHECK already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK instead + #else + #define CHECK UNITTEST_CHECK + #endif + + #ifdef CHECK_EQUAL + #error CHECK_EQUAL already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_EQUAL instead + #else + #define CHECK_EQUAL UNITTEST_CHECK_EQUAL + #endif + + #ifdef CHECK_CLOSE + #error CHECK_CLOSE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_CLOSE instead + #else + #define CHECK_CLOSE UNITTEST_CHECK_CLOSE + #endif + + #ifdef CHECK_ARRAY_EQUAL + #error CHECK_ARRAY_EQUAL already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_ARRAY_EQUAL instead + #else + #define CHECK_ARRAY_EQUAL UNITTEST_CHECK_ARRAY_EQUAL + #endif + + #ifdef CHECK_ARRAY_CLOSE + #error CHECK_ARRAY_CLOSE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_ARRAY_CLOSE instead + #else + #define CHECK_ARRAY_CLOSE UNITTEST_CHECK_ARRAY_CLOSE + #endif + + #ifdef CHECK_ARRAY2D_CLOSE + #error CHECK_ARRAY2D_CLOSE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_ARRAY2D_CLOSE instead + #else + #define CHECK_ARRAY2D_CLOSE UNITTEST_CHECK_ARRAY2D_CLOSE + #endif +#endif // CHECK_THROW and CHECK_ASSERT only exist when UNITTEST_NO_EXCEPTIONS isn't defined (see config.h) #ifndef UNITTEST_NO_EXCEPTIONS -#define CHECK_THROW(expression, ExpectedExceptionType) \ +#define UNITTEST_CHECK_THROW(expression, ExpectedExceptionType) \ UNITTEST_MULTILINE_MACRO_BEGIN \ bool caught_ = false; \ try { expression; } \ @@ -170,7 +190,7 @@ UNITTEST_MULTILINE_MACRO_END -#define CHECK_ASSERT(expression) \ +#define UNITTEST_CHECK_ASSERT(expression) \ UNITTEST_MULTILINE_MACRO_BEGIN \ UnitTest::Detail::ExpectAssert(true); \ CHECK_THROW(expression, UnitTest::AssertException); \ @@ -178,4 +198,19 @@ UNITTEST_MULTILINE_MACRO_END #endif +#ifndef UNITTEST_DISABLE_SHORT_MACROS + #ifdef CHECK_THROW + #error CHECK_THROW already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_THROW instead + #else + #define CHECK_THROW UNITTEST_CHECK_THROW + #endif + + #ifdef CHECK_ASSERT + #error CHECK_ASSERT already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_CHECK_ASSERT instead + #else + #define CHECK_ASSERT UNITTEST_CHECK_ASSERT + #endif #endif + +#endif + diff --git a/UnitTest++/Checks.h b/UnitTest++/Checks.h index 5b09768..7c37691 100644 --- a/UnitTest++/Checks.h +++ b/UnitTest++/Checks.h @@ -9,7 +9,7 @@ namespace UnitTest { template< typename Value > - bool Check(Value const value) + bool Check(Value const& value) { return !!value; // doing double negative to avoid silly VS warnings } @@ -57,10 +57,10 @@ namespace UnitTest { template< typename Expected, typename Actual > void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, - int const count, TestDetails const& details) + size_t const count, TestDetails const& details) { bool equal = true; - for (int i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) equal &= (expected[i] == actual[i]); if (!equal) @@ -69,12 +69,12 @@ namespace UnitTest { stream << "Expected [ "; - for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) + for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex) stream << expected[expectedIndex] << " "; stream << "] but was [ "; - for (int actualIndex = 0; actualIndex < count; ++actualIndex) + for (size_t actualIndex = 0; actualIndex < count; ++actualIndex) stream << actual[actualIndex] << " "; stream << "]"; @@ -84,17 +84,17 @@ namespace UnitTest { } template< typename Expected, typename Actual, typename Tolerance > - bool ArrayAreClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance) + bool ArrayAreClose(Expected const& expected, Actual const& actual, size_t const count, Tolerance const& tolerance) { bool equal = true; - for (int i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) equal &= AreClose(expected[i], actual[i], tolerance); return equal; } template< typename Expected, typename Actual, typename Tolerance > void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual, - int const count, Tolerance const& tolerance, TestDetails const& details) + size_t const count, Tolerance const& tolerance, TestDetails const& details) { bool equal = ArrayAreClose(expected, actual, count, tolerance); @@ -103,11 +103,11 @@ namespace UnitTest { UnitTest::MemoryOutStream stream; stream << "Expected [ "; - for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) + for (size_t expectedIndex = 0; expectedIndex < count; ++expectedIndex) stream << expected[expectedIndex] << " "; stream << "] +/- " << tolerance << " but was [ "; - for (int actualIndex = 0; actualIndex < count; ++actualIndex) + for (size_t actualIndex = 0; actualIndex < count; ++actualIndex) stream << actual[actualIndex] << " "; stream << "]"; @@ -117,10 +117,10 @@ namespace UnitTest { template< typename Expected, typename Actual, typename Tolerance > void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual, - int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details) + size_t const rows, size_t const columns, Tolerance const& tolerance, TestDetails const& details) { bool equal = true; - for (int i = 0; i < rows; ++i) + for (size_t i = 0; i < rows; ++i) equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance); if (!equal) @@ -129,20 +129,20 @@ namespace UnitTest { stream << "Expected [ "; - for (int expectedRow = 0; expectedRow < rows; ++expectedRow) + for (size_t expectedRow = 0; expectedRow < rows; ++expectedRow) { stream << "[ "; - for (int expectedColumn = 0; expectedColumn < columns; ++expectedColumn) + for (size_t expectedColumn = 0; expectedColumn < columns; ++expectedColumn) stream << expected[expectedRow][expectedColumn] << " "; stream << "] "; } stream << "] +/- " << tolerance << " but was [ "; - for (int actualRow = 0; actualRow < rows; ++actualRow) + for (size_t actualRow = 0; actualRow < rows; ++actualRow) { stream << "[ "; - for (int actualColumn = 0; actualColumn < columns; ++actualColumn) + for (size_t actualColumn = 0; actualColumn < columns; ++actualColumn) stream << actual[actualRow][actualColumn] << " "; stream << "] "; } diff --git a/UnitTest++/Config.h b/UnitTest++/Config.h index ff62b4e..14429ee 100644 --- a/UnitTest++/Config.h +++ b/UnitTest++/Config.h @@ -16,12 +16,13 @@ #ifdef _USRDLL #define UNITTEST_WIN32_DLL #endif - + #define UNITTEST_WIN32 #endif #if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \ - defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) + defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) \ + || defined (__HAIKU__) || defined(_AIX) #define UNITTEST_POSIX #endif @@ -71,4 +72,13 @@ #define UNIITEST_NS_QUAL_STD(x) ::std::x #endif +// By default, UnitTest++ will attempt to define "short" macro names like CHECK and CHECK_EQUAL +// for "public" interface macros etc. Defining UNITTEST_DISABLE_SHORT_MACROS in your project +// will disable this behavior, leaving only the longer macros "namespaced" with the UNITTEST_ +// prefix. +// +// "Internal" utility macros will only have the UNITTEST_IMPL_ prefix. + +// #define UNITTEST_DISABLE_SHORT_MACROS + #endif diff --git a/UnitTest++/ExceptionMacros.h b/UnitTest++/ExceptionMacros.h index ca8757e..9b2bad4 100644 --- a/UnitTest++/ExceptionMacros.h +++ b/UnitTest++/ExceptionMacros.h @@ -4,15 +4,17 @@ #include "Config.h" #ifndef UNITTEST_NO_EXCEPTIONS - #define UT_TRY(x) try x - #define UT_THROW(x) throw x - #define UT_CATCH(ExceptionType, ExceptionName, CatchBody) catch(ExceptionType& ExceptionName) CatchBody - #define UT_CATCH_ALL(CatchBody) catch(...) CatchBody + #define UNITTEST_IMPL_TRY(x) try x + #define UNITTEST_IMPL_THROW(x) throw x + #define UNITTEST_IMPL_RETHROW(ExceptionType) catch(ExceptionType&) { throw; } + #define UNITTEST_IMPL_CATCH(ExceptionType, ExceptionName, CatchBody) catch(ExceptionType& ExceptionName) CatchBody + #define UNITTEST_IMPL_CATCH_ALL(CatchBody) catch(...) CatchBody #else - #define UT_TRY(x) x - #define UT_THROW(x) - #define UT_CATCH(ExceptionType, ExceptionName, CatchBody) - #define UT_CATCH_ALL(CatchBody) + #define UNITTEST_IMPL_TRY(x) x + #define UNITTEST_IMPL_THROW(x) + #define UNITTEST_IMPL_RETHROW(ExceptionType) + #define UNITTEST_IMPL_CATCH(ExceptionType, ExceptionName, CatchBody) + #define UNITTEST_IMPL_CATCH_ALL(CatchBody) #endif #endif diff --git a/UnitTest++/ExecuteTest.h b/UnitTest++/ExecuteTest.h index c6917fc..2759aad 100644 --- a/UnitTest++/ExecuteTest.h +++ b/UnitTest++/ExecuteTest.h @@ -7,6 +7,7 @@ #include "TestResults.h" #include "MemoryOutStream.h" #include "AssertException.h" +#include "RequiredCheckException.h" #include "CurrentTest.h" #ifdef UNITTEST_NO_EXCEPTIONS @@ -30,22 +31,23 @@ namespace UnitTest { { #endif #ifndef UNITTEST_POSIX - UT_TRY({ testObject.RunImpl(); }) + UNITTEST_IMPL_TRY({ testObject.RunImpl(); }) #else - UT_TRY + UNITTEST_IMPL_TRY ({ UNITTEST_THROW_SIGNALS_POSIX_ONLY testObject.RunImpl(); }) #endif - UT_CATCH(AssertException, e, { (void)e; }) - UT_CATCH(std::exception, e, + UNITTEST_IMPL_CATCH(RequiredCheckException, e, { (void)e; }) + UNITTEST_IMPL_CATCH(AssertException, e, { (void)e; }) + UNITTEST_IMPL_CATCH(std::exception, e, { MemoryOutStream stream; stream << "Unhandled exception: " << e.what(); CurrentTest::Results()->OnTestFailure(details, stream.GetText()); }) - UT_CATCH_ALL + UNITTEST_IMPL_CATCH_ALL ({ CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: test crashed"); }) diff --git a/UnitTest++/Makefile.am b/UnitTest++/Makefile.am index 32f6477..62e246f 100644 --- a/UnitTest++/Makefile.am +++ b/UnitTest++/Makefile.am @@ -1,12 +1,13 @@ lib_LTLIBRARIES = UnitTest++/libUnitTest++.la -pkgincludedir = $(includedir)/UnitTest++/ -nobase_pkginclude_HEADERS = UnitTest++/UnitTest++.h UnitTest++/UnitTestPP.h UnitTest++/Config.h UnitTest++/HelperMacros.h UnitTest++/Test.h UnitTest++/TestDetails.h UnitTest++/TestList.h UnitTest++/TestSuite.h UnitTest++/TestResults.h UnitTest++/TestMacros.h UnitTest++/CheckMacros.h UnitTest++/TestRunner.h UnitTest++/TimeConstraint.h UnitTest++/ExecuteTest.h UnitTest++/AssertException.h UnitTest++/MemoryOutStream.h UnitTest++/CurrentTest.h UnitTest++/Checks.h UnitTest++/TimeHelpers.h UnitTest++/ExceptionMacros.h UnitTest++/ReportAssert.h UnitTest++/ReportAssertImpl.h UnitTest++/TestReporter.h UnitTest++/TestReporterStdout.h UnitTest++/CompositeTestReporter.h UnitTest++/DeferredTestReporter.h UnitTest++/DeferredTestResult.h -UnitTest___libUnitTest___la_SOURCES = UnitTest++/AssertException.cpp UnitTest++/Test.cpp UnitTest++/Checks.cpp UnitTest++/TestRunner.cpp UnitTest++/TestResults.cpp UnitTest++/TestReporter.cpp UnitTest++/TestReporterStdout.cpp UnitTest++/ReportAssert.cpp UnitTest++/TestList.cpp UnitTest++/TimeConstraint.cpp UnitTest++/TestDetails.cpp UnitTest++/MemoryOutStream.cpp UnitTest++/DeferredTestReporter.cpp UnitTest++/DeferredTestResult.cpp UnitTest++/XmlTestReporter.cpp UnitTest++/CurrentTest.cpp UnitTest++/CompositeTestReporter.cpp +pkgincludedir = $(includedir) -if WINDOWS +nobase_pkginclude_HEADERS = UnitTest++/AssertException.h UnitTest++/CheckMacros.h UnitTest++/Checks.h UnitTest++/CompositeTestReporter.h UnitTest++/Config.h UnitTest++/CurrentTest.h UnitTest++/DeferredTestReporter.h UnitTest++/DeferredTestResult.h UnitTest++/ExceptionMacros.h UnitTest++/ExecuteTest.h UnitTest++/HelperMacros.h UnitTest++/MemoryOutStream.h UnitTest++/ReportAssert.h UnitTest++/ReportAssertImpl.h UnitTest++/RequireMacros.h UnitTest++/RequiredCheckException.h UnitTest++/RequiredCheckTestReporter.h UnitTest++/Test.h UnitTest++/TestDetails.h UnitTest++/TestList.h UnitTest++/TestMacros.h UnitTest++/TestReporter.h UnitTest++/TestReporterStdout.h UnitTest++/TestResults.h UnitTest++/TestRunner.h UnitTest++/TestSuite.h UnitTest++/ThrowingTestReporter.h UnitTest++/TimeConstraint.h UnitTest++/TimeHelpers.h UnitTest++/UnitTest++.h UnitTest++/UnitTestPP.h UnitTest++/XmlTestReporter.h +UnitTest___libUnitTest___la_SOURCES = UnitTest++/AssertException.cpp UnitTest++/Checks.cpp UnitTest++/CompositeTestReporter.cpp UnitTest++/CurrentTest.cpp UnitTest++/DeferredTestReporter.cpp UnitTest++/DeferredTestResult.cpp UnitTest++/MemoryOutStream.cpp UnitTest++/ReportAssert.cpp UnitTest++/RequiredCheckException.cpp UnitTest++/RequiredCheckTestReporter.cpp UnitTest++/Test.cpp UnitTest++/TestDetails.cpp UnitTest++/TestList.cpp UnitTest++/TestReporter.cpp UnitTest++/TestReporterStdout.cpp UnitTest++/TestResults.cpp UnitTest++/TestRunner.cpp UnitTest++/ThrowingTestReporter.cpp UnitTest++/TimeConstraint.cpp UnitTest++/XmlTestReporter.cpp + +if WINDOWS nobase_pkginclude_HEADERS += UnitTest++/Win32/TimeHelpers.h UnitTest___libUnitTest___la_SOURCES += UnitTest++/Win32/TimeHelpers.cpp -else +else nobase_pkginclude_HEADERS += UnitTest++/Posix/SignalTranslator.h UnitTest++/Posix/TimeHelpers.h UnitTest___libUnitTest___la_SOURCES += UnitTest++/Posix/SignalTranslator.cpp UnitTest++/Posix/TimeHelpers.cpp endif diff --git a/UnitTest++/Posix/SignalTranslator.cpp b/UnitTest++/Posix/SignalTranslator.cpp index 4039896..69cc194 100644 --- a/UnitTest++/Posix/SignalTranslator.cpp +++ b/UnitTest++/Posix/SignalTranslator.cpp @@ -28,12 +28,12 @@ namespace UnitTest { sigaction( SIGFPE, &action, &m_old_SIGFPE_action ); sigaction( SIGTRAP, &action, &m_old_SIGTRAP_action ); sigaction( SIGBUS, &action, &m_old_SIGBUS_action ); - sigaction( SIGILL, &action, &m_old_SIGBUS_action ); + sigaction( SIGILL, &action, &m_old_SIGILL_action ); } SignalTranslator::~SignalTranslator() { - sigaction( SIGILL, &m_old_SIGBUS_action, 0 ); + sigaction( SIGILL, &m_old_SIGILL_action, 0 ); sigaction( SIGBUS, &m_old_SIGBUS_action, 0 ); sigaction( SIGTRAP, &m_old_SIGTRAP_action, 0 ); sigaction( SIGFPE, &m_old_SIGFPE_action, 0 ); diff --git a/UnitTest++/Posix/SignalTranslator.h b/UnitTest++/Posix/SignalTranslator.h index efb3618..66d388d 100644 --- a/UnitTest++/Posix/SignalTranslator.h +++ b/UnitTest++/Posix/SignalTranslator.h @@ -22,8 +22,7 @@ namespace UnitTest { struct sigaction m_old_SIGTRAP_action; struct sigaction m_old_SIGSEGV_action; struct sigaction m_old_SIGBUS_action; - struct sigaction m_old_SIGABRT_action; - struct sigaction m_old_SIGALRM_action; + struct sigaction m_old_SIGILL_action; }; #if !defined (__GNUC__) diff --git a/UnitTest++/RequireMacros.h b/UnitTest++/RequireMacros.h new file mode 100644 index 0000000..7fe793b --- /dev/null +++ b/UnitTest++/RequireMacros.h @@ -0,0 +1,16 @@ +#ifndef UNITTEST_REQUIREMACROS_H +#define UNITTEST_REQUIREMACROS_H + +#include "RequiredCheckTestReporter.h" + +#define UNITTEST_REQUIRE for(UnitTest::RequiredCheckTestReporter decoratedReporter(*UnitTest::CurrentTest::Results()); decoratedReporter.Next(); ) + +#ifndef UNITTEST_DISABLE_SHORT_MACROS + #ifdef REQUIRE + #error REQUIRE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_REQUIRE instead + #else + #define REQUIRE UNITTEST_REQUIRE + #endif +#endif + +#endif diff --git a/UnitTest++/RequiredCheckException.cpp b/UnitTest++/RequiredCheckException.cpp new file mode 100644 index 0000000..874370e --- /dev/null +++ b/UnitTest++/RequiredCheckException.cpp @@ -0,0 +1,17 @@ +#include "RequiredCheckException.h" + +#ifndef UNITTEST_NO_EXCEPTIONS + +namespace UnitTest { + + RequiredCheckException::RequiredCheckException() + { + } + + RequiredCheckException::~RequiredCheckException() throw() + { + } + +} + +#endif diff --git a/UnitTest++/RequiredCheckException.h b/UnitTest++/RequiredCheckException.h new file mode 100644 index 0000000..c9a36da --- /dev/null +++ b/UnitTest++/RequiredCheckException.h @@ -0,0 +1,23 @@ +#ifndef UNITTEST_REQUIREDCHECKEXCEPTION_H +#define UNITTEST_REQUIREDCHECKEXCEPTION_H + +#include "Config.h" +#ifndef UNITTEST_NO_EXCEPTIONS + +#include "HelperMacros.h" +#include + +namespace UnitTest { + + class UNITTEST_LINKAGE RequiredCheckException : public std::exception + { + public: + RequiredCheckException(); + virtual ~RequiredCheckException() throw(); + }; + +} + +#endif + +#endif diff --git a/UnitTest++/RequiredCheckTestReporter.cpp b/UnitTest++/RequiredCheckTestReporter.cpp new file mode 100644 index 0000000..7c21d20 --- /dev/null +++ b/UnitTest++/RequiredCheckTestReporter.cpp @@ -0,0 +1,26 @@ +#include "RequiredCheckTestReporter.h" + +#include "CurrentTest.h" +#include "TestResults.h" + +namespace UnitTest { + + RequiredCheckTestReporter::RequiredCheckTestReporter(TestResults& results) + : m_results(results) + , m_originalTestReporter(results.m_testReporter) + , m_throwingReporter(results.m_testReporter) + , m_continue(0) + { + m_results.m_testReporter = &m_throwingReporter; + } + + RequiredCheckTestReporter::~RequiredCheckTestReporter() + { + m_results.m_testReporter = m_originalTestReporter; + } + + bool RequiredCheckTestReporter::Next() + { + return m_continue++ == 0; + } +} \ No newline at end of file diff --git a/UnitTest++/RequiredCheckTestReporter.h b/UnitTest++/RequiredCheckTestReporter.h new file mode 100644 index 0000000..99d9cdd --- /dev/null +++ b/UnitTest++/RequiredCheckTestReporter.h @@ -0,0 +1,33 @@ +#ifndef UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H +#define UNITTEST_REQUIRED_CHECK_TEST_REPORTER_H + +#include "HelperMacros.h" +#include "ThrowingTestReporter.h" + +namespace UnitTest { + + class TestResults; + + // This RAII class decorates the current TestReporter with + // a version that throws after reporting a failure. + class UNITTEST_LINKAGE RequiredCheckTestReporter + { + public: + explicit RequiredCheckTestReporter(TestResults& results); + ~RequiredCheckTestReporter(); + + bool Next(); + + private: + RequiredCheckTestReporter(RequiredCheckTestReporter const&); + RequiredCheckTestReporter& operator =(RequiredCheckTestReporter const&); + + TestResults& m_results; + TestReporter* m_originalTestReporter; + ThrowingTestReporter m_throwingReporter; + int m_continue; + }; +} + +#endif + diff --git a/UnitTest++/TestMacros.h b/UnitTest++/TestMacros.h index 738c56b..0c8e903 100644 --- a/UnitTest++/TestMacros.h +++ b/UnitTest++/TestMacros.h @@ -15,19 +15,7 @@ #include "Posix/SignalTranslator.h" #endif -#ifdef TEST -#error UnitTest++ redefines TEST -#endif - -#ifdef TEST_EX -#error UnitTest++ redefines TEST_EX -#endif - -#ifdef TEST_FIXTURE_EX -#error UnitTest++ redefines TEST_FIXTURE_EX -#endif - -#define SUITE(Name) \ +#define UNITTEST_SUITE(Name) \ namespace Suite ## Name { \ namespace UnitTestSuite { \ inline char const* GetSuiteName () { \ @@ -37,34 +25,36 @@ } \ namespace Suite ## Name -#define TEST_EX(Name, List) \ +#define UNITTEST_IMPL_TEST(Name, List) \ class Test ## Name : public UnitTest::Test \ { \ public: \ Test ## Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ private: \ virtual void RunImpl() const; \ - } test ## Name ## Instance; \ + } static test ## Name ## Instance; \ \ - UnitTest::ListAdder adder ## Name (List, &test ## Name ## Instance); \ + static UnitTest::ListAdder adder ## Name (List, &test ## Name ## Instance); \ \ void Test ## Name::RunImpl() const -#define TEST(Name) TEST_EX(Name, UnitTest::Test::GetTestList()) +#define UNITTEST_TEST(Name) UNITTEST_IMPL_TEST(Name, UnitTest::Test::GetTestList()) -#define TEST_FIXTURE_EX(Fixture, Name, List) \ +#define UNITTEST_IMPL_TEST_FIXTURE(Fixture, Name, List) \ class Fixture ## Name ## Helper : public Fixture \ { \ public: \ explicit Fixture ## Name ## Helper(UnitTest::TestDetails const& details) : m_details(details) {} \ void RunImpl(); \ UnitTest::TestDetails const& m_details; \ + virtual ~Fixture ## Name ## Helper(); \ private: \ Fixture ## Name ## Helper(Fixture ## Name ## Helper const&); \ Fixture ## Name ## Helper& operator =(Fixture ## Name ## Helper const&); \ }; \ + Fixture ## Name ## Helper::~Fixture ## Name ## Helper(){} \ \ class Test ## Fixture ## Name : public UnitTest::Test \ { \ @@ -72,30 +62,30 @@ Test ## Fixture ## Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ private: \ virtual void RunImpl() const; \ - } test ## Fixture ## Name ## Instance; \ + } static test ## Fixture ## Name ## Instance; \ \ - UnitTest::ListAdder adder ## Fixture ## Name (List, &test ## Fixture ## Name ## Instance); \ + static UnitTest::ListAdder adder ## Fixture ## Name (List, &test ## Fixture ## Name ## Instance); \ \ void Test ## Fixture ## Name::RunImpl() const \ { \ volatile bool ctorOk = false; \ - UT_TRY \ + UNITTEST_IMPL_TRY \ ({ \ Fixture ## Name ## Helper fixtureHelper(m_details); \ ctorOk = true; \ UnitTest::ExecuteTest(fixtureHelper, m_details, false); \ }) \ - UT_CATCH (UnitTest::AssertException, e, \ + UNITTEST_IMPL_CATCH (UnitTest::AssertException, e, \ { \ (void)e; \ }) \ - UT_CATCH (std::exception, e, \ + UNITTEST_IMPL_CATCH (std::exception, e, \ { \ UnitTest::MemoryOutStream stream; \ stream << "Unhandled exception: " << e.what(); \ UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText()); \ }) \ - UT_CATCH_ALL \ + UNITTEST_IMPL_CATCH_ALL \ ({ \ if (ctorOk) \ { \ @@ -111,7 +101,26 @@ } \ void Fixture ## Name ## Helper::RunImpl() -#define TEST_FIXTURE(Fixture,Name) TEST_FIXTURE_EX(Fixture, Name, UnitTest::Test::GetTestList()) +#define UNITTEST_TEST_FIXTURE(Fixture,Name) UNITTEST_IMPL_TEST_FIXTURE(Fixture, Name, UnitTest::Test::GetTestList()) +#ifndef UNITTEST_DISABLE_SHORT_MACROS + #ifdef SUITE + #error SUITE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_SUITE instead + #else + #define SUITE UNITTEST_SUITE + #endif + + #ifdef TEST + #error TEST already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_TEST instead + #else + #define TEST UNITTEST_TEST + #endif + + #ifdef TEST_FIXTURE + #error TEST_FIXTURE already defined, re-configure with UNITTEST_ENABLE_SHORT_MACROS set to 0 and use UNITTEST_TEST_FIXTURE instead + #else + #define TEST_FIXTURE UNITTEST_TEST_FIXTURE + #endif +#endif #endif diff --git a/UnitTest++/TestResults.h b/UnitTest++/TestResults.h index c56a632..a4d8e60 100644 --- a/UnitTest++/TestResults.h +++ b/UnitTest++/TestResults.h @@ -5,6 +5,7 @@ namespace UnitTest { + class RequiredCheckTestReporter; class TestReporter; class TestDetails; @@ -22,6 +23,8 @@ namespace UnitTest { int GetFailureCount() const; private: + friend class RequiredCheckTestReporter; + TestReporter* m_testReporter; int m_totalTestCount; int m_failedTestCount; diff --git a/UnitTest++/ThrowingTestReporter.cpp b/UnitTest++/ThrowingTestReporter.cpp new file mode 100644 index 0000000..4e56149 --- /dev/null +++ b/UnitTest++/ThrowingTestReporter.cpp @@ -0,0 +1,61 @@ +#include "ThrowingTestReporter.h" +#include "RequiredCheckException.h" + +#ifdef UNITTEST_NO_EXCEPTIONS +#include "ReportAssertImpl.h" +#endif + +namespace UnitTest { + + ThrowingTestReporter::ThrowingTestReporter(TestReporter* decoratedReporter) + : m_decoratedReporter(decoratedReporter) + {} + + //virtual + ThrowingTestReporter::~ThrowingTestReporter() + {} + + //virtual + void ThrowingTestReporter::ReportTestStart(TestDetails const& test) + { + if(m_decoratedReporter) + { + m_decoratedReporter->ReportTestStart(test); + } + } + + //virtual + void ThrowingTestReporter::ReportFailure(TestDetails const& test, char const* failure) + { + if(m_decoratedReporter) + { + m_decoratedReporter->ReportFailure(test, failure); + } + + #ifndef UNITTEST_NO_EXCEPTIONS + throw RequiredCheckException(); + #else + static const int stopTest = 1; + UNITTEST_LONGJMP(*UnitTest::Detail::GetAssertJmpBuf(), stopTest); + #endif + } + + //virtual + void ThrowingTestReporter::ReportTestFinish(TestDetails const& test, float secondsElapsed) + { + if(m_decoratedReporter) + { + m_decoratedReporter->ReportTestFinish(test, secondsElapsed); + } + } + + //virtual + void ThrowingTestReporter::ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) + { + if(m_decoratedReporter) + { + m_decoratedReporter->ReportSummary(totalTestCount, failedTestCount, failureCount, secondsElapsed); + } + } + +} diff --git a/UnitTest++/ThrowingTestReporter.h b/UnitTest++/ThrowingTestReporter.h new file mode 100644 index 0000000..34e105e --- /dev/null +++ b/UnitTest++/ThrowingTestReporter.h @@ -0,0 +1,26 @@ +#ifndef UNITTEST_THROWINGTESTREPORTER_H +#define UNITTEST_THROWINGTESTREPORTER_H + +#include "TestReporter.h" + +namespace UnitTest { + + // A TestReporter that throws when ReportFailure is called. Otherwise it + // forwards the calls to a decorated TestReporter + class ThrowingTestReporter : public TestReporter + { + public: + explicit ThrowingTestReporter(TestReporter* reporter); + + virtual ~ThrowingTestReporter(); + virtual void ReportTestStart(TestDetails const& test); + virtual void ReportFailure(TestDetails const& test, char const* failure); + virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed); + virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); + + private: + TestReporter* m_decoratedReporter; + }; +} + +#endif diff --git a/UnitTest++/UnitTestPP.h b/UnitTest++/UnitTestPP.h index c9bbc0c..3e02d31 100644 --- a/UnitTest++/UnitTestPP.h +++ b/UnitTest++/UnitTestPP.h @@ -4,6 +4,7 @@ #include "Config.h" #include "TestMacros.h" #include "CheckMacros.h" +#include "RequireMacros.h" #include "TestRunner.h" #include "TimeConstraint.h" #include "ReportAssert.h" diff --git a/appveyor.yml b/appveyor.yml index c36218a..3a4637d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,30 @@ +version: 2.1.0.{build} + os: - Windows Server 2012 R2 -install: +environment: + matrix: + + - CMAKE_GENERATOR: Visual Studio 9 2008 + - CMAKE_GENERATOR: Visual Studio 10 2010 + - CMAKE_GENERATOR: Visual Studio 11 2012 + - CMAKE_GENERATOR: Visual Studio 12 2013 + - CMAKE_GENERATOR: Visual Studio 14 2015 + +before_build: # Generate solution files using cmake, in 'builds' directory. # No need to create it because it's part of the repo. - - cd builds && cmake -G "Visual Studio 12" ../ && cd .. + - pushd builds && cmake -G "%CMAKE_GENERATOR%" ..\ && popd configuration: - Debug - Release -build: - project: builds/UnitTest++.sln +build_script: + - pushd builds && cmake --build . && popd + +matrix: + fast_finish: true + + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..347366d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +test -e ./.autotools_aux || mkdir .autotools_aux + +libtoolize -cq +aclocal -I m4 --install # Generate aclocal +autoconf # Generate configure script +autoheader # Generate config.h +automake --add-missing --copy # Generate Makefile.in and other scripts diff --git a/cmake/UnitTest++Config.cmake b/cmake/UnitTest++Config.cmake new file mode 100644 index 0000000..afe165c --- /dev/null +++ b/cmake/UnitTest++Config.cmake @@ -0,0 +1,2 @@ +include("${CMAKE_CURRENT_LIST_DIR}/UnitTest++Targets.cmake") +get_filename_component(UTPP_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../../include/" ABSOLUTE) diff --git a/configure.ac b/configure.ac index 7b77b73..372f576 100644 --- a/configure.ac +++ b/configure.ac @@ -2,23 +2,35 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([UnitTest++], [1.5.1], [pjohnmeyer@gmail.com]) +AC_INIT([UnitTest++], + m4_esyscmd_s([git describe --tags | cut -c2-]), + [pjohnmeyer@gmail.com], + [unittest-cpp]) + AC_CONFIG_SRCDIR([UnitTest++/TestDetails.cpp]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([UnitTest++.pc]) AM_INIT_AUTOMAKE([foreign subdir-objects]) +AM_SILENT_RULES([yes]) + +AC_CANONICAL_HOST + +dnl Detect Windows, as it doesn't implement UNIX signals and requires special code AM_CONDITIONAL([WINDOWS], - [test "${host#*mingw}" != "${host}" -o "${host#*msvc}" != "${host}"]) + [test "${host//mingw/}" != "${host}" -o "${host//msvc/}" != "${host}"]) + LT_INIT() -AC_SUBST([LIBUNITTEST_SO_VERSION], [1:5:1]) +AC_SUBST([LIBUNITTEST_SO_VERSION], [2:1:0]) # Checks for programs. AC_PROG_CXX AC_PROG_CC +AX_CXX_COMPILE_STDCXX_11(noext, optional) + # Checks for libraries. # Checks for header files. diff --git a/docs b/docs index 8d4ad23..a6963b7 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 8d4ad2348f13d35ed7af7c11d6dad2f5ed67f6b4 +Subproject commit a6963b798400df760e148a6e15e9c13db965a3ec diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000..66d41f5 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,558 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXXFLAGS to +# enable support. VERSION may be '11' (for the C++11 standard) or '14' +# (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [], + [$1], [14], [], + [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++$1 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + + AC_SUBST(HAVE_CXX$1) + fi +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) \ No newline at end of file diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000..09db383 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,39 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++11. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 14 + +include([ax_cxx_compile_stdcxx.m4]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5306292..06cc26c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,5 @@ check_PROGRAMS = UnitTest++/TestUnitTest++ -UnitTest___TestUnitTest___SOURCES = tests/Main.cpp tests/TestAssertHandler.cpp tests/TestCheckMacros.cpp tests/TestChecks.cpp tests/TestCompositeTestReporter.cpp tests/TestCurrentTest.cpp tests/TestDeferredTestReporter.cpp tests/TestExceptions.cpp tests/TestMemoryOutStream.cpp tests/TestTest.cpp tests/TestTestList.cpp tests/TestTestMacros.cpp tests/TestTestResults.cpp tests/TestTestRunner.cpp tests/TestTestSuite.cpp tests/TestTimeConstraint.cpp tests/TestTimeConstraintMacro.cpp tests/TestUnitTestPP.cpp tests/TestXmlTestReporter.cpp + +UnitTest___TestUnitTest___SOURCES = tests/Main.cpp tests/TestAssertHandler.cpp tests/TestCheckMacros.cpp tests/TestChecks.cpp tests/TestCompositeTestReporter.cpp tests/TestCurrentTest.cpp tests/TestDeferredTestReporter.cpp tests/TestExceptions.cpp tests/TestMemoryOutStream.cpp tests/TestRequireMacrosWithExceptionsOff.cpp tests/TestRequireMacrosWithExceptionsOn.cpp tests/TestTest.cpp tests/TestTestList.cpp tests/TestTestMacros.cpp tests/TestTestResults.cpp tests/TestTestRunner.cpp tests/TestTestSuite.cpp tests/TestTimeConstraint.cpp tests/TestTimeConstraintMacro.cpp tests/TestUnitTestPP.cpp tests/TestXmlTestReporter.cpp tests/RecordingReporter.h tests/ScopedCurrentTest.h UnitTest___TestUnitTest___LDADD = UnitTest++/libUnitTest++.la TESTS = UnitTest++/TestUnitTest++ diff --git a/tests/TestChecks.cpp b/tests/TestChecks.cpp index 1ec64ee..2c0ac04 100644 --- a/tests/TestChecks.cpp +++ b/tests/TestChecks.cpp @@ -315,4 +315,32 @@ namespace { CHECK_EQUAL(1234, reporter.lastFailedLine); } + class TruthyUnlessCopied + { + public: + TruthyUnlessCopied() + : truthy_(true) + { + } + + TruthyUnlessCopied(const TruthyUnlessCopied&) + : truthy_(false) + { + } + + operator bool() const + { + return truthy_; + } + + private: + bool truthy_; + }; + + TEST(CheckProperlyDealsWithOperatorBoolOverrides) + { + TruthyUnlessCopied objectThatShouldBeTruthy; + CHECK(objectThatShouldBeTruthy); + } + } diff --git a/tests/TestExceptions.cpp b/tests/TestExceptions.cpp index 972e64d..08f6547 100644 --- a/tests/TestExceptions.cpp +++ b/tests/TestExceptions.cpp @@ -253,7 +253,7 @@ namespace { class ThrowingObject { public: - float operator[](int) const + float operator[](size_t) const { throw "Test throw"; } @@ -262,7 +262,7 @@ namespace { class StdThrowingObject { public: - float operator[](int) const + float operator[](size_t) const { throw std::runtime_error("Test throw"); } @@ -451,7 +451,7 @@ namespace { class ThrowingObject2D { public: - float* operator[](int) const + float* operator[](size_t) const { throw "Test throw"; } @@ -460,7 +460,7 @@ namespace { class StdThrowingObject2D { public: - float* operator[](int) const + float* operator[](size_t) const { throw std::runtime_error("Test throw"); } diff --git a/tests/TestLongMacros.cpp b/tests/TestLongMacros.cpp new file mode 100644 index 0000000..6720a97 --- /dev/null +++ b/tests/TestLongMacros.cpp @@ -0,0 +1,45 @@ +#define UNITTEST_DISABLE_SHORT_MACROS + +#include "UnitTest++/UnitTestPP.h" + +// This file is not intended to test every little thing, just a few basics to hopefully ensure +// the macros are working and the short macros are not defined. +UNITTEST_SUITE(LongMacros) +{ + UNITTEST_TEST(LongCheckMacroWorks) + { + UNITTEST_CHECK(true); + } + + class Fixture + { + public: + Fixture() : sanity_(true) {} + protected: + bool sanity_; + }; + + UNITTEST_TEST_FIXTURE(Fixture, LongFixtureMacroWorks) + { + UNITTEST_REQUIRE UNITTEST_CHECK(sanity_); + } + + UNITTEST_TEST(ShortMacrosAreNotDefined) + { +#if defined(CHECK) || \ + defined(CHECK_EQUAL) || \ + defined(CHECK_CLOSE) || \ + defined(CHECK_ARRAY_EQUAL) || \ + defined(CHECK_ARRAY_CLOSE) || \ + defined(CHECK_ARRAY2D_CLOSE) || \ + defined(CHECK_THROW) || \ + defined(CHECK_ASSERT) || \ + defined(SUITE) || \ + defined(TEST) || \ + defined(TEST_FIXTURE) || \ + defined(REQUIRE) + + UNITTEST_CHECK(false); +#endif + } +} diff --git a/tests/TestMemoryOutStream.cpp b/tests/TestMemoryOutStream.cpp index 7c1ffbc..854277e 100644 --- a/tests/TestMemoryOutStream.cpp +++ b/tests/TestMemoryOutStream.cpp @@ -11,7 +11,7 @@ using namespace std; namespace { - const char* const maxSignedIntegralStr(size_t nBytes) + const char* maxSignedIntegralStr(size_t nBytes) { switch(nBytes) { @@ -28,7 +28,7 @@ namespace { } } - const char* const minSignedIntegralStr(size_t nBytes) + const char* minSignedIntegralStr(size_t nBytes) { switch(nBytes) { @@ -45,7 +45,7 @@ namespace { } } - const char* const maxUnsignedIntegralStr(size_t nBytes) + const char* maxUnsignedIntegralStr(size_t nBytes) { switch(nBytes) { diff --git a/tests/TestRequireMacrosWithExceptionsOff.cpp b/tests/TestRequireMacrosWithExceptionsOff.cpp new file mode 100644 index 0000000..d43fbc1 --- /dev/null +++ b/tests/TestRequireMacrosWithExceptionsOff.cpp @@ -0,0 +1,738 @@ +#include "UnitTest++/UnitTestPP.h" +#include "UnitTest++/CurrentTest.h" +#include "RecordingReporter.h" +#include "ScopedCurrentTest.h" + +#include + +using namespace std; + +#ifdef UNITTEST_NO_EXCEPTIONS + +// NOTE: unit tests here use a work around for std::longjmp +// taking us out of the current running unit test. We use a +// follow on test to check the previous test exhibited correct +// behavior. + +namespace { + + static RecordingReporter reporter; + static std::string testName; + static bool next = false; + static int line = 0; + + // Use destructor to reset our globals + struct DoValidationOn + { + ~DoValidationOn() + { + testName = ""; + next = false; + line = 0; + + reporter.lastFailedLine = 0; + memset(reporter.lastFailedTest, 0, sizeof(reporter.lastFailedTest)); + memset(reporter.lastFailedSuite, 0, sizeof(reporter.lastFailedSuite)); + memset(reporter.lastFailedFile, 0, sizeof(reporter.lastFailedFile)); + } + }; + + TEST(RequireCheckSucceedsOnTrue) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK(true); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireCheckSucceedsOnTrue_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckFailsOnFalse) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK(false); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckFailsOnFalse_FollowOn) + { + CHECK(!next); + } + + TEST(RequireMacroSupportsMultipleChecks) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,1); + } + + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroSupportsMultipleChecks_FollowOn) + { + CHECK(next); + } + + TEST(RequireMacroSupportsMultipleChecksWithFailingChecks) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,2); + } + + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroSupportsMultipleChecksWithFailingChecks_FollowOn) + { + CHECK(!next); + } + + TEST(RequireMacroDoesntExecuteCodeAfterAFailingCheck) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE + { + CHECK(false); + next = true; + } + } + } + + TEST_FIXTURE(DoValidationOn, RequireMacroDoesntExecuteCodeAfterAFailingCheck_FollowOn) + { + CHECK(!next); + } + + TEST(FailureReportsCorrectTestName) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + testName = m_details.testName; + REQUIRE CHECK(false); + } + } + + TEST_FIXTURE(DoValidationOn, FailureReportsCorrectTestName_FollowOn) + { + CHECK_EQUAL(testName, reporter.lastFailedTest); + } + + TEST(RequiredCheckFailureIncludesCheckContents) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + testName = m_details.testName; + const bool yaddayadda = false; + + REQUIRE CHECK(yaddayadda); + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckFailureIncludesCheckContents_FollowOn) + { + CHECK(strstr(reporter.lastFailedMessage, "yaddayadda")); + } + + TEST(RequiredCheckEqualSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1,1); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckEqualFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1, 2); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualFailsOnNotEqual_FollowOn) + { +// TODO: check reporter last test name + CHECK(!next); + } + + TEST(RequiredCheckEqualFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails const testDetails("testName", "suiteName", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + line = __LINE__; REQUIRE CHECK_EQUAL(1, 123); + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualFailureContainsCorrectDetails_FollowOn) + { + CHECK_EQUAL("testName", reporter.lastFailedTest); + CHECK_EQUAL("suiteName", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + int g_sideEffect = 0; + int FunctionWithSideEffects() + { + ++g_sideEffect; + return 1; + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(1, FunctionWithSideEffects()); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_EQUAL(2, FunctionWithSideEffects()); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckEqualDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE(1.0f, 1.001f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE (1.0f, 1.1f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("test", "suite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + line = __LINE__; REQUIRE CHECK_CLOSE(1.0f, 1.1f, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK_EQUAL("test", reporter.lastFailedTest); + CHECK_EQUAL("suite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + + CHECK(!next); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE (1, FunctionWithSideEffects(), 0.1f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + REQUIRE CHECK_CLOSE(2, FunctionWithSideEffects(), 0.1f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckCloseDoesNotHaveSideEffectsWhenFailingOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckArrayCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + const float data[4] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, data, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArrayCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckArrayCloseFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE(data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("arrayCloseTest", "arrayCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + line = __LINE__; REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArrayCloseFailureIncludesTolerance) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[4] = { 0, 1, 2, 3 }; + float const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseFailureIncludesTolerance_FollowOn) + { + CHECK(!next); + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + TEST(RequiredCheckArrayEqualSuceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[4] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data, data, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualSuceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArrayEqualFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailsOnNotEqual) + { + CHECK(!next); + } + + TEST(RequiredCheckArrayEqualFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayEqualFailureContainsCorrectInfo) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + line = __LINE__; REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayEqualFailureContainsCorrectInfo_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("RequiredCheckArrayEqualFailureContainsCorrectInfo", reporter.lastFailedTest); + CHECK_EQUAL(__FILE__, reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + float const* FunctionWithSideEffects2() + { + ++g_sideEffect; + static float const data[] = { 0, 1, 2, 3}; + return data; + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 0, 1, 2, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(next); + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 0, 1, 3, 3 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK_EQUAL(1, g_sideEffect); + CHECK(!next); + } + + TEST(RequiredCheckArray2DCloseSucceedsOnEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE(data, data, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseSucceedsOnEqual_FollowOn) + { + CHECK(next); + } + + TEST(RequiredCheckArray2DCloseFailsOnNotEqual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailsOnNotEqual_FollowOn) + { + CHECK(!next); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesCheckExpectedAndActual) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureIncludesCheckExpectedAndActual_FollowOn) + { + CHECK(!next); + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ [ 0 1 ] [ 2 3 ] ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ [ 0 1 ] [ 3 3 ] ]")); + } + + TEST(RequiredCheckArray2DCloseFailureContainsCorrectDetails) + { + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("array2DCloseTest", "array2DCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + line = __LINE__; REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureContainsCorrectDetails_FollowOn) + { + CHECK(!next); + + CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesTolerance) + { + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[2][2] = { {0, 1}, {2, 3} }; + float const data2[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseFailureIncludesTolerance_FollowOn) + { + CHECK(!next); + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + float const* const* FunctionWithSideEffects3() + { + ++g_sideEffect; + static float const data1[] = {0,1}; + static float const data2[] = {2,3}; + static const float* const data[] = {data1, data2}; + return data; + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenPassing_FollowOn) + { + CHECK(next); + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {3, 3} }; + + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + next = true; + } + } + + TEST_FIXTURE(DoValidationOn, RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenFailing_FollowOn) + { + CHECK(!next); + CHECK_EQUAL(1, g_sideEffect); + } +} + +#endif diff --git a/tests/TestRequireMacrosWithExceptionsOn.cpp b/tests/TestRequireMacrosWithExceptionsOn.cpp new file mode 100644 index 0000000..f904708 --- /dev/null +++ b/tests/TestRequireMacrosWithExceptionsOn.cpp @@ -0,0 +1,849 @@ +#include "UnitTest++/UnitTestPP.h" +#include "UnitTest++/CurrentTest.h" +#include "RecordingReporter.h" +#include "ScopedCurrentTest.h" + +using namespace std; + +#ifndef UNITTEST_NO_EXCEPTIONS + +namespace { + + TEST(RequireCheckSucceedsOnTrue) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK(true); + } + catch(const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckFailsOnFalse) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK(false); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + + TEST(RequireMacroSupportsMultipleChecks) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try{ + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,1); + } + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + + TEST(RequireMacroSupportsMultipleChecksWithFailingChecks) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try{ + REQUIRE + { + CHECK(true); + CHECK_EQUAL(1,2); + } + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequireMacroDoesntExecuteCodeAfterAFailingCheck) + { + bool failure = false; + bool exception = false; + bool run = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try{ + REQUIRE + { + CHECK(false); + run = true; // this shouldn't get executed. + } + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + CHECK(!run); + } + + TEST(FailureReportsCorrectTestName) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK(false); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL(m_details.testName, reporter.lastFailedTest); + } + + TEST(RequiredCheckFailureIncludesCheckContents) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + const bool yaddayadda = false; + + try + { + REQUIRE CHECK(yaddayadda); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "yaddayadda")); + } + + TEST(RequiredCheckEqualSucceedsOnEqual) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_EQUAL(1,1); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckEqualFailsOnNotEqual) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_EQUAL(1, 2); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequiredCheckEqualFailureContainsCorrectDetails) + { + int line = 0; + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails const testDetails("testName", "suiteName", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + try + { + line = __LINE__; REQUIRE CHECK_EQUAL(1, 123); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL("testName", reporter.lastFailedTest); + CHECK_EQUAL("suiteName", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + int g_sideEffect = 0; + int FunctionWithSideEffects() + { + ++g_sideEffect; + return 1; + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_EQUAL(1, FunctionWithSideEffects()); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckEqualDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_EQUAL(2, FunctionWithSideEffects()); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + + + TEST(RequiredCheckCloseSucceedsOnEqual) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_CLOSE(1.0f, 1.001f, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckCloseFailsOnNotEqual) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_CLOSE (1.0f, 1.1f, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequiredCheckCloseFailureContainsCorrectDetails) + { + int line = 0; + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("test", "suite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + try + { + line = __LINE__; REQUIRE CHECK_CLOSE(1.0f, 1.1f, 0.01f); + CHECK(false); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL("test", reporter.lastFailedTest); + CHECK_EQUAL("suite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_CLOSE (1, FunctionWithSideEffects(), 0.1f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + try + { + REQUIRE CHECK_CLOSE(2, FunctionWithSideEffects(), 0.1f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArrayCloseSucceedsOnEqual) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + const float data[4] = { 0, 1, 2, 3 }; + + try + { + REQUIRE CHECK_ARRAY_CLOSE (data, data, 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckArrayCloseFailsOnNotEqual) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequiredCheckArrayCloseFailureIncludesCheckExpectedAndActual) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_CLOSE(data1, data2, 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayCloseFailureContainsCorrectDetails) + { + int line = 0; + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("arrayCloseTest", "arrayCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + line = __LINE__; REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArrayCloseFailureIncludesTolerance) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[4] = { 0, 1, 2, 3 }; + float const data2[4] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + TEST(RequiredCheckArrayEqualSuceedsOnEqual) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[4] = { 0, 1, 2, 3 }; + + try + { + REQUIRE CHECK_ARRAY_EQUAL (data, data, 4); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckArrayEqualFailsOnNotEqual) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequiredCheckArrayEqualFailureIncludesCheckExpectedAndActual) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]")); + } + + TEST(RequiredCheckArrayEqualFailureContainsCorrectInfo) + { + int line = 0; + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[4] = { 0, 1, 2, 3 }; + int const data2[4] = { 0, 1, 3, 3 }; + + try + { + line = __LINE__; REQUIRE CHECK_ARRAY_EQUAL (data1, data2, 4); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL("RequiredCheckArrayEqualFailureContainsCorrectInfo", reporter.lastFailedTest); + CHECK_EQUAL(__FILE__, reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + float const* FunctionWithSideEffects2() + { + ++g_sideEffect; + static float const data[] = {1,2,3,4}; + return data; + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 1, 2, 3, 4 }; + + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + } + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArrayCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[] = { 0, 1, 3, 3 }; + + try + { + REQUIRE CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArray2DCloseSucceedsOnEqual) + { + bool failure = true; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE(data, data, 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(!failure); + CHECK(!exception); + } + + TEST(RequiredCheckArray2DCloseFailsOnNotEqual) + { + bool failure = false; + bool exception = false; + { + RecordingReporter reporter; + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + { + exception = true; + } + + failure = (testResults.GetFailureCount() > 0); + } + + CHECK(failure); + CHECK(exception); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesCheckExpectedAndActual) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "xpected [ [ 0 1 ] [ 2 3 ] ]")); + CHECK(strstr(reporter.lastFailedMessage, "was [ [ 0 1 ] [ 3 3 ] ]")); + } + + TEST(RequiredCheckArray2DCloseFailureContainsCorrectDetails) + { + int line = 0; + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + UnitTest::TestDetails testDetails("array2DCloseTest", "array2DCloseSuite", "filename", -1); + ScopedCurrentTest scopedResults(testResults, &testDetails); + + int const data1[2][2] = { {0, 1}, {2, 3} }; + int const data2[2][2] = { {0, 1}, {3, 3} }; + + try + { + line = __LINE__; REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest); + CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite); + CHECK_EQUAL("filename", reporter.lastFailedFile); + CHECK_EQUAL(line, reporter.lastFailedLine); + } + + TEST(RequiredCheckArray2DCloseFailureIncludesTolerance) + { + RecordingReporter reporter; + { + UnitTest::TestResults testResults(&reporter); + ScopedCurrentTest scopedResults(testResults); + + float const data1[2][2] = { {0, 1}, {2, 3} }; + float const data2[2][2] = { {0, 1}, {3, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + + CHECK(strstr(reporter.lastFailedMessage, "0.01")); + } + + float const* const* FunctionWithSideEffects3() + { + ++g_sideEffect; + static float const data1[] = {0,1}; + static float const data2[] = {2,3}; + static const float* const data[] = {data1, data2}; + return data; + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenPassing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {2, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + + TEST(RequiredCheckArray2DCloseDoesNotHaveSideEffectsWhenFailing) + { + g_sideEffect = 0; + { + UnitTest::TestResults testResults; + ScopedCurrentTest scopedResults(testResults); + + const float data[2][2] = { {0, 1}, {3, 3} }; + + try + { + REQUIRE CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f); + } + catch (const UnitTest::RequiredCheckException&) + {} + } + CHECK_EQUAL(1, g_sideEffect); + } + +} + +#endif diff --git a/tests/TestTest.cpp b/tests/TestTest.cpp index 5a4e1ca..0db0650 100644 --- a/tests/TestTest.cpp +++ b/tests/TestTest.cpp @@ -72,7 +72,7 @@ namespace { CHECK_EQUAL(1, results.GetFailureCount()); } -#if !defined(UNITTEST_MINGW) && !defined(UNITTEST_WIN32) +#if !defined(UNITTEST_MINGW) && !defined(UNITTEST_WIN32) && !defined(__clang__) // Skip this test in debug because some debuggers don't like it. #if defined(NDEBUG) TEST(CrashingTestsAreReportedAsFailures) diff --git a/tests/TestTestMacros.cpp b/tests/TestTestMacros.cpp index 4a13316..e66bfb6 100644 --- a/tests/TestTestMacros.cpp +++ b/tests/TestTestMacros.cpp @@ -46,7 +46,7 @@ using namespace std; namespace { TestList list1; - TEST_EX(DummyTest, list1) + UNITTEST_IMPL_TEST(DummyTest, list1) {} TEST (TestsAreAddedToTheListThroughMacro) @@ -69,7 +69,7 @@ namespace { }; TestList list2; - TEST_FIXTURE_EX(ThrowingThingie, DummyTestName, list2) + UNITTEST_IMPL_TEST_FIXTURE(ThrowingThingie, DummyTestName, list2) {} TEST (ExceptionsInFixtureAreReportedAsHappeningInTheFixture) @@ -113,7 +113,7 @@ namespace { } TestList macroTestList1; - TEST_EX(MacroTestHelper1, macroTestList1) + UNITTEST_IMPL_TEST(MacroTestHelper1, macroTestList1) {} TEST(TestAddedWithTEST_EXMacroGetsDefaultSuite) @@ -124,7 +124,7 @@ namespace { } TestList macroTestList2; - TEST_FIXTURE_EX(DummyFixture, MacroTestHelper2, macroTestList2) + UNITTEST_IMPL_TEST_FIXTURE(DummyFixture, MacroTestHelper2, macroTestList2) {} TEST(TestAddedWithTEST_FIXTURE_EXMacroGetsDefaultSuite) @@ -144,7 +144,7 @@ namespace { }; TestList throwingFixtureTestList1; - TEST_FIXTURE_EX(FixtureCtorThrows, FixtureCtorThrowsTestName, throwingFixtureTestList1) + UNITTEST_IMPL_TEST_FIXTURE(FixtureCtorThrows, FixtureCtorThrowsTestName, throwingFixtureTestList1) {} TEST(FixturesWithThrowingCtorsAreFailures) @@ -170,7 +170,7 @@ namespace { }; TestList throwingFixtureTestList2; - TEST_FIXTURE_EX(FixtureDtorThrows, FixtureDtorThrowsTestName, throwingFixtureTestList2) + UNITTEST_IMPL_TEST_FIXTURE(FixtureDtorThrows, FixtureDtorThrowsTestName, throwingFixtureTestList2) {} TEST(FixturesWithThrowingDtorsAreFailures) @@ -200,7 +200,7 @@ namespace { }; TestList ctorAssertFixtureTestList; - TEST_FIXTURE_EX(FixtureCtorAsserts, CorrectlyReportsAssertFailureInCtor, ctorAssertFixtureTestList) + UNITTEST_IMPL_TEST_FIXTURE(FixtureCtorAsserts, CorrectlyReportsAssertFailureInCtor, ctorAssertFixtureTestList) {} TEST(CorrectlyReportsFixturesWithCtorsThatAssert)