261023.4 · 35082dd6a557aa0802e4dfccbe9f16faa23ff2a6
Tests wait for the online-repo goroutines
The tests swap the globals cacheRoot and webScheme, and their cleanup cancelled web's context without waiting. A repo probe or listing still running read the global while the next test or the cleanup wrote it, which go test -race reported. web now counts what it starts in a WaitGroup, and the cleanup waits for it. A running server sets these globals once at start, so it never raced.
TestPageBudget skips under the race detector, which slows every page past five milliseconds.
reading declarations
@@ -18,6 +18,9 @@ const pageBudget = 5 * time.Millisecond // render.go, a listing, histories and a commit's diff. Each takes the // median of 15 runs, so one slow run does not fail it. func TestPageBudget(t *testing.T) {+ if raceOn {+ t.Skip("the race detector slows every page past the budget")+ } needGit(t) dir := t.TempDir() for _, name := range []string{"README.md", "render.go"} {
@@ -0,0 +1,5 @@+//go:build !race++package main++const raceOn = false
@@ -0,0 +1,7 @@+//go:build race++package main++// raceOn reports whether the race detector is built in. It slows code+// five to 10 times, so timing tests skip under it.+const raceOn = true
@@ -52,6 +52,10 @@ type web struct { lists map[string]*listing // by the URL path of a host or account busy map[string]bool // keys being cloned or fetched, which trim leaves kicked time.Time++ // wg counts the goroutines web starts, so a test can wait for them+ // before it changes the globals they read.+ wg sync.WaitGroup } // webScheme is how web reaches forges. Tests serve repos over http.@@ -253,7 +257,7 @@ func (w *web) visit(r *webRepo) { } if !r.fetching && time.Since(r.fetched) > webRefresh && time.Since(r.tried) > webRefresh { r.fetching, r.tried = true, time.Now()- go w.refresh(r)+ w.wg.Go(func() { w.refresh(r) }) } } @@ -342,8 +346,8 @@ func (w *web) show(r *webRepo, wt string) error { old.root.Close() } logInfo("serves %s at %s from %s", r.key, filepath.Base(wt), wt)- go t.warm()- go t.warmLinks()+ w.wg.Go(t.warm)+ w.wg.Go(t.warmLinks) return nil } @@ -364,7 +368,7 @@ func (w *web) start(key string, segs []string) *webJob { } j := &webJob{urlPath: "/" + key, started: time.Now()} w.jobs[key] = j- go w.run(j, key, segs)+ w.wg.Go(func() { w.run(j, key, segs) }) return j }
@@ -92,6 +92,7 @@ func testWeb(t *testing.T, limit int64) *web { } t.Cleanup(func() { cancel()+ w.wg.Wait() cacheRoot = old }) return w