Chrono Mock
SpracheDeutsch

Datumstests in der Pipeline

Das Fenster dient zum Ausprobieren. Dies ist die andere Hälfte: ein Kommandozeilen-Build von etwa 2,4 MB ohne Laufzeitumgebung, dessen Exit-Code das Abdeckungsurteil ist und nicht der Code des Zielprogramms.

Der Exit-Code ist das Urteil

Diese Entwurfsentscheidung macht das Werkzeug skriptbar. Wenn eine Sitzung endet, beantwortet der Exit-Code „hat die Zeitersetzung gewirkt“ und nicht „was hat die Anwendung zurückgegeben“. Eine Pipeline kann also an einer Ersetzung scheitern, die stillschweigend nicht stattgefunden hat - und genau daran lohnt es sich zu scheitern, denn alles danach ist ein Test, der nichts bewiesen hat.

Der eigene Exit-Code des Ziels wird weiterhin gemeldet, in den Sitzungsdaten.

CodeBedeutung
0funktioniert - jeder Prozess, der die Zeit las, sah die Sitzungsuhr
10funktioniert teilweise - einige Kanäle abgedeckt, andere nicht
11funktioniert nicht - die Ersetzung hat die wichtigen Kanäle nicht erreicht
4unbestimmt - die Abdeckung ließ sich nicht feststellen
1Aufruffehler - eine falsche Option oder ein falscher Ausdruck
2das Ziel konnte nicht gestartet oder injiziert werden
12das Ziel ist verschwunden, was auf eine Einzelinstanz-Anwendung hindeutet
3interner Fehler - die Engine konnte nicht starten, geriet in einen unerwarteten Zustand oder hielt an, bevor sie die Sitzung abschloss (gleich welchen Code sie selbst hatte). Ein solcher Lauf trägt kein Urteil
5die Operation ist in diesem Release nicht enthalten
6der Lauf wurde abgebrochen - --timeout ist abgelaufen, oder die Engine antwortete 15 Sekunden lang nicht und wurde angehalten. Das ist kein Urteil: Die Sitzung wurde unterbrochen und beweist daher weder in die eine noch in die andere Richtung etwas über das Ziel
7eine andere Sitzung läuft bereits - immer nur eine Sitzung zur Zeit. Es genügt, es nach ihrem Ende erneut zu versuchen
8die Sitzung kam zu einem Urteil, aber ihr Nachweis steht nicht in der Datei, die --report nennt - die Festplatte war voll, oder ein anderes Programm hielt die alte Datei offen, die dann unverändert bleibt. Das Urteil steht weiterhin im Bericht, den der Befehl ausgibt

Alle Optionen beider Befehle und dieselbe Tabelle für den Rechner stehen in der Kommandozeilen-Referenz.

Begrenzte Läufe

Eine Pipeline kann nicht darauf warten, dass ein Mensch eine Desktop-Anwendung schließt. --ticks N beendet die Sitzung nach N Herzschlägen - je einer realen Sekunde - und meldet, was bis dahin gefunden wurde. Die Abdeckung steht ohnehin in den ersten Momenten des Prozesses fest, deshalb genügt meist eine kurze Grenze.

# Zehn Sekunden, dann anhalten und berichten
chrono run ".\build\test.exe" --preset year-rollover --ticks 10 --report evidence.txt

Maschinenausgabe und Nachweise

  • --json gibt die Sitzung als maschinenlesbare Datensätze aus statt als Bericht für Menschen - dieselben Fakten, einschließlich der Abdeckung je Kanal.
  • --report <path> schreibt den Bericht für Menschen in eine Datei, die sich als Build-Artefakt eignet. Hat eine Sitzung ein anderes Urteil als funktioniert, steht am Anfang dieser Datei ein Hinweis auf unzuverlässige Nachweise, statt dass die Einschränkung unten untergeht.
  • Auch der Rechner versteht --json, sodass eine Pipeline das benötigte Datum berechnen und zurückspeisen kann.
# Das Datum berechnen, dann damit ausführen
chrono calc --base today --snap eom --json
chrono run ".\build\test.exe" --preset month-end --ticks 10 --json

Ein Schritt, ungefähr so

- name: Month-end behaviour
  shell: pwsh
  run: |
    .\chrono.exe run ".\build\test.exe" --preset month-end --ticks 10 --report evidence.txt
    # ein Exit-Code ungleich null heißt: die Ersetzung hat nicht gegriffen, der
    # Test danach hätte also nichts bewiesen

- name: Keep the evidence
  uses: actions/upload-artifact@v7
  with:
    name: chrono-evidence
    path: evidence.txt

Zwei ehrliche Einschränkungen zu Runnern

  • Es braucht einen Windows-Runner. Es gibt keinen Linux- oder macOS-Build, und es wird keinen geben - unter Linux deckt libfaketime das bereits ab.
  • Virenschutz auf einem gehosteten Runner kann die Injektion blockieren. Die Zeit zu verschieben bedeutet, eine Bibliothek in den Zielprozess einzuschleusen - eine dokumentierte Windows-Technik, die auch Schadsoftware nutzt. Ein Runner, der sie blockiert, liefert einen Exit-Code, der das sagt, statt eines falschen Bestehens - aber man sollte es herausfinden, bevor man sich darauf verlässt.

Aus demselben Grund läuft die End-to-End-Suite dieses Projekts auf echten Rechnern und nicht auf einem gehosteten Runner. Die Continuous Integration baut und testet alles per Unit-Tests, und die Ersetzung selbst wird vor einem Release von Hand an echten Anwendungen geprüft, sowohl in 32-Bit- als auch in 64-Bit-Builds.

Ausprobieren