console: retirement tests: the refused create names its settling sentence, and an orphan retirement crashed before O1 recovers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+21
−2
internal/console/lifetimes_retire_test.go+21 −2
diff --git a/internal/console/lifetimes_retire_test.go b/internal/console/lifetimes_retire_test.go| index 9661d77bf..48782f752 100644 |
| --- a/internal/console/lifetimes_retire_test.go |
| +++ b/internal/console/lifetimes_retire_test.go |
| @@ -893,6 +893,25 @@ func TestRetirementRecoveryBranches(t *testing.T) { |
| writeSlot(t, l.fx.rel, ltOne, provision.HostIncarnation{Incarnation: 1, State: provision.SlotLive, Account: "bab", App: ltApp, Intent: "create someone-else"}) |
| l.recoveredTo(t, r.OpID, lifetimePending) |
| }) |
| + t.Run("orphan, crashed right after BeginRetirement", func(t *testing.T) { |
| + l := newLtOn(t) |
| + writeSlot(t, l.fx.rel, ltOne, provision.HostIncarnation{Incarnation: 1, State: provision.SlotLive, Account: "bab", App: ltApp, Intent: "create lost"}) |
| + // O1's slot write fails: the row is durable and nothing else moved. |
| + l.bucket.setHook(failNth("put", provision.HostIncarnationKey(ltOne), 1, false)) |
| + if err := retireOn(t, l.fx.srv, ltOne, retireAny); !errors.Is(err, errLifetimePending) { |
| + t.Fatalf("retire = %v, want pending", err) |
| + } |
| + l.bucket.setHook(nil) |
| + r := lastRetirement(t, l.fx.st, ltOne) |
| + if r.Kind != retireOrphan || r.State != lifetimePending { |
| + t.Fatalf("retirement = %+v, want a pending orphan", r) |
| + } |
| + if slot, _ := slotOf(t, l.fx.rel, ltOne); slot == nil || slot.State != provision.SlotLive { |
| + t.Fatalf("slot = %+v, want it still live before O1", slot) |
| + } |
| + l.recoveredTo(t, r.OpID, lifetimeCommitted) |
| + requireRetired(t, l.fx.rel, ltApp, ltOne, 1) |
| + }) |
| for _, step := range []string{"c1", "c2"} { |
| t.Run("cleanup, crashed at "+step, func(t *testing.T) { |
| l := newLtOn(t) |
| @@ -1221,8 +1240,8 @@ func TestOrphanSlotReclaimedByTheNextCreate(t *testing.T) { |
| if err := l.fx.st.BeginRetirement(Retirement{OpID: "held", Kind: retireNormal, Account: "bab", App: "web", Host: ltOne, Incarnation: 1}); err != nil { |
| t.Fatal(err) |
| } |
| - if code, body := l.create(t, ltOne); code != http.StatusConflict { |
| - t.Fatalf("create = %d %s, want 409", code, body) |
| + if code, body := l.create(t, ltOne); code != http.StatusConflict || ltErr(body) != msgLifetimeSettling { |
| + t.Fatalf("create = %d %s, want 409 %q", code, body, msgLifetimeSettling) |
| } |
| if rows := allocRows(t, l.fx.st, ltOne); len(rows) != 0 { |
| t.Fatalf("allocations = %+v, want none", rows) |