hasSub atomic.Bool // whether there are sub-benchmarks.
raceErrors int // Number of races detected during test.
runner string // Function name of tRunner running the test.
+ isParallel bool // Whether the test is parallel.
parent *common
level int // Nesting depth of test or benchmark.
// may be called simultaneously from multiple goroutines.
type T struct {
common
- isParallel bool
- isEnvSet bool
- context *testContext // For running tests and subtests.
+ isEnvSet bool
+ context *testContext // For running tests and subtests.
}
func (c *common) private() {}
//
// This cannot be used in parallel tests.
func (t *T) Setenv(key, value string) {
- if t.isParallel {
+ // Non-parallel subtests that have parallel ancestors may still
+ // run in parallel with other tests: they are only non-parallel
+ // with respect to the other subtests of the same parent.
+ // Since SetEnv affects the whole process, we need to disallow it
+ // if the current test or any parent is parallel.
+ isParallel := false
+ for c := &t.common; c != nil; c = c.parent {
+ if c.isParallel {
+ isParallel = true
+ break
+ }
+ }
+ if isParallel {
panic("testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests")
}
t.Setenv("GO_TEST_KEY_1", "value")
}
+
+func TestSetenvWithParallelParentBeforeSetenv(t *testing.T) {
+ t.Parallel()
+
+ t.Run("child", func(t *testing.T) {
+ defer func() {
+ want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
+ if got := recover(); got != want {
+ t.Fatalf("expected panic; got %#v want %q", got, want)
+ }
+ }()
+
+ t.Setenv("GO_TEST_KEY_1", "value")
+ })
+}
+
+func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
+ t.Parallel()
+
+ t.Run("child", func(t *testing.T) {
+ t.Run("grand-child", func(t *testing.T) {
+ defer func() {
+ want := "testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests"
+ if got := recover(); got != want {
+ t.Fatalf("expected panic; got %#v want %q", got, want)
+ }
+ }()
+
+ t.Setenv("GO_TEST_KEY_1", "value")
+ })
+ })
+}