Home | History | Annotate | Download | only in testenv
      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.T) {
     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.T) {
     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.T) 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 // MustHaveExec checks that the current system can start new processes
    118 // using os.StartProcess or (more commonly) exec.Command.
    119 // If not, MustHaveExec calls t.Skip with an explanation.
    120 func MustHaveExec(t *testing.T) {
    121 	if !HasExec() {
    122 		t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
    123 	}
    124 }
    125 
    126 // HasExternalNetwork reports whether the current system can use
    127 // external (non-localhost) networks.
    128 func HasExternalNetwork() bool {
    129 	return !testing.Short()
    130 }
    131 
    132 // MustHaveExternalNetwork checks that the current system can use
    133 // external (non-localhost) networks.
    134 // If not, MustHaveExternalNetwork calls t.Skip with an explanation.
    135 func MustHaveExternalNetwork(t *testing.T) {
    136 	if testing.Short() {
    137 		t.Skipf("skipping test: no external network in -short mode")
    138 	}
    139 }
    140 
    141 // HasSymlink reports whether the current system can use os.Symlink.
    142 func HasSymlink() bool {
    143 	ok, _ := hasSymlink()
    144 	return ok
    145 }
    146 
    147 // MustHaveSymlink reports whether the current system can use os.Symlink.
    148 // If not, MustHaveSymlink calls t.Skip with an explanation.
    149 func MustHaveSymlink(t *testing.T) {
    150 	ok, reason := hasSymlink()
    151 	if !ok {
    152 		t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason)
    153 	}
    154 }
    155 
    156 // HasLink reports whether the current system can use os.Link.
    157 func HasLink() bool {
    158 	// From Android release M (Marshmallow), hard linking files is blocked
    159 	// and an attempt to call link() on a file will return EACCES.
    160 	// - https://code.google.com/p/android-developer-preview/issues/detail?id=3150
    161 	return runtime.GOOS != "plan9" && runtime.GOOS != "android"
    162 }
    163 
    164 // MustHaveLink reports whether the current system can use os.Link.
    165 // If not, MustHaveLink calls t.Skip with an explanation.
    166 func MustHaveLink(t *testing.T) {
    167 	if !HasLink() {
    168 		t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
    169 	}
    170 }
    171 
    172 var flaky = flag.Bool("flaky", false, "run known-flaky tests too")
    173 
    174 func SkipFlaky(t *testing.T, issue int) {
    175 	if !*flaky {
    176 		t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue)
    177 	}
    178 }
    179 
    180 func SkipFlakyNet(t *testing.T) {
    181 	if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v {
    182 		t.Skip("skipping test on builder known to have frequent network failures")
    183 	}
    184 }
    185