Search code examples
c++windowsunit-testinggooglemock

GMock test fixture crashes on Windows


I'm new to using GMock framework. But, I have the following production application productionApp and test application testApp. My production app works perfectly. But the test crashes after executing the first test in the fixture.

class IRegEditor
{
public:
    virtual bool Read(int&) = 0;
    virtual bool Write(const int&) = 0;
    virtual ~IRegEditor() {}
};

class RegEditorImpl : public IRegEditor
{
public:
    //use windows registry APIs instead
    //read returns values based on current time.
    //write fails for odd values.
    bool Read(int& i) { if (system_clock::now().time_since_epoch().count() % 2)                 
    return false; else { i = 10; return true; } }
    bool Write(const int& j) { if (j % 2) return false; else return true; }
};

class RegEditorMock : public IRegEditor
{
public:
    MOCK_METHOD1(Read, bool(int&));
    MOCK_METHOD1(Write, bool(const int&));
};

class RegEditTest : public ::testing::Test
{
protected:
    virtual void SetUp() {
        regEditor.reset(&regMock);
    }

    std::shared_ptr<IRegEditor> regEditor;
    RegEditorMock regMock;
};

class App
{
    std::shared_ptr<IRegEditor> regEdit;
public:
    //ctor to use in production
    App() :regEdit{ std::make_shared<RegEditorImpl>() }
    {}  
    //overloaded ctor to use for unit tests
    App(std::shared_ptr<IRegEditor> regEditor) : regEdit{ regEditor }
    {}
    bool Writer(const int& number)
    {
        if (regEdit->Write(number)) 
        { std::cout << "write passed" << std::endl; return true; }
        else 
        { std::cout << "write failed" << std::endl; return false; }
    }
    bool Reader(int& number)
    {
        if (regEdit->Read(number)) 
        { std::cout << "read passed" << std::endl; return true; }
        else { std::cout << "read failed" << std::endl; return false; }
    }
};

TEST_F(RegEditTest, writeFails)
{
    int number = 1;
    EXPECT_CALL(regMock, Write(number)).Times(1).WillOnce(Return(false));

    App testApp(regEditor);
    EXPECT_FALSE(testApp.Writer(number));
}

TEST_F(RegEditTest, writeSucceeds)
{
    int number = 2;
    EXPECT_CALL(regMock, Write(number)).Times(1).WillOnce(Return(true));

    App testApp(regEditor);
    EXPECT_FALSE(testApp.Writer(number));
}

int main(int argc, char** argv) {
    // The following line must be executed to initialize Google Mock
    // (and Google Test) before running the tests.
    ::testing::InitGoogleMock(&argc, argv);
    return RUN_ALL_TESTS();
}

I get the following error on running the test. Does it have anything to do with GMock library's compiler setting compatibility ?

Unhandled exception at 0x77639D71 (ntdll.dll)
A heap has been corrupted (parameters: 0x7766D8D0).

Then shows that, it is not able to load symbols from wntdll.pdb.

The following production app works as expected

int main()
{
    App productionApp;
    int num = 9;
    productionApp.Reader(num);
    productionApp.Writer(num);
    std::cin.get();
    return 0;
}

Solution

  • One cannot do regEditor.reset(&regMock); this makes regEditor own the local regMock, Now, since regMock has two owners: its automatic storage duration, plus the shared pointer regEditor - memory is corrupted, when the scope ends. This did not have anything to do with GMock or GTest version or compiler settings or compatibility. It was because of my wrong usage of shared_ptr .Thanks to Jarod42 and Angew for the help. Please refer How to use shared_ptr to supply mock object from outside?