@@ -19,9 +19,9 @@ import (
19
19
"path"
20
20
"path/filepath"
21
21
"strings"
22
+ "sync"
22
23
"testing"
23
24
24
- "golang.org/x/tools/internal/testenv"
25
25
"golang.org/x/tools/internal/typeparams"
26
26
)
27
27
@@ -30,9 +30,22 @@ import (
30
30
// we run stringer -type X and then compile and run the program. The resulting
31
31
// binary panics if the String method for X is not correct, including for error cases.
32
32
33
+ func TestMain (m * testing.M ) {
34
+ if os .Getenv ("STRINGER_TEST_IS_STRINGER" ) != "" {
35
+ main ()
36
+ os .Exit (0 )
37
+ }
38
+
39
+ // Inform subprocesses that they should run the cmd/stringer main instead of
40
+ // running tests. It's a close approximation to building and running the real
41
+ // command, and much less complicated and expensive to build and clean up.
42
+ os .Setenv ("STRINGER_TEST_IS_STRINGER" , "1" )
43
+
44
+ os .Exit (m .Run ())
45
+ }
46
+
33
47
func TestEndToEnd (t * testing.T ) {
34
- dir , stringer := buildStringer (t )
35
- defer os .RemoveAll (dir )
48
+ stringer := stringerPath (t )
36
49
// Read the testdata directory.
37
50
fd , err := os .Open ("testdata" )
38
51
if err != nil {
@@ -64,7 +77,7 @@ func TestEndToEnd(t *testing.T) {
64
77
t .Logf ("cgo is not enabled for %s" , name )
65
78
continue
66
79
}
67
- stringerCompileAndRun (t , dir , stringer , typeName (name ), name )
80
+ stringerCompileAndRun (t , t . TempDir () , stringer , typeName (name ), name )
68
81
}
69
82
}
70
83
@@ -91,8 +104,8 @@ func moreTests(t *testing.T, dirname, prefix string) []string {
91
104
92
105
// TestTags verifies that the -tags flag works as advertised.
93
106
func TestTags (t * testing.T ) {
94
- dir , stringer := buildStringer (t )
95
- defer os . RemoveAll ( dir )
107
+ stringer := stringerPath (t )
108
+ dir := t . TempDir ( )
96
109
var (
97
110
protectedConst = []byte ("TagProtected" )
98
111
output = filepath .Join (dir , "const_string.go" )
@@ -139,8 +152,8 @@ func TestTags(t *testing.T) {
139
152
// TestConstValueChange verifies that if a constant value changes and
140
153
// the stringer code is not regenerated, we'll get a compiler error.
141
154
func TestConstValueChange (t * testing.T ) {
142
- dir , stringer := buildStringer (t )
143
- defer os . RemoveAll ( dir )
155
+ stringer := stringerPath (t )
156
+ dir := t . TempDir ( )
144
157
source := filepath .Join (dir , "day.go" )
145
158
err := copy (source , filepath .Join ("testdata" , "day.go" ))
146
159
if err != nil {
@@ -178,21 +191,20 @@ func TestConstValueChange(t *testing.T) {
178
191
}
179
192
}
180
193
181
- // buildStringer creates a temporary directory and installs stringer there.
182
- func buildStringer (t * testing.T ) (dir string , stringer string ) {
183
- t .Helper ()
184
- testenv .NeedsTool (t , "go" )
194
+ var exe struct {
195
+ path string
196
+ err error
197
+ once sync.Once
198
+ }
185
199
186
- dir , err := os .MkdirTemp ("" , "stringer" )
187
- if err != nil {
188
- t .Fatal (err )
189
- }
190
- stringer = filepath .Join (dir , "stringer.exe" )
191
- err = run ("go" , "build" , "-o" , stringer )
192
- if err != nil {
193
- t .Fatalf ("building stringer: %s" , err )
200
+ func stringerPath (t * testing.T ) string {
201
+ exe .once .Do (func () {
202
+ exe .path , exe .err = os .Executable ()
203
+ })
204
+ if exe .err != nil {
205
+ t .Fatal (exe .err )
194
206
}
195
- return dir , stringer
207
+ return exe . path
196
208
}
197
209
198
210
// stringerCompileAndRun runs stringer for the named file and compiles and
0 commit comments