diff options
| author | Kir Kolyshkin <kolyshkin@gmail.com> | 2023-09-07 17:08:56 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-08-16 23:48:50 +0000 |
| commit | 79ca434ac608d0817a5807d1c7b2138912ed55ce (patch) | |
| tree | 763cfea963ab46503845d9333d8b5c18c65c539f /src/testing/testing_test.go | |
| parent | ff271cd391bdb8963b5409c6f4cca40af8501b51 (diff) | |
| download | go-79ca434ac608d0817a5807d1c7b2138912ed55ce.tar.xz | |
testing: add Chdir
Some tests need to use os.Chdir, but the use is complicated because
- they must change back to the old working directory;
- they must not use t.Parallel.
Add Chdir that covers these cases, and sets PWD environment variable
to the new directory for the duration of the test for Unix platforms.
Unify the panic message when t.Parallel is used together with t.Setenv
or t.Chdir.
Add some tests.
For #62516.
Change-Id: Ib050d173b26eb28a27dba5a206b2d0d877d761c1
Reviewed-on: https://go-review.googlesource.com/c/go/+/529895
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/testing/testing_test.go')
| -rw-r--r-- | src/testing/testing_test.go | 171 |
1 files changed, 138 insertions, 33 deletions
diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go index 4a9303952e..af6035fd27 100644 --- a/src/testing/testing_test.go +++ b/src/testing/testing_test.go @@ -13,6 +13,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "slices" "strings" "sync" @@ -200,64 +201,168 @@ func TestSetenv(t *testing.T) { } } -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) - } - }() +func expectParallelConflict(t *testing.T) { + want := testing.ParallelConflict + if got := recover(); got != want { + t.Fatalf("expected panic; got %#v want %q", got, want) + } +} - t.Setenv("GO_TEST_KEY_1", "value") +func testWithParallelAfter(t *testing.T, fn func(*testing.T)) { + defer expectParallelConflict(t) + fn(t) 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) - } - }() +func testWithParallelBefore(t *testing.T, fn func(*testing.T)) { + defer expectParallelConflict(t) t.Parallel() - - t.Setenv("GO_TEST_KEY_1", "value") + fn(t) } -func TestSetenvWithParallelParentBeforeSetenv(t *testing.T) { +func testWithParallelParentBefore(t *testing.T, fn func(*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) - } - }() + defer expectParallelConflict(t) - t.Setenv("GO_TEST_KEY_1", "value") + fn(t) }) } -func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) { +func testWithParallelGrandParentBefore(t *testing.T, fn func(*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) - } - }() + defer expectParallelConflict(t) - t.Setenv("GO_TEST_KEY_1", "value") + fn(t) }) }) } +func tSetenv(t *testing.T) { + t.Setenv("GO_TEST_KEY_1", "value") +} + +func TestSetenvWithParallelAfter(t *testing.T) { + testWithParallelAfter(t, tSetenv) +} + +func TestSetenvWithParallelBefore(t *testing.T) { + testWithParallelBefore(t, tSetenv) +} + +func TestSetenvWithParallelParentBefore(t *testing.T) { + testWithParallelParentBefore(t, tSetenv) +} + +func TestSetenvWithParallelGrandParentBefore(t *testing.T) { + testWithParallelGrandParentBefore(t, tSetenv) +} + +func tChdir(t *testing.T) { + t.Chdir(t.TempDir()) +} + +func TestChdirWithParallelAfter(t *testing.T) { + testWithParallelAfter(t, tChdir) +} + +func TestChdirWithParallelBefore(t *testing.T) { + testWithParallelBefore(t, tChdir) +} + +func TestChdirWithParallelParentBefore(t *testing.T) { + testWithParallelParentBefore(t, tChdir) +} + +func TestChdirWithParallelGrandParentBefore(t *testing.T) { + testWithParallelGrandParentBefore(t, tChdir) +} + +func TestChdir(t *testing.T) { + oldDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + defer os.Chdir(oldDir) + + tmp := t.TempDir() + rel, err := filepath.Rel(oldDir, tmp) + if err != nil { + t.Fatal(err) + } + + for _, tc := range []struct { + name, dir, pwd string + extraChdir bool + }{ + { + name: "absolute", + dir: tmp, + pwd: tmp, + }, + { + name: "relative", + dir: rel, + pwd: tmp, + }, + { + name: "current (absolute)", + dir: oldDir, + pwd: oldDir, + }, + { + name: "current (relative) with extra os.Chdir", + dir: ".", + pwd: oldDir, + + extraChdir: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + if !filepath.IsAbs(tc.pwd) { + t.Fatalf("Bad tc.pwd: %q (must be absolute)", tc.pwd) + } + + t.Chdir(tc.dir) + + newDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if newDir != tc.pwd { + t.Fatalf("failed to chdir to %q: getwd: got %q, want %q", tc.dir, newDir, tc.pwd) + } + + switch runtime.GOOS { + case "windows", "plan9": + // Windows and Plan 9 do not use the PWD variable. + default: + if pwd := os.Getenv("PWD"); pwd != tc.pwd { + t.Fatalf("PWD: got %q, want %q", pwd, tc.pwd) + } + } + + if tc.extraChdir { + os.Chdir("..") + } + }) + + newDir, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if newDir != oldDir { + t.Fatalf("failed to restore wd to %s: getwd: %s", oldDir, newDir) + } + } +} + // testingTrueInInit is part of TestTesting. var testingTrueInInit = false |
