Googletest export

Make EXPECT_THROW print the actual exception type on the "threw the wrong exception type" case if the actual exception is a std::exception

PiperOrigin-RevId: 211519873
This commit is contained in:
Abseil Team 2018-09-04 17:00:34 -04:00 committed by Gennadiy Civil
parent 51cabc168f
commit dbd55366c8
2 changed files with 53 additions and 31 deletions

View File

@ -771,13 +771,12 @@ GTEST_API_ bool AlwaysTrue();
// Always returns false. // Always returns false.
inline bool AlwaysFalse() { return !AlwaysTrue(); } inline bool AlwaysFalse() { return !AlwaysTrue(); }
// Helper for suppressing false warning from Clang on a const char* // Helper for creating strings in if() statement branches. Always converts to
// variable declared in a conditional expression always being NULL in // true.
// the else branch. struct GTEST_API_ TrueString {
struct GTEST_API_ ConstCharPtr { TrueString() {}
ConstCharPtr(const char* str) : value(str) {}
operator bool() const { return true; } operator bool() const { return true; }
const char* value; std::string value;
}; };
// A simple Linear Congruential Generator for generating random // A simple Linear Congruential Generator for generating random
@ -1214,31 +1213,45 @@ class NativeArray {
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
if (::testing::internal::AlwaysTrue()) { statement; } if (::testing::internal::AlwaysTrue()) { statement; }
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ #define GTEST_WRONG_EXCEPTION_MESSAGE_(statement, expected_exception) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ "Expected: " #statement " throws an exception of type " #expected_exception \
if (::testing::internal::ConstCharPtr gtest_msg = "") { \ ".\n Actual: it throws "
bool gtest_caught_expected = false; \
try { \ // The nested try-catch block allows us to catch erroneous exceptions which
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ // inherit from std::exception and feed what() to the failure description. If
} \ // there was no nested try-catch and expected_exception was std::exception, then
catch (expected_exception const&) { \ // this would fail to build due to two blocks both catching std::exceptions.
gtest_caught_expected = true; \ #define GTEST_TEST_THROW_(statement, expected_exception, fail) \
} \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
catch (...) { \ if (::testing::internal::TrueString gtest_msg = \
gtest_msg.value = \ ::testing::internal::TrueString()) { \
"Expected: " #statement " throws an exception of type " \ bool gtest_caught_expected = false; \
#expected_exception ".\n Actual: it throws a different type."; \ try { \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \ } catch (expected_exception const&) { \
if (!gtest_caught_expected) { \ gtest_caught_expected = true; \
gtest_msg.value = \ } catch (...) { \
"Expected: " #statement " throws an exception of type " \ try { \
#expected_exception ".\n Actual: it throws nothing."; \ throw; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ } catch (const std::exception& e) { \
} \ gtest_msg.value = std::string(GTEST_WRONG_EXCEPTION_MESSAGE_( \
} else \ statement, expected_expression)) + \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ e.what() + "."; \
fail(gtest_msg.value) } catch (...) { \
gtest_msg.value = GTEST_WRONG_EXCEPTION_MESSAGE_( \
statement, expected_exception) "a different type."; \
} \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
gtest_msg.value = "Expected: " #statement \
" throws an exception of type " #expected_exception \
".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \
: fail(gtest_msg.value.c_str())
#define GTEST_TEST_NO_THROW_(statement, fail) \ #define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \

View File

@ -4541,12 +4541,21 @@ TEST(ExpectTest, EXPECT_THROW) {
EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool), EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool),
"Expected: ThrowAnInteger() throws an exception of " "Expected: ThrowAnInteger() throws an exception of "
"type bool.\n Actual: it throws a different type."); "type bool.\n Actual: it throws a different type.");
std::string expected = "what() arg";
EXPECT_NONFATAL_FAILURE(EXPECT_THROW(throw std::out_of_range(expected), bool),
expected);
EXPECT_NONFATAL_FAILURE( EXPECT_NONFATAL_FAILURE(
EXPECT_THROW(ThrowNothing(), bool), EXPECT_THROW(ThrowNothing(), bool),
"Expected: ThrowNothing() throws an exception of type bool.\n" "Expected: ThrowNothing() throws an exception of type bool.\n"
" Actual: it throws nothing."); " Actual: it throws nothing.");
} }
// We need to make sure always to avoid having multiple blocks which catch a
// std::exception
TEST(ExpectTest, EXPECT_THROW_STD_EXCEPTION) {
EXPECT_THROW(throw std::exception(), std::exception);
}
// Tests EXPECT_NO_THROW. // Tests EXPECT_NO_THROW.
TEST(ExpectTest, EXPECT_NO_THROW) { TEST(ExpectTest, EXPECT_NO_THROW) {
EXPECT_NO_THROW(ThrowNothing()); EXPECT_NO_THROW(ThrowNothing());