You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 line
5.4KB

  1. # E08-S01: harness self-tests. These prove the mechanics without starting an
  2. # emulator: fresh build directories, a wall-clock limit, machine-readable
  3. # results, artifact comparison, and a failed run that names the suite and its
  4. # observed signature.
  5. [CmdletBinding()]
  6. param()
  7. $ErrorActionPreference = "Stop"
  8. $project = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
  9. $harness = Join-Path $PSScriptRoot "run-regression.ps1"
  10. $root = Join-Path $project "build\regression-selftest"
  11. $suites = Join-Path $root "suites"
  12. $buildRoot = Join-Path $root "build"
  13. $baseline = Join-Path $root "baseline.json"
  14. $results = Join-Path $root "results.json"
  15. $manifest = Join-Path $root "suites.ps1"
  16. if (Test-Path -LiteralPath $root) { Remove-Item -LiteralPath $root -Recurse -Force }
  17. New-Item -ItemType Directory -Force -Path $suites, $buildRoot | Out-Null
  18. function Write-Suite([string]$Name, [string]$Body) {
  19. [IO.File]::WriteAllText((Join-Path $suites $Name), $Body,
  20. [Text.UTF8Encoding]::new($false))
  21. }
  22. # A passing suite writes one artifact and prints a stable success marker.
  23. Write-Suite "ok.ps1" @'
  24. $out = Join-Path (Split-Path $PSScriptRoot -Parent) "build\self-ok"
  25. New-Item -ItemType Directory -Force -Path $out | Out-Null
  26. [IO.File]::WriteAllBytes((Join-Path $out "self.prg"), [byte[]](1, 2, 3, 4))
  27. Write-Host "verified self ok"
  28. exit 0
  29. '@
  30. # A failing suite prints a diagnosis the harness must surface.
  31. Write-Suite "bad.ps1" @'
  32. Write-Host "self fixture ALPHA differs at token 7 (observed signature DEAD)"
  33. exit 3
  34. '@
  35. # A hanging suite must be stopped by the wall-clock limit.
  36. Write-Suite "slow.ps1" @'
  37. Start-Sleep -Seconds 60
  38. Write-Host "should never finish"
  39. exit 0
  40. '@
  41. # A suite whose artifact content changes between runs.
  42. Write-Suite "changed.ps1" @'
  43. param()
  44. $out = Join-Path (Split-Path $PSScriptRoot -Parent) "build\self-changed"
  45. New-Item -ItemType Directory -Force -Path $out | Out-Null
  46. $value = 5
  47. if (Test-Path (Join-Path $out "bump.txt")) { $value = 6 }
  48. [IO.File]::WriteAllText((Join-Path $out "bump.txt"), "$value")
  49. [IO.File]::WriteAllBytes((Join-Path $out "self.err"), [byte[]]$value)
  50. Write-Host "verified self changed"
  51. exit 0
  52. '@
  53. [IO.File]::WriteAllText($manifest, @'
  54. @(
  55. @{ Name = "ok"; Script = "build\regression-selftest\suites\ok.ps1"; BuildDir = "self-ok"; Timeout = 60; Success = "verified self ok"; Artifacts = @("*.prg") }
  56. @{ Name = "bad"; Script = "build\regression-selftest\suites\bad.ps1"; Timeout = 60 }
  57. @{ Name = "slow"; Script = "build\regression-selftest\suites\slow.ps1"; Timeout = 3 }
  58. @{ Name = "changed"; Script = "build\regression-selftest\suites\changed.ps1"; BuildDir = "self-changed"; Timeout = 60; Artifacts = @("*.err") }
  59. )
  60. '@, [Text.UTF8Encoding]::new($false))
  61. function Invoke-Harness([string[]]$Extra) {
  62. # The call operator quotes arguments that contain spaces itself. Embedding
  63. # quotes here breaks PowerShell 7.3+, which escapes them into the path.
  64. $arguments = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $harness,
  65. "-Manifest", $manifest, "-BuildRoot", $buildRoot,
  66. "-Baseline", $baseline, "-Results", $results) + $Extra
  67. $output = & (Get-Command powershell).Source @arguments 2>&1 | Out-String
  68. return @{ Output = $output; Code = $LASTEXITCODE }
  69. }
  70. function Get-Report { Get-Content -Raw -LiteralPath $results | ConvertFrom-Json }
  71. function Get-Entry([object]$Report, [string]$Name) {
  72. return $Report.suites | Where-Object { $_.name -eq $Name }
  73. }
  74. # 1: passing suite, artifact recorded, baseline written and matched on a rerun.
  75. $first = Invoke-Harness @("-UpdateBaseline")
  76. if (-not (Test-Path -LiteralPath $results)) { throw "first harness run wrote no results:`n$($first.Output)" }
  77. $report = Get-Report
  78. if ($report.passed -ne 2) { throw "expected 2 passing suites, got $($report.passed)" }
  79. $ok = Get-Entry $report "ok"
  80. if ($ok.artifacts.Count -ne 1 -or $ok.artifacts[0].status -ne "new") {
  81. throw "the passing suite did not record its artifact"
  82. }
  83. if (-not (Test-Path -LiteralPath $baseline)) { throw "-UpdateBaseline wrote no baseline" }
  84. $second = Invoke-Harness @("-NoFresh")
  85. $ok = Get-Entry (Get-Report) "ok"
  86. if ($ok.artifacts[0].status -ne "match") {
  87. throw "a rerun did not match the recorded artifact:`n$($second.Output)"
  88. }
  89. # 2: a failing suite names the suite and the observed signature.
  90. $bad = Get-Entry (Get-Report) "bad"
  91. if ($bad.status -ne "fail" -or $bad.signature -notmatch "ALPHA differs") {
  92. throw "the failing suite did not report its signature: $($bad.signature)"
  93. }
  94. $slow = Get-Entry (Get-Report) "slow"
  95. if ($slow.status -ne "fail" -or -not $slow.timedOut) {
  96. throw "the hanging suite was not stopped by the time limit"
  97. }
  98. if ($second.Code -eq 0) { throw "the harness reported success with failing suites" }
  99. # 3: an artifact whose bytes change is reported as changed on the next run.
  100. $third = Invoke-Harness @("-NoFresh")
  101. $changed = Get-Entry (Get-Report) "changed"
  102. if ($third.Code -eq 0 -or $changed.artifacts[0].status -ne "changed") {
  103. throw "a changed artifact was not detected:`n$($third.Output)"
  104. }
  105. # 4: results are machine-readable and identify the suite and its log.
  106. if (-not $report.startedAt -or -not $report.finishedAt) { throw "results lack timestamps" }
  107. foreach ($entry in $report.suites) {
  108. if (-not $entry.log -or -not (Test-Path -LiteralPath $entry.log)) {
  109. throw "suite $($entry.name) has no captured log"
  110. }
  111. }
  112. Write-Host "regression harness tests passed"
  113. Write-Host "pass/fail/timeout/artifact-change detection, JSON results, captured logs"

Powered by TurnKey Linux.