2012-04-23 20 views
21

मैं परीक्षण के लिए GoogleMock/GoogleTest का उपयोग करता हूं, और मुझे कुछ अजीब व्यवहार दिखाई दे रहा है जब एक matcher के पास पैरामीटर के रूप में एक mock के लिए shared_ptr है, और EXPECT को उसी साझा_प्टर पर कॉल किया जाता है। कोड का उल्लंघन करने वाला टुकड़ा:GoogleMock मेरा साझा_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 रूप p पकड़े, InSequence और जिस क्रम में आप अपनी अपेक्षाओं घोषणा की है का उपयोग करने का एक परिणाम है।

जब आप

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

फोन आप p की use_count वृद्धि हुई है। रिसाव का पता लगाने के लिए pTEST के अंत में (या पहले) नष्ट होना चाहिए।

यहां समस्या यह है कि आंतरिक रूप से, जीएमक पिछले उम्मीदवार को पॉइंटर धारण करके आवश्यक नकली कॉल अनुक्रम का रिकॉर्ड बनाए रखता है। तो जब आप EXPECT_CALL(*p, myMethod()); पर कॉल करते हैं, तो यह सूचक की पिछली उम्मीद पर एक प्रति प्राप्त करता है।

इसके बाद समाप्त होने पर कॉल को p के विनाशक को अवरुद्ध करने का प्रभाव पड़ता है।

आदेश में इस को हल करने के लिए, मुझे लगता है कि आपका सर्वश्रेष्ठ दांव

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

कॉल करने के लिए बस से पहले आप TEST से बाहर निकलने के लिए है। यह p पर अपेक्षाओं को साफ़ करता है, जिसमें इसकी पूर्व शर्त अपेक्षा भी शामिल है, जो बदले में p के विनाशक को सही तरीके से लागू करने की अनुमति देता है।

वैकल्पिक रूप से, यदि नकली कॉल का क्रम महत्वहीन है, तो InSequence dummy; को हटाने से p निष्पादक को निष्पादित करने की अनुमति भी मिल जाएगी।


एक तरफ के रूप में, आपके कोड में कुछ समस्याएं हैं;

  • आपका आधार structs gmock के समारोह को ओवरराइड करने के क्रम में अनुमति देने के लिए यह
  • p->myMethod(p); होना चाहिए p->myMethod();
+0

यह काम करता है, फ्रेजर आभासी विनाशकर्ता

  • MyClass::myMethod होना चाहिए आभासी होना चाहिए! मैंने आपके सुझावों के अनुसार कोड को भी सही किया। –

  • +0

    @bruno nery: GoogleMock का कौन सा संस्करण आप उपयोग कर रहे हैं? –

    +0

    सी से पहले पी बनाया गया तो क्या होगा? अंत सी को नष्ट नहीं किया जाएगा, इसकी अपेक्षाओं को सत्यापित और साफ़ किया गया है जो पी के संदर्भ काउंटर को कम करने में नेतृत्व करेगा। काउंटर के बाद अब पी नष्ट हो जाएगा, सत्यापित और पूरी तरह से नष्ट हो जाएगा। –

    संबंधित मुद्दे