github.com/go-darwin/sys@v0.0.0-20220510002607-68fd01f054ca/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  	"os"
    16  	"os/exec"
    17  	"path/filepath"
    18  	"runtime"
    19  	"strings"
    20  	"testing"
    21  )
    22  
    23  // HasGoBuild reports whether the current system can build programs with “go build”
    24  // and then run them with os.StartProcess or exec.Command.
    25  func HasGoBuild() bool {
    26  	if os.Getenv("GO_GCFLAGS") != "" {
    27  		// It's too much work to require every caller of the go command
    28  		// to pass along "-gcflags="+os.Getenv("GO_GCFLAGS").
    29  		// For now, if $GO_GCFLAGS is set, report that we simply can't
    30  		// run go build.
    31  		return false
    32  	}
    33  	switch runtime.GOOS {
    34  	case "android", "js", "ios":
    35  		return false
    36  	}
    37  	return true
    38  }
    39  
    40  // MustHaveGoBuild checks that the current system can build programs with “go build”
    41  // and then run them with os.StartProcess or exec.Command.
    42  // If not, MustHaveGoBuild calls t.Skip with an explanation.
    43  func MustHaveGoBuild(t testing.TB) {
    44  	if os.Getenv("GO_GCFLAGS") != "" {
    45  		t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS")
    46  	}
    47  	if !HasGoBuild() {
    48  		t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
    49  	}
    50  }
    51  
    52  // KnownEnv is a list of environment variables that affect the operation
    53  // of the Go command.
    54  const KnownEnv = `
    55  	AR
    56  	CC
    57  	CGO_CFLAGS
    58  	CGO_CFLAGS_ALLOW
    59  	CGO_CFLAGS_DISALLOW
    60  	CGO_CPPFLAGS
    61  	CGO_CPPFLAGS_ALLOW
    62  	CGO_CPPFLAGS_DISALLOW
    63  	CGO_CXXFLAGS
    64  	CGO_CXXFLAGS_ALLOW
    65  	CGO_CXXFLAGS_DISALLOW
    66  	CGO_ENABLED
    67  	CGO_FFLAGS
    68  	CGO_FFLAGS_ALLOW
    69  	CGO_FFLAGS_DISALLOW
    70  	CGO_LDFLAGS
    71  	CGO_LDFLAGS_ALLOW
    72  	CGO_LDFLAGS_DISALLOW
    73  	CXX
    74  	FC
    75  	GCCGO
    76  	GO111MODULE
    77  	GO386
    78  	GOAMD64
    79  	GOARCH
    80  	GOARM
    81  	GOBIN
    82  	GOCACHE
    83  	GOENV
    84  	GOEXE
    85  	GOEXPERIMENT
    86  	GOFLAGS
    87  	GOGCCFLAGS
    88  	GOHOSTARCH
    89  	GOHOSTOS
    90  	GOINSECURE
    91  	GOMIPS
    92  	GOMIPS64
    93  	GOMODCACHE
    94  	GONOPROXY
    95  	GONOSUMDB
    96  	GOOS
    97  	GOPATH
    98  	GOPPC64
    99  	GOPRIVATE
   100  	GOPROXY
   101  	GOROOT
   102  	GOSUMDB
   103  	GOTMPDIR
   104  	GOTOOLDIR
   105  	GOVCS
   106  	GOWASM
   107  	GO_EXTLINK_ENABLED
   108  	PKG_CONFIG
   109  `
   110  
   111  // GoToolPath reports the path to the Go tool.
   112  // It is a convenience wrapper around GoTool.
   113  // If the tool is unavailable GoToolPath calls t.Skip.
   114  // If the tool should be available and isn't, GoToolPath calls t.Fatal.
   115  func GoToolPath(t testing.TB) string {
   116  	MustHaveGoBuild(t)
   117  	path, err := GoTool()
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  	// Add all environment variables that affect the Go command to test metadata.
   122  	// Cached test results will be invalidate when these variables change.
   123  	// See golang.org/issue/32285.
   124  	for _, envVar := range strings.Fields(KnownEnv) {
   125  		os.Getenv(envVar)
   126  	}
   127  	return path
   128  }
   129  
   130  // GoTool reports the path to the Go tool.
   131  func GoTool() (string, error) {
   132  	if !HasGoBuild() {
   133  		return "", errors.New("platform cannot run go tool")
   134  	}
   135  	var exeSuffix string
   136  	if runtime.GOOS == "windows" {
   137  		exeSuffix = ".exe"
   138  	}
   139  	path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
   140  	if _, err := os.Stat(path); err == nil {
   141  		return path, nil
   142  	}
   143  	goBin, err := exec.LookPath("go" + exeSuffix)
   144  	if err != nil {
   145  		return "", errors.New("cannot find go tool: " + err.Error())
   146  	}
   147  	return goBin, nil
   148  }
   149  
   150  // CleanCmdEnv will fill cmd.Env with the environment, excluding certain
   151  // variables that could modify the behavior of the Go tools such as
   152  // GODEBUG and GOTRACEBACK.
   153  func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd {
   154  	if cmd.Env != nil {
   155  		panic("environment already set")
   156  	}
   157  	for _, env := range os.Environ() {
   158  		// Exclude GODEBUG from the environment to prevent its output
   159  		// from breaking tests that are trying to parse other command output.
   160  		if strings.HasPrefix(env, "GODEBUG=") {
   161  			continue
   162  		}
   163  		// Exclude GOTRACEBACK for the same reason.
   164  		if strings.HasPrefix(env, "GOTRACEBACK=") {
   165  			continue
   166  		}
   167  		cmd.Env = append(cmd.Env, env)
   168  	}
   169  	return cmd
   170  }