github.com/fisco-bcos/crypto@v0.0.0-20200202032121-bd8ab0b5d4f1/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 "internal/cfg" 17 "os" 18 "os/exec" 19 "path/filepath" 20 "runtime" 21 "strconv" 22 "strings" 23 "sync" 24 "testing" 25 ) 26 27 // Builder reports the name of the builder running this test 28 // (for example, "linux-amd64" or "windows-386-gce"). 29 // If the test is not running on the build infrastructure, 30 // Builder returns the empty string. 31 func Builder() string { 32 return os.Getenv("GO_BUILDER_NAME") 33 } 34 35 // HasGoBuild reports whether the current system can build programs with ``go build'' 36 // and then run them with os.StartProcess or exec.Command. 37 func HasGoBuild() bool { 38 if os.Getenv("GO_GCFLAGS") != "" { 39 // It's too much work to require every caller of the go command 40 // to pass along "-gcflags="+os.Getenv("GO_GCFLAGS"). 41 // For now, if $GO_GCFLAGS is set, report that we simply can't 42 // run go build. 43 return false 44 } 45 switch runtime.GOOS { 46 case "android", "nacl", "js": 47 return false 48 case "darwin": 49 if strings.HasPrefix(runtime.GOARCH, "arm") { 50 return false 51 } 52 } 53 return true 54 } 55 56 // MustHaveGoBuild checks that the current system can build programs with ``go build'' 57 // and then run them with os.StartProcess or exec.Command. 58 // If not, MustHaveGoBuild calls t.Skip with an explanation. 59 func MustHaveGoBuild(t testing.TB) { 60 if os.Getenv("GO_GCFLAGS") != "" { 61 t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS") 62 } 63 if !HasGoBuild() { 64 t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH) 65 } 66 } 67 68 // HasGoRun reports whether the current system can run programs with ``go run.'' 69 func HasGoRun() bool { 70 // For now, having go run and having go build are the same. 71 return HasGoBuild() 72 } 73 74 // MustHaveGoRun checks that the current system can run programs with ``go run.'' 75 // If not, MustHaveGoRun calls t.Skip with an explanation. 76 func MustHaveGoRun(t testing.TB) { 77 if !HasGoRun() { 78 t.Skipf("skipping test: 'go run' not available on %s/%s", runtime.GOOS, runtime.GOARCH) 79 } 80 } 81 82 // GoToolPath reports the path to the Go tool. 83 // It is a convenience wrapper around GoTool. 84 // If the tool is unavailable GoToolPath calls t.Skip. 85 // If the tool should be available and isn't, GoToolPath calls t.Fatal. 86 func GoToolPath(t testing.TB) string { 87 MustHaveGoBuild(t) 88 path, err := GoTool() 89 if err != nil { 90 t.Fatal(err) 91 } 92 // Add all environment variables that affect the Go command to test metadata. 93 // Cached test results will be invalidate when these variables change. 94 // See golang.org/issue/32285. 95 for _, envVar := range strings.Fields(cfg.KnownEnv) { 96 os.Getenv(envVar) 97 } 98 return path 99 } 100 101 // GoTool reports the path to the Go tool. 102 func GoTool() (string, error) { 103 if !HasGoBuild() { 104 return "", errors.New("platform cannot run go tool") 105 } 106 var exeSuffix string 107 if runtime.GOOS == "windows" { 108 exeSuffix = ".exe" 109 } 110 path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) 111 if _, err := os.Stat(path); err == nil { 112 return path, nil 113 } 114 goBin, err := exec.LookPath("go" + exeSuffix) 115 if err != nil { 116 return "", errors.New("cannot find go tool: " + err.Error()) 117 } 118 return goBin, nil 119 } 120 121 // HasExec reports whether the current system can start new processes 122 // using os.StartProcess or (more commonly) exec.Command. 123 func HasExec() bool { 124 switch runtime.GOOS { 125 case "nacl", "js": 126 return false 127 case "darwin": 128 if strings.HasPrefix(runtime.GOARCH, "arm") { 129 return false 130 } 131 } 132 return true 133 } 134 135 // HasSrc reports whether the entire source tree is available under GOROOT. 136 func HasSrc() bool { 137 switch runtime.GOOS { 138 case "nacl": 139 return false 140 case "darwin": 141 if strings.HasPrefix(runtime.GOARCH, "arm") { 142 return false 143 } 144 } 145 return true 146 } 147 148 // MustHaveExec checks that the current system can start new processes 149 // using os.StartProcess or (more commonly) exec.Command. 150 // If not, MustHaveExec calls t.Skip with an explanation. 151 func MustHaveExec(t testing.TB) { 152 if !HasExec() { 153 t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH) 154 } 155 } 156 157 var execPaths sync.Map // path -> error 158 159 // MustHaveExecPath checks that the current system can start the named executable 160 // using os.StartProcess or (more commonly) exec.Command. 161 // If not, MustHaveExecPath calls t.Skip with an explanation. 162 func MustHaveExecPath(t testing.TB, path string) { 163 MustHaveExec(t) 164 165 err, found := execPaths.Load(path) 166 if !found { 167 _, err = exec.LookPath(path) 168 err, _ = execPaths.LoadOrStore(path, err) 169 } 170 if err != nil { 171 t.Skipf("skipping test: %s: %s", path, err) 172 } 173 } 174 175 // HasExternalNetwork reports whether the current system can use 176 // external (non-localhost) networks. 177 func HasExternalNetwork() bool { 178 return !testing.Short() && runtime.GOOS != "nacl" && runtime.GOOS != "js" 179 } 180 181 // MustHaveExternalNetwork checks that the current system can use 182 // external (non-localhost) networks. 183 // If not, MustHaveExternalNetwork calls t.Skip with an explanation. 184 func MustHaveExternalNetwork(t testing.TB) { 185 if runtime.GOOS == "nacl" || runtime.GOOS == "js" { 186 t.Skipf("skipping test: no external network on %s", runtime.GOOS) 187 } 188 if testing.Short() { 189 t.Skipf("skipping test: no external network in -short mode") 190 } 191 } 192 193 var haveCGO bool 194 195 // HasCGO reports whether the current system can use cgo. 196 func HasCGO() bool { 197 return haveCGO 198 } 199 200 // MustHaveCGO calls t.Skip if cgo is not available. 201 func MustHaveCGO(t testing.TB) { 202 if !haveCGO { 203 t.Skipf("skipping test: no cgo") 204 } 205 } 206 207 // HasSymlink reports whether the current system can use os.Symlink. 208 func HasSymlink() bool { 209 ok, _ := hasSymlink() 210 return ok 211 } 212 213 // MustHaveSymlink reports whether the current system can use os.Symlink. 214 // If not, MustHaveSymlink calls t.Skip with an explanation. 215 func MustHaveSymlink(t testing.TB) { 216 ok, reason := hasSymlink() 217 if !ok { 218 t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason) 219 } 220 } 221 222 // HasLink reports whether the current system can use os.Link. 223 func HasLink() bool { 224 // From Android release M (Marshmallow), hard linking files is blocked 225 // and an attempt to call link() on a file will return EACCES. 226 // - https://code.google.com/p/android-developer-preview/issues/detail?id=3150 227 return runtime.GOOS != "plan9" && runtime.GOOS != "android" 228 } 229 230 // MustHaveLink reports whether the current system can use os.Link. 231 // If not, MustHaveLink calls t.Skip with an explanation. 232 func MustHaveLink(t testing.TB) { 233 if !HasLink() { 234 t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 235 } 236 } 237 238 var flaky = flag.Bool("flaky", false, "run known-flaky tests too") 239 240 func SkipFlaky(t testing.TB, issue int) { 241 t.Helper() 242 if !*flaky { 243 t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue) 244 } 245 } 246 247 func SkipFlakyNet(t testing.TB) { 248 t.Helper() 249 if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v { 250 t.Skip("skipping test on builder known to have frequent network failures") 251 } 252 } 253 254 // CleanCmdEnv will fill cmd.Env with the environment, excluding certain 255 // variables that could modify the behavior of the Go tools such as 256 // GODEBUG and GOTRACEBACK. 257 func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd { 258 if cmd.Env != nil { 259 panic("environment already set") 260 } 261 for _, env := range os.Environ() { 262 // Exclude GODEBUG from the environment to prevent its output 263 // from breaking tests that are trying to parse other command output. 264 if strings.HasPrefix(env, "GODEBUG=") { 265 continue 266 } 267 // Exclude GOTRACEBACK for the same reason. 268 if strings.HasPrefix(env, "GOTRACEBACK=") { 269 continue 270 } 271 cmd.Env = append(cmd.Env, env) 272 } 273 return cmd 274 }