import (
"bytes"
- "cmd/go/internal/base"
- "cmd/go/internal/cfg"
"fmt"
"io"
"io/ioutil"
"regexp"
"runtime"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
)
var cmdBug = &base.Command{
cmd.Stderr = os.Stderr
// Run the command in the package directory.
cmd.Dir = g.dir
- cmd.Env = mergeEnvLists(g.env, cfg.OrigEnv)
+ cmd.Env = base.MergeEnvLists(g.env, cfg.OrigEnv)
err := cmd.Run()
if err != nil {
g.errorf("running %q: %s", words[0], err)
import "strings"
-// envForDir returns a copy of the environment
+// EnvForDir returns a copy of the environment
// suitable for running in the given directory.
// The environment is the current process's environment
// but with an updated $PWD, so that an os.Getwd in the
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package test
import (
"bytes"
- "cmd/go/internal/base"
- "cmd/go/internal/cfg"
- "cmd/go/internal/load"
- "cmd/go/internal/str"
- "cmd/go/internal/work"
"errors"
"fmt"
"go/ast"
"time"
"unicode"
"unicode/utf8"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+ "cmd/go/internal/work"
)
// Break init loop.
func init() {
- cmdTest.Run = runTest
+ CmdTest.Run = runTest
}
const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]"
-var cmdTest = &base.Command{
+var CmdTest = &base.Command{
CustomFlags: true,
UsageLine: testUsage,
Short: "test packages",
flags are also accessible by 'go test'.
`
-var helpTestflag = &base.Command{
+// Usage prints the usage message for 'go test -h' and exits.
+func Usage() {
+ os.Stderr.WriteString(testUsage + "\n\n" +
+ strings.TrimSpace(testFlag1) + "\n\n\t" +
+ strings.TrimSpace(testFlag2) + "\n")
+ os.Exit(2)
+}
+
+var HelpTestflag = &base.Command{
UsageLine: "testflag",
Short: "description of testing flags",
Long: `
binary, instead of being interpreted as the package list.
`
-var helpTestfunc = &base.Command{
+var HelpTestfunc = &base.Command{
UsageLine: "testfunc",
Short: "description of testing functions",
Long: `
var pkgArgs []string
pkgArgs, testArgs = testFlags(args)
- findExecCmd() // initialize cached result
+ work.FindExecCmd() // initialize cached result
work.InstrumentInit()
work.BuildModeInit()
// builderRunTest is the action for running a test binary.
func builderRunTest(b *work.Builder, a *work.Action) error {
- args := str.StringList(findExecCmd(), a.Deps[0].Target, testArgs)
+ args := str.StringList(work.FindExecCmd(), a.Deps[0].Target, testArgs)
a.TestOutput = new(bytes.Buffer)
if cfg.BuildN || cfg.BuildX {
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.Package.Dir
- cmd.Env = envForDir(cmd.Dir, cfg.OrigEnv)
+ cmd.Env = base.EnvForDir(cmd.Dir, cfg.OrigEnv)
var buf bytes.Buffer
if testStreamOutput {
cmd.Stdout = os.Stdout
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package test
import (
"flag"
} else {
// Test-only flags.
// Arguably should be handled by f.flagValue, but aren't.
- var err error
switch f.name {
// bool flags.
case "c", "i", "v", "cover":
testO = value
testNeedBinary = true
case "exec":
- execCmd, err = str.SplitQuotedFields(value)
+ xcmd, err := str.SplitQuotedFields(value)
if err != nil {
base.Fatalf("invalid flag argument for -%s: %v", f.name, err)
}
+ work.ExecCmd = xcmd
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "msan")
}
}
+
+// ExecCmd is the command to use to run user binaries.
+// Normally it is empty, meaning run the binaries directly.
+// If cross-compiling and running on a remote system or
+// simulator, it is typically go_GOOS_GOARCH_exec, with
+// the target GOOS and GOARCH substituted.
+// The -exec flag overrides these defaults.
+var ExecCmd []string
+
+// FindExecCmd derives the value of ExecCmd to use.
+// It returns that value and leaves ExecCmd set for direct use.
+func FindExecCmd() []string {
+ if ExecCmd != nil {
+ return ExecCmd
+ }
+ ExecCmd = []string{} // avoid work the second time
+ if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
+ return ExecCmd
+ }
+ path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
+ if err == nil {
+ ExecCmd = []string{path}
+ }
+ return ExecCmd
+}
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/help"
+ "cmd/go/internal/test"
"cmd/go/internal/work"
)
work.CmdInstall,
cmdList,
cmdRun,
- cmdTest,
+ test.CmdTest,
cmdTool,
cmdVersion,
cmdVet,
help.HelpEnvironment,
help.HelpImportPath,
help.HelpPackages,
- helpTestflag,
- helpTestfunc,
+ test.HelpTestflag,
+ test.HelpTestfunc,
}
}
func mainUsage() {
// special case "go test -h"
if len(os.Args) > 1 && os.Args[1] == "test" {
- os.Stderr.WriteString(testUsage + "\n\n" +
- strings.TrimSpace(testFlag1) + "\n\n\t" +
- strings.TrimSpace(testFlag2) + "\n")
- os.Exit(2)
+ test.Usage()
}
help.PrintUsage(os.Stderr)
os.Exit(2)
}
-
-// envForDir returns a copy of the environment
-// suitable for running in the given directory.
-// The environment is the current process's environment
-// but with an updated $PWD, so that an os.Getwd in the
-// child will be faster.
-func envForDir(dir string, base []string) []string {
- // Internally we only use rooted paths, so dir is rooted.
- // Even if dir is not rooted, no harm done.
- return mergeEnvLists([]string{"PWD=" + dir}, base)
-}
-
-// mergeEnvLists merges the two environment lists such that
-// variables with the same name in "in" replace those in "out".
-// This always returns a newly allocated slice.
-func mergeEnvLists(in, out []string) []string {
- out = append([]string(nil), out...)
-NextVar:
- for _, inkv := range in {
- k := strings.SplitAfterN(inkv, "=", 2)[0]
- for i, outkv := range out {
- if strings.HasPrefix(outkv, k) {
- out[i] = inkv
- continue NextVar
- }
- }
- out = append(out, inkv)
- }
- return out
-}
import (
"fmt"
"os"
- "os/exec"
- "runtime"
"strings"
"cmd/go/internal/base"
"cmd/go/internal/work"
)
-var execCmd []string // -exec flag, for run and test
-
-func findExecCmd() []string {
- if execCmd != nil {
- return execCmd
- }
- execCmd = []string{} // avoid work the second time
- if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
- return execCmd
- }
- path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
- if err == nil {
- execCmd = []string{path}
- }
- return execCmd
-}
-
var cmdRun = &base.Command{
UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
Short: "compile and run Go program",
cmdRun.Run = runRun // break init loop
work.AddBuildFlags(cmdRun)
- cmdRun.Flag.Var((*base.StringsFlag)(&execCmd), "exec", "")
+ cmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
}
func printStderr(args ...interface{}) (int, error) {
// buildRunProgram is the action for running a binary that has already
// been compiled. We ignore exit status.
func buildRunProgram(b *work.Builder, a *work.Action) error {
- cmdline := str.StringList(findExecCmd(), a.Deps[0].Target, a.Args)
+ cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].Target, a.Args)
if cfg.BuildN || cfg.BuildX {
b.Showcmd("", "%s", strings.Join(cmdline, " "))
if cfg.BuildN {
Stdout: os.Stdout,
Stderr: os.Stderr,
// Set $GOROOT, mainly for go tool dist.
- Env: mergeEnvLists([]string{"GOROOT=" + cfg.GOROOT}, os.Environ()),
+ Env: base.MergeEnvLists([]string{"GOROOT=" + cfg.GOROOT}, os.Environ()),
}
err := toolCmd.Run()
if err != nil {
import (
"bytes"
- "cmd/go/internal/cfg"
"encoding/json"
"errors"
"fmt"
"regexp"
"strings"
"sync"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
)
// A vcsCmd describes how to use a version control system
cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir
- cmd.Env = envForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
if cfg.BuildX {
fmt.Printf("cd %s\n", dir)
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))