2017-02-07 3 views
4

Was ich tue:Wie Funktionen in Headerdateien vortäuschen?

I bin mit Unit-Tests für großes eingebettetes Projekt auszuführen. Das eingebettete Projekt wird mit einem arm-gcc-compiler kompiliert. Die Komponententests werden mit dem normalen gcc unter Verwendung von Fragmenten des eingebetteten Codes und der cmocka-Bibliothek kompiliert. Normalerweise empfiehlt cmocka, das Flag -Wl,--wrap=functionName zu verwenden, um einige nicht benötigte Unterfunktionen nachzuahmen (zu ersetzen). Das funktioniert ziemlich gut.

Das Problem:

Nun, in meinem eingebetteten Code gibt eine Header-Datei (foo.h) ist, die einige Funktionen enthält (als inline deklariert). Eine dieser Funktionen enthält einige Assembler-Codes für die arm-gcc-compiler, die natürlich nicht durch die gcc kompiliert werden können.

Dummerweise scheint das wrap-Flag nicht auf Funktionen zu funktionieren, die in Header-Dateien platziert werden.

Frage:

Wie diese Funktion in der Headerdatei weg verspotten?

Wie ich versuchte, das Problem zu lösen:

Ich dachte über einige #idef Makros Einfügen des genannten Assembler Abschnitt auszuschließen. Dies ist jedoch nicht möglich, da diese Datei zu einer lizensierten Bibliothek gehört und ich ihren Inhalt nicht ändern darf.

Ich könnte meine Funktion unter Test in eine zusätzliche Dateien extrahieren, so dass foo.h muss nicht mehr enthalten sein. Dies würde jedoch die Struktur der eingebetteten Quellcodes verwirren.

Exact Linien Problem

der genaue Code in portmacro.h von freeRtos an Leitung 233 gelegt wird:

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

wo, wie portFORCE_INLINE sind definiert als:

#define portFORCE_INLINE inline __attribute__((always_inline)) 

Antwort

2

Dummerweise scheint die Wrap-Flag nicht auf func zu funktionieren , die in Header-Dateien platziert werden.

Es ist nicht die Schuld von wrap, die Funktion wurde vom Compiler inlined, also gibt es nichts, das Linker tun kann.

Wie diese Funktion in der Headerdatei wegzuspielen?

Eine Option ist sed zu verwenden automatisch zu gcc den fehlerhaften Code zu patchen, bevor er. Z.B.

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

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

aus Ihrem Beispiel zu ändern

portFORCE_INLINE static void vPortRaiseBASEPRI(void); 

portFORCE_INLINE static void vPortRaiseBASEPRI_2(void); 

tun

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

Die Regex ziemlich schlampig ist, es beruht auf der Tatsache, dass alle Definitionen in Header haben die INLINE Marker aber sollte in Ihrem Fall wahrscheinlich genug sein.

Sie können den obigen Befehl in Ihr Makefile einbetten, um einen benutzerdefinierten Header in einem temporären Ordner zu generieren, und dann den Standardheader mit dem Flag -Ipath/to/temp/folder überschreiben.

+0

@LPs Aber wie? Linker hat keinen Zugriff auf den Quellcode und zu dem Zeitpunkt, zu dem der Linker läuft, wurde die Funktion bereits inline und stark optimiert. – yugr

0

Ich habe cmocka nicht verwendet, also bin ich mir nicht sicher, ob es eine Methode gibt, diese bereits im Rahmen zu verwalten.

cmock verwendet eine Methode, bei der die Kopfzeile an eine höhere Stelle in der Include-Hierarchie des Testbuilds kopiert wird (und nur der Testbuild, der Speicherort wird nicht implizit vom Releasebuild eingeschlossen).

Die Kopie dieses Headers kann dann so bearbeitet werden, dass die Funktionsdeklaration einfach port void vPortRaiseBASEPRI(void); wird. Dann, wenn die Mocks erzeugt werden, wird ein Mock für diese (und die anderen Funktionsdeklarationen innerhalb desselben Headers) wie in jedem anderen Fall erzeugt. Da die Mocks erzeugt werden, spielt es keine Rolle, dass es für die Funktion (en) keine übereinstimmende Quellcode-Definition (d. H. .c Datei) gibt.

Siehe „Umgang mit Compiler-spezifischen Sachen“ am https://dmitryfrank.com/articles/unit_testing_embedded_c_applications

Und meine ähnliche Frage, und wie ich es hier gelöst: Unit test C with compiler specific keywords

+0

Ich bin mir nicht sicher, wie es sich von einer anderen Antwort unterscheidet (die BTW bietet auch Lösung für die automatische Generierung fester Header). – yugr

+0

@Yugr, ja, jetzt haben Sie mit mehr Erklärung bearbeitet, es ist ziemlich ähnlich. Zuvor dachte ich, du würdest dich dafür einsetzen, 'sed' zu verwenden, um den ursprünglichen Header zu ändern, den der OP angeblich nicht ausführen konnte. Nur eine andere Erklärung der gleichen Idee, obwohl :-) – Toby

Verwandte Themen