Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock variadic functions using googlemock

Tags:

googlemock

Not so much a question as a piece of knowledge sharing.

According to the GoogleMock FAQ it is not possible to mock variadic functions since it is unknown how many arguments will be given to the function.

This is true, but in most cases one knows with how much variables the variadic function is called from the system-under-test or how to transform the variadic arguments to 1 non-variadic argument.
A colleague of mine (don't know if he is active on Stackoverflow) came up with a working solution as depicted in the example below (using a mock for an C-type interface):

class MockInterface
{
    public:
        MockInterface() {}
        ~MockInterface() {}
        MOCK_METHOD4( variadicfunction, void( const std:: string name, AN_ENUM mode,
             const std::string func_name, const std::string message ) );
};

boost::shard_ptr<MockInterface> mock_interface;

extern "C"
{
    void variadicfunction( const char *name, AN_ENUM mode,
        const char *func_name, const char *format, ... )
    {
        std::string non_variadic("");

        if (format != NULL )
        {
            va_list args;
            va_start( args, format );

            // Get length of format including arguments
            int nr = vsnprintf( NULL, 0, format, args );

            char buffer[nr];
            vsnprintf( buffer, nr+1, format, args );

            non_variadic = std::string( buffer );

            va_end( args );
        }
        
        mock_interface->variadicfunction( name, mode, func_name, non_variadic );
    }
}

Hopefully this is useful.

like image 826
Nemelis Avatar asked Dec 02 '14 15:12

Nemelis


1 Answers

I'm not allowed to comment on the previous answer, but there are two bugs in it:

  1. the buffer is too small (already mentioned by @Bert above)
  2. after the dummy vsnprintf() (to get the required buffer-size), args point behind the last variable argument, so it has to be reset before the real vsnprintf().

Here's the corrected part:

if (format != NULL )
{
    va_list args;

    va_start( args, format );
    // Get length of format including arguments
    int nr = vsnprintf( NULL, 0, format, args );
    va_end( args );

    char buffer[nr+1];
    va_start( args, format );
    vsnprintf( buffer, nr+1, format, args );
    va_end( args );

    non_variadic = std::string( buffer );
}
like image 165
Jörg Avatar answered Oct 29 '22 16:10

Jörg