涉及gcc wrap的一个问题的探索

需求分析

在做C语言的单元测试的时候,我们希望在不改动源码的情况下,额外加入单元测试用的代码。借用cmocka这样的测试框架,希望能够通过mock来替代源代码中的函数。例如待测函数是A,而A调用了B,那么最好是可以通过mock_B来让A直接获取到返回值,从而把A定义的流程走完。

尝试

通过搜索,找到了一个可以执行的例子如下

/* test_mocking.c */
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

int get_value();
int __wrap_get_value() {
    int v;
    v = mock_type(int);
    return v;
}

int add_one() {
    int v;
    v = get_value();
    return v + 1;
}

static void add_test(void **state) {
    (void)state;
    int a;

    will_return(__wrap_get_value, 3);

    a = add_one();
    assert_int_equal(a, 4);
}

int main(int argc, char *argv[]) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(add_test),
    };

    return cmocka_run_group_tests(tests, NULL, NULL);
}

进行编译,确实可以起到用add_one调用的是 __wrap_get_value而不是get_value的效果。

$ gcc test_mocking.c -I. -Wl,--wrap=get_value -lcmocka && ./a.out
[==========] Running 1 test(s).
[ RUN      ] add_test
[       OK ] add_test
[==========] 1 test(s) run.
[  PASSED  ] 1 test(s).

但是,注意到源码中只是声明get_value,而并没有实现get_value这个函数。如果实现这个函数再尝试编译执行

/* test_mocking.c */
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

int get_value() {
    return 20;
}
......

$ gcc test_mocking.c -I. -Wl,--wrap=get_value -lcmocka && ./a.out
[==========] Running 1 test(s).
[ RUN      ] add_test
[  ERROR   ] --- 0x15 != 0x4
[   LINE   ] --- test_mocking.c:30: error: Failure!
[  FAILED  ] add_test
[==========] 1 test(s) run.
[  PASSED  ] 0 test(s).
[  FAILED  ] 1 test(s), listed below:
[  FAILED  ] add_test

 1 FAILED TEST(S)

发现wrap就无效了,add_one调用的就是get_value自身定义的实现,而不是__wrap_get_value了!

结论

在stackoverflow找到了一个跟我诉求一样的帖子,回答的人特意提到,要被wrap的函数,必须是未定义实现

    --wrap=symbol

    Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to __wrap_symbol. Any undefined reference to __real_symbol will be resolved to symbol.

这样看来,想完全“不打扰”源码中的实现,额外加单元测试的念头,用cmocka是不行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值