From ba9e1ddccfe55e711ac3987f74109393dfb736af Mon Sep 17 00:00:00 2001 From: AN Long Date: Tue, 12 Aug 2025 14:06:53 +0000 Subject: [PATCH] testing: allow specify temp dir by GOTMPDIR environment variable Allow change the default temp directory returned by t.TempDir() by environment variable GOTMPDIR. Fixes #61585 Change-Id: Iba969bb02744e106cf15d80e0eda0245a55fc290 GitHub-Last-Rev: aeacea00952b11990b49a0fde6a0ce4fe910b777 GitHub-Pull-Request: golang/go#74844 Reviewed-on: https://go-review.googlesource.com/c/go/+/692455 Reviewed-by: Damien Neil Auto-Submit: Sean Liao Reviewed-by: Sean Liao LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui --- src/cmd/go/alldocs.go | 6 ++++-- src/cmd/go/internal/help/helpdoc.go | 6 ++++-- src/testing/testing.go | 4 +++- src/testing/testing_test.go | 33 +++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 69102231d2..fd23d829f5 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2407,8 +2407,10 @@ // The name of checksum database to use and optionally its public key and // URL. See https://golang.org/ref/mod#authenticating. // GOTMPDIR -// The directory where the go command will write -// temporary source files, packages, and binaries. +// Temporary directory used by the go command and testing package. +// Overrides the platform-specific temporary directory such as "/tmp". +// The go command and testing package will write temporary source files, +// packages, and binaries here. // GOTOOLCHAIN // Controls which Go toolchain is used. See https://go.dev/doc/toolchain. // GOVCS diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 9d44b862ee..ab04ce001c 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -573,8 +573,10 @@ General-purpose environment variables: The name of checksum database to use and optionally its public key and URL. See https://golang.org/ref/mod#authenticating. GOTMPDIR - The directory where the go command will write - temporary source files, packages, and binaries. + Temporary directory used by the go command and testing package. + Overrides the platform-specific temporary directory such as "/tmp". + The go command and testing package will write temporary source files, + packages, and binaries here. GOTOOLCHAIN Controls which Go toolchain is used. See https://go.dev/doc/toolchain. GOVCS diff --git a/src/testing/testing.go b/src/testing/testing.go index 3475bfca4a..2f0206b0a4 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1318,6 +1318,8 @@ func (c *common) Cleanup(f func()) { // all its subtests complete. // Each subsequent call to TempDir returns a unique directory; // if the directory creation fails, TempDir terminates the test by calling Fatal. +// If the environment variable GOTMPDIR is set, the temporary directory will +// be created somewhere beneath it. func (c *common) TempDir() string { c.checkFuzzFn("TempDir") // Use a single parent directory for all the temporary directories @@ -1362,7 +1364,7 @@ func (c *common) TempDir() string { return -1 } pattern = strings.Map(mapper, pattern) - c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern) + c.tempDir, c.tempDirErr = os.MkdirTemp(os.Getenv("GOTMPDIR"), pattern) if c.tempDirErr == nil { c.Cleanup(func() { if err := removeAll(c.tempDir); err != nil { diff --git a/src/testing/testing_test.go b/src/testing/testing_test.go index f4f5817a37..cc89e4144e 100644 --- a/src/testing/testing_test.go +++ b/src/testing/testing_test.go @@ -147,6 +147,39 @@ func testTempDir(t *testing.T) { } } +func TestTempDirGOTMPDIR(t *testing.T) { + // The first call to t.TempDir will create a parent temporary directory + // that will contain all temporary directories created by TempDir. + // + // Use os.TempDir (not t.TempDir) to get a temporary directory, + // set GOTMPDIR to that directory, + // and then verify that t.TempDir creates a directory in GOTMPDIR. + customTmpDir := filepath.Join(os.TempDir(), "custom-gotmpdir-test") + if err := os.MkdirAll(customTmpDir, 0777); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(customTmpDir) + + t.Setenv("GOTMPDIR", customTmpDir) + + dir := t.TempDir() + if dir == "" { + t.Fatal("expected dir") + } + + if !strings.HasPrefix(dir, customTmpDir) { + t.Errorf("TempDir did not use GOTMPDIR: got %q, want prefix %q", dir, customTmpDir) + } + + fi, err := os.Stat(dir) + if err != nil { + t.Fatal(err) + } + if !fi.IsDir() { + t.Errorf("dir %q is not a dir", dir) + } +} + func TestSetenv(t *testing.T) { tests := []struct { name string -- 2.52.0