Search code examples
cunit-testinggoogletest

Debug, System functions (fopen,fclose,fread,fwrite,...) and for loop in Google Test C


I am using Google Test to test C code but I encounter with the problem Write Stub for system functions like: fopen,fclose,fread,fwrite,memcpy,memset,stat,...I don't known how to Stub its input/output correctly to convenient for testing without having to care about real data. Example below:

bool open_file(void)
{
   FILE *srcfd;
   FILE *destfd;
   int dataLen;
   bool retVal=false;
   char buffer[255];
   srcfd = fopen("srcFileName", "r");
    if(NULL != srcfd)
    {
        destfd = fopen("destFileName", "w+");
        if(NULL != destfd)
        {
            retVal = true;

            while ((true == retVal) &&
                    ((dataLen = fread(buffer, sizeof(char), sizeof(buffer), srcfd)) > 0))
            {
                if (fwrite(buffer, sizeof(char), dataLen, destfd) != dataLen)
                {
                    retVal = false;
                }
            }

            fclose(destfd);

        }
        else
        {
            printf("%s: Failed to create file '%s'...\n",
                    __func__, "destFileName");
        }
        fclose(srcfd);
    }
    else
    {
        printf("%s: Failed to create file '%s'...\n", __func__, "srcFileName");
    }
return retVal;
}

Solution

  • You can always write your own definition of the external function (stub) to support your test without caring about the real implementation of the function.

    To make your life easier, you can use some already-existed stub framework such as Fake Function Framework.

    Example in your case, to test bool open_file(void) with the stub of fopen you can do like this in your test file:

    #include "fff.h"
    DEFINE_FFF_GLOBALS;
    //fake fopen, be sure about the prototype of the faked function
    FAKE_VALUE_FUNC(FILE*, fopen, const char*, const char*); 
    

    And in the test case:

    TEST_F(Test_open_file, stub_fopen){
       //call the function under test
       open_file();
       //check number of time fopen called
       ASSERT_EQ(fopen_fake.call_count, 1);
       //check input parameter
       ASSERT_EQ(strncmp(fopen_fake.arg0_val, "destFileName", 100), 0);
    }
    

    But be clear that stub is not always a good solution, do stub only when you really don't care about the real implementation of the external function and you just want the output of that function for your test purpose. Sometimes, call the real external function is better.

    (I strike the bellowed texts because you modified your question)

    You cannot control a local variable in the function under tested from your test case, you need to control it through global variables, function inputs or stub return value... whatever interfaces that set the value for that local variable you can interact with in your test cases.