Phase 12.J.E.3 — full Windows upgrade lifecycle E2E (6 tests)
Summary
- Drives the production
upgrade-windows-tentacle.ps1end-to-end against a realLocalReleaseMirror(zip +.sha256companion) + a realWindowsServiceFixture-installed Windows service; redirects$env:ProgramDatato a per-test temp dir solast-upgrade.json/upgrade.lock/upgrade.logwrites don't pollute the host. Tier🟢 high-fidelity (Rule 12). - Phase A (
Invoke-WebRequest+Get-FileHash+Expand-Archive) AND Phase B (Stop-Service+Move-Itemswap +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 missedEXPECTED_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.ps1covering 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.sha256companion files matching the served zip's actual SHA256. Cache-keyed by URL path so.zipand.sha256bytes match —ZipArchivetimestamps are non-deterministic across separate builds, which would otherwise cause spurious hash drift between requests. New configurables:StageSha256Override(body)+SuppressSha256Companion(). -
WindowsUpgradeE2ECategories.TentacleUpgradeLifecyclecategory + entry intentacle-windows-e2e.ymlworkflow 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-latestrunner via this PR's CI -
No regression in existing WindowsUpgradeWrapperE2E/WindowsUpgradeServiceE2E/WindowsUpgradeShaVerifyE2E/TentacleInstallScriptE2E/TentacleCapabilitiesE2Esuites — verified locally, 45/45 cross-platform pass -
No regression in Squid.UnitTestsWindowsTentacleUpgradeStrategy/UpgradeStatusPayloadtests — verified locally, 89/89 pass