>我在文档和服务员示例中进行了搜索,但我找不到有关如何检查正确的函数指针是否作为参数传递给函数的示例。
此示例代码应该详细说明我的意思:
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_B
替换func_A
,测试就会通过。除了expect_memory
之外,我没有看到任何可以检查指针的expect_*
函数。
你用了什么?
编辑:添加了以下示例。 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但是
- 它不起作用,
- 我没有正确理解使用它的方式
- 我在写测试时犯了一个错误。
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_a
与callback_module_b
交换,则会出现请求的情况,即前两个通过,后两个失败。