2012-04-23 3 views
21

GoogleMock/GoogleTest를 테스트 용으로 사용합니다. 정규식에 대한 정규식이 공유기에 있고 매개 변수로 EXPECT가 호출 될 때 이상한 동작이 발생합니다. 코드의 잘못된 부분 :GoogleMock에서 shared_ptr을 유출하는 이유가 무엇인가요?

#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(); 
} 

이 테스트가 실행되면, 내가

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. 

이런 일이 발생하는 이유 어떤 생각을? 차라리 Mock::AllowLeak을 사용할 필요가 없습니다.

답변

26

shared_ptr으로 잡고 InSequence을 사용하고 예상되는 순서대로 결과를 얻었습니다. 당신이

EXPECT_CALL(*c, myMethod(Eq(p))); 

를 호출 할 때

당신은 puse_count 증가한다. 누출 감지가 통과 되려면 이 (또는 그 전에) TEST 끝에서 파괴되어야합니다.

내부적으로 gmock은 앞선 기대치에 대한 포인터를 유지함으로써 필요한 모의 호출 시퀀스의 레코드를 유지합니다. 따라서 EXPECT_CALL(*p, myMethod());으로 전화하면 이전 기대치에 대한 포인터 사본을 얻습니다.

이렇게하면 TEST이 끝날 때 p의 소멸자에 대한 호출을 차단하는 효과가 있습니다. 이 문제를 해결하기 위해

, 내가 가장 좋은 건 당신이 TEST을 종료 직전

EXPECT_TRUE(Mock::VerifyAndClearExpectations(p.get())); 

를 호출하는 것입니다 생각합니다. 이렇게하면 p에 대한 기대치가 지워지고, 그 전제 조건을 포함하여 p의 소멸자가 올바르게 호출 될 수 있습니다.

모의 호출 순서가 중요하지 않은 경우 InSequence dummy;을 제거하면 p의 소멸자도 실행할 수 있습니다.


제쳐두고, 코드에는 몇 가지 문제가 있습니다.

  • 귀하의 기본 구조체는
  • p->myMethod(p); 그것은, 프레이저 작동 p->myMethod();
+0

해야 gmock의 기능을 오버라이드 (override) 할 수 있도록하기 위해 가상되어야합니다 가상 소멸자

  • MyClass::myMethod이 있어야합니다! 귀하의 제안에 따라 코드를 수정했습니다. –

  • +0

    @ bruno nery : 어떤 GoogleMock 버전을 사용하고 있습니까? –

    +0

    p가 c보다 먼저 생성되면 어떻게 될까요? 결국에는 파괴 될 것이 아니라, 그 기대가 입증되고 지워져서 p의 참조 카운터를 감소시킬 것입니다. 그 후 카운터가 0이 되었기 때문에 p는 파괴되고 검증되며 완전히 파괴됩니다. –

    관련 문제