I'm trying to unit test some source code using cmocka. Basically the (relevant) source code looks similar to Source.c.
The unit test calls each function separately. When testing the Add() function this function will eventually call util_malloc() (this function normally checks for 0 size before malloc) which is wrapped by the unit test. In the wrapped function __wrap_util_malloc(), in Wrappers.c, first the size is checked for expected after which malloc is used to allocate memory.
Next the Remove() function is tested in which the previously allocated memory gets freed.
When running the test cmocka returns with the following failures:
<failure><![CDATA[Blocks allocated... project_path/wrappers.c:46: note: block 00341e58 allocated here ERROR: Add_Test leaked 1 block(s) ]]></failure>
and
<failure><![CDATA[EXCEPTION_ACCESS_VIOLATION occurred at 004060af.
To debug in Visual Studio... [...]
]]></failure>
For now I've added a Remove() call at the end of the Add_Test() function (and an Add() at the beginning of Remove_Test()). This seems to fix the issue. Judging from this, one should free all allocated memory in each separate unit test.
Now my questions:
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
}
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();
}
void *__wrap_util_malloc(int size)
{
check_expected(size);
return malloc(size);
}
void __wrap_util_free(void *memory)
{
check_expected_ptr(memory);
free(memory);
}
When running tests using cmocka_run_group_tests
, cmocka will still run individual setup or teardown functions for each test, along with its internal functions which check if you forgot to free blocks (hence the message Add_Test leaked 1 block(s)
). After each test, cmocka will also free any blocks allocated inside that test before running the next one.
Common approach is that each of your tests should perform cleanup of anything allocated within that single test. If you want to initialize shared state at the beginning of the group test, specify group setup/teardown functions to initialize shared state (which will be passed to each unit test as a parameter), or use test setup/teardown functions to be called before each test.
As always, it's a bad idea (and makes testing harder) to have global shared variables. Your Add
and Remove
functions (and all other dealing with this object) should accept a pointer to the struct containing the data.