Search code examples
c++googletestblockinggooglemock

How to implement blocking mock function with gmock?


In my project I need to mock a blocking function that runs on a thread, I need it to release the thread few times during the tests with my control, on my command, I want it to be blocked most of the time as the read func is in while loop.

class BlockFuncsIf {
public:
    virtual bool Write(const Msg& msg) = 0;
    virtual bool Read(Msg* msg) = 0;

};

class BlockFuncs: public BlockFuncsIf {
public:
    MOCK_METHOD1(Write, bool(const Msg&));
    MOCK_METHOD1(Read, bool(Msg* msg));
};


class TestedClass {
public:
    MSG msg;
    std::condition_variable cv;
    bool success;

    ...

    bool expectRead() {
        success = true;
        while(success) {
            success = Read(&msg);
            cv.notify_all();
        }
    }

    ...

};    

Solution

  • The solution I found is to wrap the mocked functions and add a semaphore to control the blocking. In this solution I control the semaphore (sem_init, sem_post) from the tests.

    Note: I wanted to use std::semaphore but it is available only on c++20 so I used semaphore.h insted, there some other implementation for cpp semaphore avallible if needed: cpp semaphore implementation.

    class BlockFuncsIf {
    public:
        virtual bool Write(const Msg& msg) = 0;
        virtual bool Read(Msg* msg) = 0;
    };
    
    class BlockFuncsMock: public BlockFuncsIf {
    public:
        MOCK_METHOD1(Write, bool(const Msg&));
        MOCK_METHOD1(Read, bool(Msg* msg));
    
        static std::shared_ptr<BlockFuncsMock> _blockFuncsMockObj;
    };
    
    std::shared_ptr<BlockFuncsMock> BlockFuncsMock::_blockFuncsMockObj = std::make_shared< BlockFuncsMock >();
    
    class BlockFuncs {
    public:
        bool Write(const Msg& msg){
            sem_wait(&SemWriteMutex);
            return BlockFuncsMock::_blockFuncsMockObj->Write(msg);
        }
        bool Read(Msg* msg){
            sem_wait(&SemReadMutex);
            return BlockFuncsMock::_blockFuncsMockObj->Read(msg);
        }
        sem_t SemWriteMutex;
        sem_t SemReadMutex;
    };