package builder import ( "os" "os/exec" "path/filepath" "sync" "testing" ) // **A judge's build in a test starts from a warm Go cache** (novox/hq issue 717). The runtime these tests put on // PATH (aRuntimeThatBuildsTheJudge) runs the check's `go build` and `go test` on this machine with the Go cache the // check names — a fresh directory in every test — so each of them compiled the standard library from nothing: some // ten CPU-seconds a build, under twenty tests, half of the CPU the whole suite spent. The runtime now fills an empty // Go cache it is given from one this process warmed once, before it runs `go`; what the check names, mounts and // keeps is unchanged, and so is what each test reads of it. A cache entry is keyed by everything the compile // depends on, flags included, so a build with a planted -toolexec hook still misses it and still runs its hook. // // The warm cache lives beside the system's temporary directory as it was when the package started, never under a // TMPDIR a test set and then asserts left empty, and is removed when the package's tests end. var ( warmCacheBase = os.TempDir() warmCacheOnce sync.Once warmCacheDir string ) func TestMain(m *testing.M) { code := m.Run() if warmCacheDir != "" { _ = os.RemoveAll(warmCacheDir) } os.Exit(code) } // warmGoCache is a Go cache holding what a judge's build and the replays' `go test` compile of the standard // library, or "" when it cannot be warmed — a test then builds cold, as before, and is only slower. func warmGoCache(t *testing.T) string { t.Helper() warmCacheOnce.Do(func() { dir, err := os.MkdirTemp(warmCacheBase, "judge-warm-go-cache-") if err != nil { return } src := filepath.Join(dir, "src") files := map[string]string{ "go.mod": "module example.org/warm\n\ngo 1.22\n", "main.go": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() { fmt.Fprintln(os.Stdout, len(os.Args)) }\n", "main_test.go": "package main\n\nimport \"testing\"\n\nfunc TestWarm(t *testing.T) {}\n", } for name, body := range files { if err := os.MkdirAll(src, 0o755); err != nil { return } if err := os.WriteFile(filepath.Join(src, name), []byte(body), 0o644); err != nil { return } } cache := filepath.Join(dir, "go-cache") env := append(os.Environ(), "GOCACHE="+cache, "GOENV=off", "GOTOOLCHAIN=local", "GOPROXY=off", "GOWORK=off", "GOFLAGS=-buildvcs=false", "TMPDIR="+warmCacheBase) // As the check builds a judge (CGO off) and runs the replays (CGO as the toolchain has it). for _, run := range [][]string{ {"env", "CGO_ENABLED=0", "go", "build", "-o", filepath.Join(dir, "judge"), "."}, {"go", "test", "-count=1", "."}, } { cmd := exec.Command(run[0], run[1:]...) cmd.Dir, cmd.Env = src, env if out, err := cmd.CombinedOutput(); err != nil { t.Logf("the warm Go cache could not be built, so judges build cold: %v\n%s", err, out) _ = os.RemoveAll(dir) return } } warmCacheDir = dir }) if warmCacheDir == "" { return "" } return filepath.Join(warmCacheDir, "go-cache") }