0

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

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

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 但是

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

1 回答 1

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_a或被callback_module_b使用很敏感。但是,测试的意义与您在问题中所说的相反:前两个报告失败,最后两​​个报告通过。你确定你的测试方法正确吗?如果你在这段代码中交换callback_module_acallback_module_b你会遇到你要求的情况,前两个通过,最后两个失败。

于 2018-01-18T22:11:04.370 回答