diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h index bd956f3d..77b50f80 100644 --- a/include/gmock/gmock-spec-builders.h +++ b/include/gmock/gmock-spec-builders.h @@ -1426,6 +1426,7 @@ class InvokeWithHelper { bool is_excessive = false; ::std::stringstream ss; ::std::stringstream why; + ::std::stringstream loc; Action action; Expectation* exp; @@ -1435,6 +1436,11 @@ class InvokeWithHelper { args, &exp, &action, &is_excessive, &ss, &why); ss << " Function call: " << mocker->Name(); UniversalPrinter::Print(args, &ss); + // In case the action deletes a piece of the expectation, we + // generate the message beforehand. + if (found && !is_excessive) { + exp->DescribeLocationTo(&loc); + } Result result = action.IsDoDefault() ? mocker->PerformDefaultAction(args, ss.str()) : action.Perform(args); @@ -1449,8 +1455,6 @@ class InvokeWithHelper { } else { // We had an expected call and the matching expectation is // described in ss. - ::std::stringstream loc; - exp->DescribeLocationTo(&loc); Log(INFO, loc.str() + ss.str(), 3); } } else { @@ -1494,6 +1498,7 @@ class InvokeWithHelper { bool is_excessive = false; ::std::stringstream ss; ::std::stringstream why; + ::std::stringstream loc; Action action; Expectation* exp; @@ -1504,6 +1509,11 @@ class InvokeWithHelper { ss << " Function call: " << mocker->Name(); UniversalPrinter::Print(args, &ss); ss << "\n" << why.str(); + // In case the action deletes a piece of the expectation, we + // generate the message beforehand. + if (found && !is_excessive) { + exp->DescribeLocationTo(&loc); + } if (action.IsDoDefault()) { mocker->PerformDefaultAction(args, ss.str()); } else { @@ -1518,8 +1528,6 @@ class InvokeWithHelper { } else { // We had an expected call and the matching expectation is // described in ss. - ::std::stringstream loc; - exp->DescribeLocationTo(&loc); Log(INFO, loc.str() + ss.str(), 3); } } else { diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc index 4e330f0b..287a63e2 100644 --- a/test/gmock-spec-builders_test.cc +++ b/test/gmock-spec-builders_test.cc @@ -1304,7 +1304,24 @@ TEST(DeletingMockEarlyTest, Success2) { delete b2; } -// Tests that calls that violates the original spec yield failures. +// Tests that it's OK to delete a mock object itself in its action. + +ACTION_P(Delete, ptr) { delete ptr; } + +TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningVoid) { + MockA* const a = new MockA; + EXPECT_CALL(*a, DoA(_)).WillOnce(Delete(a)); + a->DoA(42); // This will cause a to be deleted. +} + +TEST(DeletingMockEarlyTest, CanDeleteSelfInActionReturningValue) { + MockA* const a = new MockA; + EXPECT_CALL(*a, ReturnResult(_)) + .WillOnce(DoAll(Delete(a), Return(Result()))); + a->ReturnResult(42); // This will cause a to be deleted. +} + +// Tests that calls that violate the original spec yield failures. TEST(DeletingMockEarlyTest, Failure1) { MockB* const b1 = new MockB; MockA* const a = new MockA; @@ -1330,7 +1347,7 @@ TEST(DeletingMockEarlyTest, Failure1) { delete b2; } -// Tests that calls that violates the original spec yield failures. +// Tests that calls that violate the original spec yield failures. TEST(DeletingMockEarlyTest, Failure2) { MockB* const b1 = new MockB; MockA* const a = new MockA;