cmocka,如何检查函数指针

时间:2018-01-16 11:57:33

标签: c cmocka

我搜索了文档和服务员示例,但是我找不到一个关于如何检查正确的函数指针作为参数传递给函数的示例。

此示例代码应详细说明我的意思:

void func_A();
void func_B();

void verify(int value) {
    if (value == 0) {
        process(func_A);
    } else if (value == 1) {
        process(func_B);
    }
}

我的想法是模仿这样的过程:

void __wrap_process(EVENT_HANDLER handler){
    check_expected(handler);
    ///I made a test also with check_expected_ptr but the result is the same.
}

而且,在测试电话中:

expect_memory(__wrap_process, handler, func_A, sizeof(func_A));
verify(0);

这不起作用,因为如果我在expect_memory中用func_A替换func_B测试通过。我没有看到除expect_*之外的任何expect_memory函数可以检查指针。

你用了什么?

编辑:添加了以下示例。 EDIT2:更新了包含的示例,并验证它是否正确编译。

例如,我可以提供这个简单的代码:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>

union EVENT{
    uint8_t event;
};

typedef void (*CALLBACK)(union EVENT * event);

void wrap_register_callback( CALLBACK callback );

void callback_module_a( union EVENT *event ) {
    //Do something with the event
    //It is out of scope for this test.
    (void)event;
}

void callback_module_b( union EVENT *event ) {
    //Do something with the event
    //It is out of scope for this test.
    (void)event;
}



void __wrap_register_callback( CALLBACK callback ) {
    check_expected(callback);
}

void code_that_set_the_callback( int status ) {
    if (status < 0){
        register_callback(callback_module_a);
    }else{
        register_callback(callback_module_b);
    }
}

void test_correct_handler( ) {
    int status = 0;
    expect_memory(__wrap_register_callback, callback,  callback_module_a, sizeof(CALLBACK));
    //TEST 1 expected result test pass. Result: test pass
    code_that_set_the_callback(status);

    status = -1;
    expect_memory(__wrap_register_callback, callback, callback_module_b, sizeof(CALLBACK));
    //TEST 2 expected result test pass. Result: test pass
    code_that_set_the_callback(status);

    //At the moment if I change the callbacks in the tests, like:
    status = 0;
    //This is not correct but the test passes.
    expect_memory(__wrap_register_callback, callback, callback_module_b, sizeof(CALLBACK));
    //TEST 3 expected result test fail. Result: test pass
    //This is wrong
    code_that_set_the_callback(status);

    status = -1;
    //This is not correct but the test passes.
    expect_memory(__wrap_register_callback, callback, callback_module_a, sizeof(CALLBACK));
    //TEST 4 expected result test fail. Result: test pass
    //This is wrong
    code_that_set_the_callback(status);
}

int main(void)
{
    //Make coverage happy
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test_correct_handler),
    };
return cmocka_run_group_tests(tests, NULL, NULL);
}

关于代码的注意事项:函数register_callback不在此测试代码中的测试中。省略了函数体,因为在编译代码期间,将参数-Wl, - wrap = register_callback传递给链接器,该函数完全被__wrap_register_callback替换

这个想法是函数初始化一个回调,这个回调取决于一些初始化值。我想根据情况检查选定的回调是否正确。

来自文档页面https://api.cmocka.org/group__cmocka__param.html

用于验证被模拟的函数接收的参数的可用宏不包含用于验证函数指针参数的函数。在我看来,我可以适应这个范围的唯一功能是expect_memory但是

  • 它不起作用,
  • 我没有正确理解使用它的方式
  • 我在编写测试时犯了错误。

1 个答案:

答案 0 :(得分:0)

cmocka似乎没有专门用于指针的参数检查宏。在许多C实现中,expect_value可能符合您的目的。 cmocka将传递给它的值转换为LargestIntegralType,它试图将其定义为宽无符号整数类型。假设类型足够宽,许多C实现将不同的指针转换为不同的整数,并将指针转换为相等的整数。 (C中的两个指针可能比较相同,即使它们内部有不同的位表示。但是一个好的C实现会在转换为整数时规范化表示。)

如果满足这些要求,您应该能够使用expect_value来测试指针,如:

void test_correct_handler( ) {
    int status = 0;
    expect_value(__wrap_register_callback, callback,  callback_module_a);
    code_that_set_the_callback(status);

    status = -1;
    expect_value(__wrap_register_callback, callback, callback_module_b);
    code_that_set_the_callback(status);

    //At the moment if I change the callbacks in the tests, like:
    status = 0;
    //This is not correct but the test passes.
    expect_value(__wrap_register_callback, callback, callback_module_b);
    code_that_set_the_callback(status);

    status = -1;
    //This is not correct but the test passes.
    expect_value(__wrap_register_callback, callback, callback_module_a);
    code_that_set_the_callback(status);
}

修补上述内容可确认对callback_module_acallback_module_b的使用是否敏感。但是,测试的意义与你在问题中所说的相反:前两个报告失败,最后两​​个报告通过。你确定你有正确的测试方法吗?如果您在此代码中将callback_module_acallback_module_b交换,则会遇到您请求的情况,前两个传递,最后两个传递失败。