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  }