From 36865d8d354465e3461eedf2949a4b7799985d5d Mon Sep 17 00:00:00 2001 From: shiqian Date: Fri, 12 Sep 2008 20:57:22 +0000 Subject: Adds exception assertions. By balaz.dan@gmail.com. --- include/gtest/gtest.h | 22 ++++ include/gtest/internal/gtest-internal.h | 61 +++++++++++ test/gtest_unittest.cc | 185 ++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+) diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index 057efa2..67cf4ac 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -928,6 +928,28 @@ class AssertHelper { // Generates a success with a generic message. #define SUCCEED() GTEST_SUCCESS("Succeeded") +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW(statement, expected_exception, GTEST_NONFATAL_FAILURE) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW(statement, GTEST_NONFATAL_FAILURE) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW(statement, GTEST_NONFATAL_FAILURE) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW(statement, expected_exception, GTEST_FATAL_FAILURE) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW(statement, GTEST_FATAL_FAILURE) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW(statement, GTEST_FATAL_FAILURE) + // Boolean assertions. #define EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN(condition, #condition, false, true, \ diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h index 8adf13e..898047e 100644 --- a/include/gtest/internal/gtest-internal.h +++ b/include/gtest/internal/gtest-internal.h @@ -717,6 +717,67 @@ class TypeParameterizedTestCase { #define GTEST_SUCCESS(message) \ GTEST_MESSAGE(message, ::testing::TPRT_SUCCESS) + +#define GTEST_TEST_THROW(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER \ + if (const char* gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + statement; \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg = "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different " \ + "type."; \ + goto GTEST_CONCAT_TOKEN(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg = "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) + +#define GTEST_TEST_NO_THROW(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER \ + if (const char* gtest_msg = "") { \ + try { \ + statement; \ + } \ + catch (...) { \ + gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws."; \ + goto GTEST_CONCAT_TOKEN(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN(gtest_label_testnothrow_, __LINE__): \ + fail(gtest_msg) + +#define GTEST_TEST_ANY_THROW(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER \ + if (const char* gtest_msg = "") { \ + bool gtest_caught_any = false; \ + try { \ + statement; \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + gtest_msg = "Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't."; \ + goto GTEST_CONCAT_TOKEN(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN(gtest_label_testanythrow_, __LINE__): \ + fail(gtest_msg) + + #define GTEST_TEST_BOOLEAN(boolexpr, booltext, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER \ if (boolexpr) \ diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index 8343795..b20b98c 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -2314,6 +2314,56 @@ TEST_F(SingleEvaluationTest, OtherCases) { EXPECT_EQ(3, b_); } +#if GTEST_HAS_EXCEPTIONS + +void ThrowAnInteger() { + throw 1; +} + +// Tests that assertion arguments are evaluated exactly once. +TEST_F(SingleEvaluationTest, ExceptionTests) { + // successful EXPECT_THROW + EXPECT_THROW({ // NOLINT + a_++; + ThrowAnInteger(); + }, int); + EXPECT_EQ(1, a_); + + // failed EXPECT_THROW, throws different + EXPECT_NONFATAL_FAILURE(EXPECT_THROW({ // NOLINT + a_++; + ThrowAnInteger(); + }, bool), "throws a different type"); + EXPECT_EQ(2, a_); + + // failed EXPECT_THROW, throws nothing + EXPECT_NONFATAL_FAILURE(EXPECT_THROW(a_++, bool), "throws nothing"); + EXPECT_EQ(3, a_); + + // successful EXPECT_NO_THROW + EXPECT_NO_THROW(a_++); + EXPECT_EQ(4, a_); + + // failed EXPECT_NO_THROW + EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW({ // NOLINT + a_++; + ThrowAnInteger(); + }), "it throws"); + EXPECT_EQ(5, a_); + + // successful EXPECT_ANY_THROW + EXPECT_ANY_THROW({ // NOLINT + a_++; + ThrowAnInteger(); + }); + EXPECT_EQ(6, a_); + + // failed EXPECT_ANY_THROW + EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(a_++), "it doesn't"); + EXPECT_EQ(7, a_); +} + +#endif // GTEST_HAS_EXCEPTIONS // Tests non-string assertions. @@ -2487,6 +2537,37 @@ TEST(AssertionTest, ASSERT_GT) { "Expected: (2) > (2), actual: 2 vs 2"); } +#if GTEST_HAS_EXCEPTIONS + +// Tests ASSERT_THROW. +TEST(AssertionTest, ASSERT_THROW) { + ASSERT_THROW(ThrowAnInteger(), int); + EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool), + "Expected: ThrowAnInteger() throws an exception of type"\ + " bool.\n Actual: it throws a different type."); + EXPECT_FATAL_FAILURE(ASSERT_THROW(1, bool), + "Expected: 1 throws an exception of type bool.\n"\ + " Actual: it throws nothing."); +} + +// Tests ASSERT_NO_THROW. +TEST(AssertionTest, ASSERT_NO_THROW) { + ASSERT_NO_THROW(1); + EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()), + "Expected: ThrowAnInteger() doesn't throw an exception."\ + "\n Actual: it throws."); +} + +// Tests ASSERT_ANY_THROW. +TEST(AssertionTest, ASSERT_ANY_THROW) { + ASSERT_ANY_THROW(ThrowAnInteger()); + EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(1), + "Expected: 1 throws an exception.\n Actual: it "\ + "doesn't."); +} + +#endif // GTEST_HAS_EXCEPTIONS + // Makes sure we deal with the precedence of <<. This test should // compile. TEST(AssertionTest, AssertPrecedence) { @@ -2764,6 +2845,32 @@ TEST(AssertionSyntaxTest, BehavesLikeSingleStatement) { ; else EXPECT_GT(3, 2) << ""; + +#if GTEST_HAS_EXCEPTIONS + if (false) + EXPECT_THROW(1, bool); + + if (true) + EXPECT_THROW(ThrowAnInteger(), int); + else + ; + + if (false) + EXPECT_NO_THROW(ThrowAnInteger()); + + if (true) + EXPECT_NO_THROW(1); + else + ; + + if (false) + EXPECT_ANY_THROW(1); + + if (true) + EXPECT_ANY_THROW(ThrowAnInteger()); + else + ; +#endif // GTEST_HAS_EXCEPTIONS } // Tests that the assertion macros work well with switch statements. @@ -2792,6 +2899,22 @@ TEST(AssertionSyntaxTest, WorksWithSwitch) { EXPECT_NE(1, 2); } +#if GTEST_HAS_EXCEPTIONS + +void ThrowAString() { + throw "String"; +} + +// Test that the exception assertion macros compile and work with const +// type qualifier. +TEST(AssertionSyntaxTest, WorksWithConst) { + ASSERT_THROW(ThrowAString(), const char*); + + EXPECT_THROW(ThrowAString(), const char*); +} + +#endif // GTEST_HAS_EXCEPTIONS + } // namespace // Returns the number of successful parts in the current test. @@ -2971,6 +3094,37 @@ TEST(ExpectTest, EXPECT_GT) { "(2) > (3)"); } +#if GTEST_HAS_EXCEPTIONS + +// Tests EXPECT_THROW. +TEST(ExpectTest, EXPECT_THROW) { + EXPECT_THROW(ThrowAnInteger(), int); + EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool), + "Expected: ThrowAnInteger() throws an exception of "\ + "type bool.\n Actual: it throws a different type."); + EXPECT_NONFATAL_FAILURE(EXPECT_THROW(1, bool), + "Expected: 1 throws an exception of type bool.\n"\ + " Actual: it throws nothing."); +} + +// Tests EXPECT_NO_THROW. +TEST(ExpectTest, EXPECT_NO_THROW) { + EXPECT_NO_THROW(1); + EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()), + "Expected: ThrowAnInteger() doesn't throw an "\ + "exception.\n Actual: it throws."); +} + +// Tests EXPECT_ANY_THROW. +TEST(ExpectTest, EXPECT_ANY_THROW) { + EXPECT_ANY_THROW(ThrowAnInteger()); + EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(1), + "Expected: 1 throws an exception.\n Actual: it "\ + "doesn't."); +} + +#endif // GTEST_HAS_EXCEPTIONS + // Make sure we deal with the precedence of <<. TEST(ExpectTest, ExpectPrecedence) { EXPECT_EQ(1 < 2, true); @@ -4477,6 +4631,37 @@ TEST(StreamingAssertionsTest, FloatingPointEquals) { "expected failure"); } +#if GTEST_HAS_EXCEPTIONS + +TEST(StreamingAssertionsTest, Throw) { + EXPECT_THROW(ThrowAnInteger(), int) << "unexpected failure"; + ASSERT_THROW(ThrowAnInteger(), int) << "unexpected failure"; + EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool) << + "expected failure", "expected failure"); + EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool) << + "expected failure", "expected failure"); +} + +TEST(StreamingAssertionsTest, NoThrow) { + EXPECT_NO_THROW(1) << "unexpected failure"; + ASSERT_NO_THROW(1) << "unexpected failure"; + EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()) << + "expected failure", "expected failure"); + EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()) << + "expected failure", "expected failure"); +} + +TEST(StreamingAssertionsTest, AnyThrow) { + EXPECT_ANY_THROW(ThrowAnInteger()) << "unexpected failure"; + ASSERT_ANY_THROW(ThrowAnInteger()) << "unexpected failure"; + EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(1) << + "expected failure", "expected failure"); + EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(1) << + "expected failure", "expected failure"); +} + +#endif // GTEST_HAS_EXCEPTIONS + // Tests that Google Test correctly decides whether to use colors in the output. TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsYes) { -- cgit v0.12