cmd/stringer: streamline test subprocesses
- Execute the test binary itself as cmd/stringer instead of invoking (and
cleaning up after) 'go build'.
- Replace os.MkdirTemp with T.TempDir
Changes are similar to https://go.dev/cl/377836.
Change-Id: I5f9fca20e0f1f045826c385d556257fc5982ed53
GitHub-Last-Rev: f6c6b7735c97d3c2f508de91a268cf6795291ffd
GitHub-Pull-Request: golang/tools#425
Reviewed-on: https://go-review.googlesource.com/c/tools/+/464350
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Daniel Martà <mvdan@mvdan.cc>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
diff --git a/cmd/stringer/endtoend_test.go b/cmd/stringer/endtoend_test.go
index 268c2f6..29eb918 100644
--- a/cmd/stringer/endtoend_test.go
+++ b/cmd/stringer/endtoend_test.go
@@ -19,9 +19,9 @@
"path"
"path/filepath"
"strings"
+ "sync"
"testing"
- "golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/typeparams"
)
@@ -30,9 +30,22 @@
// we run stringer -type X and then compile and run the program. The resulting
// binary panics if the String method for X is not correct, including for error cases.
+func TestMain(m *testing.M) {
+ if os.Getenv("STRINGER_TEST_IS_STRINGER") != "" {
+ main()
+ os.Exit(0)
+ }
+
+ // Inform subprocesses that they should run the cmd/stringer main instead of
+ // running tests. It's a close approximation to building and running the real
+ // command, and much less complicated and expensive to build and clean up.
+ os.Setenv("STRINGER_TEST_IS_STRINGER", "1")
+
+ os.Exit(m.Run())
+}
+
func TestEndToEnd(t *testing.T) {
- dir, stringer := buildStringer(t)
- defer os.RemoveAll(dir)
+ stringer := stringerPath(t)
// Read the testdata directory.
fd, err := os.Open("testdata")
if err != nil {
@@ -64,7 +77,7 @@
t.Logf("cgo is not enabled for %s", name)
continue
}
- stringerCompileAndRun(t, dir, stringer, typeName(name), name)
+ stringerCompileAndRun(t, t.TempDir(), stringer, typeName(name), name)
}
}
@@ -91,8 +104,8 @@
// TestTags verifies that the -tags flag works as advertised.
func TestTags(t *testing.T) {
- dir, stringer := buildStringer(t)
- defer os.RemoveAll(dir)
+ stringer := stringerPath(t)
+ dir := t.TempDir()
var (
protectedConst = []byte("TagProtected")
output = filepath.Join(dir, "const_string.go")
@@ -139,8 +152,8 @@
// TestConstValueChange verifies that if a constant value changes and
// the stringer code is not regenerated, we'll get a compiler error.
func TestConstValueChange(t *testing.T) {
- dir, stringer := buildStringer(t)
- defer os.RemoveAll(dir)
+ stringer := stringerPath(t)
+ dir := t.TempDir()
source := filepath.Join(dir, "day.go")
err := copy(source, filepath.Join("testdata", "day.go"))
if err != nil {
@@ -178,21 +191,20 @@
}
}
-// buildStringer creates a temporary directory and installs stringer there.
-func buildStringer(t *testing.T) (dir string, stringer string) {
- t.Helper()
- testenv.NeedsTool(t, "go")
+var exe struct {
+ path string
+ err error
+ once sync.Once
+}
- dir, err := os.MkdirTemp("", "stringer")
- if err != nil {
- t.Fatal(err)
+func stringerPath(t *testing.T) string {
+ exe.once.Do(func() {
+ exe.path, exe.err = os.Executable()
+ })
+ if exe.err != nil {
+ t.Fatal(exe.err)
}
- stringer = filepath.Join(dir, "stringer.exe")
- err = run("go", "build", "-o", stringer)
- if err != nil {
- t.Fatalf("building stringer: %s", err)
- }
- return dir, stringer
+ return exe.path
}
// stringerCompileAndRun runs stringer for the named file and compiles and
diff --git a/cmd/stringer/golden_test.go b/cmd/stringer/golden_test.go
index 2e2ec58..250af05 100644
--- a/cmd/stringer/golden_test.go
+++ b/cmd/stringer/golden_test.go
@@ -451,12 +451,7 @@
func TestGolden(t *testing.T) {
testenv.NeedsTool(t, "go")
- dir, err := os.MkdirTemp("", "stringer")
- if err != nil {
- t.Error(err)
- }
- defer os.RemoveAll(dir)
-
+ dir := t.TempDir()
for _, test := range golden {
g := Generator{
trimPrefix: test.trimPrefix,