cunit-testingoopstubcunit

C Unit Test: stub a constant structure (gcc --wrap)


Hi All here is my specific case:

service.h:

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

    extern service_struct_t service_api ;

service.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,
    };

I need to stub (to mock, to replace) these functions but I have no right to change that original code. I'm using gcc to compile the unit tests. I've failed to:


    #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 */


    #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 */


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

thanks already for your help


Solution

  • You can't mock the functions in the structure, as you already found out.

    So it depends on what you like to test:

    If your source code does not allow this, the design is bad for testing. This is often the case when the architecture is not done with testability in mind.