]> Cypherpunks repositories - gostls13.git/commitdiff
testing: add TB.Setenv
authorAlexey Vilenski <bynovhack@gmail.com>
Fri, 5 Mar 2021 11:37:54 +0000 (11:37 +0000)
committerDaniel Martí <mvdan@mvdan.cc>
Fri, 5 Mar 2021 11:58:31 +0000 (11:58 +0000)
Add a new method TB.Setenv that'll set environment variables
only for the isolated lifetime of the test, and will clean up
and unset these variables when the test ends.
This method disables the test or benchmark from running in
parallel.

Fixes #41260

Change-Id: I0a18f094ec1c6ec3157b4b12993ea3075e2e9867
GitHub-Last-Rev: 0ca12fa565318f350b927e2ef94f3b4f792c75c2
GitHub-Pull-Request: golang/go#41857
Reviewed-on: https://go-review.googlesource.com/c/go/+/260577
Trust: Daniel Martí <mvdan@mvdan.cc>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: roger peppe <rogpeppe@gmail.com>
src/testing/testing.go
src/testing/testing_test.go

index 466dd96981acca75264e559ce79a617fc813415e..fc52f3c547ef5a41254dcd8b6c7cbd664267f54a 100644 (file)
@@ -667,6 +667,7 @@ var _ TB = (*B)(nil)
 type T struct {
        common
        isParallel bool
+       isEnvSet   bool
        context    *testContext // For running tests and subtests.
 }
 
@@ -964,6 +965,29 @@ func (c *common) TempDir() string {
        return dir
 }
 
+// Setenv calls os.Setenv(key, value) and uses Cleanup to
+// restore the environment variable to its original value
+// after the test.
+//
+// This cannot be used in parallel tests.
+func (c *common) Setenv(key, value string) {
+       prevValue, ok := os.LookupEnv(key)
+
+       if err := os.Setenv(key, value); err != nil {
+               c.Fatalf("cannot set environment variable: %v", err)
+       }
+
+       if ok {
+               c.Cleanup(func() {
+                       os.Setenv(key, prevValue)
+               })
+       } else {
+               c.Cleanup(func() {
+                       os.Unsetenv(key)
+               })
+       }
+}
+
 // panicHanding is an argument to runCleanup.
 type panicHandling int
 
@@ -1035,6 +1059,9 @@ func (t *T) Parallel() {
        if t.isParallel {
                panic("testing: t.Parallel called multiple times")
        }
+       if t.isEnvSet {
+               panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests")
+       }
        t.isParallel = true
 
        // We don't want to include the time we spend waiting for serial tests
@@ -1068,6 +1095,21 @@ func (t *T) Parallel() {
        t.raceErrors += -race.Errors()
 }
 
+// Setenv calls os.Setenv(key, value) and uses Cleanup to
+// restore the environment variable to its original value
+// after the test.
+//
+// This cannot be used in parallel tests.
+func (t *T) Setenv(key, value string) {
+       if t.isParallel {
+               panic("testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests")
+       }
+
+       t.isEnvSet = true
+
+       t.common.Setenv(key, value)
+}
+
 // InternalTest is an internal type but exported because it is cross-package;
 // it is part of the implementation of the "go test" command.
 type InternalTest struct {
index 0f096980ca4561798f227f567161cdc19d97d23a..55a4df4739ee0f955a9cce563ad5f956f3c7a2dd 100644 (file)
@@ -109,3 +109,86 @@ func testTempDir(t *testing.T) {
                t.Errorf("unexpected %d files in TempDir: %v", len(files), files)
        }
 }
+
+func TestSetenv(t *testing.T) {
+       tests := []struct {
+               name               string
+               key                string
+               initialValueExists bool
+               initialValue       string
+               newValue           string
+       }{
+               {
+                       name:               "initial value exists",
+                       key:                "GO_TEST_KEY_1",
+                       initialValueExists: true,
+                       initialValue:       "111",
+                       newValue:           "222",
+               },
+               {
+                       name:               "initial value exists but empty",
+                       key:                "GO_TEST_KEY_2",
+                       initialValueExists: true,
+                       initialValue:       "",
+                       newValue:           "222",
+               },
+               {
+                       name:               "initial value is not exists",
+                       key:                "GO_TEST_KEY_3",
+                       initialValueExists: false,
+                       initialValue:       "",
+                       newValue:           "222",
+               },
+       }
+
+       for _, test := range tests {
+               if test.initialValueExists {
+                       if err := os.Setenv(test.key, test.initialValue); err != nil {
+                               t.Fatalf("unable to set env: got %v", err)
+                       }
+               } else {
+                       os.Unsetenv(test.key)
+               }
+
+               t.Run(test.name, func(t *testing.T) {
+                       t.Setenv(test.key, test.newValue)
+                       if os.Getenv(test.key) != test.newValue {
+                               t.Fatalf("unexpected value after t.Setenv: got %s, want %s", os.Getenv(test.key), test.newValue)
+                       }
+               })
+
+               got, exists := os.LookupEnv(test.key)
+               if got != test.initialValue {
+                       t.Fatalf("unexpected value after t.Setenv cleanup: got %s, want %s", got, test.initialValue)
+               }
+               if exists != test.initialValueExists {
+                       t.Fatalf("unexpected value after t.Setenv cleanup: got %t, want %t", exists, test.initialValueExists)
+               }
+       }
+}
+
+func TestSetenvWithParallelAfterSetenv(t *testing.T) {
+       defer func() {
+               want := "testing: t.Parallel called after t.Setenv; 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")
+
+       t.Parallel()
+}
+
+func TestSetenvWithParallelBeforeSetenv(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.Parallel()
+
+       t.Setenv("GO_TEST_KEY_1", "value")
+}