简体   繁体   中英

How to mock functions in headerfiles?

What I am doing:

I am using cmocka to run unit tests for large embedded project. The embedded project is compiled with a arm-gcc-compiler . The unit tests are compiled with the normal gcc using fragments of the embedded code and the cmocka library.

Normally cmocka recommends to use the -Wl,--wrap=functionName flag to mock (replace) some unneeded sub-functions. This works pretty good.

The Problem:

Well, within my embedded code there is one header file ( foo.h ), which contains some functions (declared as inline). One of these functions contains some assembler code for the arm-gcc-compiler , which, of course, cannot be compiled by the gcc .

Stupidly the wrap -flag seems not to work on functions which are placed in header files.

Question:

How to mock this function in the headerfile away?

How I tried to solve the Problem:

I thought about inserting some #idef macros to exclude the mentioned assembler section. But this cannot be done because this file belongs to a licensed library and I am not allowed to change its content.

I could extract my function-under-test into an additional files so that foo.h doesn't need to be included anymore. But this would confuse the embedded source codes structure.

Exact lines of problem

The exact code is placed in portmacro.h of freeRtos at line 233:

portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;

    __asm volatile
    (
        "   mov %0, %1                                              \n" \
        "   msr basepri, %0                                         \n" \
        "   isb                                                     \n" \
        "   dsb                                                     \n" \
        :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
    );
}

where as portFORCE_INLINE is defined as:

#define portFORCE_INLINE inline __attribute__(( always_inline))

Stupidly the wrap-flag seems not to work on functions which are placed in header files.

It's not the fault of wrap , the function has been inlined by compiler so there's nothing linker can do.

How to mock this function in the headerfile away?

One option is to use sed to automatically patch the offending code before passing it to gcc. Eg to change

portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
  uint32_t ulNewBASEPRI;
  ...
}

portFORCE_INLINE static void vPortRaiseBASEPRI_2( void )
{
  uint32_t ulNewBASEPRI;
  ...
}

from your example to

portFORCE_INLINE static void vPortRaiseBASEPRI( void );

portFORCE_INLINE static void vPortRaiseBASEPRI_2( void );

do

cat tmp.c | sed '/inline\|INLINE/,/^}$/{ s/^\(.*\(inline\|INLINE\).*\)/\1;/; /inline\|INLINE/!d }'

The regex is quite sloppy, it relies on the fact that all definitions in header will have the INLINE marker but should probably be enough in your case.

You can embed above command into your Makefile to generate custom header in a temp folder and then override default header with -Ipath/to/temp/folder flag.

I've not used cmocka so I'm unsure if there is a method for managing this already within the framework.

However, cmock uses a method whereby the header is copied to a location somewhere higher in the include hierarchy of the test build (and only the test build, the location is not included even implicitly by the release build).

The copy of this header then can be edited such that the function declaration simply becomes port void vPortRaiseBASEPRI( void ); . Then when the mocks are generated a mock is generated for this (and the other function declarations within the same header) just like in any other case. Because hte mocks are being generated it does not matter that there is no matching source code definition (ie .c file) for the function(s).

See the "Dealing with compiler-specific stuff" section at https://dmitryfrank.com/articles/unit_testing_embedded_c_applications

And my similar question and how I solved it here: Unit test C with compiler specific keywords

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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