package harness
import (
"encoding/json"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"testing"
"craftdesign.group/quarry/internal/api"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
// A strata says where a walk would stop before anything is pressed
// (1f8c4148). Three rungs, r1 → trunk, r2 → r1, r3 → r2; r2 edits the
// line trunk has since changed. Each rung probed against the one below
// is clean, and that was all the page could say. Probed as a stack onto
// trunk (zit#211), r1 lands, r2 stops on f.txt and r3 is not reached:
// the base's map says "would stop at 2/3" and the land control offers
// rung 1 alone, as such, never the whole strata.
func TestAStrataSaysWhereItWouldStop(t *testing.T) {
if _, err := exec.LookPath("zit"); err != nil {
t.Skip("zit not on PATH")
}
store := t.TempDir()
run := func(args ...string) {
t.Helper()
cmd := exec.Command("zit", args...)
cmd.Dir = store
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("zit %v: %v\n%s", args, err, out)
}
}
write := func(name, body string) {
t.Helper()
if err := os.WriteFile(filepath.Join(store, name), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
run("init")
write("f.txt", "one\ntwo\nthree\n")
run("add", "f.txt")
run("commit", "-m", "base", "--user", "dan")
write("a.txt", "a\n")
run("add", "a.txt")
run("commit", "-m", "rung one", "--branch", "r1", "--user", "dan")
write("f.txt", "one\nTWO-from-r2\nthree\n")
run("commit", "-m", "rung two", "--branch", "r2", "--user", "dan")
write("c.txt", "c\n")
run("add", "c.txt")
run("commit", "-m", "rung three", "--branch", "r3", "--user", "dan")
run("update", "trunk")
write("f.txt", "one\nTWO-from-trunk\nthree\n")
run("commit", "-m", "trunk moves", "--user", "dan")
run("landing", "open", "--branch", "r1", "-m", "rung one", "--user", "dan")
run("landing", "open", "--branch", "r2", "--to", "r1", "-m", "rung two", "--user", "dan")
run("landing", "open", "--branch", "r3", "--to", "r2", "-m", "rung three", "--user", "dan")
dataDir := t.TempDir()
srv := ingestAndServeAuth(t, map[string]string{"alpha": store}, dataDir,
func(repo, user, pass string, need ops.Auth) api.Decision {
if user == "" {
return api.Denied
}
return api.Allowed
})
odb, err := oltp.Open(filepath.Join(dataDir, "oltp.db"))
if err != nil {
t.Fatal(err)
}
defer odb.Close()
if err := odb.AddAccount("lander", "pw12345678", false); err != nil {
t.Fatal(err)
}
if err := odb.SetCaps("lander", "alpha", "oi"); err != nil {
t.Fatal(err)
}
get := func(path string) string {
t.Helper()
req, _ := http.NewRequest("GET", srv.URL+path, nil)
req.SetBasicAuth("lander", "pw12345678")
resp, err := srv.Client().Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
return string(b)
}
// The base is the rung whose record page names r1 as its branch.
list := get("/r/alpha/landing")
var base string
for _, id := range regexp.MustCompile(`/r/alpha/landing/([0-9a-f]{12,})"`).FindAllStringSubmatch(list, -1) {
if p := get("/r/alpha/landing/" + id[1]); strings.Contains(p, `data-hook="strata-preflight"`) &&
strings.Contains(p, `aria-current="true"`) && regexp.MustCompile(`class="here"[^>]*>\s*<span[^>]*>1/3<`).MatchString(p) {
base = id[1]
break
}
}
if base == "" {
t.Fatalf("FAIL: no landing page carries a pre-flight as rung 1/3; listing:\n%.2000s", list)
}
page := get("/r/alpha/landing/" + base)
if !strings.Contains(page, `data-hook="strata-preflight" data-stops="2"`) {
t.Fatalf("FAIL: the base's map does not say the walk stops at rung 2")
}
states := regexp.MustCompile(`data-hook="rung-preflight" data-state="([a-z-]+)"`).FindAllStringSubmatch(page, -1)
var got []string
for _, s := range states {
got = append(got, s[1])
}
if strings.Join(got, " ") != "clean conflict not-reached" {
t.Fatalf("FAIL: rung verdicts %v, want clean conflict not-reached", got)
}
if !strings.Contains(page, "<code>f.txt</code>") {
t.Error("FAIL: the rung that stops does not name its conflicting path")
}
// How far a walk would get is the op's answer; the page draws the
// control from it (the control itself is covered in web, where a
// viewer who may accept can be rendered).
req, _ := http.NewRequest("GET", srv.URL+"/api/v1/r/alpha/landing/"+base, nil)
req.SetBasicAuth("lander", "pw12345678")
resp, err := srv.Client().Do(req)
if err != nil {
t.Fatal(err)
}
var rec struct {
Stack struct {
Preflight string `json:"preflight"`
StopsAt int `json:"stopsAt"`
LandTo string `json:"landTo"`
LandCount int `json:"landCount"`
} `json:"stack"`
}
err = json.NewDecoder(resp.Body).Decode(&rec)
resp.Body.Close()
if err != nil {
t.Fatal(err)
}
if st := rec.Stack; st.Preflight != "stops" || st.StopsAt != 2 || st.LandCount != 1 || !strings.HasPrefix(st.LandTo, base) {
t.Fatalf("FAIL: landing.get stack %+v, want stops at 2, land 1 up to the base %s", st, base)
}
t.Logf("ok: base %s says would stop at 2/3 (clean, conflict on f.txt, not reached) and offers landing up to 1", base[:12])
}