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  }