dir string // If non-empty, run in GOROOT/src-relative directory dir
env []string // Environment variables to add, as KEY=VAL. KEY= unsets a variable
+ runOnHost bool // When cross-compiling, run this test on the host instead of guest
+
// We have both pkg and pkgs as a convenience. Both may be set, in which
// case they will be combined. If both are empty, the default is ".".
pkgs []string // Multiple packages to test
// bgCommand returns a go test Cmd. The result has Stdout and Stderr set to nil
// and is intended to be added to the work queue.
func (opts *goTest) bgCommand(t *tester) *exec.Cmd {
- goCmd, build, run, pkgs, setupCmd := opts.buildArgs(t)
+ goCmd, build, run, pkgs, testFlags, setupCmd := opts.buildArgs(t)
// Combine the flags.
args := append([]string{"test"}, build...)
}
args = append(args, pkgs...)
if !t.compileOnly {
- args = append(args, opts.testFlags...)
+ args = append(args, testFlags...)
}
cmd := exec.Command(goCmd, args...)
// the host, but its resulting binaries will be run through a go_exec wrapper
// that runs them on the target.
func (opts *goTest) runHostTest(t *tester) error {
- goCmd, build, run, pkgs, setupCmd := opts.buildArgs(t)
+ goCmd, build, run, pkgs, testFlags, setupCmd := opts.buildArgs(t)
// Build the host test binary
if len(pkgs) != 1 {
}
// Run the test
- args = append(run, opts.testFlags...)
+ args = append(run, testFlags...)
cmd = exec.Command(bin, args...)
setupCmd(cmd)
cmd.Stdout = os.Stdout
// buildArgs is in internal helper for goTest that constructs the elements of
// the "go test" command line. goCmd is the path to the go command to use. build
// is the flags for building the test. run is the flags for running the test.
-// pkgs is the list of packages to build and run.
+// pkgs is the list of packages to build and run. testFlags is the list of flags
+// to pass to the test package.
//
-// The caller is responsible for adding opts.testFlags, and must call setupCmd
-// on the resulting exec.Cmd to set its directory and environment.
-func (opts *goTest) buildArgs(t *tester) (goCmd string, build, run, pkgs []string, setupCmd func(*exec.Cmd)) {
+// The caller must call setupCmd on the resulting exec.Cmd to set its directory
+// and environment.
+func (opts *goTest) buildArgs(t *tester) (goCmd string, build, run, pkgs, testFlags []string, setupCmd func(*exec.Cmd)) {
goCmd = gorootBinGo
if opts.goroot != "" {
goCmd = filepath.Join(opts.goroot, "bin", "go")
pkgs = []string{"."}
}
+ runOnHost := opts.runOnHost && (goarch != gohostarch || goos != gohostos)
+ needTestFlags := len(opts.testFlags) > 0 || runOnHost
+ if needTestFlags {
+ testFlags = append([]string{"-args"}, opts.testFlags...)
+ }
+ if runOnHost {
+ // -target is a special flag understood by tests that can run on the host
+ testFlags = append(testFlags, "-target="+goos+"/"+goarch)
+ }
+
thisGoroot := goroot
if opts.goroot != "" {
thisGoroot = opts.goroot
}
}
}
+ if runOnHost {
+ setEnv(cmd, "GOARCH", gohostarch)
+ setEnv(cmd, "GOOS", gohostos)
+ }
}
return
&goTest{
dir: "internal/testdir",
testFlags: []string{fmt.Sprintf("-shard=%d", shard), fmt.Sprintf("-shards=%d", nShards)},
+ runOnHost: true,
},
- rtHostTest{},
)
}
}
updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output")
runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
force = flag.Bool("f", false, "ignore expected-failure test lists")
+ target = flag.String("target", "", "cross-compile tests for `goos/goarch`")
shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.")
shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.")
var (
// Package-scoped variables that are initialized at the start of Test.
goTool string
- goos string
- goarch string
+ goos string // Target GOOS
+ goarch string // Target GOARCH
cgoEnabled bool
goExperiment string
// Each .go file test case in GOROOT/test is registered as a subtest with a
// a full name like "Test/fixedbugs/bug000.go" ('/'-separated relative path).
func Test(t *testing.T) {
+ if *target != "" {
+ // When -target is set, propagate it to GOOS/GOARCH in our environment
+ // so that all commands run with the target GOOS/GOARCH.
+ //
+ // We do this before even calling "go env", because GOOS/GOARCH can
+ // affect other settings we get from go env (notably CGO_ENABLED).
+ goos, goarch, ok := strings.Cut(*target, "/")
+ if !ok {
+ t.Fatalf("bad -target flag %q, expected goos/goarch", *target)
+ }
+ t.Setenv("GOOS", goos)
+ t.Setenv("GOARCH", goarch)
+ }
+
goTool = testenv.GoToolPath(t)
cmd := exec.Command(goTool, "env", "-json")
stdout, err := cmd.StdoutPipe()