11

I am facing problems in writing unit tests to C functions which involve IO operation. For example, below is the code I wrote to get an input string from the user from console. I do not know as to how to automate testing user input using getchar() function.

char * GetStringFromConsole()
{

    char *strToReturn = NULL;
    int len = 128;

    strToReturn = (char*)malloc(len);
    if (strToReturn) 
    {
        int ch;
        char *ptr  = strToReturn;
        int counter = 0;
        for (; ;) 
        {
            ch = getchar();
            counter++;

            if (counter == len)
            {
                strToReturn = realloc(strToReturn, len*=2 );
                ptr = strToReturn + counter-1;
            }

            if ((ch != EOF) && (ch != '\n') && (counter < len))
            {
                *ptr++ = ch;
            }
            else 
            {
                break;
            }

        }
        *ptr = '\0';
    }
    return strToReturn;
}   
Adeel Ahmed
  • 1,591
  • 8
  • 10
ramkumarhn
  • 121
  • 1
  • 6

1 Answers1

6

Mock getchar:

  1. Utilizing preprocessor, e.g. in your test file.

    #define getchar mock_getchar
    #include "GetStringFromConsole.h"
    ...
    const char* mock_getchar_data_ptr;
    char mock_getchar()
    {
        return *mock_getchar_data_ptr++;
    }
    ...
    // in test function
    mock_getchar_data_ptr = "hello!\n";
    YourAssertEquals("hello", GetStringFromConsole());
    
  2. Substitute symbol for the linker(harder, in my opinion), e.g. define your own getchar somewhere in your source .c files instead of linking to a stdlib(e.g. msvcrt on windows)

  3. Modify function under test to accept a function returning char, best choice(IMHO) - no conflicts with stdlib. And setup a test by passing a thingy like mock_getchar from point 1 in test code.

    typedef char (*getchartype)();
    char * GetStringFromConsole(getchartype mygetchar)
    {
        ...
        c  = mygetchar()
    

For points 1 and 2 I'd propose to use your own function instead of getchar (e.g. mygetchar) - this way you could mock/substitute it without facing conflicts with std includes/libs.

kerim
  • 2,412
  • 18
  • 16
  • 1
    The cmocka unit testing framework has support for mock objects and shows how to override the original function with the mock functions. Click on Learn More on http://cmocka.org/ – asn Dec 20 '13 at 13:49