Ich arbeite daran, verschiedene Dinge zu schreiben, die relativ komplizierte Win32-API-Funktionen aufrufen. Hier ist ein Beispiel:
%Vor% Mein Problem ist es, die NtDll::NtQuerySystemInformation
-Methode zu verspotten - nämlich, dass die zurückgegebene Datenstruktur kompliziert ist (Nun, hier ist es eigentlich relativ einfach, aber es kann kompliziert sein), und einen Test schreiben, der die Datenstruktur baut Der API-Aufruf kann 5-6 mal so lange dauern wie das Schreiben des Codes, der die API verwendet.
Ich möchte die API aufrufen und irgendwie aufzeichnen, damit ich den aufgezeichneten Wert an den getesteten Code zurückgeben kann, ohne die API tatsächlich aufzurufen. Die zurückgegebenen Strukturen können nicht einfach gemerkt werden, da sie oft innere Zeiger enthalten (Zeiger auf andere Orte im selben Puffer). Die betreffende Bibliothek müsste auf diese Art von Dingen prüfen und in der Lage sein, Zeigerwerte bei einer Wiederholung in einen ähnlichen Puffer zurückzuversetzen. (d. h., prüfen Sie jeden Zeigergrößenwert, wenn er als ein Zeiger innerhalb des Puffers interpretiert werden könnte, ändern Sie diesen in einen Offset und denken Sie daran, ihn bei der Wiedergabe wieder in einen Zeiger zu ändern - eine falsche positive Rate ist hier akzeptabel)
Gibt es etwas da draußen, das so etwas macht?
Ist es wirklich so schwer von Hand zu implementieren?
%Vor%(Entschuldigung, ich habe es noch nicht getestet, aber es sollte verdammt bald funktionieren.)
Das einzige Problem ist die Annahme, dass alle Werte, die möglicherweise Zeiger sind, tatsächlich Zeiger sind, aber ansonsten scheint es einfach.
Dieses Problem ist zumindest eine Teilmenge eines Forschungsproblems in seiner vollen Allgemeinheit, was darauf hindeutet, dass es für Sie kein Standardsystem geben wird. Ein Artikel zum Thema Aufzeichnung und Wiedergabe von API-Anrufen erschien vor zwei Jahren auf einer der führenden Betriebssystem-Konferenzen (OSDI 2008). Ein Blick auf ihre Website zeigt keinen verfügbaren Code - nichtsdestoweniger ist der Code, wenn verfügbar, möglicherweise nicht Produktionsqualität.
R2: Ein Kernel auf Anwendungsebene für Record und Replay Zhenyu Guo, Xi Wang, Jian Tang, Xuezheng Liu, Zhilei Xu, Ming Wu, M. Frans Kaashoek und Zheng Zhang, OSDI 2008
Bibliotheksbasierte Aufzeichnungs- und Wiedergabetools zielen darauf ab, die Ausführung einer Anwendung zu reproduzieren, indem die Ergebnisse ausgewählter Funktionen in einem Protokoll aufgezeichnet und während der Wiedergabe die Ergebnisse aus dem Protokoll zurückgegeben werden, anstatt die Funktionen auszuführen. Diese Werkzeuge müssen sicherstellen, dass ein Wiederholungslauf identisch mit dem Aufzeichnungslauf ist. Die Herausforderung dabei ist, dass nur Aufrufe einer Funktion durch die Anwendung aufgezeichnet werden sollen, das Aufzeichnen der Nebeneffekte eines Funktionsaufrufs kann schwierig sein und keine Funktionsaufrufe während der Wiedergabe, Multithreading und der Anwesenheit des Tools können das ändern Anwendungsverhalten von der Aufnahme bis zur Wiedergabe. Diese Probleme haben den Einsatz solcher Tools eingeschränkt.
MitR2 können Entwickler Funktionen auswählen, die korrekt aufgezeichnet und wiedergegeben werden können. Entwickler kommentieren die ausgewählten Funktionen mit einfachen Schlüsselwörtern, sodass R2 Anrufe mit Nebeneffekten und Multithreading verarbeiten kann. R2 generiert Code für die Aufzeichnung und Wiedergabe von Vorlagen, sodass Entwickler Stubs für Hunderte von Funktionen nicht manuell implementieren können. Um zu verfolgen, ob ein Aufruf im Auftrag der Anwendung oder der Implementierung einer ausgewählten Funktion erfolgt, behält R2 ein Modusbit bei, das Stubs speichert und wiederherstellt.
Wir haben R2 unter Windows implementiert und große Teile (1.300 Funktionen) der Win32-API und zwei übergeordnete Schnittstellen (MPI und SQLite) kommentiert. R2 kann Multithread-Web- und Datenbankserver wiedergeben, die frühere bibliotheksbasierte Tools nicht wiedergeben können. Da Entwickler High-Level-Schnittstellen auswählen können, kann R2 auch den Overhead der Aufzeichnung gering halten. Experimente zeigen, dass der Aufzeichnungsaufwand für Apache ungefähr 10% beträgt. Das Aufzeichnen und Wiedergeben an der SQLite-Schnittstelle kann die Protokollgröße um bis zu 99% reduzieren (im Vergleich zur Win32-API) und Optimierungsanmerkungen für BitTorrent und MPI verwenden Anwendungen erreicht Log-Größe Reduktion von 13,7% bis 99,4%.
(keine Abstimmungen erwarten, einfach nur helfen / mit der Community kommunizieren) Sie sagen, Sie möchten eine einfachere Datenstruktur zu lesen, aber wenn Sie die API verwenden (was ich denke, was Sie sagen, Sie wollen .. direkt tun), stecken Sie fest mit der, die es Ihnen gibt. Also willst du nur die api-Funktion aufrufen können, aber sie müssen ihre Zeiger / Var-Werte wiederherstellen, als hättest du sie nicht aufgerufen? \ N Ich denke du suchst nach dem fast unmöglichem Freund (oder sehr komplex!). Sie müssten den API-Code ändern, um seine Zeigerwerte wiederherzustellen, aber Sie wissen das bereits. Werden diese Werte wiederhergestellt, wenn das Programm endet? Wenn ja, könnten Sie diesen API-Aufruf wahrscheinlich in eine andere Lösung / ein anderes Programm einfügen und von Ihrem Programm aus aufrufen?
Es gibt mehrere Möglichkeiten:
Ändern Sie die oberste Klasse als Vorlage mit einem Vorlagenparameter. Für Ihre tatsächliche Implementierung werden Sie NtDll verwenden, aber für den Test verwenden Sie einen Mock, der die Aufrufe protokolliert
erstellt einen Wrapper für die NtDll-Klasse mit einer Schnittstelle. Sie können Objekt dieses Typs mit dieser Klasse an den Konstruktor im echten Code übergeben und im Test mocksen.
Versuchen Sie, Ihre Klasse mit der NtDll-Klasse in eine einzelne Klasse umzuwandeln.
Bei allen Ansätzen wird davon ausgegangen, dass Sie die Abhängigkeitsinjektion verwenden.
Tags und Links unit-testing c++