summaryrefslogtreecommitdiff
path: root/src/cmd/go/test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/go/test.go')
-rw-r--r--src/cmd/go/test.go161
1 files changed, 119 insertions, 42 deletions
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 870ab190f..3132ab210 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -48,6 +48,7 @@ followed by detailed output for each failed package.
'Go test' recompiles each package along with any files with names matching
the file pattern "*_test.go". These additional files can contain test functions,
benchmark functions, and example functions. See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
By default, go test needs no arguments. It compiles and tests the package
with source in the current directory, including tests, and runs the tests.
@@ -80,28 +81,47 @@ var helpTestflag = &Command{
The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
-The test binary, called pkg.test, where pkg is the name of the
-directory containing the package sources, has its own flags:
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
- -test.v
- Verbose output: log all tests as they are run.
-
- -test.run pattern
- Run only those tests and examples matching the regular
- expression.
-
- -test.bench pattern
+ -bench regexp
Run benchmarks matching the regular expression.
- By default, no benchmarks run.
+ By default, no benchmarks run. To run all benchmarks,
+ use '-bench .' or '-bench=.'.
+
+ -benchmem
+ Print memory allocation statistics for benchmarks.
+
+ -benchtime t
+ Run enough iterations of each benchmark to take t, specified
+ as a time.Duration (for example, -benchtime 1h30s).
+ The default is 1 second (1s).
+
+ -blockprofile block.out
+ Write a goroutine blocking profile to the specified file
+ when all tests are complete.
+
+ -blockprofilerate n
+ Control the detail provided in goroutine blocking profiles by setting
+ runtime.BlockProfileRate to n. See 'godoc runtime BlockProfileRate'.
+ The profiler aims to sample, on average, one blocking event every
+ n nanoseconds the program spends blocked. By default,
+ if -test.blockprofile is set without this flag, all blocking events
+ are recorded, equivalent to -test.blockprofilerate=1.
+
+ -cpu 1,2,4
+ Specify a list of GOMAXPROCS values for which the tests or
+ benchmarks should be executed. The default is the current value
+ of GOMAXPROCS.
- -test.cpuprofile cpu.out
+ -cpuprofile cpu.out
Write a CPU profile to the specified file before exiting.
- -test.memprofile mem.out
+ -memprofile mem.out
Write a memory profile to the specified file when all tests
are complete.
- -test.memprofilerate n
+ -memprofilerate n
Enable more precise (and expensive) memory profiles by setting
runtime.MemProfileRate. See 'godoc runtime MemProfileRate'.
To profile all memory allocations, use -test.memprofilerate=1
@@ -109,38 +129,46 @@ directory containing the package sources, has its own flags:
garbage collector, provided the test can run in the available
memory without garbage collection.
- -test.parallel n
+ -parallel n
Allow parallel execution of test functions that call t.Parallel.
The value of this flag is the maximum number of tests to run
simultaneously; by default, it is set to the value of GOMAXPROCS.
- -test.short
+ -run regexp
+ Run only those tests and examples matching the regular
+ expression.
+
+ -short
Tell long-running tests to shorten their run time.
It is off by default but set during all.bash so that installing
the Go tree can run a sanity check but not spend time running
exhaustive tests.
- -test.timeout t
+ -timeout t
If a test runs longer than t, panic.
- -test.benchtime n
- Run enough iterations of each benchmark to take n seconds.
- The default is 1 second.
+ -v
+ Verbose output: log all tests as they are run.
- -test.cpu 1,2,4
- Specify a list of GOMAXPROCS values for which the tests or
- benchmarks should be executed. The default is the current value
- of GOMAXPROCS.
+The test binary, called pkg.test where pkg is the name of the
+directory containing the package sources, can be invoked directly
+after building it with 'go test -c'. When invoking the test binary
+directly, each of the standard flag names must be prefixed with 'test.',
+as in -test.run=TestMyFunc or -test.v.
-For convenience, each of these -test.X flags of the test binary is
-also available as the flag -X in 'go test' itself. Flags not listed
-here are passed through unaltered. For instance, the command
+When running 'go test', flags not listed above are passed through
+unaltered. For instance, the command
go test -x -v -cpuprofile=prof.out -dir=testdata -update
will compile the test binary and then run it as
pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+The test flags that generate profiles also leave the test binary in pkg.test
+for use when analyzing the profiles.
+
+Flags not recognized by 'go test' must be placed after any specified packages.
`,
}
@@ -160,8 +188,8 @@ A benchmark function is one named BenchmarkXXX and should have the signature,
func BenchmarkXXX(b *testing.B) { ... }
-An example function is similar to a test function but, instead of using *testing.T
-to report success or failure, prints output to os.Stdout and os.Stderr.
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
That output is compared against the function's "Output:" comment, which
must be the last comment in the function body (see example below). An
example with no such comment, or with no text after "Output:" is compiled
@@ -191,6 +219,7 @@ See the documentation of the testing package for more information.
var (
testC bool // -c flag
+ testProfile bool // some profiling flag
testI bool // -i flag
testV bool // -v flag
testFiles []string // -file flag(s) TODO: not respected
@@ -207,6 +236,7 @@ func runTest(cmd *Command, args []string) {
var pkgArgs []string
pkgArgs, testArgs = testFlags(args)
+ raceInit()
pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 {
fatalf("no packages to test")
@@ -215,12 +245,15 @@ func runTest(cmd *Command, args []string) {
if testC && len(pkgs) != 1 {
fatalf("cannot use -c flag with multiple packages")
}
+ if testProfile && len(pkgs) != 1 {
+ fatalf("cannot use test profile flag with multiple packages")
+ }
// If a test timeout was given and is parseable, set our kill timeout
// to that timeout plus one minute. This is a backup alarm in case
// the test wedges with a goroutine spinning and its background
// timer does not get a chance to fire.
- if dt, err := time.ParseDuration(testTimeout); err == nil {
+ if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
testKillTimeout = dt + 1*time.Minute
}
@@ -276,7 +309,9 @@ func runTest(cmd *Command, args []string) {
all := []string{}
for path := range deps {
- all = append(all, path)
+ if !build.IsLocalImport(path) {
+ all = append(all, path)
+ }
}
sort.Strings(all)
@@ -361,7 +396,11 @@ func runTest(cmd *Command, args []string) {
if args != "" {
args = " " + args
}
- fmt.Fprintf(os.Stderr, "installing these packages with 'go test -i%s' will speed future tests.\n\n", args)
+ extraOpts := ""
+ if buildRace {
+ extraOpts = "-race "
+ }
+ fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
}
b.do(root)
@@ -405,7 +444,14 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// Use last element of import path, not package name.
// They differ when package name is "main".
- _, elem := path.Split(p.ImportPath)
+ // But if the import path is "command-line-arguments",
+ // like it is during 'go run', use the package name.
+ var elem string
+ if p.ImportPath == "command-line-arguments" {
+ elem = p.Name
+ } else {
+ _, elem = path.Split(p.ImportPath)
+ }
testBinary := elem + ".test"
// The ptest package needs to be importable under the
@@ -532,14 +578,17 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
a.target = filepath.Join(testDir, testBinary) + exeSuffix
pmainAction := a
- if testC {
- // -c flag: create action to copy binary to ./test.out.
+ if testC || testProfile {
+ // -c or profiling flag: create action to copy binary to ./test.out.
runAction = &action{
f: (*builder).install,
deps: []*action{pmainAction},
p: pmain,
- target: testBinary + exeSuffix,
+ target: filepath.Join(cwd, testBinary+exeSuffix),
}
+ pmainAction = runAction // in case we are running the test
+ }
+ if testC {
printAction = &action{p: p, deps: []*action{runAction}} // nop
} else {
// run test
@@ -586,6 +635,7 @@ func (b *builder) runTest(a *action) error {
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.p.Dir
+ cmd.Env = envForDir(cmd.Dir)
var buf bytes.Buffer
if testStreamOutput {
cmd.Stdout = os.Stdout
@@ -595,14 +645,34 @@ func (b *builder) runTest(a *action) error {
cmd.Stderr = &buf
}
+ // If there are any local SWIG dependencies, we want to load
+ // the shared library from the build directory.
+ if a.p.usesSwig() {
+ env := cmd.Env
+ found := false
+ prefix := "LD_LIBRARY_PATH="
+ for i, v := range env {
+ if strings.HasPrefix(v, prefix) {
+ env[i] = v + ":."
+ found = true
+ break
+ }
+ }
+ if !found {
+ env = append(env, "LD_LIBRARY_PATH=.")
+ }
+ cmd.Env = env
+ }
+
t0 := time.Now()
err := cmd.Start()
// This is a last-ditch deadline to detect and
// stop wedged test binaries, to keep the builders
// running.
- tick := time.NewTimer(testKillTimeout)
if err == nil {
+ tick := time.NewTimer(testKillTimeout)
+ startSigHandlers()
done := make(chan error)
go func() {
done <- cmd.Wait()
@@ -613,13 +683,12 @@ func (b *builder) runTest(a *action) error {
case <-tick.C:
cmd.Process.Kill()
err = <-done
- fmt.Fprintf(&buf, "*** Test killed: ran too long.\n")
+ fmt.Fprintf(&buf, "*** Test killed: ran too long (%v).\n", testKillTimeout)
}
tick.Stop()
}
out := buf.Bytes()
- t1 := time.Now()
- t := fmt.Sprintf("%.3fs", t1.Sub(t0).Seconds())
+ t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
if err == nil {
if testShowPass {
a.testOutput.Write(out)
@@ -750,8 +819,10 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error {
*seen = true
}
}
- for _, e := range doc.Examples(f) {
- if e.Output == "" {
+ ex := doc.Examples(f)
+ sort.Sort(byOrder(ex))
+ for _, e := range ex {
+ if e.Output == "" && !e.EmptyOutput {
// Don't run examples with no output.
continue
}
@@ -761,6 +832,12 @@ func (t *testFuncs) load(filename, pkg string, seen *bool) error {
return nil
}
+type byOrder []*doc.Example
+
+func (x byOrder) Len() int { return len(x) }
+func (x byOrder) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order }
+
var testmainTmpl = template.Must(template.New("main").Parse(`
package main