From f626deda19e54adaaff1cd0d7b22421f934dec55 Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Tue, 6 Aug 2019 16:22:08 +0300 Subject: [PATCH] Added special catch for std::exception in GTEST_TEST_NO_THROW_ --- .../include/gtest/internal/gtest-internal.h | 34 +++++++++++++++++-- googletest/test/gtest_unittest.cc | 13 +++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 08531d8c..918fd4dd 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -825,6 +825,16 @@ struct GTEST_API_ ConstCharPtr { const char* value; }; +// Helper for declaring std::string within 'if' statement +// in pre C++17 build environment. +struct GTEST_API_ TrueWithString { + TrueWithString() = default; + explicit TrueWithString(const char* str) : value(str) {} + explicit TrueWithString(const std::string& str) : value(str) {} + explicit operator bool() const { return true; } + std::string value; +}; + // A simple Linear Congruential Generator for generating random // numbers with a uniform distribution. Unlike rand() and srand(), it // doesn't use global state (and therefore can't interfere with user @@ -1335,19 +1345,37 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ fail(gtest_msg.value) +#if GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ + catch (std::exception const& e) { \ + gtest_msg.value = "it throws std::exception-derived exception with description: \""; \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() + +#endif // GTEST_HAS_EXCEPTIONS + #define GTEST_TEST_NO_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ + GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ catch (...) { \ + gtest_msg.value = "it throws."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ - fail("Expected: " #statement " doesn't throw an exception.\n" \ - " Actual: it throws.") + fail(("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: " + gtest_msg.value).c_str()) #define GTEST_TEST_ANY_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 2b00b70a..2496c59d 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -3351,6 +3351,9 @@ TEST_F(SingleEvaluationTest, OtherCases) { void ThrowAnInteger() { throw 1; } +void ThrowRuntimeError(const char* what) { + throw std::runtime_error(what); +} // Tests that assertion arguments are evaluated exactly once. TEST_F(SingleEvaluationTest, ExceptionTests) { @@ -3830,6 +3833,11 @@ TEST(AssertionTest, ASSERT_NO_THROW) { EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()), "Expected: ThrowAnInteger() doesn't throw an exception." "\n Actual: it throws."); + EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowRuntimeError("A description")), + "Expected: ThrowRuntimeError(\"A description\") " + "doesn't throw an exception.\n " + "Actual: it throws std::exception-derived exception " + "with description: \"A description\"."); } // Tests ASSERT_ANY_THROW. @@ -4567,6 +4575,11 @@ TEST(ExpectTest, EXPECT_NO_THROW) { EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()), "Expected: ThrowAnInteger() doesn't throw an " "exception.\n Actual: it throws."); + EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowRuntimeError("A description")), + "Expected: ThrowRuntimeError(\"A description\") " + "doesn't throw an exception.\n " + "Actual: it throws std::exception-derived exception " + "with description: \"A description\"."); } // Tests EXPECT_ANY_THROW.