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