package index
import (
"sort"
"strings"
"testing"
)
func landingRows(t *testing.T, ix *Index) string {
t.Helper()
rows, err := ix.db.Query(`SELECT id, state, claimed_by FROM landing`)
if err != nil {
t.Fatal(err)
}
defer rows.Close()
var out []string
for rows.Next() {
var id, st, cl string
rows.Scan(&id, &st, &cl)
out = append(out, id+"="+st+"/"+cl)
}
sort.Strings(out)
return strings.Join(out, " ")
}
// #263: on the edge path only open landings and those on a branch that
// gained a check-in are refolded, and that reads exactly what refolding
// every landing reads: a new merge settles an open landing, and a new
// check-in on a branch zit settled by containment un-settles it.
func TestTheEdgeLandingRefreshMatchesTheWholeOne(t *testing.T) {
ix := openIndex(t)
ci(t, ix, "t1", "trunk", "2026-01-01T09:00:00", "base")
landingOn(t, ix, "aaaa1111", "feat-a", "2026-01-01T10:00:00", "A")
ci(t, ix, "a1", "feat-a", "2026-01-01T11:00:00", "a work", "t1")
landingOn(t, ix, "bbbb1111", "feat-b", "2026-01-01T10:30:00", "B")
ci(t, ix, "b1", "feat-b", "2026-01-01T11:30:00", "b work", "t1")
ci(t, ix, "t2", "trunk", "2026-01-01T12:00:00", "fast-forward over b", "b1")
foldForumBody(t, ix, "bbbb2222", "bbbb1111", "", "2026-01-01T12:05:00", landingState("accepted", "merges up to date"))
refresh := func(edge bool, branches ...string) string {
t.Helper()
tx, err := ix.db.Begin()
if err != nil {
t.Fatal(err)
}
if edge {
err = refreshLandingStatesFor(tx, branches)
} else {
err = refreshLandingStates(tx)
}
if err != nil {
t.Fatal(err)
}
if err := tx.Commit(); err != nil {
t.Fatal(err)
}
return landingRows(t, ix)
}
refresh(false)
if got := landingRows(t, ix); !strings.Contains(got, "aaaa1111=open") || !strings.Contains(got, "bbbb1111=accepted") {
t.Fatalf("FAIL: the starting states read %s", got)
}
// A merge of feat-a on trunk: the open landing settles.
ci(t, ix, "m1", "trunk", "2026-01-02T10:00:00", "land feat-a", "t2", "a1")
edge := refresh(true, "trunk")
if whole := refresh(false); edge != whole || !strings.Contains(edge, "aaaa1111=accepted") {
t.Fatalf("FAIL: after a merge the edge refresh reads %s, the whole one %s", edge, whole)
}
// feat-b grows past trunk: its containment, and so its settling, ends.
ci(t, ix, "b2", "feat-b", "2026-01-02T11:00:00", "more b", "b1")
edge = refresh(true, "feat-b")
if whole := refresh(false); edge != whole || strings.Contains(edge, "bbbb1111=accepted") {
t.Fatalf("FAIL: after feat-b grew the edge refresh reads %s, the whole one %s", edge, whole)
}
}