0

大家好,这是我的具体情况:

服务.h:

    typedef struct {
        uint8_t (*function1)(void);
        uint8_t (*function2)(void);
    } const service_struct_t;

    extern service_struct_t service_api ;

服务.c:

    #include "service.h"

    static uint8_t foo(void){
         return 13+6;
    }
    static uint8_t bar(void){
         return 7*6;
    }

    service_struct_t service_api = {
        .function1 = foo,
        .function2 = bar,
    };

我需要存根(模拟、替换)这些函数,但我无权更改原始代码。我正在使用 gcc 来编译单元测试。我未能:

  • 直接使用 gcc 的 --wrap 选项,foo因为bar它们对于 source.c 是静态的:

    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    uint8_t __real_foo(void);
    uint8_t __wrap_foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_foo();
        }
    }
    /* same for bar */

  • 在对象符号上使用 gcc 的 --wrap 选项,service_api因为它不是函数

    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    uint8_t __real_service_api ;
    uint8_t __wrap_service_api = {
        .function1 = foo,
        .function2 = bar,
    }

    static uint8_t foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_service_api.function1();
        }
    }
    /* same for bar */

  • 只需重新分配service_api成员函数,因为结构是常量并且已经分配。

    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    service_struct_t backup_service_api = {
        .function1 = service_api.function1;
        .function2 = service_api.function2;
    }
    service_struct_t stub_service_api = {
        .function1 = foo;
        .function2 = bar;
    }

    uint8_t foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_foo();
        }
    }/* same for bar */

    void service_poke_stub(bool_t enable_stubs){
        if(enable_stubs){
            service_api.function1 = stub_service_api.function1
            service_api.function2 = stub_service_api.function2
        }else{
            service_api.function1 = backup_service_api.function1
            service_api.function2 = backup_service_api.function2
        }
    }

已经感谢您的帮助

4

1 回答 1

1

正如您已经发现的那样,您不能模拟结构中的函数。

所以这取决于你喜欢测试什么

  • 如果你想测试结构是否包含正确的功能,模块service.c就是你的被测模块,应该按原样使用。您需要通过查看函数所做的事情来检查正确性。

  • 如果您想测试该结构是否正确使用,您将模拟整个模块。现在你可以随意放入它。

如果您的源代码不允许这样做,则该设计不利于测试。当架构没有考虑到可测试性时,通常会出现这种情况。

于 2020-03-24T17:57:23.300 回答