test: end-to-end clone through a real listener
commit d095c08f9a8cbe60690bcc55f9a3df10964874f4 · parent 619b45eb15
· browse this tree
Ximianth, 2026-10-26 20:08:11 UTC
Three variants of an actual git clone against httptest: protocol v2 (the modern default), forced v0 (which needs the "# service=" preamble), and the .git-suffixed URL alias. Checkout content and HEAD sha are asserted against the fixture's pinned values. One trap worth recording: the server must be torn down via t.Cleanup, not defer, because parallel subtests outlive the parent function body (the deferred Close otherwise lands before any clone starts).
diff --git a/clone_test.go b/clone_test.go new file mode 100644 index 0000000..27ec4c4 --- /dev/null +++ b/clone_test.go @@ -0,0 +1,53 @@ +package main + +import ( + "net/http/httptest" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +// TestCloneEndToEnd runs real `git clone`s against a real listener: the whole point +// of the smart-HTTP endpoints, exercised by the actual client. +// Variants cover protocol v2 (a modern client's default), forced v0 (the preamble path), +// and the ".git"-suffixed URL alias. The client runs under the same hermetic env +// as fixture building, so no user config can steer its behavior. +func TestCloneEndToEnd(t *testing.T) { + t.Parallel() + srv := httptest.NewServer(fixtureServer(t)) + // Cleanup, not defer: the parallel subtests outlive this function body. + t.Cleanup(srv.Close) + for _, c := range []struct { + name string + suffix string + preArgs []string + }{ + {name: "protocol v2", suffix: ""}, + {name: "dot-git alias", suffix: ".git"}, + {name: "protocol v0", preArgs: []string{"-c", "protocol.version=0"}}, + } { + t.Run(c.name, func(t *testing.T) { + t.Parallel() + scratch := t.TempDir() + dest := filepath.Join(scratch, "clone") + args := append(c.preArgs, "clone", "-q", srv.URL+"/fixturama"+c.suffix, dest) + gitFixture(t, scratch, args...) + + got, err := os.ReadFile(filepath.Join(dest, "README.md")) + if err != nil || string(got) != fixtureReadme { + t.Errorf("cloned README = %q, %v; want the fixture README", got, err) + } + cmd := exec.Command("git", "-C", dest, "rev-parse", "HEAD") + cmd.Env = append(os.Environ(), fixtureEnv...) + out, err := cmd.Output() + if err != nil { + t.Fatalf("rev-parse in clone: %v", err) + } + if sha := strings.TrimSpace(string(out)); sha != fixtureShaMain { + t.Errorf("cloned HEAD = %s, want %s", sha, fixtureShaMain) + } + }) + } +}