Browse Source

util/testenv: add func to report whether a testing.TB is in parallel mode

For future in-memory network changes (#15558) to be able to be
stricter and do automatic leak detection when it's safe to do so, in
non-parallel tests.

Updates tailscale/corp#27636

Change-Id: I50f03b16a3f92ce61a7ed88264b49d8c6628f638
Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 11 months ago
parent
commit
6d117d64a2
2 changed files with 52 additions and 0 deletions
  1. 39 0
      util/testenv/testenv.go
  2. 13 0
      util/testenv/testenv_test.go

+ 39 - 0
util/testenv/testenv.go

@@ -6,6 +6,7 @@
 package testenv
 
 import (
+	"context"
 	"flag"
 
 	"tailscale.com/types/lazy"
@@ -19,3 +20,41 @@ func InTest() bool {
 		return flag.Lookup("test.v") != nil
 	})
 }
+
+// TB is testing.TB, to avoid importing "testing" in non-test code.
+type TB interface {
+	Cleanup(func())
+	Error(args ...any)
+	Errorf(format string, args ...any)
+	Fail()
+	FailNow()
+	Failed() bool
+	Fatal(args ...any)
+	Fatalf(format string, args ...any)
+	Helper()
+	Log(args ...any)
+	Logf(format string, args ...any)
+	Name() string
+	Setenv(key, value string)
+	Chdir(dir string)
+	Skip(args ...any)
+	SkipNow()
+	Skipf(format string, args ...any)
+	Skipped() bool
+	TempDir() string
+	Context() context.Context
+}
+
+// InParallelTest reports whether t is running as a parallel test.
+//
+// Use of this function taints t such that its Parallel method (assuming t is an
+// actual *testing.T) will panic if called after this function.
+func InParallelTest(t TB) (isParallel bool) {
+	defer func() {
+		if r := recover(); r != nil {
+			isParallel = true
+		}
+	}()
+	t.Chdir(".") // panics in a t.Parallel test
+	return false
+}

+ 13 - 0
util/testenv/testenv_test.go

@@ -16,3 +16,16 @@ func TestDeps(t *testing.T) {
 		},
 	}.Check(t)
 }
+
+func TestInParallelTestTrue(t *testing.T) {
+	t.Parallel()
+	if !InParallelTest(t) {
+		t.Fatal("InParallelTest should return true once t.Parallel has been called")
+	}
+}
+
+func TestInParallelTestFalse(t *testing.T) {
+	if InParallelTest(t) {
+		t.Fatal("InParallelTest should return false before t.Parallel has been called")
+	}
+}