diff options
author | Abseil Team <absl-team@google.com> | 2020-08-05 14:42:03 (GMT) |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2020-08-07 17:08:09 (GMT) |
commit | d0de618a58d5dcf1014123fc5e829a307066bf9a (patch) | |
tree | 5e175b6352a96e8ef8ab2eacb919058d79b4f3ca /googlemock | |
parent | 5a5caab358c2c7059adef1acb22f6cab907b888d (diff) | |
download | googletest-d0de618a58d5dcf1014123fc5e829a307066bf9a.zip googletest-d0de618a58d5dcf1014123fc5e829a307066bf9a.tar.gz googletest-d0de618a58d5dcf1014123fc5e829a307066bf9a.tar.bz2 |
Googletest export
Fixing exception-safety bug in googletest. Previously, if an exception was
thrown during a call to a mock that would have triggered an error, the error
was discarded.
Fixes #2890
PiperOrigin-RevId: 325017806
Diffstat (limited to 'googlemock')
-rw-r--r-- | googlemock/src/gmock-spec-builders.cc | 58 | ||||
-rw-r--r-- | googlemock/test/gmock-more-actions_test.cc | 29 |
2 files changed, 66 insertions, 21 deletions
diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc index 346e680..05a50f6 100644 --- a/googlemock/src/gmock-spec-builders.cc +++ b/googlemock/src/gmock-spec-builders.cc @@ -433,10 +433,10 @@ UntypedActionResultHolderBase* UntypedFunctionMockerBase::UntypedInvokeWith( // The UntypedFindMatchingExpectation() function acquires and // releases g_gmock_mutex. + const ExpectationBase* const untyped_expectation = - this->UntypedFindMatchingExpectation( - untyped_args, &untyped_action, &is_excessive, - &ss, &why); + this->UntypedFindMatchingExpectation(untyped_args, &untyped_action, + &is_excessive, &ss, &why); const bool found = untyped_expectation != nullptr; // True if and only if we need to print the call's arguments @@ -461,26 +461,42 @@ UntypedActionResultHolderBase* UntypedFunctionMockerBase::UntypedInvokeWith( untyped_expectation->DescribeLocationTo(&loc); } - UntypedActionResultHolderBase* const result = - untyped_action == nullptr - ? this->UntypedPerformDefaultAction(untyped_args, ss.str()) - : this->UntypedPerformAction(untyped_action, untyped_args); - if (result != nullptr) result->PrintAsActionResult(&ss); - ss << "\n" << why.str(); - - if (!found) { - // No expectation matches this call - reports a failure. - Expect(false, nullptr, -1, ss.str()); - } else if (is_excessive) { - // We had an upper-bound violation and the failure message is in ss. - Expect(false, untyped_expectation->file(), - untyped_expectation->line(), ss.str()); - } else { - // We had an expected call and the matching expectation is - // described in ss. - Log(kInfo, loc.str() + ss.str(), 2); + UntypedActionResultHolderBase* result = nullptr; + + auto perform_action = [&] { + return untyped_action == nullptr + ? this->UntypedPerformDefaultAction(untyped_args, ss.str()) + : this->UntypedPerformAction(untyped_action, untyped_args); + }; + auto handle_failures = [&] { + ss << "\n" << why.str(); + + if (!found) { + // No expectation matches this call - reports a failure. + Expect(false, nullptr, -1, ss.str()); + } else if (is_excessive) { + // We had an upper-bound violation and the failure message is in ss. + Expect(false, untyped_expectation->file(), untyped_expectation->line(), + ss.str()); + } else { + // We had an expected call and the matching expectation is + // described in ss. + Log(kInfo, loc.str() + ss.str(), 2); + } + }; +#if GTEST_HAS_EXCEPTIONS + try { + result = perform_action(); + } catch (...) { + handle_failures(); + throw; } +#else + result = perform_action(); +#endif + if (result != nullptr) result->PrintAsActionResult(&ss); + handle_failures(); return result; } diff --git a/googlemock/test/gmock-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc index 97ec5cf..d6a078b 100644 --- a/googlemock/test/gmock-more-actions_test.cc +++ b/googlemock/test/gmock-more-actions_test.cc @@ -38,7 +38,9 @@ #include <memory> #include <sstream> #include <string> + #include "gmock/gmock.h" +#include "gtest/gtest-spi.h" #include "gtest/gtest.h" namespace testing { @@ -604,6 +606,33 @@ TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) { EXPECT_THROW(a.Perform(std::make_tuple()), MyException); } +class Object { + public: + virtual ~Object() {} + virtual void Func() {} +}; + +class MockObject : public Object { + public: + ~MockObject() override {} + MOCK_METHOD(void, Func, (), (override)); +}; + +TEST(ThrowActionTest, Times0) { + EXPECT_NONFATAL_FAILURE( + [] { + try { + MockObject m; + ON_CALL(m, Func()).WillByDefault([] { throw "something"; }); + EXPECT_CALL(m, Func()).Times(0); + m.Func(); + } catch (...) { + // Exception is caught but Times(0) still triggers a failure. + } + }(), + ""); +} + #endif // GTEST_HAS_EXCEPTIONS // Tests that SetArrayArgument<N>(first, last) sets the elements of the array |