diff options
author | vladlosev <vladlosev@8415998a-534a-0410-bf83-d39667b30386> | 2011-10-24 23:41:07 +0000 |
---|---|---|
committer | vladlosev <vladlosev@8415998a-534a-0410-bf83-d39667b30386> | 2011-10-24 23:41:07 +0000 |
commit | 9bcb5f9146db42bc38b6bb744fb0cf518a0205be (patch) | |
tree | 25eaddb193823d54b9dce3878b0f32d2eba6739a /test/gmock-spec-builders_test.cc | |
parent | 4d60a596b4135c5a7e21ef7b4fe24a5c90329e0f (diff) | |
download | googletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.tar.gz googletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.tar.bz2 googletest-9bcb5f9146db42bc38b6bb744fb0cf518a0205be.zip |
Fixes a lock reentrancy when destroying a mock causes destruction of another mock (issue 79) (by Aaron Jacobs).
Diffstat (limited to 'test/gmock-spec-builders_test.cc')
-rw-r--r-- | test/gmock-spec-builders_test.cc | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc index 29d47d12..9177b322 100644 --- a/test/gmock-spec-builders_test.cc +++ b/test/gmock-spec-builders_test.cc @@ -88,13 +88,14 @@ using testing::Mock; using testing::Ne; using testing::Return; using testing::Sequence; +using testing::SetArgPointee; using testing::internal::ExpectationTester; using testing::internal::FormatFileLocation; -using testing::internal::g_gmock_mutex; using testing::internal::kErrorVerbosity; using testing::internal::kInfoVerbosity; using testing::internal::kWarningVerbosity; using testing::internal::String; +using testing::internal::linked_ptr; using testing::internal::string; #if GTEST_HAS_STREAM_REDIRECTION @@ -157,6 +158,16 @@ class MockB { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB); }; +class ReferenceHoldingMock { + public: + ReferenceHoldingMock() {} + + MOCK_METHOD1(AcceptReference, void(linked_ptr<MockA>*)); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReferenceHoldingMock); +}; + // Tests that EXPECT_CALL and ON_CALL compile in a presence of macro // redefining a mock method name. This could happen, for example, when // the tested code #includes Win32 API headers which define many APIs @@ -2439,6 +2450,46 @@ TEST(VerifyAndClearTest, DoesNotAffectOtherMockObjects) { EXPECT_EQ(2, b1.DoB(0)); } +TEST(VerifyAndClearTest, + DestroyingChainedMocksDoesNotDeadlockThroughExpectations) { + linked_ptr<MockA> a(new MockA); + ReferenceHoldingMock test_mock; + + // EXPECT_CALL stores a reference to a inside test_mock. + EXPECT_CALL(test_mock, AcceptReference(_)) + .WillRepeatedly(SetArgPointee<0>(a)); + + // Throw away the reference to the mock that we have in a. After this, the + // only reference to it is stored by test_mock. + a.reset(); + + // When test_mock goes out of scope, it destroys the last remaining reference + // to the mock object originally pointed to by a. This will cause the MockA + // destructor to be called from inside the ReferenceHoldingMock destructor. + // The state of all mocks is protected by a single global lock, but there + // should be no deadlock. +} + +TEST(VerifyAndClearTest, + DestroyingChainedMocksDoesNotDeadlockThroughDefaultAction) { + linked_ptr<MockA> a(new MockA); + ReferenceHoldingMock test_mock; + + // ON_CALL stores a reference to a inside test_mock. + ON_CALL(test_mock, AcceptReference(_)) + .WillByDefault(SetArgPointee<0>(a)); + + // Throw away the reference to the mock that we have in a. After this, the + // only reference to it is stored by test_mock. + a.reset(); + + // When test_mock goes out of scope, it destroys the last remaining reference + // to the mock object originally pointed to by a. This will cause the MockA + // destructor to be called from inside the ReferenceHoldingMock destructor. + // The state of all mocks is protected by a single global lock, but there + // should be no deadlock. +} + // Tests that a mock function's action can call a mock function // (either the same function or a different one) either as an explicit // action or as a default action without causing a dead lock. It |