@@ -12,7 +12,6 @@ package testenv
12
12
13
13
import (
14
14
"bytes"
15
- "errors"
16
15
"flag"
17
16
"fmt"
18
17
"os"
@@ -43,15 +42,22 @@ func Builder() string {
43
42
44
43
// HasGoBuild reports whether the current system can build programs with “go build”
45
44
// and then run them with os.StartProcess or exec.Command.
46
- // Modified by Hugo (not needed)
47
45
func HasGoBuild () bool {
48
- return false
46
+ if os .Getenv ("GO_GCFLAGS" ) != "" {
47
+ // It's too much work to require every caller of the go command
48
+ // to pass along "-gcflags="+os.Getenv("GO_GCFLAGS").
49
+ // For now, if $GO_GCFLAGS is set, report that we simply can't
50
+ // run go build.
51
+ return false
52
+ }
53
+
54
+ return tryGoBuild () == nil
49
55
}
50
56
51
- var (
52
- goBuildOnce sync. Once
53
- goBuildErr error
54
- )
57
+ var tryGoBuild = sync . OnceValue ( func () error {
58
+ // Removed by Hugo, not used.
59
+ return nil
60
+ } )
55
61
56
62
// MustHaveGoBuild checks that the current system can build programs with “go build”
57
63
// and then run them with os.StartProcess or exec.Command.
@@ -63,7 +69,7 @@ func MustHaveGoBuild(t testing.TB) {
63
69
}
64
70
if ! HasGoBuild () {
65
71
t .Helper ()
66
- t .Skipf ("skipping test: 'go build' unavailable: %v" , goBuildErr )
72
+ t .Skipf ("skipping test: 'go build' unavailable: %v" , tryGoBuild () )
67
73
}
68
74
}
69
75
@@ -77,6 +83,7 @@ func HasGoRun() bool {
77
83
// If not, MustHaveGoRun calls t.Skip with an explanation.
78
84
func MustHaveGoRun (t testing.TB ) {
79
85
if ! HasGoRun () {
86
+ t .Helper ()
80
87
t .Skipf ("skipping test: 'go run' not available on %s/%s" , runtime .GOOS , runtime .GOARCH )
81
88
}
82
89
}
@@ -96,6 +103,7 @@ func HasParallelism() bool {
96
103
// threads in parallel. If not, MustHaveParallelism calls t.Skip with an explanation.
97
104
func MustHaveParallelism (t testing.TB ) {
98
105
if ! HasParallelism () {
106
+ t .Helper ()
99
107
t .Skipf ("skipping test: no parallelism available on %s/%s" , runtime .GOOS , runtime .GOARCH )
100
108
}
101
109
}
@@ -119,82 +127,67 @@ func GoToolPath(t testing.TB) string {
119
127
return path
120
128
}
121
129
122
- var (
123
- gorootOnce sync.Once
124
- gorootPath string
125
- gorootErr error
126
- )
127
-
128
- func findGOROOT () (string , error ) {
129
- gorootOnce .Do (func () {
130
- gorootPath = runtime .GOROOT ()
131
- if gorootPath != "" {
132
- // If runtime.GOROOT() is non-empty, assume that it is valid.
133
- //
134
- // (It might not be: for example, the user may have explicitly set GOROOT
135
- // to the wrong directory. But this case is
136
- // rare, and if that happens the user can fix what they broke.)
137
- return
138
- }
139
-
140
- // runtime.GOROOT doesn't know where GOROOT is (perhaps because the test
141
- // binary was built with -trimpath).
130
+ var findGOROOT = sync .OnceValues (func () (path string , err error ) {
131
+ if path := runtime .GOROOT (); path != "" {
132
+ // If runtime.GOROOT() is non-empty, assume that it is valid.
142
133
//
143
- // Since this is internal/testenv, we can cheat and assume that the caller
144
- // is a test of some package in a subdirectory of GOROOT/src. ('go test'
145
- // runs the test in the directory containing the packaged under test.) That
146
- // means that if we start walking up the tree, we should eventually find
147
- // GOROOT/src/go.mod, and we can report the parent directory of that.
148
- //
149
- // Notably, this works even if we can't run 'go env GOROOT' as a
150
- // subprocess.
134
+ // (It might not be: for example, the user may have explicitly set GOROOT
135
+ // to the wrong directory. But this case is
136
+ // rare, and if that happens the user can fix what they broke.)
137
+ return path , nil
138
+ }
151
139
152
- cwd , err := os .Getwd ()
153
- if err != nil {
154
- gorootErr = fmt .Errorf ("finding GOROOT: %w" , err )
155
- return
140
+ // runtime.GOROOT doesn't know where GOROOT is (perhaps because the test
141
+ // binary was built with -trimpath).
142
+ //
143
+ // Since this is internal/testenv, we can cheat and assume that the caller
144
+ // is a test of some package in a subdirectory of GOROOT/src. ('go test'
145
+ // runs the test in the directory containing the packaged under test.) That
146
+ // means that if we start walking up the tree, we should eventually find
147
+ // GOROOT/src/go.mod, and we can report the parent directory of that.
148
+ //
149
+ // Notably, this works even if we can't run 'go env GOROOT' as a
150
+ // subprocess.
151
+
152
+ cwd , err := os .Getwd ()
153
+ if err != nil {
154
+ return "" , fmt .Errorf ("finding GOROOT: %w" , err )
155
+ }
156
+
157
+ dir := cwd
158
+ for {
159
+ parent := filepath .Dir (dir )
160
+ if parent == dir {
161
+ // dir is either "." or only a volume name.
162
+ return "" , fmt .Errorf ("failed to locate GOROOT/src in any parent directory" )
156
163
}
157
164
158
- dir := cwd
159
- for {
160
- parent := filepath .Dir (dir )
161
- if parent == dir {
162
- // dir is either "." or only a volume name.
163
- gorootErr = fmt .Errorf ("failed to locate GOROOT/src in any parent directory" )
164
- return
165
- }
165
+ if base := filepath .Base (dir ); base != "src" {
166
+ dir = parent
167
+ continue // dir cannot be GOROOT/src if it doesn't end in "src".
168
+ }
166
169
167
- if base := filepath .Base (dir ); base != "src" {
170
+ b , err := os .ReadFile (filepath .Join (dir , "go.mod" ))
171
+ if err != nil {
172
+ if os .IsNotExist (err ) {
168
173
dir = parent
169
- continue // dir cannot be GOROOT/src if it doesn't end in "src".
170
- }
171
-
172
- b , err := os .ReadFile (filepath .Join (dir , "go.mod" ))
173
- if err != nil {
174
- if os .IsNotExist (err ) {
175
- dir = parent
176
- continue
177
- }
178
- gorootErr = fmt .Errorf ("finding GOROOT: %w" , err )
179
- return
174
+ continue
180
175
}
181
- goMod := string ( b )
182
-
183
- for goMod != "" {
184
- var line string
185
- line , goMod , _ = strings . Cut ( goMod , " \n " )
186
- fields := strings . Fields ( line )
187
- if len ( fields ) >= 2 && fields [ 0 ] == "module" && fields [ 1 ] == "std" {
188
- // Found "module std", which is the module declaration in GOROOT/src!
189
- gorootPath = parent
190
- return
191
- }
176
+ return "" , fmt . Errorf ( "finding GOROOT: %w" , err )
177
+ }
178
+ goMod := string ( b )
179
+
180
+ for goMod != "" {
181
+ var line string
182
+ line , goMod , _ = strings . Cut ( goMod , " \n " )
183
+ fields := strings . Fields ( line )
184
+ if len ( fields ) >= 2 && fields [ 0 ] == "module" && fields [ 1 ] == "std" {
185
+ // Found "module std", which is the module declaration in GOROOT/src!
186
+ return parent , nil
192
187
}
193
188
}
194
- })
195
-
196
- return gorootPath , gorootErr
197
- }
189
+ }
190
+ })
198
191
199
192
// GOROOT reports the path to the directory containing the root of the Go
200
193
// project source tree. This is normally equivalent to runtime.GOROOT, but
@@ -217,28 +210,22 @@ func GOROOT(t testing.TB) string {
217
210
218
211
// GoTool reports the path to the Go tool.
219
212
func GoTool () (string , error ) {
220
- if ! HasGoBuild () {
221
- return "" , errors .New ("platform cannot run go tool" )
222
- }
223
- goToolOnce .Do (func () {
224
- goToolPath , goToolErr = exec .LookPath ("go" )
225
- })
226
- return goToolPath , goToolErr
213
+ // Removed by Hugo, not used.
214
+ return "" , nil
227
215
}
228
216
229
- var (
230
- goToolOnce sync.Once
231
- goToolPath string
232
- goToolErr error
233
- )
217
+ var goTool = sync .OnceValues (func () (string , error ) {
218
+ return exec .LookPath ("go" )
219
+ })
234
220
235
- // HasSrc reports whether the entire source tree is available under GOROOT.
236
- func HasSrc () bool {
221
+ // MustHaveSource checks that the entire source tree is available under GOROOT.
222
+ // If not, it calls t.Skip with an explanation.
223
+ func MustHaveSource (t testing.TB ) {
237
224
switch runtime .GOOS {
238
225
case "ios" :
239
- return false
226
+ t .Helper ()
227
+ t .Skip ("skipping test: no source tree on " + runtime .GOOS )
240
228
}
241
- return true
242
229
}
243
230
244
231
// HasExternalNetwork reports whether the current system can use
@@ -263,41 +250,39 @@ func MustHaveExternalNetwork(t testing.TB) {
263
250
264
251
// HasCGO reports whether the current system can use cgo.
265
252
func HasCGO () bool {
266
- hasCgoOnce .Do (func () {
267
- goTool , err := GoTool ()
268
- if err != nil {
269
- return
270
- }
271
- cmd := exec .Command (goTool , "env" , "CGO_ENABLED" )
272
- cmd .Env = origEnv
273
- out , err := cmd .Output ()
274
- if err != nil {
275
- panic (fmt .Sprintf ("%v: %v" , cmd , out ))
276
- }
277
- hasCgo , err = strconv .ParseBool (string (bytes .TrimSpace (out )))
278
- if err != nil {
279
- panic (fmt .Sprintf ("%v: non-boolean output %q" , cmd , out ))
280
- }
281
- })
282
- return hasCgo
253
+ return hasCgo ()
283
254
}
284
255
285
- var (
286
- hasCgoOnce sync.Once
287
- hasCgo bool
288
- )
256
+ var hasCgo = sync .OnceValue (func () bool {
257
+ goTool , err := goTool ()
258
+ if err != nil {
259
+ return false
260
+ }
261
+ cmd := exec .Command (goTool , "env" , "CGO_ENABLED" )
262
+ cmd .Env = origEnv
263
+ out , err := cmd .Output ()
264
+ if err != nil {
265
+ panic (fmt .Sprintf ("%v: %v" , cmd , out ))
266
+ }
267
+ ok , err := strconv .ParseBool (string (bytes .TrimSpace (out )))
268
+ if err != nil {
269
+ panic (fmt .Sprintf ("%v: non-boolean output %q" , cmd , out ))
270
+ }
271
+ return ok
272
+ })
289
273
290
274
// MustHaveCGO calls t.Skip if cgo is not available.
291
275
func MustHaveCGO (t testing.TB ) {
292
276
if ! HasCGO () {
277
+ t .Helper ()
293
278
t .Skipf ("skipping test: no cgo" )
294
279
}
295
280
}
296
281
297
282
// CanInternalLink reports whether the current system can link programs with
298
283
// internal linking.
299
- // Modified by Hugo (not needed)
300
284
func CanInternalLink (withCgo bool ) bool {
285
+ // Removed by Hugo, not used.
301
286
return false
302
287
}
303
288
@@ -306,6 +291,7 @@ func CanInternalLink(withCgo bool) bool {
306
291
// If not, MustInternalLink calls t.Skip with an explanation.
307
292
func MustInternalLink (t testing.TB , withCgo bool ) {
308
293
if ! CanInternalLink (withCgo ) {
294
+ t .Helper ()
309
295
if withCgo && CanInternalLink (false ) {
310
296
t .Skipf ("skipping test: internal linking on %s/%s is not supported with cgo" , runtime .GOOS , runtime .GOARCH )
311
297
}
@@ -316,15 +302,15 @@ func MustInternalLink(t testing.TB, withCgo bool) {
316
302
// MustInternalLinkPIE checks whether the current system can link PIE binary using
317
303
// internal linking.
318
304
// If not, MustInternalLinkPIE calls t.Skip with an explanation.
319
- // Modified by Hugo (not needed)
320
305
func MustInternalLinkPIE (t testing.TB ) {
306
+ // Removed by Hugo, not used.
321
307
}
322
308
323
309
// MustHaveBuildMode reports whether the current system can build programs in
324
310
// the given build mode.
325
311
// If not, MustHaveBuildMode calls t.Skip with an explanation.
326
- // Modified by Hugo (not needed)
327
312
func MustHaveBuildMode (t testing.TB , buildmode string ) {
313
+ // Removed by Hugo, not used.
328
314
}
329
315
330
316
// HasSymlink reports whether the current system can use os.Symlink.
@@ -338,6 +324,7 @@ func HasSymlink() bool {
338
324
func MustHaveSymlink (t testing.TB ) {
339
325
ok , reason := hasSymlink ()
340
326
if ! ok {
327
+ t .Helper ()
341
328
t .Skipf ("skipping test: cannot make symlinks on %s/%s: %s" , runtime .GOOS , runtime .GOARCH , reason )
342
329
}
343
330
}
@@ -354,22 +341,23 @@ func HasLink() bool {
354
341
// If not, MustHaveLink calls t.Skip with an explanation.
355
342
func MustHaveLink (t testing.TB ) {
356
343
if ! HasLink () {
344
+ t .Helper ()
357
345
t .Skipf ("skipping test: hardlinks are not supported on %s/%s" , runtime .GOOS , runtime .GOARCH )
358
346
}
359
347
}
360
348
361
349
var flaky = flag .Bool ("flaky" , false , "run known-flaky tests too" )
362
350
363
351
func SkipFlaky (t testing.TB , issue int ) {
364
- t .Helper ()
365
352
if ! * flaky {
353
+ t .Helper ()
366
354
t .Skipf ("skipping known flaky test without the -flaky flag; see golang.org/issue/%d" , issue )
367
355
}
368
356
}
369
357
370
358
func SkipFlakyNet (t testing.TB ) {
371
- t .Helper ()
372
359
if v , _ := strconv .ParseBool (os .Getenv ("GO_BUILDER_FLAKY_NET" )); v {
360
+ t .Helper ()
373
361
t .Skip ("skipping test on builder known to have frequent network failures" )
374
362
}
375
363
}
@@ -455,6 +443,6 @@ func SyscallIsNotSupported(err error) bool {
455
443
// ParallelOn64Bit calls t.Parallel() unless there is a case that cannot be parallel.
456
444
// This function should be used when it is necessary to avoid t.Parallel on
457
445
// 32-bit machines, typically because the test uses lots of memory.
458
- // Disabled by Hugo.
459
446
func ParallelOn64Bit (t * testing.T ) {
447
+ // Removed by Hugo, not used.
460
448
}
0 commit comments