repo-sync/server/trace_test.go
James Coleman 5af1dd8928
Some checks failed
Go package / build (push) Has been cancelled
first commit
2026-07-28 19:22:20 -05:00

137 lines
4 KiB
Go

package server
import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
cfg "github.com/grmrgecko/repo-sync/config"
"github.com/grmrgecko/repo-sync/internal/testrepos"
"github.com/grmrgecko/repo-sync/mirror"
"github.com/grmrgecko/repo-sync/state"
)
// traceFixture builds an upstream apk repository that publishes a trace of
// its own, configures the mirror server against it with tracing enabled,
// and returns the mirror's test server and the online root.
func traceFixture(t *testing.T) (*httptest.Server, string) {
t.Helper()
www := t.TempDir()
repo := filepath.Join(www, "alpine", "v3.24", "main", "x86_64")
testrepos.BuildApkRepo(t, repo)
testrepos.WriteFile(t, filepath.Join(repo, filepath.FromSlash(mirror.TraceDir), "origin.example.net"),
[]byte("origin trace\n"))
upstream := testrepos.ServeDir(t, www)
onlineRoot := t.TempDir()
confDir := t.TempDir()
conf := fmt.Sprintf(`
state_path: %s/state.yaml
domains:
- domain: 127.0.0.1
role: online
root: %s
mounts:
- path: /
upstream: %s
trace:
enabled: true
host: mirror.example.com
maintainer: Test Maintainer <test@example.com>
`, confDir, onlineRoot, upstream.URL)
confPath := filepath.Join(confDir, "config.yaml")
testrepos.WriteFile(t, confPath, []byte(conf))
if err := cfg.Init(confPath); err != nil {
t.Fatal(err)
}
if err := state.Load(); err != nil {
t.Fatal(err)
}
srv := httptest.NewServer(Handler())
t.Cleanup(srv.Close)
t.Cleanup(WaitCrawls)
return srv, onlineRoot
}
// TestServeCrawlWritesTrace verifies a server crawl publishes this mirror's
// trace and mirrors upstream's, and that both are then served like any
// other repository file.
func TestServeCrawlWritesTrace(t *testing.T) {
srv, onlineRoot := traceFixture(t)
repo := "/alpine/v3.24/main/x86_64"
resp, _ := get(t, srv, "", repo+"/APKINDEX.tar.gz")
if resp.StatusCode != http.StatusOK {
t.Fatalf("index status = %d", resp.StatusCode)
}
traceDir := filepath.Join(onlineRoot, filepath.FromSlash(repo[1:]), filepath.FromSlash(mirror.TraceDir))
own := filepath.Join(traceDir, "mirror.example.com")
waitFor(t, "crawl trace", func() bool {
_, err := os.Stat(own)
return err == nil
})
data, err := os.ReadFile(own)
if err != nil {
t.Fatal("reading trace:", err)
}
trace := string(data)
for _, want := range []string{
"Running on host: mirror.example.com",
"Maintainer: Test Maintainer <test@example.com>",
"Repository type: apk",
"Total bytes received: ",
} {
if !strings.Contains(trace, want) {
t.Errorf("trace missing %q\ngot:\n%s", want, trace)
}
}
if upstreamTrace, err := os.ReadFile(filepath.Join(traceDir, "origin.example.net")); err != nil {
t.Error("upstream trace not mirrored:", err)
} else if string(upstreamTrace) != "origin trace\n" {
t.Errorf("upstream trace = %q, want %q", upstreamTrace, "origin trace\n")
}
// The published traces are served from the crawled tree.
resp, body := get(t, srv, "", repo+"/"+mirror.TraceDir+"/mirror.example.com")
if resp.StatusCode != http.StatusOK {
t.Fatalf("trace request status = %d", resp.StatusCode)
}
if string(body) != trace {
t.Errorf("served trace does not match the published file\ngot:\n%s", body)
}
}
// TestTraceInfo verifies the configured trace section maps onto the mirror
// package's description of this mirror, including the host fallback.
func TestTraceInfo(t *testing.T) {
got := traceInfo(cfg.TraceConfig{
Host: "mirror.example.com",
Maintainer: "Jane <jane@example.com>",
Sponsor: "Example Inc",
Country: "US",
Location: "Texas",
Throughput: "10Gb",
})
want := mirror.TraceInfo{
Host: "mirror.example.com",
Maintainer: "Jane <jane@example.com>",
Sponsor: "Example Inc",
Country: "US",
Location: "Texas",
Throughput: "10Gb",
}
if got != want {
t.Errorf("traceInfo = %+v, want %+v", got, want)
}
if host := traceInfo(cfg.TraceConfig{}).Host; host == "" {
t.Error("traceInfo left the host empty; the system hostname should stand in")
}
}