Chrono Mock
TaalNederlands

Datumtesten in een pipeline

Het venster is om te verkennen. Dit is de andere helft: een opdrachtregelbuild van ongeveer 2,4 MB zonder runtime om te installeren, waarvan de afsluitcode het dekkingsoordeel is en niet die van het doel zelf.

De afsluitcode is het oordeel

Dit is de ontwerpkeuze die het gereedschap scriptbaar maakt. Als een sessie eindigt, beantwoordt de afsluitcode “heeft de tijdvervanging gewerkt”, niet “wat gaf de applicatie terug”. Een pipeline kan dus falen op een vervanging die stilzwijgend niet heeft plaatsgevonden - en dat is het falen waar het de moeite waard is om op te falen, want alles wat daarna komt is een test die niets heeft bewezen.

De eigen afsluitcode van het doel wordt nog steeds gemeld, in de sessiegegevens.

CodeBetekenis
0werkt - elk proces dat de tijd las, zag de sessieklok
10werkt gedeeltelijk - sommige kanalen gedekt, andere niet
11werkt niet - de vervanging heeft de belangrijkste kanalen niet bereikt
4onbepaald - de dekking kon niet worden vastgesteld
1gebruiksfout - een foute optie of een foute expressie
2het doel kon niet worden gestart of geïnjecteerd
12het doel verdween, wat wijst op een applicatie met één instantie
3interne fout - de engine kon niet starten, kwam in een onverwachte toestand of stopte voordat de sessie werd afgesloten (wat haar eigen afsluitcode ook was). Zo'n run draagt geen oordeel
5de bewerking is niet opgenomen in deze release
6de run is afgebroken - --timeout verliep, of de engine reageerde 15 seconden niet meer en werd gestopt. Dit is geen oordeel: de sessie is onderbroken, dus ze bewijst niets over het doel, in welke richting dan ook
7er loopt al een andere sessie - één sessie tegelijk. Opnieuw proberen zodra die klaar is, is genoeg
8de sessie kwam tot een oordeel, maar het bewijs staat niet in het bestand dat --report noemt - de schijf was vol, of een ander programma hield het oude bestand open, dat dan blijft zoals het was. Het oordeel staat nog steeds in het rapport dat de opdracht toont

Elke optie van beide commando's, en dezelfde tabel voor de calculator, staan in de opdrachtregelreferentie.

Begrensde runs

Een pipeline kan er niet op wachten dat een mens een desktopapplicatie sluit. --ticks N beëindigt de sessie na N hartslagen - elk één echte seconde - en meldt wat het tot dat moment heeft gevonden. De dekking wordt toch al in de eerste ogenblikken van het proces vastgesteld, dus een korte grens is meestal genoeg.

# Tien seconden, dan stoppen en rapporteren
chrono run ".\build\test.exe" --preset year-rollover --ticks 10 --report evidence.txt

Machine-uitvoer en bewijs

  • --json geeft de sessie als machineleesbare records in plaats van het rapport voor mensen - dezelfde feiten, inclusief de dekking per kanaal.
  • --report <path> schrijft het rapport voor mensen naar een bestand, wat een redelijk buildartefact is. Een sessie waarvan het oordeel iets anders is dan werkt opent dat bestand met een banner over onbetrouwbaar bewijs, in plaats van het voorbehoud onderaan te begraven.
  • Ook de calculator begrijpt --json, zodat een pipeline de datum kan berekenen die ze nodig heeft en terugvoeren.
# De datum berekenen en dan op die datum draaien
chrono calc --base today --snap eom --json
chrono run ".\build\test.exe" --preset month-end --ticks 10 --json

Een stap, ongeveer

- name: Month-end behaviour
  shell: pwsh
  run: |
    .\chrono.exe run ".\build\test.exe" --preset month-end --ticks 10 --report evidence.txt
    # een afsluitcode ongelijk aan nul betekent dat de vervanging niet is aangeslagen, dus de
    # test hierna zou niets hebben bewezen

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

Twee eerlijke kanttekeningen over runners

  • Het heeft een Windows-runner nodig. Er is geen Linux- of macOS-build, en die komt er niet - op Linux dekt libfaketime dit al.
  • Antivirus op een gehoste runner kan de injectie blokkeren. De tijd verschuiven betekent een bibliotheek in het doelproces injecteren, een gedocumenteerde Windows-techniek die ook malware gebruikt. Een runner die dat blokkeert, levert een afsluitcode op die dat zegt in plaats van een vals slagen - maar het is iets om uit te zoeken voordat je erop vertrouwt.

Om dezelfde reden draait de end-to-end-suite van dit project op echte machines en niet op een gehoste runner. De continuous integration bouwt en unit-test alles, en de vervanging zelf wordt voor elke release met de hand beproefd op echte applicaties, zowel in 32-bits- als in 64-bitsbuilds.

Probeer het