[英]How to mock functions in headerfiles?
我在做什么:
我正在使用cmocka為大型嵌入式項目運行單元測試。 嵌入式項目使用arm-gcc-compiler
。 使用嵌入代碼的片段和cmocka庫,使用普通gcc
編譯單元測試。
通常cmocka建議使用-Wl -Wl,--wrap=functionName
標志來模擬(替換)一些不需要的子函數。 這非常好用。
問題:
好吧,在我的嵌入式代碼中有一個頭文件( foo.h
),它包含一些函數(聲明為內聯)。 其中一個函數包含arm-gcc-compiler
一些匯編代碼,當然,它不能由gcc
。
愚蠢的是, wrap
-flag似乎不適用於放在頭文件中的函數。
題:
如何在頭文件中模擬這個函數?
我是如何嘗試解決問題的:
我想插入一些#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))
愚蠢的是,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 );
做
cat tmp.c | sed '/inline\|INLINE/,/^}$/{ s/^\(.*\(inline\|INLINE\).*\)/\1;/; /inline\|INLINE/!d }'
正則表達式非常草率,它依賴於標題中的所有定義都將具有INLINE
標記但在您的情況下應該足夠的事實。
您可以將上面的命令嵌入到Makefile中,以在temp文件夾中生成自定義標頭,然后使用-Ipath/to/temp/folder
標志覆蓋默認標頭。
我沒有使用cmocka所以我不確定是否有一種方法可以在框架內管理它。
但是, cmock使用一種方法,將標頭復制到測試版本的包含層次結構中較高位置的位置(並且只有測試版本,即使發布版本也隱式包含該位置)。
然后可以編輯此標頭的副本,使得函數聲明只是變為port void vPortRaiseBASEPRI( void );
。 然后,當生成模擬時,會為此生成模擬(以及同一標頭內的其他函數聲明),就像在任何其他情況下一樣。 因為正在生成hte模擬,所以函數沒有匹配的源代碼定義(即.c
文件)並不重要。
請參閱https://dmitryfrank.com/articles/unit_testing_embedded_c_applications上的“處理特定於編譯器的內容”部分
我的類似問題以及我如何解決它: 使用編譯器特定關鍵字對單元測試C進行單元測試
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.