Cmocka:检查作为参数传递的结构
Cmocka: checking a structure passed as a parameter
假设我声明了一个名为 foo 的 C 结构,它有一个名为 bar 的 int 字段和一个名为 baz 的 char *。
如何使用 Cmocka expect_
和 check_expected
宏来检查传递的结构是否正确以及两个字段是否具有预期值?如果文档中有示例,我错过了。
[更新] 也许我可以使用 expect_check()?但是我找不到例子:-(
使用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 )
returns 5. 但是,如果您尝试这样做,您会令人惊讶的是 sizeof( tSomeStruct )
实际上 returns 更有可能是 8。这是因为提到的填充字节。您不知道这些其他字节的值是什么。您可以通过在使用结构之前将结构 memsetting 为 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);
// ...
}
假设我声明了一个名为 foo 的 C 结构,它有一个名为 bar 的 int 字段和一个名为 baz 的 char *。
如何使用 Cmocka expect_
和 check_expected
宏来检查传递的结构是否正确以及两个字段是否具有预期值?如果文档中有示例,我错过了。
[更新] 也许我可以使用 expect_check()?但是我找不到例子:-(
使用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 )
returns 5. 但是,如果您尝试这样做,您会令人惊讶的是 sizeof( tSomeStruct )
实际上 returns 更有可能是 8。这是因为提到的填充字节。您不知道这些其他字节的值是什么。您可以通过在使用结构之前将结构 memsetting 为 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);
// ...
}