Artifact 55c1b0c6b5db779cf030afd2c2ed5d465b7701906a0e84081210c0f406dba89d:
- File
internal/index/supersede_test.go
— part of check-in
[c2930a1351]
at
2026-08-26 12:53:49
on branch landings-batch
— One open landing per branch: refuse the second, and agree which wins
zit#127 left this as 'probably yes, refused by name on the second' and neither side enforced it, so two threads naming one branch produced two open landings with nothing saying which accept should honour.
Both halves, because refusing is not enough: two peers can each open one in separate clones and both are valid artifacts when they meet. landing.open refuses by name; the fold picks the newest root as current and marks the rest, recomputed each fold so a record revives if the one that displaced it is settled.
Settled landings never take part — a later proposal for the same branch is a new proposal, not a correction of a finished one. Nothing is deleted; a record somebody argued in is not noise. (user: dmestas, size: 4786) [annotate] [blame] [check-ins using] [more...]
package index import ( "testing" ) func landingOn(t *testing.T, ix *Index, root, branch, opened, title string) { t.Helper() foldForumBody(t, ix, root, "", title, opened, landingBody(branch, "trunk", "please")) } // zit#127 left one-open-landing-per-branch as "probably yes, refused by // name on the second" and neither side enforced it. Refusing at open // cannot be the whole answer: two people can open a landing for one // branch in separate clones, and both are ordinary forum threads that // are valid artifacts when they meet. So the readers agree instead. func TestSecondOpenLandingOnABranchIsSuperseded(t *testing.T) { ix := openIndex(t) landingOn(t, ix, "aaaa1111", "feat-x", "2026-01-01T10:00:00", "First try") landingOn(t, ix, "bbbb2222", "feat-x", "2026-01-05T10:00:00", "Second try") first := onlyOne(t, ix, "aaaa1111") second := onlyOne(t, ix, "bbbb2222") if second.SupersededBy != "" { t.Errorf("the newest landing was superseded by %q", second.SupersededBy) } if first.SupersededBy != "bbbb2222" { t.Errorf("the older landing defers to %q, want bbbb2222", first.SupersededBy) } // The open queue is a work list and shows one per branch... open, err := ix.Landings("open", 0) if err != nil { t.Fatal(err) } if len(open) != 1 || open[0].ID != "bbbb2222" { t.Fatalf("open queue holds %d landings, want just the current one", len(open)) } // ...and nothing is lost: the record and its discussion remain. all, _ := ix.Landings("", 0) if len(all) != 2 { t.Fatalf("the superseded record disappeared: %d listed, want 2", len(all)) } } func onlyOne(t *testing.T, ix *Index, id string) LandingSummary { t.Helper() l, ok, err := ix.Landing(id) if err != nil || !ok { t.Fatalf("landing %s: ok=%v err=%v", id, ok, err) } return l } // Recomputed every fold rather than accumulated, so a record can become // current again when the one that displaced it is settled. func TestSupersedingIsRecomputedNotAccumulated(t *testing.T) { ix := openIndex(t) landingOn(t, ix, "aaaa1111", "feat-x", "2026-01-01T10:00:00", "First try") landingOn(t, ix, "bbbb2222", "feat-x", "2026-01-05T10:00:00", "Second try") if l := onlyOne(t, ix, "aaaa1111"); l.SupersededBy != "bbbb2222" { t.Fatalf("precondition: %+v", l) } // The newer one is rejected, so it is no longer open. foldForumBody(t, ix, "cccc3333", "bbbb2222", "", "2026-01-06T10:00:00", landingState("rejected", "not this")) if l := onlyOne(t, ix, "aaaa1111"); l.SupersededBy != "" { t.Errorf("the surviving open landing is still marked superseded by %q", l.SupersededBy) } if open, _ := ix.Landings("open", 0); len(open) != 1 || open[0].ID != "aaaa1111" { t.Errorf("open queue is %+v, want the revived first landing", open) } } // A settled landing is history and its check-in is on the target. A // later proposal for the same branch is a new proposal, not a // correction of a finished one. func TestSettledLandingsAreNeverSuperseded(t *testing.T) { ix := openIndex(t) landingOn(t, ix, "aaaa1111", "feat-x", "2026-01-01T10:00:00", "Landed already") foldForumBody(t, ix, "dddd4444", "aaaa1111", "", "2026-01-02T10:00:00", landingState("accepted", "in it goes")) landingOn(t, ix, "bbbb2222", "feat-x", "2026-01-05T10:00:00", "Round two") if l := onlyOne(t, ix, "aaaa1111"); l.SupersededBy != "" { t.Errorf("an ACCEPTED landing was superseded by %q", l.SupersededBy) } if l := onlyOne(t, ix, "bbbb2222"); l.SupersededBy != "" { t.Errorf("the new proposal was superseded by %q", l.SupersededBy) } } // One landing on a branch is the ordinary case and must stay untouched. func TestASingleLandingIsNeverMarked(t *testing.T) { ix := openIndex(t) landingOn(t, ix, "aaaa1111", "feat-x", "2026-01-01T10:00:00", "Only one") landingOn(t, ix, "bbbb2222", "feat-y", "2026-01-02T10:00:00", "Different branch") for _, id := range []string{"aaaa1111", "bbbb2222"} { if l := onlyOne(t, ix, id); l.SupersededBy != "" { t.Errorf("%s marked superseded by %q with no rival on its branch", id, l.SupersededBy) } } if open, _ := ix.Landings("open", 0); len(open) != 2 { t.Errorf("open queue holds %d, want both", len(open)) } } // The courtesy check the writer makes before opening a second. func TestOpenLandingOnFindsTheCurrentOne(t *testing.T) { ix := openIndex(t) if _, found, err := ix.OpenLandingOn("feat-x"); found || err != nil { t.Fatalf("empty index: found=%v err=%v", found, err) } landingOn(t, ix, "aaaa1111", "feat-x", "2026-01-01T10:00:00", "First try") landingOn(t, ix, "bbbb2222", "feat-x", "2026-01-05T10:00:00", "Second try") l, found, err := ix.OpenLandingOn("feat-x") if err != nil || !found { t.Fatalf("found=%v err=%v", found, err) } if l.ID != "bbbb2222" { t.Errorf("the check names %q, want the current landing", l.ID) } }