Как издеваться над вариативными функциями с помощью googlemock

Не столько вопрос, сколько обмен знаниями.

Согласно GoogleMock Часто задаваемые вопросы невозможно имитировать функции с переменным числом аргументов, поскольку неизвестно, сколько аргументов будет передано функции.

Это так, но в большинстве случаев известно, с каким количеством переменных вызывается вариационная функция из тестируемой системы или как преобразовать вариативные аргументы в 1 невариативный аргумент.
Мой коллега (don не знаю, активен ли он в Stackoverflow) придумал рабочее решение, как показано в примере ниже (с использованием макета для интерфейса C-типа):

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 );
    }
}

Надеюсь, это полезно.


person Nemelis    schedule 02.12.2014    source источник
comment
Действительно хитрый трюк! Но, я думаю, у вас переполнение буфера (буфер должен быть объявлен с индексом nr + 1 i.m.o). Спасибо, что поделился.   -  person Bert Regelink    schedule 27.05.2020


Ответы (1)


Мне не разрешено комментировать предыдущий ответ, но в нем есть две ошибки:

  1. буфер слишком мал (уже упомянутый @Bert выше)
  2. после фиктивного vsnprintf() (чтобы получить требуемое buffer-size), args указывает за последним переменным аргументом, поэтому его необходимо сбросить перед реальным vsnprintf().

Вот исправленная часть:

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 );
}
person Jörg    schedule 16.07.2020