Cmocka: проверка структуры, переданной в качестве параметра
Допустим, я объявляю структуру C с именем foo, которая имеет поле int с именем bar и char * с именем baz.
Как я могу использовать Cmocka expect_
а также check_expected
макросы, чтобы проверить, что переданная структура была правильной и оба поля имеют ожидаемые значения? Если в документации есть пример, я его пропустил.
[Обновление] Может быть, я могу использовать функцию ожидаемой проверки ()? Но я не могу найти пример:-(
3 ответа
Использование expect_memory(...)
а также check_expected(...)
:
Пример:
Я полагаю, у вас есть тестируемая функция fut
который вызывает подфункцию subfunc
, Ваша структура выглядит так:
typedef struct foo_s {
int bar;
int baz;
} foo;
И ваша тестовая функция вождения может выглядеть так:
void test(void **state) {
foo myfoo = {
.bar = 42,
.baz = 13,
};
expect_memory(subfunc, param, &myfoo, sizeof(foo));
fut();
}
И подфункции могут выглядеть так:
void subfunc(foo *param){
check_expected(param);
}
Сравнение памяти структуры может работать в большинстве случаев, однако, если ваш компилятор помещает туда некоторые байты-заполнители, у вас есть некоторые байты, которые вы не можете контролировать и которые могут иметь случайные значения. Это означает, что ваш тест может не всегда давать один и тот же результат, что может привести к очень раздражающему сеансу отладки.
Например, если у вас есть такая структура:
typedef struct {
uint8_t c;
uint32_t i;
} tSomeStruct
Вы могли подумать, что
c
и
i
ставятся рядом друг с другом и
sizeof( tSomeStruct )
возвращает 5. Однако, если вы попробуете это, вы будете удивлены, что более вероятно, что
sizeof( tSomeStruct )
фактически возвращает 8. Это из-за упомянутых байтов-заполнителей. Вы не знаете, каковы значения этих других байтов. Вы можете обойти это, установив для своих структур значение 0 перед их использованием, однако это немного взломано и работает не во всех случаях.
Чтобы сравнить структуры чистым способом cmocka, вы можете использовать
expect_check( ... )
и
check_expected( ... )
. Это дает вам возможность написать свою собственную функцию сравнения.
Вот пример того, как это использовать (измененный пример: Cmocka Gitlab)
typedef struct {
char c;
int i;
} tSomeStruct;
void mock_function( tSomeStruct* param )
{
check_expected(param)
}
/* return 1 = true, return 0 = false */
int my_int_equal_check(const LargestIntegralType value,
const LargestIntegralType check_value_data)
{
tSomeStruct* cast_value = ( tSomeStruct* ) value;
tSomeStruct* cast_check_value_data = ( tSomeStruct* ) check_value_data;
if ( ( cast_value->c == cast_check_value_data->c )
&& ( cast_value->i == cast_check_value_data->i ) ) {
return 1;
}
return 0;
}
void mytest(void **state)
{
tSomeStruct struct = {
.c = 'c',
.i = 'i',
}
expect_check(mock_function, param, my_int_equal_check, &struct);
}
Однако я не уверен, возможно ли это, если вы не передадите свою структуру в качестве указателя на свою функцию, поскольку функция проверки принимает только LargestIntegralType.
Недавно я узнал, что вы можете использовать члены структуры внутри
check_expected
а также
expect_value
:
typedef struct
{
int a;
float b;
} SomeStruct_t;
void mocked_function(SomeStruct_t* s)
{
check_expected(s->a);
check_expected(s->b);
}
void someTest(void **state)
{
expect_value(mocked_function, s->a, 3);
expect_value(mocked_function, s->b, 7.2);
// ...
}