From abfa9478fe37f616597be551a227746353bcd8de Mon Sep 17 00:00:00 2001 From: Edward Woolhouse Date: Wed, 30 Oct 2013 20:59:23 +0000 Subject: [PATCH] Added support for C++11 strongly typed enums To use invoke cmake with -DUTPP_USE_CPP11 option and uncomment #define UNITTEST_FORCE_CPP11_DETECTION in Config.h --- CMakeLists.txt | 7 +++ UnitTest++/Checks.h | 111 +++++++++++++++++++++++++++++++++++++++++++ UnitTest++/Config.h | 18 +++++++ tests/TestChecks.cpp | 44 +++++++++++++++++ 4 files changed, 180 insertions(+) mode change 100644 => 100755 CMakeLists.txt mode change 100644 => 100755 UnitTest++/Checks.h mode change 100644 => 100755 UnitTest++/Config.h mode change 100644 => 100755 tests/TestChecks.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 7b2482d..588d10d --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8.1) project(UnitTest++) 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_CPP11 "Set this to ON is you with support C++11 features such as strongly typed enum" OFF) # get the main sources file(GLOB headers_ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} UnitTest++/*.h) @@ -16,6 +17,12 @@ else() set(platformDir_ Posix) endif(WIN32) +if(${UTPP_USE_CPP11}) + if (${CMAKE_COMPILER_IS_GNUCXX}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() +endif() + file(GLOB platformHeaders_ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} UnitTest++/${platformDir_}/*.h) file(GLOB platformSources_ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} UnitTest++/${platformDir_}/*.cpp) source_group(${platformDir_} FILES ${platformHeaders_} ${platformSources_}) diff --git a/UnitTest++/Checks.h b/UnitTest++/Checks.h old mode 100644 new mode 100755 index b2cc4db..2e492c4 --- a/UnitTest++/Checks.h +++ b/UnitTest++/Checks.h @@ -5,6 +5,10 @@ #include "TestResults.h" #include "MemoryOutStream.h" +#ifdef UNITTEST_CPP11 +#include +#endif + namespace UnitTest { @@ -15,6 +19,40 @@ bool Check(Value const value) } +#ifdef UNITTEST_CPP11 + +// C++11 strongly typed enum overload +template< typename Expected, typename Actual > +typename std::enable_if::value && std::is_enum::value>::type +CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details) +{ + if (!(expected == actual)) + { + UnitTest::MemoryOutStream stream; + stream << "Expected " << static_cast(expected) + << " but was " << static_cast(actual); + + results.OnTestFailure(details, stream.GetText()); + } +} + + +// Non-strongly type enum overload +template< typename Expected, typename Actual > +typename std::enable_if::value || !std::is_enum::value>::type +CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details) +{ + if (!(expected == actual)) + { + UnitTest::MemoryOutStream stream; + stream << "Expected " << expected << " but was " << actual; + + results.OnTestFailure(details, stream.GetText()); + } +} + +#else + template< typename Expected, typename Actual > void CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details) { @@ -27,6 +65,9 @@ void CheckEqual(TestResults& results, Expected const& expected, Actual const& ac } } +#endif + + UNITTEST_LINKAGE void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details); UNITTEST_LINKAGE void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details); @@ -54,6 +95,74 @@ void CheckClose(TestResults& results, Expected const& expected, Actual const& ac } } +#ifdef UNITTEST_CPP11 + +// C++11 strongly typed enum overload +template< typename Expected, typename Actual > +typename std::enable_if::type>::value && + std::is_enum::type>::value>::type +CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, + int const count, TestDetails const& details) +{ + bool equal = true; + for (int i = 0; i < count; ++i) + equal &= (expected[i] == actual[i]); + + if (!equal) + { + UnitTest::MemoryOutStream stream; + + stream << "Expected [ "; + + for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) + stream << static_cast(expected[expectedIndex]) << " "; + + stream << "] but was [ "; + + for (int actualIndex = 0; actualIndex < count; ++actualIndex) + stream << static_cast(actual[actualIndex]) << " "; + + stream << "]"; + + results.OnTestFailure(details, stream.GetText()); + } +} + + +// Non-strongly type enum overload +template< typename Expected, typename Actual > +typename std::enable_if::type>::value || + !std::is_enum::type>::value>::type +CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, + int const count, TestDetails const& details) +{ + bool equal = true; + for (int i = 0; i < count; ++i) + equal &= (expected[i] == actual[i]); + + if (!equal) + { + UnitTest::MemoryOutStream stream; + + stream << "Expected [ "; + + for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) + stream << expected[expectedIndex] << " "; + + stream << "] but was [ "; + + for (int actualIndex = 0; actualIndex < count; ++actualIndex) + stream << actual[actualIndex] << " "; + + stream << "]"; + + results.OnTestFailure(details, stream.GetText()); + } +} + + + +#else template< typename Expected, typename Actual > void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, @@ -83,6 +192,8 @@ void CheckArrayEqual(TestResults& results, Expected const& expected, Actual cons } } +#endif + template< typename Expected, typename Actual, typename Tolerance > bool ArrayAreClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance) { diff --git a/UnitTest++/Config.h b/UnitTest++/Config.h old mode 100644 new mode 100755 index 4f695f7..84599d0 --- a/UnitTest++/Config.h +++ b/UnitTest++/Config.h @@ -70,4 +70,22 @@ #define UNIITEST_NS_QUAL_STD(x) ::std::x #endif + +//#define UNITTEST_FORCE_CPP11_DETECTION +//#define UNITTEST_DISABLE_CPP11 + +/* C++11 features are enabled when __cplusplus > 199711L + * but compiler support is patchy. You can manually force or disable C++11 + * by defining UNITTEST_FORCE_CPP11_DETECTION + * or UNITTEST_DISABLE_CPP11 + * You will also require compiler options that enable C++11 eg + * gcc 4.6: -std=c++0x + * gcc 4.7+: -std=c++11 + * MSVC 2012+: No options required + * MSVC 2010 and earlier do not support strongly typed enums + */ +#if ((__cplusplus > 199711L ) || defined( UNITTEST_FORCE_CPP11_DETECTION )) && !defined( UNITTEST_DISABLE_CPP11 ) + #define UNITTEST_CPP11 +#endif + #endif diff --git a/tests/TestChecks.cpp b/tests/TestChecks.cpp old mode 100644 new mode 100755 index 9554b31..ee5e3fd --- a/tests/TestChecks.cpp +++ b/tests/TestChecks.cpp @@ -315,4 +315,48 @@ TEST(CheckArray2DCloseFailureIncludesDetails) CHECK_EQUAL(1234, reporter.lastFailedLine); } +// C++11 specific tests +#ifdef UNITTEST_CPP11 + +enum class StronglyTypedColorEnum : unsigned short +{ + Red, Blue +}; + +TEST(CheckEqualWithStronglyTypedEnum) +{ + TestResults results; + + CheckEqual(results, StronglyTypedColorEnum::Red, StronglyTypedColorEnum::Blue, TestDetails("", "", "", 0)); + CHECK_EQUAL(1, results.GetFailureCount()); + + CheckEqual(results, StronglyTypedColorEnum::Red, StronglyTypedColorEnum::Red, TestDetails("", "", "", 0)); + CHECK_EQUAL(1, results.GetFailureCount()); +} + +TEST(CheckArrayEqualWithStronglyTypedEnum) +{ + TestResults results; + + StronglyTypedColorEnum expected[] = {StronglyTypedColorEnum::Red, + StronglyTypedColorEnum::Red, + StronglyTypedColorEnum::Blue}; + + StronglyTypedColorEnum results1[] = {StronglyTypedColorEnum::Red, + StronglyTypedColorEnum::Red, + StronglyTypedColorEnum::Blue}; + + StronglyTypedColorEnum results2[] = {StronglyTypedColorEnum::Red, + StronglyTypedColorEnum::Blue, + StronglyTypedColorEnum::Blue}; + + CheckArrayEqual(results, expected, results1, 3, TestDetails("", "", "", 0)); + CHECK_EQUAL(0, results.GetFailureCount()); + + CheckArrayEqual(results, expected, results2, 3, TestDetails("", "", "", 0)); + CHECK_EQUAL(1, results.GetFailureCount()); +} + +#endif + }