How to mock variadic functions using googlemock
Asked Answered
C

1

11

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.

Champac answered 2/12, 2014 at 15:16 Comment(4)
A clever trick indeed! But, I think you have a buffer overflow (buffer should be declared with index nr + 1 i.m.o). Thanks for sharing.Nursling
I think this can be done even without the conversion to non_variadic. See a complete example here: https://mcmap.net/q/120922/-mocking-variadic-functions-in-google-test-and-google-mockGeometrid
@Ari: You are commenting on a very old "question" (more a recipe) ;-). Nowadays it can be done without the conversion. But back in the days that I wrote it (2014) it was not possible. Googlemock has evolved a LOT (e.g. the 10 parameters limit for methods you want to mock is also gone)Champac
@Champac Agreed. Sorry for the random comment. I did not pay attention to the date! Just wanted to put a link in case someone wanted to see a more recent example. No intentions of devaluing your answer here.Geometrid
R
3

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 );
}
Rimarimas answered 16/7, 2020 at 13:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.