with Googletest i am not able to mock system function

别来无恙 提交于 2021-01-07 10:42:32

问题


I am trying to mock the system fun ioctl and socket but it is always calling the original definition of system function. Here is the gtest code i have written using gmock.

Please go through the code and help me find what is wrong. Is there a way to mock the system functions using gmock in unit testing. If any please provide me with an example code that mocks system function.

In the test.hpp file

class SystemFun
{
    public:
        virtual ~SystemFun() {}
        virtual int ioctl(int inetSocket, int counters, struct ifreq *device) = 0;
        virtual int socket(int domain, int type, int protocol) = 0;
};

class SystemFunMock : public SystemFun
{
    private:
        static SystemFunMock *oSystemFunMockInstance;
        static bool instanceFlag;
    public:
        virtual ~SystemFunMock() { instanceFlag = false; }
        MOCK_METHOD3(ioctl, int(int inetSocket, int counters ,struct ifreq *device));
        MOCK_METHOD3(socket, int(int domain, int type, int protocol));
        static SystemFunMock *getInstance()
        {
            if (!instanceFlag)
            {
                oSystemFunMockInstance = new SystemFunMock();
                instanceFlag = true;
            }
            return oSystemFunMockInstance;
        }
};

In the test.cpp file the code
bool SystemFunMock::instanceFlag = false;
SystemFunMock* SystemFunMock::oSystemFunMockInstance = NULL;

int socket(int domain, int type, int protocol)
{
    SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();
    return oSystemFunMock->socket(domain, type, protocol);
}
int ioctl(int inetSocket, int counters, struct ifreq *device)
{
    SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();
    return oSystemFunMock->ioctl(inetSocket, counters, device);
}

TEST_F(EtherPortUT, linuxHalCommonTest)    
{
    SetUp();    
    SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();    
    {    
        InSequence s;    
        EXPECT_CALL(*oSystemFunMock, ioctl(_,_,_))
            .WillOnce(Return(0))
            .WillOnce(Return(-1));
        EXPECT_CALL(*oSystemFunMock, socket(_,_,_))
            .WillOnce(Return(-1));
    }
.....
pLNXNetIface->getLinkSpeed( 356,  &speed ); // this fun def has 2 ioctl     calls but calling the original function.
pLNXNetIface->watchNetLink( iPort ); // this fun def has socket call.
...

}

Definition of the functions getLinkSpeed
bool LinuxNetworkInterface::getLinkSpeed( int sd, uint32_t *speed )
{
     struct ifreq ifr;
     struct ethtool_cmd edata;
     ifr.ifr_ifindex = ifindex;
     if( ioctl( sd, SIOCGIFNAME, &ifr ) == -1 )
     {
          GPTP_LOG_ERROR
               ( "%s: SIOCGIFNAME failed: %s", __PRETTY_FUNCTION__,
                 strerror( errno ));
          return false;
     }
     ifr.ifr_data = (char *) &edata;
     edata.cmd = ETHTOOL_GSET;
     if( ioctl( sd, SIOCETHTOOL, &ifr ) == -1 )
     {
          GPTP_LOG_ERROR
               ( "%s: SIOCETHTOOL failed: %s", __PRETTY_FUNCTION__,
                 strerror( errno ));
          return false;
     }
...
}

回答1:


You cannot mock a free function. You have to use an interface and call the function using the interface:

bool LinuxNetworkInterface::getLinkSpeed( int sd, uint32_t *speed )
{
     ...
     if(m_pSystemFun->ioctl( sd, SIOCGIFNAME, &ifr ) == -1 )

You must provide some way for LinuxNetworkInterface to get a pointer or reference to SystemFun. In your tests you provide the mock class to LinuxNetworkInterface. In your actual application you provide an actual implementation to LinuxNetworkInterface.

It seems you are on the right track. But the interface SystemFun is not just for testing but is also to be used in the application.



来源:https://stackoverflow.com/questions/57950808/with-googletest-i-am-not-able-to-mock-system-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!