mirror of
https://github.com/imjasonh/infinite-git
synced 2026-07-08 17:15:37 +00:00
Rewrite infinite-go tests to use git clone + go build
Replace the go-git library tests with tests that shell out to `git clone` and `git pull`, then verify each clone/pull produces a compilable Go package with a unique PullTime. This more closely simulates the real `go get @latest` with GOPROXY=direct flow. - TestGoGet: 3 fresh clones, each builds and has unique PullTime - TestGoGetPull: clone then 3 pulls, each builds and updates PullTime - TestGoGetDiscovery: ?go-get=1 returns correct go-import meta tag https://claude.ai/code/session_01HpvELk7HnbJoXEUjqHP7SU
This commit is contained in:
parent
96dd2d9604
commit
4455b83a47
1 changed files with 129 additions and 50 deletions
|
|
@ -5,17 +5,17 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/imjasonh/infinite-git/internal/repo"
|
||||
"github.com/imjasonh/infinite-git/internal/server"
|
||||
)
|
||||
|
||||
func TestGoCloneAndPull(t *testing.T) {
|
||||
modulePath := "example.com/infinite-go"
|
||||
func newGoTestServer(t *testing.T, modulePath string) *httptest.Server {
|
||||
t.Helper()
|
||||
content := newGoContent(modulePath)
|
||||
serverRepo, err := repo.New(t.TempDir(), content.InitialFiles())
|
||||
if err != nil {
|
||||
|
|
@ -23,70 +23,149 @@ func TestGoCloneAndPull(t *testing.T) {
|
|||
}
|
||||
srv := server.New(serverRepo, content)
|
||||
ts := httptest.NewServer(goGetMiddleware(modulePath, srv.Handler()))
|
||||
defer ts.Close()
|
||||
t.Cleanup(ts.Close)
|
||||
return ts
|
||||
}
|
||||
|
||||
// Clone the repository
|
||||
clientDir := t.TempDir()
|
||||
gitRepo, err := git.PlainClone(clientDir, false, &git.CloneOptions{
|
||||
URL: ts.URL,
|
||||
})
|
||||
// TestGoGet clones the infinite-go server repeatedly using git (which is what
|
||||
// `go get` does under the hood with GOPROXY=direct) and verifies that each
|
||||
// clone produces a valid, buildable Go package with a unique PullTime.
|
||||
func TestGoGet(t *testing.T) {
|
||||
goBin, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to clone: %v", err)
|
||||
t.Skip("go binary not found in PATH")
|
||||
}
|
||||
gitBin, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
t.Skip("git binary not found in PATH")
|
||||
}
|
||||
|
||||
// Verify go.mod exists with correct module path
|
||||
goMod, err := os.ReadFile(filepath.Join(clientDir, "go.mod"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read go.mod: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(goMod), fmt.Sprintf("module %s", modulePath)) {
|
||||
t.Errorf("go.mod does not contain expected module path, got: %s", goMod)
|
||||
modulePath := "example.com/infinite-go"
|
||||
ts := newGoTestServer(t, modulePath)
|
||||
|
||||
var pullTimes []string
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
cloneDir := t.TempDir()
|
||||
|
||||
// Clone via git — this is exactly what `go get` with GOPROXY=direct does.
|
||||
cmd := exec.Command(gitBin, "clone", ts.URL, cloneDir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("git clone #%d failed: %v\noutput: %s", i+1, err, out)
|
||||
}
|
||||
|
||||
// Verify go.mod has the right module path.
|
||||
goMod, err := os.ReadFile(filepath.Join(cloneDir, "go.mod"))
|
||||
if err != nil {
|
||||
t.Fatalf("clone #%d: failed to read go.mod: %v", i+1, err)
|
||||
}
|
||||
if !strings.Contains(string(goMod), fmt.Sprintf("module %s", modulePath)) {
|
||||
t.Fatalf("clone #%d: go.mod has wrong module path: %s", i+1, goMod)
|
||||
}
|
||||
|
||||
// Verify the package builds.
|
||||
cmd = exec.Command(goBin, "build", "./...")
|
||||
cmd.Dir = cloneDir
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("clone #%d: go build failed: %v\noutput: %s", i+1, err, out)
|
||||
}
|
||||
|
||||
// Read pulltime.go and extract the PullTime declaration.
|
||||
data, err := os.ReadFile(filepath.Join(cloneDir, "pulltime.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("clone #%d: failed to read pulltime.go: %v", i+1, err)
|
||||
}
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "var PullTime") {
|
||||
pullTimes = append(pullTimes, strings.TrimSpace(line))
|
||||
t.Logf("clone #%d: %s", i+1, strings.TrimSpace(line))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify pulltime.go exists with PullTime var
|
||||
goFile, err := os.ReadFile(filepath.Join(clientDir, "pulltime.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read pulltime.go: %v", err)
|
||||
}
|
||||
goFileStr := string(goFile)
|
||||
if !strings.Contains(goFileStr, "package infinitego") {
|
||||
t.Errorf("pulltime.go does not contain expected package name, got: %s", goFile)
|
||||
}
|
||||
if !strings.Contains(goFileStr, "var PullTime = time.Date(") {
|
||||
t.Errorf("pulltime.go does not contain PullTime var, got: %s", goFile)
|
||||
if len(pullTimes) != 3 {
|
||||
t.Fatalf("expected 3 PullTime values, got %d", len(pullTimes))
|
||||
}
|
||||
|
||||
// Pull again and verify PullTime changed
|
||||
firstGoFile := goFileStr
|
||||
w, err := gitRepo.Worktree()
|
||||
// Every clone must produce a unique PullTime.
|
||||
seen := make(map[string]bool)
|
||||
for i, pt := range pullTimes {
|
||||
if seen[pt] {
|
||||
t.Errorf("clone #%d returned duplicate PullTime: %s", i+1, pt)
|
||||
}
|
||||
seen[pt] = true
|
||||
}
|
||||
}
|
||||
|
||||
// TestGoGetPull verifies that git pull on an already-cloned repo also
|
||||
// produces a new PullTime.
|
||||
func TestGoGetPull(t *testing.T) {
|
||||
goBin, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get worktree: %v", err)
|
||||
t.Skip("go binary not found in PATH")
|
||||
}
|
||||
err = w.Pull(&git.PullOptions{RemoteName: "origin"})
|
||||
if err != nil && err != git.NoErrAlreadyUpToDate {
|
||||
t.Fatalf("pull failed: %v", err)
|
||||
}
|
||||
goFile, err = os.ReadFile(filepath.Join(clientDir, "pulltime.go"))
|
||||
gitBin, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read pulltime.go after pull: %v", err)
|
||||
t.Skip("git binary not found in PATH")
|
||||
}
|
||||
if string(goFile) == firstGoFile {
|
||||
t.Error("pulltime.go did not change after pull")
|
||||
|
||||
modulePath := "example.com/infinite-go"
|
||||
ts := newGoTestServer(t, modulePath)
|
||||
|
||||
cloneDir := t.TempDir()
|
||||
|
||||
// Initial clone.
|
||||
cmd := exec.Command(gitBin, "clone", ts.URL, cloneDir)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git clone failed: %v\noutput: %s", err, out)
|
||||
}
|
||||
|
||||
readPullTime := func() string {
|
||||
data, err := os.ReadFile(filepath.Join(cloneDir, "pulltime.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read pulltime.go: %v", err)
|
||||
}
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if strings.Contains(line, "var PullTime") {
|
||||
return strings.TrimSpace(line)
|
||||
}
|
||||
}
|
||||
t.Fatal("pulltime.go does not contain PullTime declaration")
|
||||
return ""
|
||||
}
|
||||
|
||||
prev := readPullTime()
|
||||
t.Logf("clone: %s", prev)
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
cmd := exec.Command(gitBin, "-C", cloneDir, "pull")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git pull #%d failed: %v\noutput: %s", i+1, err, out)
|
||||
}
|
||||
|
||||
// Verify it still builds.
|
||||
cmd = exec.Command(goBin, "build", "./...")
|
||||
cmd.Dir = cloneDir
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("pull #%d: go build failed: %v\noutput: %s", i+1, err, out)
|
||||
}
|
||||
|
||||
cur := readPullTime()
|
||||
t.Logf("pull #%d: %s", i+1, cur)
|
||||
if cur == prev {
|
||||
t.Errorf("pull #%d did not change PullTime", i+1)
|
||||
}
|
||||
prev = cur
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoGetDiscovery(t *testing.T) {
|
||||
modulePath := "example.com/infinite-go"
|
||||
content := newGoContent(modulePath)
|
||||
serverRepo, err := repo.New(t.TempDir(), content.InitialFiles())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create server repo: %v", err)
|
||||
}
|
||||
srv := server.New(serverRepo, content)
|
||||
ts := httptest.NewServer(goGetMiddleware(modulePath, srv.Handler()))
|
||||
defer ts.Close()
|
||||
ts := newGoTestServer(t, modulePath)
|
||||
|
||||
// Test ?go-get=1 returns go-import meta tag
|
||||
resp, err := http.Get(ts.URL + "/?go-get=1")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to fetch go-get: %v", err)
|
||||
|
|
@ -99,6 +178,6 @@ func TestGoGetDiscovery(t *testing.T) {
|
|||
|
||||
expected := fmt.Sprintf(`<meta name="go-import" content="%s git`, modulePath)
|
||||
if !strings.Contains(body, expected) {
|
||||
t.Errorf("go-get response does not contain expected meta tag.\nexpected to contain: %s\ngot: %s", expected, body)
|
||||
t.Errorf("go-get response missing expected meta tag.\nwant substring: %s\ngot: %s", expected, body)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue