host: the E2E drives armOffline's own releaser against a held row
Task 7 fix round 1, item 2. A sibling subtest arms a fresh moveCfg with armOffline over its own registry and data directory and calls the ReleaseHoldSeq it installed: the held row reads ready at the release's pair, the stage-requested marker is written, and a release that changes nothing writes no marker.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 file changed,
+45
−0
internal/host/movesoffline_e2e_test.go+45 −0
diff --git a/internal/host/movesoffline_e2e_test.go b/internal/host/movesoffline_e2e_test.go| index 6e5ae03e0..cdd63a704 100644 |
| --- a/internal/host/movesoffline_e2e_test.go |
| +++ b/internal/host/movesoffline_e2e_test.go |
| @@ -1093,6 +1093,7 @@ func TestOfflineMoveE2E(t *testing.T) { |
| // today's ReleaseHold, whatever incarnation its held rows carry. |
| t.Run("claims on, open over a row of an older incarnation", func(t *testing.T) { offlineClaimsOnOlderRow(t, false) }) |
| t.Run("claims on, revert over a row of an older incarnation", func(t *testing.T) { offlineClaimsOnOlderRow(t, true) }) |
| + t.Run("armOffline's releaser", offlineArmedReleaser) |
| // Harness Run 9, finding 7: the doors driven with nothing between them |
| // but what production runs (each door's serial bump, the boxes' own |
| // nudges and the offline re-assert loop), first back to back, then with |
| @@ -1718,3 +1719,47 @@ func offlineClaimsOnOlderRow(t *testing.T, revert bool) { |
| } |
| } |
| +// The releaser armOffline installs, not a test override: it opens a held |
| +// row with the release's pair and touches the stage-requested marker. |
| +func offlineArmedReleaser(t *testing.T) { |
| + dd := t.TempDir() |
| + reg, err := registry.Open(filepath.Join(dd, "registry.db")) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + t.Cleanup(func() { reg.Close() }) |
| + const op = "mv_abcdefghijklmnopqrstuvwxyz" |
| + if err := reg.Upsert(registry.Route{Host: offHost, Kind: "instance", Socket: "/s", Status: "landing", HoldOp: op, Incarnation: 1, ServingSeq: 1}); err != nil { |
| + t.Fatal(err) |
| + } |
| + cfg := moveCfg{} |
| + armOffline(&cfg, dd, reg, nil, nil, hostwrite.Config{}, func(string) string { return "" }) |
| + if cfg.ReleaseHoldSeq == nil || cfg.ReleaseHold == nil { |
| + t.Fatal("armOffline wires no releaser") |
| + } |
| + marker := filepath.Join(dd, stageRequestMarker) |
| + if lexists(marker) { |
| + t.Fatal("fixture: the stage marker exists before the release") |
| + } |
| + ok, err := cfg.ReleaseHoldSeq(offHost, op, registry.Pair{Incarnation: 1, ServingSeq: 2}) |
| + if err != nil || !ok { |
| + t.Fatalf("release: %v %v", ok, err) |
| + } |
| + rt, err := reg.Get(offHost) |
| + if err != nil || rt == nil || rt.Status != "ready" || rt.HoldOp != "" || rt.Incarnation != 1 || rt.ServingSeq != 2 { |
| + t.Fatalf("after the release: %+v %v", rt, err) |
| + } |
| + if !lexists(marker) { // the first request writes at once (stageThrottle) |
| + t.Fatal("the release did not touch the stage-requested marker") |
| + } |
| + // A release that changes nothing touches nothing. |
| + if err := os.Remove(marker); err != nil { |
| + t.Fatal(err) |
| + } |
| + if ok, err := cfg.ReleaseHoldSeq(offHost, op, registry.Pair{Incarnation: 1, ServingSeq: 2}); err != nil || ok { |
| + t.Fatalf("a second release: %v %v", ok, err) |
| + } |
| + if lexists(marker) { |
| + t.Fatal("a release that changed nothing touched the marker") |
| + } |
| +} |