如何在headerfiles中模拟函数?

时间:2017-02-07 10:48:48

标签: c unit-testing gcc cmocka

我在做什么:

我正在使用cmocka为大型嵌入式项目运行单元测试。 嵌入式项目使用arm-gcc-compiler进行编译。 使用嵌入代码片段和cmocka库,使用普通gcc编译单元测试。

通常cmocka建议使用-Wl,--wrap=functionName标志来模拟(替换)一些不需要的子函数。这非常好。

问题:

好吧,在我的嵌入式代码中有一个头文件(foo.h),它包含一些函数(声明为内联)。其中一个函数包含arm-gcc-compiler的一些汇编代码,当然,gcc无法编译它们。

愚蠢地,wrap - 标志似乎不适用于放在头文件中的函数。

问题:

如何在头文件中模拟这个函数?

我是如何尝试解决问题的:

我考虑过插入一些#idef宏来排除上面提到的汇编程序部分。但是这不可能,因为这个文件属于许可的库,我不允许更改其内容。

我可以将我的测试功能提取到其他文件中,以便不再需要包含foo.h。但这会混淆嵌入式源代码结构。

问题的确切线

确切的代码放在第{233}行的freeRtos的portmacro.h中:

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 )
    );
}

其中portFORCE_INLINE定义为:

#define portFORCE_INLINE inline __attribute__(( always_inline))

2 个答案:

答案 0 :(得分:2)

  

愚蠢的wrap-flag似乎不适用于函数   它们放在头文件中。

这不是wrap的错,函数已被编译器内联,因此链接器无法做任何事情。

  

如何在头文件中模拟这个函数?

一种选择是使用sed自动修补有问题的代码,然后再将其传递给gcc。例如。改变

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

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

从你的例子到

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

正则表达式非常草率,它依赖于标题中的所有定义都有INLINE标记这一事实,但在您的情况下应该足够了。

您可以将上面的命令嵌入到Makefile中,以在temp文件夹中生成自定义标头,然后使用-Ipath/to/temp/folder标记覆盖默认标头。

答案 1 :(得分:0)

我没有使用cmocka,所以我不确定是否有一种方法可以在框架内管理它。

但是, cmock 使用一种方法,将标头复制到测试版本的包含层次结构中较高位置的位置(并且只有测试版本,该位置甚至不包括在内。发布版本。

然后可以编辑此标题的副本,使函数声明变为port void vPortRaiseBASEPRI( void );。然后,当生成模拟时,会为此生成模拟(以及同一标头内的其他函数声明),就像在任何其他情况下一样。因为正在生成hte mocks,所以函数没有匹配的源代码定义(即.c文件)并不重要。

请参阅"处理特定于编译器的内容" https://dmitryfrank.com/articles/unit_testing_embedded_c_applications

部分

我的类似问题以及我是如何解决的:Unit test C with compiler specific keywords