Artifact cb8f34098b0ee730dcddc1ab88eba786a902d9ee47a8eb7d3edc211914a20c08:
- File
internal/xfer/xfer_test.go
— part of check-in
[31b695c5cb]
at
2026-08-15 21:30:33
on branch trunk
— xfer: sync fronting (0001 §7 v1 slice)
POST /r/{repo} (+/xfer alias) proxies to lazily-started per-repo zit serve children; dead children restart on the next request. E2E: clone through quarry, push back, watcher folds the push. Push auth waits for the forge-OLTP slice; leases stay v-next. (user: dmestas, size: 3023) [annotate] [blame] [check-ins using]
package xfer import ( "net/http" "net/http/httptest" "os" "os/exec" "path/filepath" "strings" "testing" ) func zrun(t *testing.T, dir string, args ...string) string { t.Helper() cmd := exec.Command("zit", args...) cmd.Dir = dir out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("zit %v: %v\n%s", args, err, out) } return string(out) } // TestCloneAndPushThroughFronter is the 0001 §7 acceptance: `zit clone // <quarry>/r/<repo>` works, and a push through the same URL lands // artifacts in the fronted store. func TestCloneAndPushThroughFronter(t *testing.T) { if _, err := exec.LookPath("zit"); err != nil { t.Skip("zit not on PATH") } origin := t.TempDir() zrun(t, origin, "init") if err := os.WriteFile(filepath.Join(origin, "README.md"), []byte("# fronted\n"), 0o644); err != nil { t.Fatal(err) } zrun(t, origin, "add", "README.md") zrun(t, origin, "commit", "-m", "first") f := New() defer f.Close() f.Register("alpha", origin) mux := http.NewServeMux() mux.Handle("POST /r/{repo}", f) mux.Handle("POST /r/{repo}/xfer", f) srv := httptest.NewServer(mux) defer srv.Close() // Clone through quarry: the repo URL is used verbatim by zit. work := t.TempDir() clone := filepath.Join(work, "clone") zrun(t, work, "clone", srv.URL+"/r/alpha", clone) if tl := zrun(t, clone, "timeline", "-n", "3"); !strings.Contains(tl, "first") { t.Fatalf("clone missing history:\n%s", tl) } // Push back through the same URL (saved as the clone's remote). if err := os.WriteFile(filepath.Join(clone, "NOTES.md"), []byte("pushed\n"), 0o644); err != nil { t.Fatal(err) } zrun(t, clone, "add", "NOTES.md") zrun(t, clone, "commit", "-m", "pushed through quarry") zrun(t, clone, "push") if tl := zrun(t, origin, "timeline", "-n", "3"); !strings.Contains(tl, "pushed through quarry") { t.Fatalf("push did not land in origin:\n%s", tl) } // The /xfer alias answers too. zrun(t, work, "clone", srv.URL+"/r/alpha/xfer", filepath.Join(work, "clone2")) // Unknown repos 404 rather than 502. resp, err := http.Post(srv.URL+"/r/nope", "application/x-fossil", strings.NewReader("")) if err != nil { t.Fatal(err) } resp.Body.Close() if resp.StatusCode != http.StatusNotFound { t.Fatalf("unknown repo: status %d", resp.StatusCode) } } // TestBackendRestartAfterDeath: a dead child is restarted on the next // request instead of 502ing forever. func TestBackendRestartAfterDeath(t *testing.T) { if _, err := exec.LookPath("zit"); err != nil { t.Skip("zit not on PATH") } origin := t.TempDir() zrun(t, origin, "init") f := New() defer f.Close() f.Register("alpha", origin) mux := http.NewServeMux() mux.Handle("POST /r/{repo}", f) srv := httptest.NewServer(mux) defer srv.Close() work := t.TempDir() zrun(t, work, "clone", srv.URL+"/r/alpha", filepath.Join(work, "c1")) // Kill the child behind its back. f.mu.Lock() b := f.repos["alpha"] b.cmd.Process.Kill() f.mu.Unlock() zrun(t, work, "clone", srv.URL+"/r/alpha", filepath.Join(work, "c2")) }