]> Cypherpunks repositories - gostls13.git/commitdiff
testing: panic in AllocsPerRun if parallel tests are running
authorRuss Cox <rsc@golang.org>
Wed, 20 Nov 2024 16:01:27 +0000 (11:01 -0500)
committerGopher Robot <gobot@golang.org>
Fri, 14 Feb 2025 14:09:08 +0000 (06:09 -0800)
If other tests are running, AllocsPerRun's result will be inherently flaky.
Saw this with CL 630136 and #70327.

Proposed in #70464.

Fixes #70464.

Change-Id: I190afdf26bc31299f6e5e8665b4fb420ffd554ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/630137
Auto-Submit: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/testing/allocs.go
src/testing/testing.go

index 1eeb2d4802c31c538fec745dd8dea46a151ecd33..8161fad06fb9ea84e151fc6a52db85d881320ae3 100644 (file)
@@ -18,6 +18,9 @@ import (
 // AllocsPerRun sets GOMAXPROCS to 1 during its measurement and will restore
 // it before returning.
 func AllocsPerRun(runs int, f func()) (avg float64) {
+       if parallelStart.Load() != parallelStop.Load() {
+               panic("testing: AllocsPerRun called during parallel test")
+       }
        defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
 
        // Warm up the function
index aefcb84fc8de2017da8bae565cfae18adf3d386a..8b0915a0ef79010b4c7ff4f8f9e8b8134110f4fc 100644 (file)
@@ -424,6 +424,11 @@ import (
 
 var initRan bool
 
+var (
+       parallelStart atomic.Int64 // number of parallel tests started
+       parallelStop  atomic.Int64 // number of parallel tests stopped
+)
+
 // Init registers testing flags. These flags are automatically registered by
 // the "go test" command before running test functions, so Init is only needed
 // when calling functions such as Benchmark without using "go test".
@@ -1536,7 +1541,6 @@ func (t *T) Parallel() {
        if t.denyParallel {
                panic(parallelConflict)
        }
-       t.isParallel = true
        if t.parent.barrier == nil {
                // T.Parallel has no effect when fuzzing.
                // Multiple processes may run in parallel, but only one input can run at a
@@ -1544,6 +1548,8 @@ func (t *T) Parallel() {
                return
        }
 
+       t.isParallel = true
+
        // We don't want to include the time we spend waiting for serial tests
        // in the test duration. Record the elapsed time thus far and reset the
        // timer afterwards.
@@ -1572,6 +1578,7 @@ func (t *T) Parallel() {
        t.signal <- true   // Release calling test.
        <-t.parent.barrier // Wait for the parent test to complete.
        t.tstate.waitParallel()
+       parallelStart.Add(1)
 
        if t.chatty != nil {
                t.chatty.Updatef(t.name, "=== CONT  %s\n", t.name)
@@ -1707,6 +1714,9 @@ func tRunner(t *T, fn func(t *T)) {
                                panic(err)
                        }
                        running.Delete(t.name)
+                       if t.isParallel {
+                               parallelStop.Add(1)
+                       }
                        t.signal <- signal
                }()