1
0
Fork 0
mirror of https://github.com/imjasonh/infinite-git synced 2026-07-08 17:15:37 +00:00

Add end-to-end go get test on :80

Add TestGoGetE2E that binds to 127.0.0.1:80 and runs real
`go get 127.0.0.1@latest` against the server. Each iteration uses a
fresh module cache and verifies it gets a unique PullTime. Skips
gracefully when :80 can't be bound.

https://claude.ai/code/session_01HpvELk7HnbJoXEUjqHP7SU
This commit is contained in:
Claude 2026-04-03 12:15:40 +00:00
parent 4455b83a47
commit 89734da0dd
No known key found for this signature in database

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"net"
"net/http"
"net/http/httptest"
"os"
@ -27,6 +28,110 @@ func newGoTestServer(t *testing.T, modulePath string) *httptest.Server {
return ts
}
// newGoTestServerOnPort starts a test server bound to 127.0.0.1:port.
// It skips the test if the port cannot be bound (e.g. no permission for :80).
func newGoTestServerOnPort(t *testing.T, modulePath string, port int) *httptest.Server {
t.Helper()
ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
t.Skipf("cannot bind to :%d: %v", port, err)
}
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.NewUnstartedServer(goGetMiddleware(modulePath, srv.Handler()))
ts.Listener = ln
ts.Start()
t.Cleanup(ts.Close)
return ts
}
// TestGoGetE2E runs `go get 127.0.0.1@latest` against the server on :80.
// This is the full end-to-end test of the Go module workflow.
// Skipped when :80 cannot be bound (requires CAP_NET_BIND_SERVICE or root).
func TestGoGetE2E(t *testing.T) {
goBin, err := exec.LookPath("go")
if err != nil {
t.Skip("go binary not found in PATH")
}
modulePath := "127.0.0.1"
newGoTestServerOnPort(t, modulePath, 80)
var pullTimes []string
for i := 0; i < 3; i++ {
modCache := t.TempDir()
workDir := t.TempDir()
if err := os.WriteFile(filepath.Join(workDir, "go.mod"), []byte("module test\n\ngo 1.24\n"), 0644); err != nil {
t.Fatalf("iteration %d: failed to write go.mod: %v", i, err)
}
if err := os.WriteFile(filepath.Join(workDir, "tools.go"), []byte(fmt.Sprintf("package tools\n\nimport _ \"%s\"\n", modulePath)), 0644); err != nil {
t.Fatalf("iteration %d: failed to write tools.go: %v", i, err)
}
cmd := exec.Command(goBin, "get", modulePath+"@latest")
cmd.Dir = workDir
cmd.Env = append(os.Environ(),
"GOMODCACHE="+modCache,
"GOPROXY=direct",
"GONOSUMCHECK=*",
"GONOSUMDB=*",
"GOINSECURE="+modulePath,
)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go get #%d failed: %v\noutput: %s", i+1, err, out)
}
t.Logf("go get #%d succeeded", i+1)
// Find pulltime.go in the module cache.
var pulltimeFile string
filepath.Walk(modCache, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.Name() == "pulltime.go" {
pulltimeFile = path
return filepath.SkipAll
}
return nil
})
if pulltimeFile == "" {
t.Fatalf("go get #%d: pulltime.go not found in module cache", i+1)
}
data, err := os.ReadFile(pulltimeFile)
if err != nil {
t.Fatalf("go get #%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("go get #%d: %s", i+1, strings.TrimSpace(line))
break
}
}
}
if len(pullTimes) != 3 {
t.Fatalf("expected 3 PullTime values, got %d", len(pullTimes))
}
seen := make(map[string]bool)
for i, pt := range pullTimes {
if seen[pt] {
t.Errorf("go get #%d returned duplicate PullTime: %s", i+1, pt)
}
seen[pt] = true
}
}
// 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.