github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/internal/testenv/testenv.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package testenv provides information about what functionality 6 // is available in different testing environments run by the Go team. 7 // 8 // It is an internal package because these details are specific 9 // to the Go team's test setup (on build.golang.org) and not 10 // fundamental to tests in general. 11 package testenv 12 13 import ( 14 "errors" 15 "flag" 16 "os" 17 "os/exec" 18 "path/filepath" 19 "runtime" 20 "strconv" 21 "strings" 22 "testing" 23 ) 24 25 // Builder reports the name of the builder running this test 26 // (for example, "linux-amd64" or "windows-386-gce"). 27 // If the test is not running on the build infrastructure, 28 // Builder returns the empty string. 29 func Builder() string { 30 return os.Getenv("GO_BUILDER_NAME") 31 } 32 33 // HasGoBuild reports whether the current system can build programs with ``go build'' 34 // and then run them with os.StartProcess or exec.Command. 35 func HasGoBuild() bool { 36 switch runtime.GOOS { 37 case "android", "nacl": 38 return false 39 case "darwin": 40 if strings.HasPrefix(runtime.GOARCH, "arm") { 41 return false 42 } 43 } 44 return true 45 } 46 47 // MustHaveGoBuild checks that the current system can build programs with ``go build'' 48 // and then run them with os.StartProcess or exec.Command. 49 // If not, MustHaveGoBuild calls t.Skip with an explanation. 50 func MustHaveGoBuild(t testing.TB) { 51 if !HasGoBuild() { 52 t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH) 53 } 54 } 55 56 // HasGoRun reports whether the current system can run programs with ``go run.'' 57 func HasGoRun() bool { 58 // For now, having go run and having go build are the same. 59 return HasGoBuild() 60 } 61 62 // MustHaveGoRun checks that the current system can run programs with ``go run.'' 63 // If not, MustHaveGoRun calls t.Skip with an explanation. 64 func MustHaveGoRun(t testing.TB) { 65 if !HasGoRun() { 66 t.Skipf("skipping test: 'go run' not available on %s/%s", runtime.GOOS, runtime.GOARCH) 67 } 68 } 69 70 // GoToolPath reports the path to the Go tool. 71 // It is a convenience wrapper around GoTool. 72 // If the tool is unavailable GoToolPath calls t.Skip. 73 // If the tool should be available and isn't, GoToolPath calls t.Fatal. 74 func GoToolPath(t testing.TB) string { 75 MustHaveGoBuild(t) 76 path, err := GoTool() 77 if err != nil { 78 t.Fatal(err) 79 } 80 return path 81 } 82 83 // GoTool reports the path to the Go tool. 84 func GoTool() (string, error) { 85 if !HasGoBuild() { 86 return "", errors.New("platform cannot run go tool") 87 } 88 var exeSuffix string 89 if runtime.GOOS == "windows" { 90 exeSuffix = ".exe" 91 } 92 path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) 93 if _, err := os.Stat(path); err == nil { 94 return path, nil 95 } 96 goBin, err := exec.LookPath("go" + exeSuffix) 97 if err != nil { 98 return "", errors.New("cannot find go tool: " + err.Error()) 99 } 100 return goBin, nil 101 } 102 103 // HasExec reports whether the current system can start new processes 104 // using os.StartProcess or (more commonly) exec.Command. 105 func HasExec() bool { 106 switch runtime.GOOS { 107 case "nacl": 108 return false 109 case "darwin": 110 if strings.HasPrefix(runtime.GOARCH, "arm") { 111 return false 112 } 113 } 114 return true 115 } 116 117 // HasSrc reports whether the entire source tree is available under GOROOT. 118 func HasSrc() bool { 119 switch runtime.GOOS { 120 case "nacl": 121 return false 122 case "darwin": 123 if strings.HasPrefix(runtime.GOARCH, "arm") { 124 return false 125 } 126 } 127 return true 128 } 129 130 // MustHaveExec checks that the current system can start new processes 131 // using os.StartProcess or (more commonly) exec.Command. 132 // If not, MustHaveExec calls t.Skip with an explanation. 133 func MustHaveExec(t testing.TB) { 134 if !HasExec() { 135 t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH) 136 } 137 } 138 139 // HasExternalNetwork reports whether the current system can use 140 // external (non-localhost) networks. 141 func HasExternalNetwork() bool { 142 return !testing.Short() 143 } 144 145 // MustHaveExternalNetwork checks that the current system can use 146 // external (non-localhost) networks. 147 // If not, MustHaveExternalNetwork calls t.Skip with an explanation. 148 func MustHaveExternalNetwork(t testing.TB) { 149 if testing.Short() { 150 t.Skipf("skipping test: no external network in -short mode") 151 } 152 } 153 154 var haveCGO bool 155 156 // HasCGO reports whether the current system can use cgo. 157 func HasCGO() bool { 158 return haveCGO 159 } 160 161 // MustHaveCGO calls t.Skip if cgo is not available. 162 func MustHaveCGO(t testing.TB) { 163 if !haveCGO { 164 t.Skipf("skipping test: no cgo") 165 } 166 } 167 168 // HasSymlink reports whether the current system can use os.Symlink. 169 func HasSymlink() bool { 170 ok, _ := hasSymlink() 171 return ok 172 } 173 174 // MustHaveSymlink reports whether the current system can use os.Symlink. 175 // If not, MustHaveSymlink calls t.Skip with an explanation. 176 func MustHaveSymlink(t testing.TB) { 177 ok, reason := hasSymlink() 178 if !ok { 179 t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason) 180 } 181 } 182 183 // HasLink reports whether the current system can use os.Link. 184 func HasLink() bool { 185 // From Android release M (Marshmallow), hard linking files is blocked 186 // and an attempt to call link() on a file will return EACCES. 187 // - https://code.google.com/p/android-developer-preview/issues/detail?id=3150 188 return runtime.GOOS != "plan9" && runtime.GOOS != "android" 189 } 190 191 // MustHaveLink reports whether the current system can use os.Link. 192 // If not, MustHaveLink calls t.Skip with an explanation. 193 func MustHaveLink(t testing.TB) { 194 if !HasLink() { 195 t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 196 } 197 } 198 199 var flaky = flag.Bool("flaky", false, "run known-flaky tests too") 200 201 func SkipFlaky(t testing.TB, issue int) { 202 if !*flaky { 203 t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue) 204 } 205 } 206 207 func SkipFlakyNet(t testing.TB) { 208 if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v { 209 t.Skip("skipping test on builder known to have frequent network failures") 210 } 211 } 212 213 // CleanCmdEnv will fill cmd.Env with the environment, excluding certain 214 // variables that could modify the behavior of the Go tools such as 215 // GODEBUG and GOTRACEBACK. 216 func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd { 217 if cmd.Env != nil { 218 panic("environment already set") 219 } 220 for _, env := range os.Environ() { 221 // Exclude GODEBUG from the environment to prevent its output 222 // from breaking tests that are trying to parse other command output. 223 if strings.HasPrefix(env, "GODEBUG=") { 224 continue 225 } 226 // Exclude GOTRACEBACK for the same reason. 227 if strings.HasPrefix(env, "GOTRACEBACK=") { 228 continue 229 } 230 cmd.Env = append(cmd.Env, env) 231 } 232 return cmd 233 }