carlos / platform Public

e2e: the reclaim witness's empty reason only for the unreadable holder; the recreated and two-moves witnesses say what they leave to other witnesses

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 0b27dfb967ca45abe94c41a9f5104106126980ad parent 359a6e9
1 file changed, +19 −13
  • internal/e2e/selfserve/selfserve_rows_test.go +19 −13
diff --git a/internal/e2e/selfserve/selfserve_rows_test.go b/internal/e2e/selfserve/selfserve_rows_test.go
index ec945e62d..2ea8622b3 100644
--- a/internal/e2e/selfserve/selfserve_rows_test.go
+++ b/internal/e2e/selfserve/selfserve_rows_test.go
@@ -102,7 +102,11 @@ func (w *jobWorld) lifetimeHost(hostname string, inc uint64) {
// finishes the row aborted "the instance was recreated" and never writes
// the new lifetime's record (no move, its sequence unchanged); nothing
// stays reserved; and the member's poll of the new instance shows nothing
-// of the old lifetime's move.
+// of the old lifetime's move. This is reconciliation's "gone" path (the
+// row's lifetime has no record before any write); a recreation between a
+// request's issue and its bound write, refused on the incarnation at the
+// write, is TestBoundWritesNeverLandAfterAVoid's "recreated at the same
+// sequence".
func TestSelfServeRecreatedBetweenRowAndRecord(t *testing.T) {
w := newMemberWorld(t)
id := w.prepare()
@@ -128,7 +132,10 @@ func TestSelfServeRecreatedBetweenRowAndRecord(t *testing.T) {
// the two boxes. A second instance's move on the same boxes waits before
// it reserves, its poll saying why; a third instance's move on two other
// boxes reserves at once, beside the first. Once the first is done and its
-// boxes released, the second takes them. The orderings on their own are
+// boxes released, the second takes them. The second and third rows are
+// admitted directly (admitFor), not through the member's door: their hosts
+// are fixture records with no replica on any box, so the door's source
+// facts could never pass. The orderings on their own are
// TestTwoMovesOnOneBoxQueueInOrder, TestTwoMovesOnDisjointBoxesRunAtOnce
// and TestQueueOrderAndDisjointProgress.
func TestSelfServeTwoMovesDisjointAndQueued(t *testing.T) {
@@ -212,9 +219,10 @@ func TestSelfServeReservationReclaimOnlyOnEvidence(t *testing.T) {
entry := func(w *jobWorld, at time.Time) moves.OfflineReservation {
return moves.OfflineReservation{Kind: moves.OfflineKindMove, ID: orphan, Host: holder, Account: w.acct, App: host.E2EApp, ReservedAt: at}
}
- // waits is the member's move kept in reserving over ticks, the entry
- // kept, its poll saying why.
- waits := func(w *jobWorld, id string) {
+ // waits is the member's move kept in reserving over ticks with the
+ // entry kept, its row saying reason ("" for an unreadable holder: the
+ // job retries the reservation on the next tick without one).
+ waits := func(w *jobWorld, id, reason string) {
w.t.Helper()
for i := 0; i < 3; i++ {
w.boxes()
@@ -224,13 +232,11 @@ func TestSelfServeReservationReclaimOnlyOnEvidence(t *testing.T) {
switch {
case r.Phase != "reserving" || !w.reservedBy(orphan) || w.reservedBy(id):
w.t.Fatalf("the holder's entry was not kept: %s, reservations %v", describe(r), w.reservations())
- case r.Reason != "waiting for another move on this box":
- // The unreadable holder is retried without a reason.
- if r.Reason != "" {
- w.t.Fatalf("the waiting move's reason %q", r.Reason)
- }
+ case r.Reason != reason:
+ w.t.Fatalf("the waiting move's reason %q, want %q", r.Reason, reason)
}
}
+ const busy = "waiting for another move on this box"
// reclaimed is the member's move past reserving on its own entry.
reclaimed := func(w *jobWorld, id string) {
w.t.Helper()
@@ -247,7 +253,7 @@ func TestSelfServeReservationReclaimOnlyOnEvidence(t *testing.T) {
{"no evidence: reclaimed after the fence", func(w *jobWorld) {}, nil},
{"young: kept, then reclaimed once old", func(w *jobWorld) {}, func(w *jobWorld, id string) {
w.putEntry(w.e.Box(host.E2ESourceBox).BoxID(), entry(w, time.Now().UTC()))
- waits(w, id)
+ waits(w, id, busy)
w.putEntry(w.e.Box(host.E2ESourceBox).BoxID(), entry(w, old))
}},
{"the holder's record carries the move: kept, nothing written", func(w *jobWorld) {
@@ -259,7 +265,7 @@ func TestSelfServeReservationReclaimOnlyOnEvidence(t *testing.T) {
}
}, func(w *jobWorld, id string) {
seq := w.recordOf(holder).RecordSeq
- waits(w, id)
+ waits(w, id, busy)
if got := w.recordOf(holder).RecordSeq; got != seq {
w.t.Fatalf("the live holder's record was written: seq %d, was %d", got, seq)
}
@@ -280,7 +286,7 @@ func TestSelfServeReservationReclaimOnlyOnEvidence(t *testing.T) {
if err != nil {
w.t.Fatal(err)
}
- waits(w, id)
+ waits(w, id, "")
if _, err := w.raw.Put(w.ctx, key, good, etag); err != nil {
w.t.Fatal(err)
}