3

假设我声明了一个名为 foo 的 C 结构,它有一个名为 bar 的 int 字段和一个名为 baz 的 char *。

如何使用Cmocka expect_check_expected宏来检查传递的结构是否正确以及两个字段是否具有预期值?如果文档中有示例,我错过了。


[更新] 也许我可以使用expect_check()?但我找不到一个例子:-(

4

2 回答 2

5

使用expect_memory(...)check_expected(...)

例子:

我假设您有一个正在测试的函数,fut它调用一个 subfunction 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);
}
于 2017-02-10T09:48:20.543 回答
2

在大多数情况下,比较结构的内存可能有效,但是如果您的编译器在其中放置了一些填充字节,那么您将有一些您无法控制的字节并且可能具有随机值。这意味着您的测试可能不会总是产生相同的结果,这可能会导致非常烦人的调试会话。

例如,如果您有这样的结构:

typedef struct {
    uint8_t c;
    uint32_t i;
} tSomeStruct

您可能认为candi紧挨着放置并sizeof( tSomeStruct )返回 5。但是,如果您尝试这样做,您会惊讶地发现sizeof( tSomeStruct )实际上返回 8 的可能性更大。这是因为提到的填充字节。您不知道这些其他字节的值是什么。您可以通过在使用它们之前将结构设置为 0 来解决此问题,但这有点 hacky 并且并非在所有情况下都有效。

要以干净的方式比较结构,您可以使用 cmockaexpect_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。

于 2020-09-21T14:04:24.963 回答