From 3d63458a3d7b46b2720871ec2884bdb331ce935e Mon Sep 17 00:00:00 2001 From: Olek Raymond <123381967+OlekRaymond@users.noreply.github.com> Date: Sun, 26 Oct 2025 13:52:54 +0000 Subject: [PATCH 1/2] Allows for exiting assertions to be used in constructors and destructors --- CMakeLists.txt | 3 ++ CppUnit2Gtest.hpp | 80 +++++++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f5f8f1..ce9e172 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ add_library(CppUnit2Gtest::CppUnit2Gtest ALIAS CppUnit2Gtest) if (EnableMainHelperClasses) target_compile_definitions(CppUnit2Gtest INTERFACE Cpp2Unit2Gtest_EnableMainHelperClasses) endif() +if (AllowAssertsInConstructors) + target_compile_definitions(CppUnit2Gtest INTERFACE CppUnit2Gtest_AllowAssertsInConstructors) +endif() # Set include directories target_include_directories(CppUnit2Gtest INTERFACE diff --git a/CppUnit2Gtest.hpp b/CppUnit2Gtest.hpp index 1adcdf3..c63f1a5 100644 --- a/CppUnit2Gtest.hpp +++ b/CppUnit2Gtest.hpp @@ -39,7 +39,8 @@ namespace CppUnit { #endif namespace to { namespace gtest { - + // Stream operators make things forward compatable with gtest + struct ExitingAssertion : std::stringstream { }; #define CppUnit2Gtest_CHECK(condition) \ if (!(condition)) { \ throw std::runtime_error("Internal Check failed when running test harness " #condition ); \ @@ -90,7 +91,13 @@ namespace to { namespace gtest { void TestBody() override { // We inherit from this so safe to cast. auto& a = static_cast(*this); - (testMethod)(a); + try { + (testMethod)(a); + } catch (const ExitingAssertion& e) { + // Hack to get around non-exiting assertions + // Mostly only needed when CppUnit2Gtest_AllowAssertsInConstructors is on + FAIL() << e.str(); + } } }; @@ -225,41 +232,60 @@ namespace to { namespace gtest { # define CU_TEST_SUITE_END() CPPUNIT_TEST_SUITE_END() # define CU_TEST_SUITE_REGISTRATION(tc) CPPUNIT_TEST_SUITE_REGISTRATION(tc) #endif + +#if defined(CppUnit2Gtest_AllowAssertsInConstructors) + +/// Note: gtest args must be surrounded by brackets: +// CppUnit2Gtest_assertion_wrapper_(TRUE, (true)) +// CppUnit2Gtest_assertion_wrapper_(TRUE, (true) << "expected true") +# define CppUnit2Gtest_assertion_wrapper_(gtest_assertion, args) \ + EXPECT_ ## gtest_assertion args ; if (::testing::Test::HasFailure()) throw ::CppUnit::to::gtest::ExitingAssertion{} + +# define CppUnit2Gtest_fail_wrapper_() ADD_FAILURE() + +#else // CppUnit2Gtest_AllowAssertsInConstructors +# define CppUnit2Gtest_assertion_wrapper_(gtest_assertion, args) \ + ASSERT_ ## gtest_assertion args + +# define CppUnit2Gtest_fail_wrapper_() FAIL() + +#endif + // For backwards compatibility, not recommended #if CPPUNIT_ENABLE_NAKED_ASSERT # undef assert -# define assert(c) ASSERT_TRUE(c) -# define assertEqual(e,a) ASSERT_EQ(e,a) -# define assertDoublesEqual(e,a,d) ASSERT_NEAR(e,a,d) -# define assertLongsEqual(e,a) ASSERT_EQ(e,a) +# define assert(c) CppUnit2Gtest_assertion_wrapper_(TRUE, (c)) +# define assertEqual(e,a) CppUnit2Gtest_assertion_wrapper_(EQ, (e,a)) +# define assertDoublesEqual(e,a,d) CppUnit2Gtest_assertion_wrapper_(NEAR, (e,a,d)) +# define assertLongsEqual(e,a) CppUnit2Gtest_assertion_wrapper_(EQ, (e,a)) #endif #define CPPUNIT_TEST_FIXTURE(FixtureClass,testName) TEST_F(FixtureClass, testName) // Asserting -#define CPPUNIT_ASSERT(condition) ASSERT_TRUE(condition) -#define CPPUNIT_ASSERT_MESSAGE(message, condition) ASSERT_TRUE(condition) << message -#define CPPUNIT_ASSERT_EQUAL(a, b) ASSERT_EQ(a, b) -#define CPPUNIT_ASSERT_EQUAL_MESSAGE(msg, a, b) ASSERT_EQ(a, b) << msg -#define CPPUNIT_ASSERT_NO_THROW(expression) ASSERT_NO_THROW(expression) -#define CPPUNIT_ASSERT_NO_THROW_MESSAGE(msg, expression) ASSERT_NO_THROW(expression) << message -#define CPPUNIT_ASSERT_THROW(expression, expected) ASSERT_THROW(expression, expected) -#define CPPUNIT_ASSERT_THROW_MESSAGE(message, expression, expected) ASSERT_THROW(expression, expected) << message -#define CPPUNIT_ASSERT_DOUBLES_EQUAL(a,b, t) ASSERT_NEAR(a, b, t) -#define CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(msg, a, b, t) ASSERT_NEAR(a, b, t) << msg -#define CPPUNIT_FAIL(message) FAIL() << message -#define CPPUNIT_ASSERT_ASSERTION_PASS(e) ASSERT_NO_THROW(e) -#define CPPUNIT_ASSERT_ASSERTION_PASS_MESSAGE(msg, e) ASSERT_NO_THROW(e) << msg -#define CPPUNIT_ASSERT_LESS(expected, actual) ASSERT_LT(actual, expected) -#define CPPUNIT_ASSERT_LESSEQUAL(expected, actual) ASSERT_LE(actual, expected) -#define CPPUNIT_ASSERT_GREATER(expected, actual) ASSERT_GT(actual, expected) -#define CPPUNIT_ASSERT_GREATEREQUAL(expected, actual) ASSERT_GE(actual, expected) +#define CPPUNIT_ASSERT(condition) CppUnit2Gtest_assertion_wrapper_(TRUE, (condition)) +#define CPPUNIT_ASSERT_MESSAGE(message, condition) CppUnit2Gtest_assertion_wrapper_(TRUE, (condition) << message) +#define CPPUNIT_ASSERT_EQUAL(a, b) CppUnit2Gtest_assertion_wrapper_(EQ, (a, b)) +#define CPPUNIT_ASSERT_EQUAL_MESSAGE(msg, a, b) CppUnit2Gtest_assertion_wrapper_(EQ, (a, b) << msg) +#define CPPUNIT_ASSERT_NO_THROW(expression) CppUnit2Gtest_assertion_wrapper_(NO_THROW,(expression)) +#define CPPUNIT_ASSERT_NO_THROW_MESSAGE(msg, expression) CppUnit2Gtest_assertion_wrapper_(NO_THROW,(expression) << message) +#define CPPUNIT_ASSERT_THROW(expression, expected) CppUnit2Gtest_assertion_wrapper_(THROW, (expression, expected)) +#define CPPUNIT_ASSERT_THROW_MESSAGE(message, expression, expected) CppUnit2Gtest_assertion_wrapper_(THROW,(expression, expected) << message) +#define CPPUNIT_ASSERT_DOUBLES_EQUAL(a,b, t) CppUnit2Gtest_assertion_wrapper_(NEAR, (a, b, t)) +#define CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(msg, a, b, t) CppUnit2Gtest_assertion_wrapper_(NEAR, (a, b, t) << msg) +#define CPPUNIT_FAIL(message) CppUnit2Gtest_fail_wrapper_() << message +#define CPPUNIT_ASSERT_ASSERTION_PASS(e) CppUnit2Gtest_assertion_wrapper_(NO_THROW, (e)) +#define CPPUNIT_ASSERT_ASSERTION_PASS_MESSAGE(msg, e) CppUnit2Gtest_assertion_wrapper_(NO_THROW, (e) << msg) +#define CPPUNIT_ASSERT_LESS(expected, actual) CppUnit2Gtest_assertion_wrapper_(LT, (actual, expected)) +#define CPPUNIT_ASSERT_LESSEQUAL(expected, actual) CppUnit2Gtest_assertion_wrapper_(LE, (actual, expected)) +#define CPPUNIT_ASSERT_GREATER(expected, actual) CppUnit2Gtest_assertion_wrapper_(GT, (actual, expected)) +#define CPPUNIT_ASSERT_GREATEREQUAL(expected, actual) CppUnit2Gtest_assertion_wrapper_(GE, (actual, expected)) // These aren't in CppUnit but we can be nicer to the user -#define CPPUNIT_ASSERT_LESS_MESSAGE(msg, expected, actual) ASSERT_LT(actual, expected) << msg -#define CPPUNIT_ASSERT_GREATER_MESSAGE(msg, expected, actual) ASSERT_GT(actual, expected) << msg -#define CPPUNIT_ASSERT_LESSEQUAL_MESSAGE(msg, expected, actual) ASSERT_LE(actual, expected) << msg -#define CPPUNIT_ASSERT_GREATEREQUAL_MESSAGE(msg, expected, actual) ASSERT_GE(actual, expected) << msg +#define CPPUNIT_ASSERT_LESS_MESSAGE(msg, expected, actual) CppUnit2Gtest_assertion_wrapper_(LT, (actual, expected) << msg) +#define CPPUNIT_ASSERT_GREATER_MESSAGE(msg, expected, actual) CppUnit2Gtest_assertion_wrapper_(GT, (actual, expected) << msg) +#define CPPUNIT_ASSERT_LESSEQUAL_MESSAGE(msg, expected, actual) CppUnit2Gtest_assertion_wrapper_(LE, (actual, expected) << msg) +#define CPPUNIT_ASSERT_GREATEREQUAL_MESSAGE(msg, expected, actual) CppUnit2Gtest_assertion_wrapper_(GE, (actual, expected) << msg) #define CppUnit2Gtest_FailCompilation_NotSupported static_assert(false, \ "This CppUnit macro is not supported. Please rewrite this test in GTest or with normal macros") From 25d245a0aaac90550a96bff58aa38689aa97d253 Mon Sep 17 00:00:00 2001 From: Olek Raymond <123381967+OlekRaymond@users.noreply.github.com> Date: Sun, 26 Oct 2025 14:30:53 +0000 Subject: [PATCH 2/2] Adds option to CML to allow for exiting assertions --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce9e172..e1fc2c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,14 +8,14 @@ project( option(build_testing "Should we build our examples and tests" OFF) option(EnableMainHelperClasses - "Aims to allow for drop in replacement. Users should prefer refactoring the main function" - OFF - ) - + "Aims to allow for drop in replacement. Users should prefer refactoring the main function" + OFF) option(InstallAsCppUnit - "Install the package as 'cppunit' to allow drop-in replacement" - OFF - ) + "Install the package as 'cppunit' to allow drop-in replacement" + OFF) +option(AllowAssertsInConstructors + "Allows use of gtest exiting asserts (ASSERT_*) in constructors and destructors" + OFF) if(build_testing) enable_testing()