I use GoogleMock/GoogleTest for testing, and I’m seeing some strange behavior when a matcher has a shared_ptr to a mock as a parameter, and EXPECT is called on the same shared_ptr. The offending piece of code:
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
using namespace testing;
struct MyParameter
{
virtual ~MyParameter() {}
virtual void myMethod() = 0;
};
struct MyParameterMock : public MyParameter
{
MOCK_METHOD0(myMethod, void());
};
struct MyClass
{
virtual ~MyClass() {}
virtual void myMethod(shared_ptr<MyParameter> p) {}
};
struct MyClassMock : public MyClass
{
MOCK_METHOD1(myMethod, void(shared_ptr<MyParameter>));
};
TEST(LeakTest, GoogleMockLeaksMatchedPointer)
{
shared_ptr<MyClassMock> c = make_shared<MyClassMock>();
shared_ptr<MyParameterMock> p = make_shared<MyParameterMock>();
{
InSequence dummy;
EXPECT_CALL(*c, myMethod(Eq(p)));
EXPECT_CALL(*p, myMethod());
}
c->myMethod(p);
p->myMethod();
}
When this test is run, I get
leak_ptr_mock.cpp:37: ERROR: this mock object (used in test LeakTest.GoogleMockLeaksMatchedPointer) should be deleted but never is. Its address is @0x9309544.
ERROR: 1 leaked mock object found at program exit.
Any idea of why this happens? I rather not have to use Mock::AllowLeak.
This is a result of holding
pas ashared_ptr, usingInSequenceand the order in which you have declared your expectations.When you call
you increase the
use_countofp. In order for the leak detection to pass,pmust be destroyed at (or before) the end ofTEST.The problem here is that internally, gmock maintains a record of the required mock call sequence by holding a pointer to the preceding expectation. So when you call
EXPECT_CALL(*p, myMethod());, it gets a copy of the pointer to the previous expectation.This then has the effect of blocking the call to
p‘s destructor whenTESTends.In order to work around this, I think your best bet is to call
just before you exit
TEST. This clears the expectations onp, including critically its prerequisite expectation, which in turn allows the destructor ofpto be invoked correctly.Alternatively, if the order of the mock calls is unimportant, simply removing
InSequence dummy;will also allowp‘s destructor to execute.As an aside, your code has a couple of issues;
MyClass::myMethodshould be virtual in order to allow gmock’s function to override itp->myMethod(p);should bep->myMethod();