1
2
3
4
5
6
7
8
9
10
11 package testenv
12
13 import (
14 "errors"
15 "flag"
16 "internal/cfg"
17 "os"
18 "os/exec"
19 "path/filepath"
20 "runtime"
21 "strconv"
22 "strings"
23 "sync"
24 "testing"
25 )
26
27
28
29
30
31 func Builder() string {
32 return os.Getenv("GO_BUILDER_NAME")
33 }
34
35
36
37 func HasGoBuild() bool {
38 if os.Getenv("GO_GCFLAGS") != "" {
39
40
41
42
43 return false
44 }
45 switch runtime.GOOS {
46 case "android", "js", "ios":
47 return false
48 }
49 return true
50 }
51
52
53
54
55 func MustHaveGoBuild(t testing.TB) {
56 if os.Getenv("GO_GCFLAGS") != "" {
57 t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS")
58 }
59 if !HasGoBuild() {
60 t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
61 }
62 }
63
64
65 func HasGoRun() bool {
66
67 return HasGoBuild()
68 }
69
70
71
72 func MustHaveGoRun(t testing.TB) {
73 if !HasGoRun() {
74 t.Skipf("skipping test: 'go run' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
75 }
76 }
77
78
79
80
81
82 func GoToolPath(t testing.TB) string {
83 MustHaveGoBuild(t)
84 path, err := GoTool()
85 if err != nil {
86 t.Fatal(err)
87 }
88
89
90
91 for _, envVar := range strings.Fields(cfg.KnownEnv) {
92 os.Getenv(envVar)
93 }
94 return path
95 }
96
97
98 func GoTool() (string, error) {
99 if !HasGoBuild() {
100 return "", errors.New("platform cannot run go tool")
101 }
102 var exeSuffix string
103 if runtime.GOOS == "windows" {
104 exeSuffix = ".exe"
105 }
106 path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
107 if _, err := os.Stat(path); err == nil {
108 return path, nil
109 }
110 goBin, err := exec.LookPath("go" + exeSuffix)
111 if err != nil {
112 return "", errors.New("cannot find go tool: " + err.Error())
113 }
114 return goBin, nil
115 }
116
117
118
119 func HasExec() bool {
120 switch runtime.GOOS {
121 case "js", "ios":
122 return false
123 }
124 return true
125 }
126
127
128 func HasSrc() bool {
129 switch runtime.GOOS {
130 case "ios":
131 return false
132 }
133 return true
134 }
135
136
137
138
139 func MustHaveExec(t testing.TB) {
140 if !HasExec() {
141 t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
142 }
143 }
144
145 var execPaths sync.Map
146
147
148
149
150 func MustHaveExecPath(t testing.TB, path string) {
151 MustHaveExec(t)
152
153 err, found := execPaths.Load(path)
154 if !found {
155 _, err = exec.LookPath(path)
156 err, _ = execPaths.LoadOrStore(path, err)
157 }
158 if err != nil {
159 t.Skipf("skipping test: %s: %s", path, err)
160 }
161 }
162
163
164
165 func HasExternalNetwork() bool {
166 return !testing.Short() && runtime.GOOS != "js"
167 }
168
169
170
171
172 func MustHaveExternalNetwork(t testing.TB) {
173 if runtime.GOOS == "js" {
174 t.Skipf("skipping test: no external network on %s", runtime.GOOS)
175 }
176 if testing.Short() {
177 t.Skipf("skipping test: no external network in -short mode")
178 }
179 }
180
181 var haveCGO bool
182
183
184 func HasCGO() bool {
185 return haveCGO
186 }
187
188
189 func MustHaveCGO(t testing.TB) {
190 if !haveCGO {
191 t.Skipf("skipping test: no cgo")
192 }
193 }
194
195
196
197
198 func CanInternalLink() bool {
199 switch runtime.GOOS {
200 case "android":
201 if runtime.GOARCH != "arm64" {
202 return false
203 }
204 case "ios":
205 if runtime.GOARCH == "arm64" {
206 return false
207 }
208 }
209 return true
210 }
211
212
213
214
215 func MustInternalLink(t testing.TB) {
216 if !CanInternalLink() {
217 t.Skipf("skipping test: internal linking on %s/%s is not supported", runtime.GOOS, runtime.GOARCH)
218 }
219 }
220
221
222 func HasSymlink() bool {
223 ok, _ := hasSymlink()
224 return ok
225 }
226
227
228
229 func MustHaveSymlink(t testing.TB) {
230 ok, reason := hasSymlink()
231 if !ok {
232 t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason)
233 }
234 }
235
236
237 func HasLink() bool {
238
239
240
241 return runtime.GOOS != "plan9" && runtime.GOOS != "android"
242 }
243
244
245
246 func MustHaveLink(t testing.TB) {
247 if !HasLink() {
248 t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
249 }
250 }
251
252 var flaky = flag.Bool("flaky", false, "run known-flaky tests too")
253
254 func SkipFlaky(t testing.TB, issue int) {
255 t.Helper()
256 if !*flaky {
257 t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue)
258 }
259 }
260
261 func SkipFlakyNet(t testing.TB) {
262 t.Helper()
263 if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v {
264 t.Skip("skipping test on builder known to have frequent network failures")
265 }
266 }
267
268
269
270
271 func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd {
272 if cmd.Env != nil {
273 panic("environment already set")
274 }
275 for _, env := range os.Environ() {
276
277
278 if strings.HasPrefix(env, "GODEBUG=") {
279 continue
280 }
281
282 if strings.HasPrefix(env, "GOTRACEBACK=") {
283 continue
284 }
285 cmd.Env = append(cmd.Env, env)
286 }
287 return cmd
288 }
289
290
291 func CPUIsSlow() bool {
292 switch runtime.GOARCH {
293 case "arm", "mips", "mipsle", "mips64", "mips64le":
294 return true
295 }
296 return false
297 }
298
299
300
301
302
303 func SkipIfShortAndSlow(t testing.TB) {
304 if testing.Short() && CPUIsSlow() {
305 t.Helper()
306 t.Skipf("skipping test in -short mode on %s", runtime.GOARCH)
307 }
308 }
309
View as plain text