summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2020-08-05 14:42:03 (GMT)
committerDerek Mauro <dmauro@google.com>2020-08-07 17:08:09 (GMT)
commitd0de618a58d5dcf1014123fc5e829a307066bf9a (patch)
tree5e175b6352a96e8ef8ab2eacb919058d79b4f3ca
parent5a5caab358c2c7059adef1acb22f6cab907b888d (diff)
downloadgoogletest-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
-rw-r--r--googlemock/src/gmock-spec-builders.cc58
-rw-r--r--googlemock/test/gmock-more-actions_test.cc29
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