简体   繁体   English

cmocka,如何检查函数指针

[英]cmocka, how to check a function pointer

I searched in the documentation and in the waiter example but I can't find an example about how to check if the right function pointer is passed as parameter to a function. 我在文档和服务员示例中进行了搜索,但是找不到如何检查正确的函数指针是否作为参数传递给函数的示例。

This sample code should detail well what I mean: 此示例代码应详细说明我的意思:

void func_A();
void func_B();

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

My idea was to mock process like this: 我的想法是模拟这样的流程:

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

And, in the test call: 并且,在测试调用中:

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

This does not work because if I replace func_A with func_B in the expect_memory the test pass. 如果我更换这并不因为工作func_Afunc_B在expect_memory测试通过。 I don't see any expect_* function other than expect_memory that can check a pointer. 除了expect_memory ,我没有看到任何expect_*函数可以检查指针。

What did you use? 你用了什么?

EDIT: Added the following example. 编辑:添加了以下示例。 EDIT2: Updated example with includes and verified that it compiles correctly. EDIT2:更新了包含的示例,并验证了它可以正确编译。

As example I can provide this simple code: 作为示例,我可以提供以下简单代码:

#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);
}

Note on the code: The function register_callback is not under the test in this test code. 关于代码的注释:在此测试代码中,未对函数register_callback进行测试。 The body of the function is omitted because during the compilation of the code, passing the argument -Wl,--wrap=register_callback to the linker the function is completely replaced with __wrap_register_callback 该函数的主体被省略,因为在代码编译期间,将参数-Wl,-wrap = register_callback传递给链接程序,该函数完全被__wrap_register_callback取代

The idea is that a function initialize a callback, this callback depends on some initialization value. 这个想法是一个函数初始化一个回调,这个回调依赖于一些初始化值。 I want to check that the selected callback is the right one depending on the situation. 我想根据情况检查选定的回调是否正确。

from the documentation page https://api.cmocka.org/group__cmocka__param.html 从文档页面https://api.cmocka.org/group__cmocka__param.html

the available macros for verify the parameters received by a function that was mocked does not contain a function for verify a function pointer parameter. 用于验证被模拟的函数接收的参数的可用宏不包含用于验证函数指针参数的函数。 In my opinion the only function that I can adapt for this scope is expect_memory but 在我看来,我可以适应此范围的唯一功能是Expect_memory但

  • it is not working, 它不起作用,
  • I didn't understand correctly the way to use it 我不正确地理解使用方式
  • I made a mistake writing the test. 我在写测试时犯了一个错误。

cmocka does not appear to have any parameter-checking macro specifically intended for pointers. cmocka似乎没有任何专门用于指针的参数检查宏。 In many C implementations, expect_value may serve your purpose. 在许多C实现中, expect_value您的目的。 cmocka converts the value you pass it to LargestIntegralType , which it attempts to define to be a wide unsigned integer type. cmocka会将您传递给它的值转换为LargestIntegralType ,它将尝试将其定义为宽无符号整数类型。 Assuming the type is wide enough, many C implementations will convert different pointers to different integers and equal pointers to equal integers. 假设类型足够宽,许多C实现将不同的指针转换为不同的整数,并将相等的指针转换为相等的整数。 (Two pointers in C may compare as equal even though they have different bit representations internally. But a good C implementation will normalize the representation when converting to integer.) (即使内部有不同的位表示形式,C中的两个指针也可能比较相等。但是,良好的C实现会在转换为整数时将其标准化。)

If these requirements are met, you should be able to use expect_value to test pointers, as with: 如果满足这些要求,则应该能够使用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);
}

Tinkering with the above confirms it is sensitive to whether callback_module_a or callback_module_b is used. 修改以上内容确认它对使用callback_module_acallback_module_b是敏感的。 However, the sense of the tests is reversed from what you say in the question: The first two report failure, and the last two report pass. 但是,测试的意义与您在问题中所说的相反:前两个报告失败,最后两​​个报告通过。 Are you sure you have the tests the right way around? 您确定您的测试方法正确吗? If you swap callback_module_a with callback_module_b in this code, you will have the situation you request, where the first two pass and the last two fail. 如果在此代码中将callback_module_acallback_module_b交换,则会遇到您所要求的情况,其中前两个通过,后两个失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM