Skip to content

Phase 12.J.E.3 — full Windows upgrade lifecycle E2E (6 tests)

Placeholder ppxd requested to merge phase12.J.E.3-upgrade-lifecycle into main

Summary

  • Drives the production upgrade-windows-tentacle.ps1 end-to-end against a real LocalReleaseMirror (zip + .sha256 companion) + a real WindowsServiceFixture-installed Windows service; redirects $env:ProgramData to a per-test temp dir so last-upgrade.json / upgrade.lock / upgrade.log writes don't pollute the host. Tier 🟢 high-fidelity (Rule 12).
  • Phase A (Invoke-WebRequest + Get-FileHash + Expand-Archive) AND Phase B (Stop-Service + Move-Item swap + Start-Service) run against real OS resources — closes the largest J.E. coverage gap (Section E was at 19% before this PR; 37% after).
  • 6 new tests + a drift detector that pins the placeholder set against production (caught a real bug in the regex during development — [A-Z_]+ silently missed EXPECTED_SHA256; documented inline for future operators).

Scenarios covered (matrix IDs)

ID Scenario Test
E1.h Full Phase A+B happy path → SUCCESS in last-upgrade.json E1h_FullLifecycle_HappyPath_WritesSuccessStatusAndSwapsBinary
E1.u1 / E5.u1 Download URL 404 → exit 2 + FAILED with download detail E1u1_DownloadVersionNotFound_ExitsTwoAndWritesFailedStatusWithDownloadDetail
E12.u1 SHA256 mismatch → exit 7 + FAILED + Phase B did NOT proceed E12u1_Sha256Mismatch_ExitsSevenAndWritesFailedStatusWithChecksumDetail
E8.h last-upgrade.json schema v2 round-trips through UpgradeStatusPayload.TryParse E8h_LastUpgradeJson_AfterSuccess_RoundTripsViaCapabilitiesProbe
E8.u1 6 corrupt-JSON shapes (empty / whitespace / non-JSON / truncated / wrong-shape / HTML error page) all return null without throwing E8u1_CorruptLastUpgradeJson_ParseReturnsNullWithoutThrow
(drift) .ps1 placeholder set pinned against test substitution map UpgradeScript_PlaceholderSet_PinnedToProductionContract

Coverage delta

  • vs WindowsUpgradeServiceE2E (Phase B inline mirror): that suite tests Stop/Move/Start mechanics in isolation. This suite runs the actual production .ps1 covering download, SHA fetch+verify, archive extract, AND swap+restart — catches regressions invisible to PhaseB.
  • vs WindowsUpgradeShaVerifyE2E: ShaVerify isolates the SHA-handling block. This suite proves SHA failures correctly abort before Phase B (security regression target — corrupt download must not get swapped in).

Infrastructure changes

  • LocalReleaseMirror: serves .sha256 companion files matching the served zip's actual SHA256. Cache-keyed by URL path so .zip and .sha256 bytes match — ZipArchive timestamps are non-deterministic across separate builds, which would otherwise cause spurious hash drift between requests. New configurables: StageSha256Override(body) + SuppressSha256Companion().
  • WindowsUpgradeE2ECategories.TentacleUpgradeLifecycle category + entry in tentacle-windows-e2e.yml workflow filter (Rule 12.6).

Matrix update

  • Section E: 6/32 → 12/32 (37%)
  • Grand total: 75 → 81 tests (40% covered)

Test plan

  • Cross-platform tests (drift detector + corrupt-JSON parse) pass on macOS — verified locally, 6/6 pass
  • Windows-only tests (E1.h / E1.u1 / E12.u1 / E8.h) verified on windows-latest runner via this PR's CI
  • No regression in existing WindowsUpgradeWrapperE2E / WindowsUpgradeServiceE2E / WindowsUpgradeShaVerifyE2E / TentacleInstallScriptE2E / TentacleCapabilitiesE2E suites — verified locally, 45/45 cross-platform pass
  • No regression in Squid.UnitTests WindowsTentacleUpgradeStrategy / UpgradeStatusPayload tests — verified locally, 89/89 pass

🤖 Generated with Claude Code

Merge request reports

Loading