Выделенная память в нескольких модульных тестах cmocka
Я пытаюсь тестировать модуль с помощью cmocka. В основном (соответствующий) исходный код выглядит аналогично Source.c.
Модульный тест вызывает каждую функцию отдельно. При тестировании функции Add() эта функция в конце концов вызовет util_malloc () (эта функция обычно проверяет размер 0 перед malloc), который оборачивается модульным тестом. В обернутой функции __wrap_util_malloc() в Wrappers.c сначала проверяется ожидаемый размер, после чего malloc используется для выделения памяти.
Затем проверяется функция Remove(), в которой освобождается ранее выделенная память.
При запуске теста cmocka возвращается со следующими сбоями:
<failure><![CDATA[Blocks allocated... project_path/wrappers.c:46: note: block 00341e58 allocated here ERROR: Add_Test leaked 1 block(s) ]]></failure>
а также
<failure><![CDATA[EXCEPTION_ACCESS_VIOLATION occurred at 004060af.
To debug in Visual Studio... [...]
]]></failure>
Пока что я добавил вызов Remove() в конце функции Add_Test() (и Add() в начале Remove_Test ()). Кажется, это решает проблему. Исходя из этого, следует освобождать всю выделенную память в каждом отдельном модульном тесте.
Теперь мои вопросы:
- Можно ли использовать выделенную память в нескольких модульных тестах?
- Что было бы лучшим способом решить это?
source.c:
static ST_SOME_STRUCT GlobStruct;
void Add()
{
GlobStruct = util_malloc(sizeof(ST_SOME_STRUCT));
}
void Remove()
{
util_free(&GlobStruct);
}
void DoStuff()
{
//Do stuff using the global structure GlobStruct
}
Unit_test.c:
int main( int argc, char **argv )
{
const struct CMUnitTest Test[] =
{
cmocka_unit_test(Add_Test),
cmocka_unit_test(Remove_Test),
};
cmocka_set_message_output( CM_OUTPUT_XML );
return cmocka_run_group_tests( Test, NULL, NULL );
}
static void Add_Test (void** state)
{
expect_value(__wrap_util_malloc, size, sizeof(ST_SOME_STRUCT ));
Add();
}
static void Remove_Test (void** state)
{
expect_not_value(__wrap_util_free, memory, cast_ptr_to_largest_integral_type(NULL));
Remove();
}
Wrappers.c:
void *__wrap_util_malloc(int size)
{
check_expected(size);
return malloc(size);
}
void __wrap_util_free(void *memory)
{
check_expected_ptr(memory);
free(memory);
}
1 ответ
При запуске тестов с использованием cmocka_run_group_tests
, cmocka будет по-прежнему запускать индивидуальные функции настройки или разрыва для каждого теста вместе со своими внутренними функциями, которые проверяют, не забыли ли вы освободить блоки (отсюда и сообщение Add_Test leaked 1 block(s)
). После каждого теста cmocka также освобождает все блоки, выделенные внутри этого теста, прежде чем запускать следующий.
Общий подход заключается в том, что каждый из ваших тестов должен выполнять очистку всего, что выделено в этом отдельном тесте. Если вы хотите инициализировать общее состояние в начале группового теста, задайте функции настройки / разрыва группы для инициализации общего состояния (которое будет передаваться каждому модульному тесту в качестве параметра), или используйте функции настройки / разрыва теста, которые должны вызываться до каждый тест.
Как всегда, плохая идея (и затрудняет тестирование) иметь глобальные общие переменные. Ваш Add
а также Remove
функции (и все остальные, имеющие дело с этим объектом) должны принимать указатель на структуру, содержащую данные.