Tester des dates dans un pipeline
La fenêtre sert à explorer. Voici l'autre moitié : une version en ligne de commande d'environ 2,4 Mo, sans environnement d'exécution à installer, dont le code de sortie est le verdict de couverture et non celui de la cible.
Le code de sortie est le verdict
C'est le choix de conception qui rend l'outil scriptable. Quand une session se termine, le code de sortie répond à « la substitution du temps a-t-elle pris effet », et non à « qu'a renvoyé l'application ». Un pipeline peut donc échouer sur une substitution qui n'a silencieusement pas eu lieu - et c'est l'échec qui mérite de faire échouer, car tout ce qui vient après est un test qui n'a rien prouvé.
Le propre code de sortie de la cible est toujours rapporté, dans les données de session.
| Code | Signification |
|---|---|
| 0 | fonctionne - tout processus qui a lu l'heure a vu l'horloge de la session |
| 10 | fonctionne partiellement - certains canaux couverts, d'autres non |
| 11 | ne fonctionne pas - la substitution n'a pas atteint les canaux essentiels |
| 4 | indéterminé - la couverture n'a pas pu être établie |
| 1 | erreur d'utilisation - une option ou une expression incorrecte |
| 2 | la cible n'a pas pu être lancée ou injectée |
| 12 | la cible a disparu, ce qui évoque une application à instance unique |
| 3 | erreur interne - le moteur n'a pas pu démarrer, a rencontré un état inattendu ou s'est arrêté avant de clore la session (quel que soit son propre code de sortie). Une telle exécution ne porte aucun verdict |
| 5 | l'opération n'est pas intégrée à cette version |
| 6 | l'exécution a été écourtée - --timeout a expiré, ou le moteur a cessé de répondre pendant 15 secondes et a été arrêté. Ce n'est pas un verdict : la session a été interrompue, elle ne prouve donc rien sur la cible, dans un sens ou dans l'autre |
| 7 | une autre session est déjà en cours - une seule session à la fois. Il suffit de réessayer une fois qu'elle est terminée |
| 8 | la session a abouti à un verdict, mais sa preuve n'est pas dans le fichier que désigne --report - le disque était plein, ou un autre programme gardait l'ancien fichier ouvert, qui reste alors tel quel. Le verdict figure toujours dans le rapport qu'affiche la commande |
Toutes les options des deux commandes, et le même tableau pour le calculateur, sont dans la référence de la ligne de commande.
Exécutions bornées
Un pipeline ne peut pas attendre qu'un humain ferme une application de bureau.
--ticks N termine la session après N battements - d'une seconde réelle chacun - et
rapporte ce qu'il a trouvé jusque-là. La couverture est de toute façon établie dans les premiers
instants du processus, si bien qu'une borne courte suffit généralement.
# Dix secondes, puis arrêt et rapport chrono run ".\build\test.exe" --preset year-rollover --ticks 10 --report evidence.txt
Sortie machine et preuves
--jsonémet la session sous forme d'enregistrements lisibles par une machine au lieu du rapport pour humains - les mêmes faits, y compris la couverture par canal.--report <path>écrit le rapport pour humains dans un fichier, ce qui fait un artefact de build raisonnable. Une session dont le verdict n'est pas fonctionne place en tête de ce fichier un bandeau de preuve peu fiable, plutôt que d'enfouir la réserve en bas.- Le calculateur comprend aussi
--json, de sorte qu'un pipeline peut calculer la date dont il a besoin et la réinjecter.
# Calculer la date, puis exécuter à cette date chrono calc --base today --snap eom --json chrono run ".\build\test.exe" --preset month-end --ticks 10 --json
Une étape, en gros
- name: Month-end behaviour
shell: pwsh
run: |
.\chrono.exe run ".\build\test.exe" --preset month-end --ticks 10 --report evidence.txt
# un code de sortie non nul ici signifie que la substitution n'a pas pris, donc le
# test qui suit n'aurait rien prouvé
- name: Keep the evidence
uses: actions/upload-artifact@v7
with:
name: chrono-evidence
path: evidence.txt
Deux réserves honnêtes sur les runners
- Il faut un runner Windows. Il n'existe pas de version Linux ou macOS, et il n'y en aura pas - sous Linux, libfaketime couvre déjà ce besoin.
- L'antivirus d'un runner hébergé peut bloquer l'injection. Décaler le temps revient à injecter une bibliothèque dans le processus cible, une technique Windows documentée qu'utilisent aussi les logiciels malveillants. Un runner qui la bloque produit un code de sortie qui le dit, plutôt qu'un faux succès - mais c'est à découvrir avant d'en dépendre.
Pour la même raison, la suite de tests de bout en bout de ce projet s'exécute sur de vraies machines et non sur un runner hébergé. Son intégration continue compile et teste unitairement tout, et la substitution elle-même est exercée à la main sur de vraies applications, en 32 bits comme en 64 bits, avant chaque version.