2008-11-18 15:29:10 -08:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2011-04-20 09:57:05 +10:00
|
|
|
// Package testing provides support for automated testing of Go packages.
|
2012-01-17 14:20:27 -08:00
|
|
|
// It is intended to be used in concert with the ``go test'' command, which automates
|
2009-03-05 17:50:36 -08:00
|
|
|
// execution of any function of the form
|
|
|
|
|
// func TestXxx(*testing.T)
|
2010-02-07 23:11:54 -08:00
|
|
|
// where Xxx can be any alphanumeric string (but the first letter must not be in
|
2009-03-05 17:50:36 -08:00
|
|
|
// [a-z]) and serves to identify the test routine.
|
2009-11-19 16:35:34 -08:00
|
|
|
//
|
2014-02-21 14:35:54 -08:00
|
|
|
// Within these functions, use the Error, Fail or related methods to signal failure.
|
|
|
|
|
//
|
|
|
|
|
// To write a new test suite, create a file whose name ends _test.go that
|
|
|
|
|
// contains the TestXxx functions as described here. Put the file in the same
|
|
|
|
|
// package as the one being tested. The file will be excluded from regular
|
|
|
|
|
// package builds but will be included when the ``go test'' command is run.
|
|
|
|
|
// For more detail, run ``go help test'' and ``go help testflag''.
|
|
|
|
|
//
|
|
|
|
|
// Tests and benchmarks may be skipped if not applicable with a call to
|
|
|
|
|
// the Skip method of *T and *B:
|
testing: add Skip/Skipf
This proposal adds two methods to *testing.T, Skip(string) and Skipf(format, args...). The intent is to replace the existing log and return idiom which currently has 97 cases in the standard library. A simple example of Skip would be:
func TestSomethingLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
// not reached
}
... time consuming work
}
Additionally tests can be skipped anywhere a *testing.T is present. An example adapted from the go.crypto/ssh/test package would be:
// setup performs some before test action and returns a func()
// which should be defered by the caller for cleanup.
func setup(t *testing.T) func() {
...
cmd := exec.Command("sshd", "-f", configfile, "-i")
if err := cmd.Run(); err != nil {
t.Skipf("could not execute mock ssh server: %v", err)
}
...
return func() {
// stop subprocess and cleanup
}
}
func TestDialMockServer(t *testing.T) {
cleanup := setup(t)
defer cleanup()
...
}
In verbose mode tests that are skipped are now reported as a SKIP, rather than PASS.
Link to discussion: https://groups.google.com/d/topic/golang-nuts/BqorNARzt4U/discussion
R=adg, rsc, r, n13m3y3r
CC=golang-dev, minux.ma
https://golang.org/cl/6501094
2013-01-23 10:22:33 +11:00
|
|
|
// func TestTimeConsuming(t *testing.T) {
|
|
|
|
|
// if testing.Short() {
|
|
|
|
|
// t.Skip("skipping test in short mode.")
|
|
|
|
|
// }
|
|
|
|
|
// ...
|
|
|
|
|
// }
|
|
|
|
|
//
|
2013-04-05 13:43:18 +11:00
|
|
|
// Benchmarks
|
|
|
|
|
//
|
2009-11-19 16:35:34 -08:00
|
|
|
// Functions of the form
|
|
|
|
|
// func BenchmarkXxx(*testing.B)
|
2012-02-10 13:49:50 +11:00
|
|
|
// are considered benchmarks, and are executed by the "go test" command when
|
2013-06-17 07:32:28 -07:00
|
|
|
// its -bench flag is provided. Benchmarks are run sequentially.
|
2012-10-30 13:38:01 -07:00
|
|
|
//
|
2012-09-24 13:05:47 -07:00
|
|
|
// For a description of the testing flags, see
|
2015-07-10 17:17:11 -06:00
|
|
|
// https://golang.org/cmd/go/#hdr-Description_of_testing_flags.
|
2009-11-19 16:35:34 -08:00
|
|
|
//
|
|
|
|
|
// A sample benchmark function looks like this:
|
|
|
|
|
// func BenchmarkHello(b *testing.B) {
|
|
|
|
|
// for i := 0; i < b.N; i++ {
|
|
|
|
|
// fmt.Sprintf("hello")
|
|
|
|
|
// }
|
|
|
|
|
// }
|
2012-01-17 14:20:27 -08:00
|
|
|
//
|
2013-02-09 13:43:15 -05:00
|
|
|
// The benchmark function must run the target code b.N times.
|
2015-05-12 19:19:29 -04:00
|
|
|
// During benchmark execution, b.N is adjusted until the benchmark function lasts
|
2016-03-01 23:21:55 +00:00
|
|
|
// long enough to be timed reliably. The output
|
2012-10-03 11:41:18 +08:00
|
|
|
// BenchmarkHello 10000000 282 ns/op
|
2011-12-20 09:51:39 -08:00
|
|
|
// means that the loop ran 10000000 times at a speed of 282 ns per loop.
|
2009-11-19 16:35:34 -08:00
|
|
|
//
|
|
|
|
|
// If a benchmark needs some expensive setup before running, the timer
|
2012-10-03 11:41:18 +08:00
|
|
|
// may be reset:
|
2014-02-17 06:29:56 +04:00
|
|
|
//
|
2009-11-19 16:35:34 -08:00
|
|
|
// func BenchmarkBigLen(b *testing.B) {
|
2010-04-11 10:18:49 -07:00
|
|
|
// big := NewBig()
|
2012-10-03 11:41:18 +08:00
|
|
|
// b.ResetTimer()
|
2009-11-19 16:35:34 -08:00
|
|
|
// for i := 0; i < b.N; i++ {
|
2010-04-11 10:18:49 -07:00
|
|
|
// big.Len()
|
2009-11-19 16:35:34 -08:00
|
|
|
// }
|
|
|
|
|
// }
|
2012-01-17 14:20:27 -08:00
|
|
|
//
|
2014-02-17 06:29:56 +04:00
|
|
|
// If a benchmark needs to test performance in a parallel setting, it may use
|
|
|
|
|
// the RunParallel helper function; such benchmarks are intended to be used with
|
|
|
|
|
// the go test -cpu flag:
|
|
|
|
|
//
|
|
|
|
|
// func BenchmarkTemplateParallel(b *testing.B) {
|
|
|
|
|
// templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
|
|
|
|
|
// b.RunParallel(func(pb *testing.PB) {
|
|
|
|
|
// var buf bytes.Buffer
|
|
|
|
|
// for pb.Next() {
|
|
|
|
|
// buf.Reset()
|
|
|
|
|
// templ.Execute(&buf, "World")
|
|
|
|
|
// }
|
|
|
|
|
// })
|
|
|
|
|
// }
|
|
|
|
|
//
|
2013-04-05 13:43:18 +11:00
|
|
|
// Examples
|
|
|
|
|
//
|
2012-02-16 11:50:28 +11:00
|
|
|
// The package also runs and verifies example code. Example functions may
|
2013-02-22 12:23:19 +11:00
|
|
|
// include a concluding line comment that begins with "Output:" and is compared with
|
2013-01-12 11:18:15 +11:00
|
|
|
// the standard output of the function when the tests are run. (The comparison
|
|
|
|
|
// ignores leading and trailing space.) These are examples of an example:
|
2012-01-17 14:20:27 -08:00
|
|
|
//
|
|
|
|
|
// func ExampleHello() {
|
2017-04-10 20:57:45 +02:00
|
|
|
// fmt.Println("hello")
|
|
|
|
|
// // Output: hello
|
2012-01-17 14:20:27 -08:00
|
|
|
// }
|
|
|
|
|
//
|
2012-02-16 11:50:28 +11:00
|
|
|
// func ExampleSalutations() {
|
2017-04-10 20:57:45 +02:00
|
|
|
// fmt.Println("hello, and")
|
|
|
|
|
// fmt.Println("goodbye")
|
|
|
|
|
// // Output:
|
|
|
|
|
// // hello, and
|
|
|
|
|
// // goodbye
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// The comment prefix "Unordered output:" is like "Output:", but matches any
|
|
|
|
|
// line order:
|
|
|
|
|
//
|
|
|
|
|
// func ExamplePerm() {
|
|
|
|
|
// for _, value := range Perm(4) {
|
|
|
|
|
// fmt.Println(value)
|
|
|
|
|
// }
|
|
|
|
|
// // Unordered output: 4
|
|
|
|
|
// // 2
|
|
|
|
|
// // 1
|
|
|
|
|
// // 3
|
|
|
|
|
// // 0
|
2012-02-16 11:50:28 +11:00
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// Example functions without output comments are compiled but not executed.
|
2012-01-17 14:20:27 -08:00
|
|
|
//
|
2013-11-11 12:09:24 +11:00
|
|
|
// The naming convention to declare examples for the package, a function F, a type T and
|
2012-01-17 14:20:27 -08:00
|
|
|
// method M on type T are:
|
|
|
|
|
//
|
2013-11-11 12:09:24 +11:00
|
|
|
// func Example() { ... }
|
2012-01-17 14:20:27 -08:00
|
|
|
// func ExampleF() { ... }
|
|
|
|
|
// func ExampleT() { ... }
|
|
|
|
|
// func ExampleT_M() { ... }
|
|
|
|
|
//
|
2013-11-11 12:09:24 +11:00
|
|
|
// Multiple example functions for a package/type/function/method may be provided by
|
2012-01-17 14:20:27 -08:00
|
|
|
// appending a distinct suffix to the name. The suffix must start with a
|
|
|
|
|
// lower-case letter.
|
|
|
|
|
//
|
2013-11-11 12:09:24 +11:00
|
|
|
// func Example_suffix() { ... }
|
2012-01-17 14:20:27 -08:00
|
|
|
// func ExampleF_suffix() { ... }
|
|
|
|
|
// func ExampleT_suffix() { ... }
|
|
|
|
|
// func ExampleT_M_suffix() { ... }
|
|
|
|
|
//
|
2012-02-14 17:19:59 +11:00
|
|
|
// The entire test file is presented as the example when it contains a single
|
|
|
|
|
// example function, at least one other function, type, variable, or constant
|
|
|
|
|
// declaration, and no test or benchmark functions.
|
2014-09-19 13:51:06 -04:00
|
|
|
//
|
2016-05-24 20:03:31 +02:00
|
|
|
// Subtests and Sub-benchmarks
|
|
|
|
|
//
|
|
|
|
|
// The Run methods of T and B allow defining subtests and sub-benchmarks,
|
|
|
|
|
// without having to define separate functions for each. This enables uses
|
|
|
|
|
// like table-driven benchmarks and creating hierarchical tests.
|
|
|
|
|
// It also provides a way to share common setup and tear-down code:
|
|
|
|
|
//
|
|
|
|
|
// func TestFoo(t *testing.T) {
|
|
|
|
|
// // <setup code>
|
|
|
|
|
// t.Run("A=1", func(t *testing.T) { ... })
|
|
|
|
|
// t.Run("A=2", func(t *testing.T) { ... })
|
|
|
|
|
// t.Run("B=1", func(t *testing.T) { ... })
|
|
|
|
|
// // <tear-down code>
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// Each subtest and sub-benchmark has a unique name: the combination of the name
|
|
|
|
|
// of the top-level test and the sequence of names passed to Run, separated by
|
|
|
|
|
// slashes, with an optional trailing sequence number for disambiguation.
|
|
|
|
|
//
|
2016-09-12 13:17:02 +10:00
|
|
|
// The argument to the -run and -bench command-line flags is an unanchored regular
|
|
|
|
|
// expression that matches the test's name. For tests with multiple slash-separated
|
|
|
|
|
// elements, such as subtests, the argument is itself slash-separated, with
|
|
|
|
|
// expressions matching each name element in turn. Because it is unanchored, an
|
|
|
|
|
// empty expression matches any string.
|
|
|
|
|
// For example, using "matching" to mean "whose name contains":
|
|
|
|
|
//
|
|
|
|
|
// go test -run '' # Run all tests.
|
|
|
|
|
// go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar".
|
|
|
|
|
// go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=".
|
|
|
|
|
// go test -run /A=1 # For all top-level tests, run subtests matching "A=1".
|
2016-05-24 20:03:31 +02:00
|
|
|
//
|
|
|
|
|
// Subtests can also be used to control parallelism. A parent test will only
|
|
|
|
|
// complete once all of its subtests complete. In this example, all tests are
|
|
|
|
|
// run in parallel with each other, and only with each other, regardless of
|
|
|
|
|
// other top-level tests that may be defined:
|
|
|
|
|
//
|
|
|
|
|
// func TestGroupedParallel(t *testing.T) {
|
|
|
|
|
// for _, tc := range tests {
|
|
|
|
|
// tc := tc // capture range variable
|
|
|
|
|
// t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
|
// t.Parallel()
|
|
|
|
|
// ...
|
|
|
|
|
// })
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// Run does not return until parallel subtests have completed, providing a way
|
|
|
|
|
// to clean up after a group of parallel tests:
|
|
|
|
|
//
|
|
|
|
|
// func TestTeardownParallel(t *testing.T) {
|
|
|
|
|
// // This Run will not return until the parallel tests finish.
|
|
|
|
|
// t.Run("group", func(t *testing.T) {
|
|
|
|
|
// t.Run("Test1", parallelTest1)
|
|
|
|
|
// t.Run("Test2", parallelTest2)
|
|
|
|
|
// t.Run("Test3", parallelTest3)
|
|
|
|
|
// })
|
|
|
|
|
// // <tear-down code>
|
|
|
|
|
// }
|
|
|
|
|
//
|
2014-09-19 13:51:06 -04:00
|
|
|
// Main
|
|
|
|
|
//
|
|
|
|
|
// It is sometimes necessary for a test program to do extra setup or teardown
|
|
|
|
|
// before or after testing. It is also sometimes necessary for a test to control
|
|
|
|
|
// which code runs on the main thread. To support these and other cases,
|
|
|
|
|
// if a test file contains a function:
|
|
|
|
|
//
|
|
|
|
|
// func TestMain(m *testing.M)
|
|
|
|
|
//
|
|
|
|
|
// then the generated test will call TestMain(m) instead of running the tests
|
|
|
|
|
// directly. TestMain runs in the main goroutine and can do whatever setup
|
|
|
|
|
// and teardown is necessary around a call to m.Run. It should then call
|
2015-03-15 21:08:57 -04:00
|
|
|
// os.Exit with the result of m.Run. When TestMain is called, flag.Parse has
|
|
|
|
|
// not been run. If TestMain depends on command-line flags, including those
|
|
|
|
|
// of the testing package, it should call flag.Parse explicitly.
|
2014-09-19 13:51:06 -04:00
|
|
|
//
|
2015-03-15 21:08:57 -04:00
|
|
|
// A simple implementation of TestMain is:
|
2014-09-19 13:51:06 -04:00
|
|
|
//
|
2015-03-15 21:08:57 -04:00
|
|
|
// func TestMain(m *testing.M) {
|
2016-11-16 12:26:23 +00:00
|
|
|
// // call flag.Parse() here if TestMain uses flags
|
2015-03-15 21:08:57 -04:00
|
|
|
// os.Exit(m.Run())
|
|
|
|
|
// }
|
2014-09-19 13:51:06 -04:00
|
|
|
//
|
2008-11-18 15:29:10 -08:00
|
|
|
package testing
|
|
|
|
|
|
2008-11-18 17:52:05 -08:00
|
|
|
import (
|
2012-07-17 07:56:25 +02:00
|
|
|
"bytes"
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
"errors"
|
2009-12-15 15:41:46 -08:00
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
2016-11-02 21:40:47 -04:00
|
|
|
"internal/race"
|
2016-01-19 22:43:52 +01:00
|
|
|
"io"
|
2009-12-15 15:41:46 -08:00
|
|
|
"os"
|
2017-06-04 00:29:40 -04:00
|
|
|
"os/signal"
|
2009-12-15 15:41:46 -08:00
|
|
|
"runtime"
|
2015-12-18 11:24:55 -05:00
|
|
|
"runtime/debug"
|
2015-07-22 13:09:26 +02:00
|
|
|
"runtime/trace"
|
2017-06-04 00:29:40 -04:00
|
|
|
"sort"
|
2011-06-27 13:31:40 -04:00
|
|
|
"strconv"
|
2011-10-06 09:58:36 -07:00
|
|
|
"strings"
|
2012-07-25 10:17:27 -07:00
|
|
|
"sync"
|
2017-01-18 00:05:32 -05:00
|
|
|
"sync/atomic"
|
2017-06-04 00:29:40 -04:00
|
|
|
"syscall"
|
2011-02-11 18:00:58 -05:00
|
|
|
"time"
|
2008-11-18 17:52:05 -08:00
|
|
|
)
|
|
|
|
|
|
2011-03-16 09:53:58 -07:00
|
|
|
var (
|
2011-03-25 14:50:44 -07:00
|
|
|
// The short flag requests that tests run more quickly, but its functionality
|
2016-03-01 23:21:55 +00:00
|
|
|
// is provided by test writers themselves. The testing package is just its
|
|
|
|
|
// home. The all.bash installation script sets it to make installation more
|
2012-02-10 13:49:50 +11:00
|
|
|
// efficient, but by default the flag is off so a plain "go test" will do a
|
2011-03-25 14:50:44 -07:00
|
|
|
// full test of the package.
|
|
|
|
|
short = flag.Bool("test.short", false, "run smaller test suite to save time")
|
|
|
|
|
|
2013-06-12 18:13:34 -07:00
|
|
|
// The directory in which to create profile files and the like. When run from
|
|
|
|
|
// "go test", the binary always runs in the source directory for the package;
|
|
|
|
|
// this flag lets "go test" tell the binary to write the files in the directory where
|
|
|
|
|
// the "go test" command is run.
|
2016-10-17 23:30:38 -04:00
|
|
|
outputDir = flag.String("test.outputdir", "", "write profiles to `dir`")
|
2013-06-12 18:13:34 -07:00
|
|
|
|
2011-03-16 09:53:58 -07:00
|
|
|
// Report as tests are run; default is silent for success.
|
2016-09-22 09:48:30 -04:00
|
|
|
chatty = flag.Bool("test.v", false, "verbose: print additional output")
|
|
|
|
|
count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
|
|
|
|
|
coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to `file`")
|
2017-04-20 10:26:10 -06:00
|
|
|
matchList = flag.String("test.list", "", "list tests, examples, and benchmarch maching `regexp` then exit")
|
2016-09-22 09:48:30 -04:00
|
|
|
match = flag.String("test.run", "", "run only tests and examples matching `regexp`")
|
|
|
|
|
memProfile = flag.String("test.memprofile", "", "write a memory profile to `file`")
|
|
|
|
|
memProfileRate = flag.Int("test.memprofilerate", 0, "set memory profiling `rate` (see runtime.MemProfileRate)")
|
|
|
|
|
cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to `file`")
|
|
|
|
|
blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to `file`")
|
|
|
|
|
blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
|
|
|
|
|
mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
|
|
|
|
|
mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
|
|
|
|
|
traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
|
2017-06-14 20:11:21 -07:00
|
|
|
timeout = flag.Duration("test.timeout", 0, "panic test binary after duration `d` (0 means unlimited)")
|
2016-09-22 09:48:30 -04:00
|
|
|
cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
|
|
|
|
|
parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
|
2011-06-27 13:31:40 -04:00
|
|
|
|
2012-03-07 14:54:31 -05:00
|
|
|
haveExamples bool // are there examples?
|
|
|
|
|
|
2011-06-27 13:31:40 -04:00
|
|
|
cpuList []int
|
2017-06-04 00:29:40 -04:00
|
|
|
|
|
|
|
|
inProgressMu sync.Mutex // guards this group of fields
|
|
|
|
|
inProgressRegistry = make(map[string]int)
|
|
|
|
|
inProgressIdx int
|
2011-03-16 09:53:58 -07:00
|
|
|
)
|
2009-06-04 15:40:28 -07:00
|
|
|
|
2011-12-20 09:51:39 -08:00
|
|
|
// common holds the elements common between T and B and
|
|
|
|
|
// captures common methods such as Errorf.
|
|
|
|
|
type common struct {
|
2017-04-20 16:19:55 -04:00
|
|
|
mu sync.RWMutex // guards this group of fields
|
|
|
|
|
output []byte // Output generated by test or benchmark.
|
|
|
|
|
w io.Writer // For flushToParent.
|
|
|
|
|
ran bool // Test or benchmark (or one of its subtests) was executed.
|
|
|
|
|
failed bool // Test or benchmark has failed.
|
|
|
|
|
skipped bool // Test of benchmark has been skipped.
|
|
|
|
|
done bool // Test is finished and all subtests have completed.
|
|
|
|
|
helpers map[string]struct{} // functions to be skipped when writing file/line info
|
|
|
|
|
|
|
|
|
|
chatty bool // A copy of the chatty flag.
|
|
|
|
|
finished bool // Test function has completed.
|
|
|
|
|
hasSub int32 // written atomically
|
|
|
|
|
raceErrors int // number of races detected during test
|
|
|
|
|
runner string // function name of tRunner running the test
|
2012-07-25 10:17:27 -07:00
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
parent *common
|
2016-01-29 16:55:35 +01:00
|
|
|
level int // Nesting depth of test or benchmark.
|
2016-01-19 22:43:52 +01:00
|
|
|
name string // Name of test or benchmark.
|
2011-12-20 09:51:39 -08:00
|
|
|
start time.Time // Time test or benchmark started
|
|
|
|
|
duration time.Duration
|
2016-01-19 22:43:52 +01:00
|
|
|
barrier chan bool // To signal parallel subtests they may start.
|
|
|
|
|
signal chan bool // To signal a test is done.
|
|
|
|
|
sub []*T // Queue of subtests to be run in parallel.
|
2011-12-20 09:51:39 -08:00
|
|
|
}
|
|
|
|
|
|
2011-03-25 14:50:44 -07:00
|
|
|
// Short reports whether the -test.short flag is set.
|
|
|
|
|
func Short() bool {
|
|
|
|
|
return *short
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-01 11:01:39 -07:00
|
|
|
// CoverMode reports what the test coverage mode is set to. The
|
|
|
|
|
// values are "set", "count", or "atomic". The return value will be
|
|
|
|
|
// empty if test coverage is not enabled.
|
|
|
|
|
func CoverMode() string {
|
|
|
|
|
return cover.Mode
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-09 23:41:09 +08:00
|
|
|
// Verbose reports whether the -test.v flag is set.
|
|
|
|
|
func Verbose() bool {
|
|
|
|
|
return *chatty
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-29 15:04:40 -07:00
|
|
|
// frameSkip searches, starting after skip frames, for the first caller frame
|
|
|
|
|
// in a function not marked as a helper and returns the frames to skip
|
|
|
|
|
// to reach that site. The search stops if it finds a tRunner function that
|
|
|
|
|
// was the entry point into the test.
|
|
|
|
|
// This function must be called with c.mu held.
|
|
|
|
|
func (c *common) frameSkip(skip int) int {
|
|
|
|
|
if c.helpers == nil {
|
|
|
|
|
return skip
|
|
|
|
|
}
|
|
|
|
|
var pc [50]uintptr
|
|
|
|
|
// Skip two extra frames to account for this function
|
|
|
|
|
// and runtime.Callers itself.
|
|
|
|
|
n := runtime.Callers(skip+2, pc[:])
|
|
|
|
|
if n == 0 {
|
|
|
|
|
panic("testing: zero callers found")
|
|
|
|
|
}
|
|
|
|
|
frames := runtime.CallersFrames(pc[:n])
|
|
|
|
|
var frame runtime.Frame
|
|
|
|
|
more := true
|
|
|
|
|
for i := 0; more; i++ {
|
|
|
|
|
frame, more = frames.Next()
|
2017-04-20 16:19:55 -04:00
|
|
|
if frame.Function == c.runner {
|
2017-03-29 15:04:40 -07:00
|
|
|
// We've gone up all the way to the tRunner calling
|
|
|
|
|
// the test function (so the user must have
|
|
|
|
|
// called tb.Helper from inside that test function).
|
|
|
|
|
// Only skip up to the test function itself.
|
|
|
|
|
return skip + i - 1
|
|
|
|
|
}
|
2017-04-20 16:19:55 -04:00
|
|
|
if _, ok := c.helpers[frame.Function]; !ok {
|
2017-03-29 15:04:40 -07:00
|
|
|
// Found a frame that wasn't inside a helper function.
|
|
|
|
|
return skip + i
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return skip
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-17 07:56:25 +02:00
|
|
|
// decorate prefixes the string with the file and line of the call site
|
|
|
|
|
// and inserts the final newline if needed and indentation tabs for formatting.
|
2017-03-29 15:04:40 -07:00
|
|
|
// This function must be called with c.mu held.
|
|
|
|
|
func (c *common) decorate(s string) string {
|
|
|
|
|
skip := c.frameSkip(3) // decorate + log + public function.
|
|
|
|
|
_, file, line, ok := runtime.Caller(skip)
|
2012-07-17 07:56:25 +02:00
|
|
|
if ok {
|
|
|
|
|
// Truncate file name at last file name separator.
|
|
|
|
|
if index := strings.LastIndex(file, "/"); index >= 0 {
|
|
|
|
|
file = file[index+1:]
|
|
|
|
|
} else if index = strings.LastIndex(file, "\\"); index >= 0 {
|
|
|
|
|
file = file[index+1:]
|
2011-11-10 11:59:50 -08:00
|
|
|
}
|
2012-07-17 07:56:25 +02:00
|
|
|
} else {
|
|
|
|
|
file = "???"
|
|
|
|
|
line = 1
|
2011-11-10 11:59:50 -08:00
|
|
|
}
|
2012-07-17 07:56:25 +02:00
|
|
|
buf := new(bytes.Buffer)
|
2013-02-21 14:17:43 -08:00
|
|
|
// Every line is indented at least one tab.
|
|
|
|
|
buf.WriteByte('\t')
|
2012-07-17 07:56:25 +02:00
|
|
|
fmt.Fprintf(buf, "%s:%d: ", file, line)
|
|
|
|
|
lines := strings.Split(s, "\n")
|
2012-10-08 00:21:53 +08:00
|
|
|
if l := len(lines); l > 1 && lines[l-1] == "" {
|
|
|
|
|
lines = lines[:l-1]
|
|
|
|
|
}
|
2012-07-17 07:56:25 +02:00
|
|
|
for i, line := range lines {
|
|
|
|
|
if i > 0 {
|
2011-11-10 11:59:50 -08:00
|
|
|
// Second and subsequent lines are indented an extra tab.
|
2013-02-21 14:17:43 -08:00
|
|
|
buf.WriteString("\n\t\t")
|
2008-11-20 18:10:46 -08:00
|
|
|
}
|
2012-07-17 07:56:25 +02:00
|
|
|
buf.WriteString(line)
|
|
|
|
|
}
|
2012-10-08 00:21:53 +08:00
|
|
|
buf.WriteByte('\n')
|
2012-07-17 07:56:25 +02:00
|
|
|
return buf.String()
|
2008-11-20 18:10:46 -08:00
|
|
|
}
|
|
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
// flushToParent writes c.output to the parent after first writing the header
|
|
|
|
|
// with the given format and arguments.
|
|
|
|
|
func (c *common) flushToParent(format string, args ...interface{}) {
|
|
|
|
|
p := c.parent
|
|
|
|
|
p.mu.Lock()
|
|
|
|
|
defer p.mu.Unlock()
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(p.w, format, args...)
|
|
|
|
|
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
io.Copy(p.w, bytes.NewReader(c.output))
|
|
|
|
|
c.output = c.output[:0]
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-25 16:27:23 +01:00
|
|
|
type indenter struct {
|
|
|
|
|
c *common
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w indenter) Write(b []byte) (n int, err error) {
|
|
|
|
|
n = len(b)
|
|
|
|
|
for len(b) > 0 {
|
|
|
|
|
end := bytes.IndexByte(b, '\n')
|
|
|
|
|
if end == -1 {
|
|
|
|
|
end = len(b)
|
|
|
|
|
} else {
|
|
|
|
|
end++
|
|
|
|
|
}
|
|
|
|
|
// An indent of 4 spaces will neatly align the dashes with the status
|
|
|
|
|
// indicator of the parent.
|
|
|
|
|
const indent = " "
|
|
|
|
|
w.c.output = append(w.c.output, indent...)
|
|
|
|
|
w.c.output = append(w.c.output, b[:end]...)
|
|
|
|
|
b = b[end:]
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-18 10:59:25 -07:00
|
|
|
// fmtDuration returns a string representing d in the form "87.00s".
|
|
|
|
|
func fmtDuration(d time.Duration) string {
|
|
|
|
|
return fmt.Sprintf("%.2fs", d.Seconds())
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 23:21:32 -07:00
|
|
|
// TB is the interface common to T and B.
|
|
|
|
|
type TB interface {
|
|
|
|
|
Error(args ...interface{})
|
|
|
|
|
Errorf(format string, args ...interface{})
|
|
|
|
|
Fail()
|
|
|
|
|
FailNow()
|
|
|
|
|
Failed() bool
|
|
|
|
|
Fatal(args ...interface{})
|
|
|
|
|
Fatalf(format string, args ...interface{})
|
|
|
|
|
Log(args ...interface{})
|
|
|
|
|
Logf(format string, args ...interface{})
|
2016-09-28 13:31:33 +10:00
|
|
|
Name() string
|
2013-08-14 23:21:32 -07:00
|
|
|
Skip(args ...interface{})
|
|
|
|
|
SkipNow()
|
|
|
|
|
Skipf(format string, args ...interface{})
|
|
|
|
|
Skipped() bool
|
2017-03-29 15:04:40 -07:00
|
|
|
Helper()
|
2013-08-14 23:21:32 -07:00
|
|
|
|
|
|
|
|
// A private method to prevent users implementing the
|
|
|
|
|
// interface and so future additions to it will not
|
|
|
|
|
// violate Go 1 compatibility.
|
|
|
|
|
private()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ TB = (*T)(nil)
|
|
|
|
|
var _ TB = (*B)(nil)
|
|
|
|
|
|
2009-03-05 17:50:36 -08:00
|
|
|
// T is a type passed to Test functions to manage test state and support formatted test logs.
|
2016-06-21 15:17:56 -07:00
|
|
|
// Logs are accumulated during execution and dumped to standard output when done.
|
2015-11-25 16:15:45 -05:00
|
|
|
//
|
|
|
|
|
// A test ends when its Test function returns or calls any of the methods
|
|
|
|
|
// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as
|
|
|
|
|
// the Parallel method, must be called only from the goroutine running the
|
|
|
|
|
// Test function.
|
|
|
|
|
//
|
|
|
|
|
// The other reporting methods, such as the variations of Log and Error,
|
|
|
|
|
// may be called simultaneously from multiple goroutines.
|
2009-01-20 14:40:40 -08:00
|
|
|
type T struct {
|
2011-12-20 09:51:39 -08:00
|
|
|
common
|
2016-01-19 22:43:52 +01:00
|
|
|
isParallel bool
|
|
|
|
|
context *testContext // For running tests and subtests.
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2013-08-14 23:21:32 -07:00
|
|
|
func (c *common) private() {}
|
|
|
|
|
|
2016-09-28 13:31:33 +10:00
|
|
|
// Name returns the name of the running test or benchmark.
|
|
|
|
|
func (c *common) Name() string {
|
|
|
|
|
return c.name
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-20 14:29:30 -03:00
|
|
|
func (c *common) setRan() {
|
|
|
|
|
if c.parent != nil {
|
|
|
|
|
c.parent.setRan()
|
|
|
|
|
}
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
c.ran = true
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-20 09:51:39 -08:00
|
|
|
// Fail marks the function as having failed but continues execution.
|
2012-07-25 10:17:27 -07:00
|
|
|
func (c *common) Fail() {
|
2016-01-19 22:43:52 +01:00
|
|
|
if c.parent != nil {
|
|
|
|
|
c.parent.Fail()
|
|
|
|
|
}
|
2012-07-25 10:17:27 -07:00
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
2016-05-21 14:37:29 +02:00
|
|
|
// c.done needs to be locked to synchronize checks to c.done in parent tests.
|
|
|
|
|
if c.done {
|
|
|
|
|
panic("Fail in goroutine after " + c.name + " has completed")
|
|
|
|
|
}
|
2012-07-25 10:17:27 -07:00
|
|
|
c.failed = true
|
|
|
|
|
}
|
2008-11-19 14:38:05 -08:00
|
|
|
|
testing: add Skip/Skipf
This proposal adds two methods to *testing.T, Skip(string) and Skipf(format, args...). The intent is to replace the existing log and return idiom which currently has 97 cases in the standard library. A simple example of Skip would be:
func TestSomethingLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
// not reached
}
... time consuming work
}
Additionally tests can be skipped anywhere a *testing.T is present. An example adapted from the go.crypto/ssh/test package would be:
// setup performs some before test action and returns a func()
// which should be defered by the caller for cleanup.
func setup(t *testing.T) func() {
...
cmd := exec.Command("sshd", "-f", configfile, "-i")
if err := cmd.Run(); err != nil {
t.Skipf("could not execute mock ssh server: %v", err)
}
...
return func() {
// stop subprocess and cleanup
}
}
func TestDialMockServer(t *testing.T) {
cleanup := setup(t)
defer cleanup()
...
}
In verbose mode tests that are skipped are now reported as a SKIP, rather than PASS.
Link to discussion: https://groups.google.com/d/topic/golang-nuts/BqorNARzt4U/discussion
R=adg, rsc, r, n13m3y3r
CC=golang-dev, minux.ma
https://golang.org/cl/6501094
2013-01-23 10:22:33 +11:00
|
|
|
// Failed reports whether the function has failed.
|
2012-07-25 10:17:27 -07:00
|
|
|
func (c *common) Failed() bool {
|
|
|
|
|
c.mu.RLock()
|
2017-04-06 18:47:01 -07:00
|
|
|
failed := c.failed
|
|
|
|
|
c.mu.RUnlock()
|
|
|
|
|
return failed || c.raceErrors+race.Errors() > 0
|
2012-07-25 10:17:27 -07:00
|
|
|
}
|
2009-05-19 11:00:55 -07:00
|
|
|
|
2011-12-20 09:51:39 -08:00
|
|
|
// FailNow marks the function as having failed and stops its execution.
|
2012-02-10 13:49:50 +11:00
|
|
|
// Execution will continue at the next test or benchmark.
|
2013-02-01 21:01:32 -05:00
|
|
|
// FailNow must be called from the goroutine running the
|
|
|
|
|
// test or benchmark function, not from other goroutines
|
|
|
|
|
// created during the test. Calling FailNow does not stop
|
|
|
|
|
// those other goroutines.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) FailNow() {
|
|
|
|
|
c.Fail()
|
2012-01-12 10:18:12 -08:00
|
|
|
|
|
|
|
|
// Calling runtime.Goexit will exit the goroutine, which
|
|
|
|
|
// will run the deferred functions in this goroutine,
|
|
|
|
|
// which will eventually run the deferred lines in tRunner,
|
|
|
|
|
// which will signal to the test loop that this test is done.
|
|
|
|
|
//
|
|
|
|
|
// A previous version of this code said:
|
|
|
|
|
//
|
|
|
|
|
// c.duration = ...
|
|
|
|
|
// c.signal <- c.self
|
|
|
|
|
// runtime.Goexit()
|
|
|
|
|
//
|
|
|
|
|
// This previous version duplicated code (those lines are in
|
|
|
|
|
// tRunner no matter what), but worse the goroutine teardown
|
|
|
|
|
// implicit in runtime.Goexit was not guaranteed to complete
|
2016-03-01 23:21:55 +00:00
|
|
|
// before the test exited. If a test deferred an important cleanup
|
2012-01-12 10:18:12 -08:00
|
|
|
// function (like removing temporary files), there was no guarantee
|
2016-03-01 23:21:55 +00:00
|
|
|
// it would run on a test failure. Because we send on c.signal during
|
2012-01-12 10:18:12 -08:00
|
|
|
// a top-of-stack deferred function now, we know that the send
|
|
|
|
|
// only happens after any other stacked defers have completed.
|
2014-01-22 16:34:02 -05:00
|
|
|
c.finished = true
|
2009-12-15 15:41:46 -08:00
|
|
|
runtime.Goexit()
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2011-11-10 11:59:50 -08:00
|
|
|
// log generates the output. It's always at the same stack depth.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) log(s string) {
|
2012-07-25 10:17:27 -07:00
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
2017-03-29 15:04:40 -07:00
|
|
|
c.output = append(c.output, c.decorate(s)...)
|
2011-12-20 09:51:39 -08:00
|
|
|
}
|
2011-11-10 11:59:50 -08:00
|
|
|
|
2013-02-01 21:01:32 -05:00
|
|
|
// Log formats its arguments using default formatting, analogous to Println,
|
2015-05-06 13:19:30 -07:00
|
|
|
// and records the text in the error log. For tests, the text will be printed only if
|
|
|
|
|
// the test fails or the -test.v flag is set. For benchmarks, the text is always
|
|
|
|
|
// printed to avoid having performance depend on the value of the -test.v flag.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
|
2008-11-19 14:38:05 -08:00
|
|
|
|
2016-10-16 11:28:45 -07:00
|
|
|
// Logf formats its arguments according to the format, analogous to Printf, and
|
|
|
|
|
// records the text in the error log. A final newline is added if not provided. For
|
|
|
|
|
// tests, the text will be printed only if the test fails or the -test.v flag is
|
|
|
|
|
// set. For benchmarks, the text is always printed to avoid having performance
|
|
|
|
|
// depend on the value of the -test.v flag.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
|
2008-11-19 14:38:05 -08:00
|
|
|
|
2013-02-01 21:01:32 -05:00
|
|
|
// Error is equivalent to Log followed by Fail.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Error(args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintln(args...))
|
|
|
|
|
c.Fail()
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2013-02-01 21:01:32 -05:00
|
|
|
// Errorf is equivalent to Logf followed by Fail.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Errorf(format string, args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintf(format, args...))
|
|
|
|
|
c.Fail()
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2013-02-01 21:01:32 -05:00
|
|
|
// Fatal is equivalent to Log followed by FailNow.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Fatal(args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintln(args...))
|
|
|
|
|
c.FailNow()
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2013-02-01 21:01:32 -05:00
|
|
|
// Fatalf is equivalent to Logf followed by FailNow.
|
2011-12-20 09:51:39 -08:00
|
|
|
func (c *common) Fatalf(format string, args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintf(format, args...))
|
|
|
|
|
c.FailNow()
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2013-02-23 11:57:51 +11:00
|
|
|
// Skip is equivalent to Log followed by SkipNow.
|
|
|
|
|
func (c *common) Skip(args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintln(args...))
|
|
|
|
|
c.SkipNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skipf is equivalent to Logf followed by SkipNow.
|
|
|
|
|
func (c *common) Skipf(format string, args ...interface{}) {
|
|
|
|
|
c.log(fmt.Sprintf(format, args...))
|
|
|
|
|
c.SkipNow()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SkipNow marks the test as having been skipped and stops its execution.
|
2016-10-18 10:46:55 -04:00
|
|
|
// If a test fails (see Error, Errorf, Fail) and is then skipped,
|
|
|
|
|
// it is still considered to have failed.
|
2013-02-23 11:57:51 +11:00
|
|
|
// Execution will continue at the next test or benchmark. See also FailNow.
|
|
|
|
|
// SkipNow must be called from the goroutine running the test, not from
|
|
|
|
|
// other goroutines created during the test. Calling SkipNow does not stop
|
|
|
|
|
// those other goroutines.
|
|
|
|
|
func (c *common) SkipNow() {
|
|
|
|
|
c.skip()
|
2014-01-22 16:34:02 -05:00
|
|
|
c.finished = true
|
2013-02-23 11:57:51 +11:00
|
|
|
runtime.Goexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *common) skip() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
c.skipped = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skipped reports whether the test was skipped.
|
|
|
|
|
func (c *common) Skipped() bool {
|
|
|
|
|
c.mu.RLock()
|
|
|
|
|
defer c.mu.RUnlock()
|
|
|
|
|
return c.skipped
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-29 15:04:40 -07:00
|
|
|
// Helper marks the calling function as a test helper function.
|
|
|
|
|
// When printing file and line information, that function will be skipped.
|
|
|
|
|
// Helper may be called simultaneously from multiple goroutines.
|
|
|
|
|
// Helper has no effect if it is called directly from a TestXxx/BenchmarkXxx
|
|
|
|
|
// function or a subtest/sub-benchmark function.
|
|
|
|
|
func (c *common) Helper() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
if c.helpers == nil {
|
2017-04-20 16:19:55 -04:00
|
|
|
c.helpers = make(map[string]struct{})
|
2017-03-29 15:04:40 -07:00
|
|
|
}
|
2017-04-20 16:19:55 -04:00
|
|
|
c.helpers[callerName(1)] = struct{}{}
|
2017-03-29 15:04:40 -07:00
|
|
|
}
|
|
|
|
|
|
2017-04-20 16:19:55 -04:00
|
|
|
// callerName gives the function name (qualified with a package path)
|
|
|
|
|
// for the caller after skip frames (where 0 means the current function).
|
|
|
|
|
func callerName(skip int) string {
|
|
|
|
|
// Make room for the skip PC.
|
|
|
|
|
var pc [2]uintptr
|
|
|
|
|
n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName
|
2017-03-29 15:04:40 -07:00
|
|
|
if n == 0 {
|
|
|
|
|
panic("testing: zero callers found")
|
|
|
|
|
}
|
2017-04-20 16:19:55 -04:00
|
|
|
frames := runtime.CallersFrames(pc[:n])
|
2017-03-29 15:04:40 -07:00
|
|
|
frame, _ := frames.Next()
|
2017-04-20 16:19:55 -04:00
|
|
|
return frame.Function
|
2017-03-29 15:04:40 -07:00
|
|
|
}
|
|
|
|
|
|
2012-10-30 13:38:01 -07:00
|
|
|
// Parallel signals that this test is to be run in parallel with (and only with)
|
2017-02-03 10:18:04 +00:00
|
|
|
// other parallel tests. When a test is run multiple times due to use of
|
|
|
|
|
// -test.count or -test.cpu, multiple instances of a single test never run in
|
|
|
|
|
// parallel with each other.
|
2011-10-06 09:58:36 -07:00
|
|
|
func (t *T) Parallel() {
|
2015-12-29 12:10:01 -05:00
|
|
|
if t.isParallel {
|
|
|
|
|
panic("testing: t.Parallel called multiple times")
|
|
|
|
|
}
|
|
|
|
|
t.isParallel = true
|
2015-12-29 12:10:01 -05:00
|
|
|
|
|
|
|
|
// We don't want to include the time we spend waiting for serial tests
|
|
|
|
|
// in the test duration. Record the elapsed time thus far and reset the
|
|
|
|
|
// timer afterwards.
|
2015-11-16 19:34:54 -08:00
|
|
|
t.duration += time.Since(t.start)
|
2016-01-19 22:43:52 +01:00
|
|
|
|
|
|
|
|
// Add to the list of tests to be released by the parent.
|
|
|
|
|
t.parent.sub = append(t.parent.sub, t)
|
2016-11-02 21:40:47 -04:00
|
|
|
t.raceErrors += race.Errors()
|
2016-01-19 22:43:52 +01:00
|
|
|
|
|
|
|
|
t.signal <- true // Release calling test.
|
|
|
|
|
<-t.parent.barrier // Wait for the parent test to complete.
|
|
|
|
|
t.context.waitParallel()
|
2013-08-19 10:15:30 +10:00
|
|
|
t.start = time.Now()
|
2016-11-02 21:40:47 -04:00
|
|
|
t.raceErrors += -race.Errors()
|
2011-10-06 09:58:36 -07:00
|
|
|
}
|
|
|
|
|
|
2009-03-05 17:50:36 -08:00
|
|
|
// An internal type but exported because it is cross-package; part of the implementation
|
2012-02-10 13:49:50 +11:00
|
|
|
// of the "go test" command.
|
2010-11-05 23:05:53 -04:00
|
|
|
type InternalTest struct {
|
2009-12-15 15:41:46 -08:00
|
|
|
Name string
|
|
|
|
|
F func(*T)
|
2008-11-19 14:38:05 -08:00
|
|
|
}
|
|
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
func tRunner(t *T, fn func(t *T)) {
|
2017-04-20 16:19:55 -04:00
|
|
|
t.runner = callerName(0)
|
2017-03-29 15:04:40 -07:00
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
// When this goroutine is done, either because fn(t)
|
2012-10-30 13:38:01 -07:00
|
|
|
// returned normally or because a test failure triggered
|
2012-01-12 10:18:12 -08:00
|
|
|
// a call to runtime.Goexit, record the duration and send
|
|
|
|
|
// a signal saying that the test is done.
|
|
|
|
|
defer func() {
|
2016-11-02 21:40:47 -04:00
|
|
|
t.raceErrors += race.Errors()
|
|
|
|
|
if t.raceErrors > 0 {
|
|
|
|
|
t.Errorf("race detected during execution of test")
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-16 19:34:54 -08:00
|
|
|
t.duration += time.Now().Sub(t.start)
|
testing: let runtime catch the panic.
It's not as pretty, but it deletes some irrelevant information from the
printout and avoids a dependency.
It also means the test binary will stop if a test panics. That's a feature,
not a bug.
Any output printed by the test appears before the panic traceback.
before:
--- FAIL: TestPanic (0.00 seconds)
fmt_test.go:19: HI
testing.go:257: runtime error: index out of range
/Users/r/go/src/pkg/testing/testing.go:257 (0x23998)
_func_003: t.Logf("%s\n%s", err, debug.Stack())
/Users/r/go/src/pkg/runtime/proc.c:1388 (0x10d2d)
panic: reflect·call(d->fn, d->args, d->siz);
/Users/r/go/src/pkg/runtime/runtime.c:128 (0x119b0)
panicstring: runtime·panic(err);
/Users/r/go/src/pkg/runtime/runtime.c:85 (0x11857)
panicindex: runtime·panicstring("index out of range");
/Users/r/go/src/pkg/fmt/fmt_test.go:21 (0x23d72)
TestPanic: a[10]=1
/Users/r/go/src/pkg/testing/testing.go:264 (0x21b75)
tRunner: test.F(t)
/Users/r/go/src/pkg/runtime/proc.c:258 (0xee9e)
goexit: runtime·goexit(void)
FAIL
after:
--- FAIL: TestPanic (0.00 seconds)
fmt_test.go:19: HI
panic: runtime error: index out of range [recovered]
panic: (*testing.T) (0xec3b0,0xf8400001c0)
goroutine 2 [running]:
testing._func_003(0x21f5fa8, 0x21f5100, 0x21f5fb8, 0x21f5e88)
/Users/r/go/src/pkg/testing/testing.go:259 +0x108
----- stack segment boundary -----
fmt_test.TestPanic(0xf8400001c0, 0x27603728)
/Users/r/go/src/pkg/fmt/fmt_test.go:21 +0x6b
testing.tRunner(0xf8400001c0, 0x18edb8, 0x0, 0x0)
/Users/r/go/src/pkg/testing/testing.go:264 +0x6f
created by testing.RunTests
/Users/r/go/src/pkg/testing/testing.go:343 +0x76e
goroutine 1 [chan receive]:
testing.RunTests(0x2000, 0x18edb8, 0x2400000024, 0x100000001, 0x200000001, ...)
/Users/r/go/src/pkg/testing/testing.go:344 +0x791
testing.Main(0x2000, 0x18edb8, 0x2400000024, 0x188a58, 0x800000008, ...)
/Users/r/go/src/pkg/testing/testing.go:275 +0x62
main.main()
/var/folders/++/+++Fn+++6+0++4RjPqRgNE++2Qk/-Tmp-/go-build743922747/fmt/_test/_testmain.go:129 +0x91
exit status 2
R=rsc, dsymonds
CC=golang-dev
https://golang.org/cl/5658048
2012-02-14 14:53:30 +11:00
|
|
|
// If the test panicked, print any test output before dying.
|
2014-01-22 16:04:50 -05:00
|
|
|
err := recover()
|
2014-01-22 16:34:02 -05:00
|
|
|
if !t.finished && err == nil {
|
|
|
|
|
err = fmt.Errorf("test executed panic(nil) or runtime.Goexit")
|
2014-01-22 16:04:50 -05:00
|
|
|
}
|
|
|
|
|
if err != nil {
|
2013-04-01 22:36:41 +11:00
|
|
|
t.Fail()
|
testing: let runtime catch the panic.
It's not as pretty, but it deletes some irrelevant information from the
printout and avoids a dependency.
It also means the test binary will stop if a test panics. That's a feature,
not a bug.
Any output printed by the test appears before the panic traceback.
before:
--- FAIL: TestPanic (0.00 seconds)
fmt_test.go:19: HI
testing.go:257: runtime error: index out of range
/Users/r/go/src/pkg/testing/testing.go:257 (0x23998)
_func_003: t.Logf("%s\n%s", err, debug.Stack())
/Users/r/go/src/pkg/runtime/proc.c:1388 (0x10d2d)
panic: reflect·call(d->fn, d->args, d->siz);
/Users/r/go/src/pkg/runtime/runtime.c:128 (0x119b0)
panicstring: runtime·panic(err);
/Users/r/go/src/pkg/runtime/runtime.c:85 (0x11857)
panicindex: runtime·panicstring("index out of range");
/Users/r/go/src/pkg/fmt/fmt_test.go:21 (0x23d72)
TestPanic: a[10]=1
/Users/r/go/src/pkg/testing/testing.go:264 (0x21b75)
tRunner: test.F(t)
/Users/r/go/src/pkg/runtime/proc.c:258 (0xee9e)
goexit: runtime·goexit(void)
FAIL
after:
--- FAIL: TestPanic (0.00 seconds)
fmt_test.go:19: HI
panic: runtime error: index out of range [recovered]
panic: (*testing.T) (0xec3b0,0xf8400001c0)
goroutine 2 [running]:
testing._func_003(0x21f5fa8, 0x21f5100, 0x21f5fb8, 0x21f5e88)
/Users/r/go/src/pkg/testing/testing.go:259 +0x108
----- stack segment boundary -----
fmt_test.TestPanic(0xf8400001c0, 0x27603728)
/Users/r/go/src/pkg/fmt/fmt_test.go:21 +0x6b
testing.tRunner(0xf8400001c0, 0x18edb8, 0x0, 0x0)
/Users/r/go/src/pkg/testing/testing.go:264 +0x6f
created by testing.RunTests
/Users/r/go/src/pkg/testing/testing.go:343 +0x76e
goroutine 1 [chan receive]:
testing.RunTests(0x2000, 0x18edb8, 0x2400000024, 0x100000001, 0x200000001, ...)
/Users/r/go/src/pkg/testing/testing.go:344 +0x791
testing.Main(0x2000, 0x18edb8, 0x2400000024, 0x188a58, 0x800000008, ...)
/Users/r/go/src/pkg/testing/testing.go:275 +0x62
main.main()
/var/folders/++/+++Fn+++6+0++4RjPqRgNE++2Qk/-Tmp-/go-build743922747/fmt/_test/_testmain.go:129 +0x91
exit status 2
R=rsc, dsymonds
CC=golang-dev
https://golang.org/cl/5658048
2012-02-14 14:53:30 +11:00
|
|
|
t.report()
|
|
|
|
|
panic(err)
|
2012-02-06 14:00:23 +11:00
|
|
|
}
|
2016-01-19 22:43:52 +01:00
|
|
|
|
|
|
|
|
if len(t.sub) > 0 {
|
|
|
|
|
// Run parallel subtests.
|
|
|
|
|
// Decrease the running count for this test.
|
|
|
|
|
t.context.release()
|
|
|
|
|
// Release the parallel subtests.
|
|
|
|
|
close(t.barrier)
|
|
|
|
|
// Wait for subtests to complete.
|
|
|
|
|
for _, sub := range t.sub {
|
|
|
|
|
<-sub.signal
|
|
|
|
|
}
|
|
|
|
|
if !t.isParallel {
|
|
|
|
|
// Reacquire the count for sequential tests. See comment in Run.
|
|
|
|
|
t.context.waitParallel()
|
|
|
|
|
}
|
|
|
|
|
} else if t.isParallel {
|
|
|
|
|
// Only release the count for this test if it was run as a parallel
|
|
|
|
|
// test. See comment in Run method.
|
|
|
|
|
t.context.release()
|
|
|
|
|
}
|
|
|
|
|
t.report() // Report after all subtests have finished.
|
|
|
|
|
|
2016-05-21 14:37:29 +02:00
|
|
|
// Do not lock t.done to allow race detector to detect race in case
|
|
|
|
|
// the user does not appropriately synchronizes a goroutine.
|
|
|
|
|
t.done = true
|
2017-01-18 00:05:32 -05:00
|
|
|
if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 {
|
2016-04-20 14:29:30 -03:00
|
|
|
t.setRan()
|
|
|
|
|
}
|
2016-01-19 22:43:52 +01:00
|
|
|
t.signal <- true
|
2012-01-12 10:18:12 -08:00
|
|
|
}()
|
|
|
|
|
|
2013-08-19 10:15:30 +10:00
|
|
|
t.start = time.Now()
|
2016-11-02 21:40:47 -04:00
|
|
|
t.raceErrors = -race.Errors()
|
2016-01-19 22:43:52 +01:00
|
|
|
fn(t)
|
2014-01-22 16:34:02 -05:00
|
|
|
t.finished = true
|
2008-11-18 15:29:10 -08:00
|
|
|
}
|
|
|
|
|
|
2017-05-30 12:11:04 +02:00
|
|
|
// Run runs f as a subtest of t called name. It reports whether f succeeded. Run
|
|
|
|
|
// runs f in a separate goroutine and will block until all its parallel subtests
|
|
|
|
|
// have completed.
|
2017-01-18 00:05:32 -05:00
|
|
|
//
|
2017-05-30 12:11:04 +02:00
|
|
|
// Run may be called simultaneously from multiple goroutines, but all such calls
|
|
|
|
|
// must happen before the outer test function for t returns.
|
2016-01-29 17:14:51 +01:00
|
|
|
func (t *T) Run(name string, f func(t *T)) bool {
|
2017-01-18 00:05:32 -05:00
|
|
|
atomic.StoreInt32(&t.hasSub, 1)
|
2016-01-29 16:57:02 +01:00
|
|
|
testName, ok := t.context.match.fullName(&t.common, name)
|
|
|
|
|
if !ok {
|
|
|
|
|
return true
|
2016-01-29 16:55:35 +01:00
|
|
|
}
|
|
|
|
|
t = &T{
|
|
|
|
|
common: common{
|
|
|
|
|
barrier: make(chan bool),
|
|
|
|
|
signal: make(chan bool),
|
|
|
|
|
name: testName,
|
|
|
|
|
parent: &t.common,
|
|
|
|
|
level: t.level + 1,
|
2016-04-04 18:22:29 +02:00
|
|
|
chatty: t.chatty,
|
2016-01-29 16:55:35 +01:00
|
|
|
},
|
|
|
|
|
context: t.context,
|
|
|
|
|
}
|
2016-01-25 16:27:23 +01:00
|
|
|
t.w = indenter{&t.common}
|
2016-01-29 16:55:35 +01:00
|
|
|
|
2016-04-04 18:22:29 +02:00
|
|
|
if t.chatty {
|
|
|
|
|
// Print directly to root's io.Writer so there is no delay.
|
|
|
|
|
root := t.parent
|
2016-04-06 09:59:32 +02:00
|
|
|
for ; root.parent != nil; root = root.parent {
|
2016-04-04 18:22:29 +02:00
|
|
|
}
|
2017-06-04 00:29:40 -04:00
|
|
|
inProgressMu.Lock()
|
2017-01-21 20:07:26 -08:00
|
|
|
root.mu.Lock()
|
2017-06-04 00:29:40 -04:00
|
|
|
t.registerInProgress()
|
2016-04-04 18:22:29 +02:00
|
|
|
fmt.Fprintf(root.w, "=== RUN %s\n", t.name)
|
2017-01-21 20:07:26 -08:00
|
|
|
root.mu.Unlock()
|
2017-06-04 00:29:40 -04:00
|
|
|
inProgressMu.Unlock()
|
2016-01-29 16:55:35 +01:00
|
|
|
}
|
|
|
|
|
// Instead of reducing the running count of this test before calling the
|
|
|
|
|
// tRunner and increasing it afterwards, we rely on tRunner keeping the
|
|
|
|
|
// count correct. This ensures that a sequence of sequential tests runs
|
|
|
|
|
// without being preempted, even when their parent is a parallel test. This
|
|
|
|
|
// may especially reduce surprises if *parallel == 1.
|
|
|
|
|
go tRunner(t, f)
|
|
|
|
|
<-t.signal
|
|
|
|
|
return !t.failed
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
// testContext holds all fields that are common to all tests. This includes
|
|
|
|
|
// synchronization primitives to run at most *parallel tests.
|
|
|
|
|
type testContext struct {
|
2016-01-29 16:57:02 +01:00
|
|
|
match *matcher
|
|
|
|
|
|
2016-01-19 22:43:52 +01:00
|
|
|
mu sync.Mutex
|
|
|
|
|
|
|
|
|
|
// Channel used to signal tests that are ready to be run in parallel.
|
|
|
|
|
startParallel chan bool
|
|
|
|
|
|
|
|
|
|
// running is the number of tests currently running in parallel.
|
|
|
|
|
// This does not include tests that are waiting for subtests to complete.
|
|
|
|
|
running int
|
|
|
|
|
|
|
|
|
|
// numWaiting is the number tests waiting to be run in parallel.
|
|
|
|
|
numWaiting int
|
|
|
|
|
|
|
|
|
|
// maxParallel is a copy of the parallel flag.
|
|
|
|
|
maxParallel int
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-29 16:57:02 +01:00
|
|
|
func newTestContext(maxParallel int, m *matcher) *testContext {
|
2016-01-19 22:43:52 +01:00
|
|
|
return &testContext{
|
2016-01-29 16:57:02 +01:00
|
|
|
match: m,
|
2016-01-19 22:43:52 +01:00
|
|
|
startParallel: make(chan bool),
|
2016-03-18 19:11:19 +01:00
|
|
|
maxParallel: maxParallel,
|
2016-01-19 22:43:52 +01:00
|
|
|
running: 1, // Set the count to 1 for the main (sequential) test.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *testContext) waitParallel() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
if c.running < c.maxParallel {
|
|
|
|
|
c.running++
|
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.numWaiting++
|
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
<-c.startParallel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *testContext) release() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
if c.numWaiting == 0 {
|
|
|
|
|
c.running--
|
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.numWaiting--
|
|
|
|
|
c.mu.Unlock()
|
|
|
|
|
c.startParallel <- true // Pick a waiting test to be run.
|
|
|
|
|
}
|
|
|
|
|
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
// No one should be using func Main anymore.
|
|
|
|
|
// See the doc comment on func Main and use MainStart instead.
|
|
|
|
|
var errMain = errors.New("testing: unexpected use of func Main")
|
|
|
|
|
|
|
|
|
|
type matchStringOnly func(pat, str string) (bool, error)
|
|
|
|
|
|
|
|
|
|
func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) }
|
|
|
|
|
func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain }
|
|
|
|
|
func (f matchStringOnly) StopCPUProfile() {}
|
|
|
|
|
func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
|
|
|
|
|
func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
|
2017-02-06 11:59:01 -05:00
|
|
|
func (f matchStringOnly) ImportPath() string { return "" }
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
|
|
|
|
|
// Main is an internal function, part of the implementation of the "go test" command.
|
|
|
|
|
// It was exported because it is cross-package and predates "internal" packages.
|
|
|
|
|
// It is no longer used by "go test" but preserved, as much as possible, for other
|
|
|
|
|
// systems that simulate "go test" using Main, but Main sometimes cannot be updated as
|
|
|
|
|
// new functionality is added to the testing package.
|
|
|
|
|
// Systems simulating "go test" should be updated to use MainStart.
|
2011-11-01 22:05:34 -04:00
|
|
|
func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
|
2014-09-19 13:51:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// M is a type passed to a TestMain function to run the actual tests.
|
|
|
|
|
type M struct {
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
deps testDeps
|
|
|
|
|
tests []InternalTest
|
|
|
|
|
benchmarks []InternalBenchmark
|
|
|
|
|
examples []InternalExample
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// testDeps is an internal interface of functionality that is
|
|
|
|
|
// passed into this package by a test's generated main package.
|
|
|
|
|
// The canonical implementation of this interface is
|
|
|
|
|
// testing/internal/testdeps's TestDeps.
|
|
|
|
|
type testDeps interface {
|
|
|
|
|
MatchString(pat, str string) (bool, error)
|
|
|
|
|
StartCPUProfile(io.Writer) error
|
|
|
|
|
StopCPUProfile()
|
|
|
|
|
WriteHeapProfile(io.Writer) error
|
|
|
|
|
WriteProfileTo(string, io.Writer, int) error
|
2017-02-06 11:59:01 -05:00
|
|
|
ImportPath() string
|
2014-09-19 13:51:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MainStart is meant for use by tests generated by 'go test'.
|
|
|
|
|
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
|
|
|
|
|
// It may change signature from release to release.
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
|
2014-09-19 13:51:06 -04:00
|
|
|
return &M{
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
deps: deps,
|
|
|
|
|
tests: tests,
|
|
|
|
|
benchmarks: benchmarks,
|
|
|
|
|
examples: examples,
|
2014-09-19 13:51:06 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run runs the tests. It returns an exit code to pass to os.Exit.
|
|
|
|
|
func (m *M) Run() int {
|
2015-11-06 01:40:56 +00:00
|
|
|
// TestMain may have already called flag.Parse.
|
|
|
|
|
if !flag.Parsed() {
|
|
|
|
|
flag.Parse()
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 10:26:10 -06:00
|
|
|
if len(*matchList) != 0 {
|
|
|
|
|
listTests(m.deps.MatchString, m.tests, m.benchmarks, m.examples)
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-27 13:31:40 -04:00
|
|
|
parseCpuList()
|
2011-03-16 09:53:58 -07:00
|
|
|
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
m.before()
|
2011-03-31 15:27:51 -07:00
|
|
|
startAlarm()
|
2014-09-19 13:51:06 -04:00
|
|
|
haveExamples = len(m.examples) > 0
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
testRan, testOk := runTests(m.deps.MatchString, m.tests)
|
|
|
|
|
exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
|
2017-01-29 20:53:35 +01:00
|
|
|
stopAlarm()
|
2016-10-27 19:47:47 +01:00
|
|
|
if !testRan && !exampleRan && *matchBenchmarks == "" {
|
2016-04-20 14:29:30 -03:00
|
|
|
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
|
|
|
|
}
|
2017-02-06 11:59:01 -05:00
|
|
|
if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
|
2011-11-15 13:09:19 -05:00
|
|
|
fmt.Println("FAIL")
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
m.after()
|
2014-09-19 13:51:06 -04:00
|
|
|
return 1
|
2011-10-06 11:56:17 -07:00
|
|
|
}
|
2016-04-20 14:29:30 -03:00
|
|
|
|
2011-11-15 13:09:19 -05:00
|
|
|
fmt.Println("PASS")
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
m.after()
|
2014-09-19 13:51:06 -04:00
|
|
|
return 0
|
2011-03-23 18:17:14 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-20 09:51:39 -08:00
|
|
|
func (t *T) report() {
|
2016-01-19 22:43:52 +01:00
|
|
|
if t.parent == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2014-06-18 10:59:25 -07:00
|
|
|
dstr := fmtDuration(t.duration)
|
2016-04-04 18:22:29 +02:00
|
|
|
format := "--- %s: %s (%s)\n"
|
2017-06-04 00:29:40 -04:00
|
|
|
|
|
|
|
|
inProgressMu.Lock()
|
|
|
|
|
defer inProgressMu.Unlock()
|
|
|
|
|
defer t.registerComplete()
|
|
|
|
|
|
2012-07-25 10:17:27 -07:00
|
|
|
if t.Failed() {
|
2016-01-19 22:43:52 +01:00
|
|
|
t.flushToParent(format, "FAIL", t.name, dstr)
|
2016-04-04 18:22:29 +02:00
|
|
|
} else if t.chatty {
|
testing: add Skip/Skipf
This proposal adds two methods to *testing.T, Skip(string) and Skipf(format, args...). The intent is to replace the existing log and return idiom which currently has 97 cases in the standard library. A simple example of Skip would be:
func TestSomethingLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
// not reached
}
... time consuming work
}
Additionally tests can be skipped anywhere a *testing.T is present. An example adapted from the go.crypto/ssh/test package would be:
// setup performs some before test action and returns a func()
// which should be defered by the caller for cleanup.
func setup(t *testing.T) func() {
...
cmd := exec.Command("sshd", "-f", configfile, "-i")
if err := cmd.Run(); err != nil {
t.Skipf("could not execute mock ssh server: %v", err)
}
...
return func() {
// stop subprocess and cleanup
}
}
func TestDialMockServer(t *testing.T) {
cleanup := setup(t)
defer cleanup()
...
}
In verbose mode tests that are skipped are now reported as a SKIP, rather than PASS.
Link to discussion: https://groups.google.com/d/topic/golang-nuts/BqorNARzt4U/discussion
R=adg, rsc, r, n13m3y3r
CC=golang-dev, minux.ma
https://golang.org/cl/6501094
2013-01-23 10:22:33 +11:00
|
|
|
if t.Skipped() {
|
2016-01-19 22:43:52 +01:00
|
|
|
t.flushToParent(format, "SKIP", t.name, dstr)
|
testing: add Skip/Skipf
This proposal adds two methods to *testing.T, Skip(string) and Skipf(format, args...). The intent is to replace the existing log and return idiom which currently has 97 cases in the standard library. A simple example of Skip would be:
func TestSomethingLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
// not reached
}
... time consuming work
}
Additionally tests can be skipped anywhere a *testing.T is present. An example adapted from the go.crypto/ssh/test package would be:
// setup performs some before test action and returns a func()
// which should be defered by the caller for cleanup.
func setup(t *testing.T) func() {
...
cmd := exec.Command("sshd", "-f", configfile, "-i")
if err := cmd.Run(); err != nil {
t.Skipf("could not execute mock ssh server: %v", err)
}
...
return func() {
// stop subprocess and cleanup
}
}
func TestDialMockServer(t *testing.T) {
cleanup := setup(t)
defer cleanup()
...
}
In verbose mode tests that are skipped are now reported as a SKIP, rather than PASS.
Link to discussion: https://groups.google.com/d/topic/golang-nuts/BqorNARzt4U/discussion
R=adg, rsc, r, n13m3y3r
CC=golang-dev, minux.ma
https://golang.org/cl/6501094
2013-01-23 10:22:33 +11:00
|
|
|
} else {
|
2016-01-19 22:43:52 +01:00
|
|
|
t.flushToParent(format, "PASS", t.name, dstr)
|
testing: add Skip/Skipf
This proposal adds two methods to *testing.T, Skip(string) and Skipf(format, args...). The intent is to replace the existing log and return idiom which currently has 97 cases in the standard library. A simple example of Skip would be:
func TestSomethingLong(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
// not reached
}
... time consuming work
}
Additionally tests can be skipped anywhere a *testing.T is present. An example adapted from the go.crypto/ssh/test package would be:
// setup performs some before test action and returns a func()
// which should be defered by the caller for cleanup.
func setup(t *testing.T) func() {
...
cmd := exec.Command("sshd", "-f", configfile, "-i")
if err := cmd.Run(); err != nil {
t.Skipf("could not execute mock ssh server: %v", err)
}
...
return func() {
// stop subprocess and cleanup
}
}
func TestDialMockServer(t *testing.T) {
cleanup := setup(t)
defer cleanup()
...
}
In verbose mode tests that are skipped are now reported as a SKIP, rather than PASS.
Link to discussion: https://groups.google.com/d/topic/golang-nuts/BqorNARzt4U/discussion
R=adg, rsc, r, n13m3y3r
CC=golang-dev, minux.ma
https://golang.org/cl/6501094
2013-01-23 10:22:33 +11:00
|
|
|
}
|
2011-10-06 09:58:36 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-04 00:29:40 -04:00
|
|
|
func (t *T) registerInProgress() {
|
|
|
|
|
if !t.chatty {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
inProgressRegistry[t.name] = inProgressIdx
|
|
|
|
|
inProgressIdx++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (t *T) registerComplete() {
|
|
|
|
|
if !t.chatty {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
delete(inProgressRegistry, t.name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func reportTestsInProgress() {
|
|
|
|
|
if len(inProgressRegistry) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
idxToName := make(map[int]string)
|
|
|
|
|
var indexes []int
|
|
|
|
|
for name, idx := range inProgressRegistry {
|
|
|
|
|
idxToName[idx] = name
|
|
|
|
|
indexes = append(indexes, idx)
|
|
|
|
|
}
|
|
|
|
|
sort.Ints(indexes)
|
|
|
|
|
var namesInOrder []string
|
|
|
|
|
for _, idx := range indexes {
|
|
|
|
|
namesInOrder = append(namesInOrder, idxToName[idx])
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("\ntests in progress: %s\n", strings.Join(namesInOrder, ", "))
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 10:26:10 -06:00
|
|
|
func listTests(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
|
|
|
|
|
if _, err := matchString(*matchList, "non-empty"); err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "testing: invalid regexp in -test.list (%q): %s\n", *matchList, err)
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
if ok, _ := matchString(*matchList, test.Name); ok {
|
|
|
|
|
fmt.Println(test.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, bench := range benchmarks {
|
|
|
|
|
if ok, _ := matchString(*matchList, bench.Name); ok {
|
|
|
|
|
fmt.Println(bench.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, example := range examples {
|
|
|
|
|
if ok, _ := matchString(*matchList, example.Name); ok && example.Output != "" {
|
|
|
|
|
fmt.Println(example.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-20 14:29:30 -03:00
|
|
|
// An internal function but exported because it is cross-package; part of the implementation
|
|
|
|
|
// of the "go test" command.
|
2011-11-01 22:05:34 -04:00
|
|
|
func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
|
2016-04-20 14:29:30 -03:00
|
|
|
ran, ok := runTests(matchString, tests)
|
|
|
|
|
if !ran && !haveExamples {
|
2011-10-06 09:58:36 -07:00
|
|
|
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
2008-11-19 19:11:01 -08:00
|
|
|
}
|
2016-04-20 14:29:30 -03:00
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
|
|
|
|
|
ok = true
|
2011-10-06 09:58:36 -07:00
|
|
|
for _, procs := range cpuList {
|
|
|
|
|
runtime.GOMAXPROCS(procs)
|
2016-01-29 16:57:02 +01:00
|
|
|
ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
|
2016-01-19 22:43:52 +01:00
|
|
|
t := &T{
|
|
|
|
|
common: common{
|
|
|
|
|
signal: make(chan bool),
|
|
|
|
|
barrier: make(chan bool),
|
|
|
|
|
w: os.Stdout,
|
2016-04-04 18:22:29 +02:00
|
|
|
chatty: *chatty,
|
2016-01-19 22:43:52 +01:00
|
|
|
},
|
|
|
|
|
context: ctx,
|
2011-10-06 09:58:36 -07:00
|
|
|
}
|
2016-01-19 22:43:52 +01:00
|
|
|
tRunner(t, func(t *T) {
|
2016-01-29 16:55:35 +01:00
|
|
|
for _, test := range tests {
|
2016-01-29 17:14:51 +01:00
|
|
|
t.Run(test.Name, test.F)
|
2011-06-27 13:31:40 -04:00
|
|
|
}
|
2016-01-19 22:43:52 +01:00
|
|
|
// Run catching the signal rather than the tRunner as a separate
|
|
|
|
|
// goroutine to avoid adding a goroutine during the sequential
|
|
|
|
|
// phase as this pollutes the stacktrace output when aborting.
|
|
|
|
|
go func() { <-t.signal }()
|
|
|
|
|
})
|
|
|
|
|
ok = ok && !t.Failed()
|
2016-04-20 14:29:30 -03:00
|
|
|
ran = ran || t.ran
|
2008-11-18 15:29:10 -08:00
|
|
|
}
|
2016-04-20 14:29:30 -03:00
|
|
|
return ran, ok
|
2008-11-18 15:29:10 -08:00
|
|
|
}
|
2011-03-16 09:53:58 -07:00
|
|
|
|
|
|
|
|
// before runs before all testing.
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
func (m *M) before() {
|
2011-03-16 09:53:58 -07:00
|
|
|
if *memProfileRate > 0 {
|
|
|
|
|
runtime.MemProfileRate = *memProfileRate
|
|
|
|
|
}
|
2011-03-23 18:17:14 -04:00
|
|
|
if *cpuProfile != "" {
|
2013-06-12 18:13:34 -07:00
|
|
|
f, err := os.Create(toOutputDir(*cpuProfile))
|
2011-03-23 18:17:14 -04:00
|
|
|
if err != nil {
|
2017-01-04 10:13:18 -08:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
|
2011-03-23 18:17:14 -04:00
|
|
|
return
|
|
|
|
|
}
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
if err := m.deps.StartCPUProfile(f); err != nil {
|
2017-01-04 10:13:18 -08:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s\n", err)
|
2011-03-23 18:17:14 -04:00
|
|
|
f.Close()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// Could save f so after can call f.Close; not worth the effort.
|
|
|
|
|
}
|
2015-07-22 13:09:26 +02:00
|
|
|
if *traceFile != "" {
|
|
|
|
|
f, err := os.Create(toOutputDir(*traceFile))
|
2014-12-12 19:43:23 +01:00
|
|
|
if err != nil {
|
2017-01-04 10:13:18 -08:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
|
2014-12-12 19:43:23 +01:00
|
|
|
return
|
|
|
|
|
}
|
2015-07-22 13:09:26 +02:00
|
|
|
if err := trace.Start(f); err != nil {
|
2017-01-04 10:13:18 -08:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s\n", err)
|
2014-12-12 19:43:23 +01:00
|
|
|
f.Close()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// Could save f so after can call f.Close; not worth the effort.
|
|
|
|
|
}
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 12:56:04 +04:00
|
|
|
if *blockProfile != "" && *blockProfileRate >= 0 {
|
|
|
|
|
runtime.SetBlockProfileRate(*blockProfileRate)
|
|
|
|
|
}
|
2016-09-22 09:48:30 -04:00
|
|
|
if *mutexProfile != "" && *mutexProfileFraction >= 0 {
|
|
|
|
|
runtime.SetMutexProfileFraction(*mutexProfileFraction)
|
|
|
|
|
}
|
2013-07-12 20:40:30 -04:00
|
|
|
if *coverProfile != "" && cover.Mode == "" {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
|
|
|
|
|
os.Exit(2)
|
|
|
|
|
}
|
2017-06-04 00:29:40 -04:00
|
|
|
if Verbose() {
|
|
|
|
|
sigCh := make(chan os.Signal, 1)
|
|
|
|
|
signal.Notify(sigCh, os.Interrupt)
|
|
|
|
|
go func() {
|
|
|
|
|
<-sigCh
|
|
|
|
|
signal.Stop(sigCh)
|
|
|
|
|
inProgressMu.Lock()
|
|
|
|
|
reportTestsInProgress()
|
|
|
|
|
inProgressMu.Unlock()
|
|
|
|
|
proc, err := os.FindProcess(syscall.Getpid())
|
|
|
|
|
if err == nil {
|
|
|
|
|
err = proc.Signal(os.Interrupt)
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(2)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
2011-03-16 09:53:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// after runs after all testing.
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
func (m *M) after() {
|
2011-03-23 18:17:14 -04:00
|
|
|
if *cpuProfile != "" {
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
m.deps.StopCPUProfile() // flushes profile to disk
|
2011-03-16 09:53:58 -07:00
|
|
|
}
|
2015-07-22 13:09:26 +02:00
|
|
|
if *traceFile != "" {
|
|
|
|
|
trace.Stop() // flushes trace to disk
|
2014-12-12 19:43:23 +01:00
|
|
|
}
|
2011-03-23 18:17:14 -04:00
|
|
|
if *memProfile != "" {
|
2013-06-12 18:13:34 -07:00
|
|
|
f, err := os.Create(toOutputDir(*memProfile))
|
2011-03-23 18:17:14 -04:00
|
|
|
if err != nil {
|
2013-06-12 18:13:34 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
|
|
|
|
|
os.Exit(2)
|
2011-03-23 18:17:14 -04:00
|
|
|
}
|
2014-10-16 22:11:26 +04:00
|
|
|
runtime.GC() // materialize all statistics
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
if err = m.deps.WriteHeapProfile(f); err != nil {
|
2013-06-12 18:13:34 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
|
|
|
|
|
os.Exit(2)
|
2011-03-23 18:17:14 -04:00
|
|
|
}
|
|
|
|
|
f.Close()
|
2011-03-16 09:53:58 -07:00
|
|
|
}
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 12:56:04 +04:00
|
|
|
if *blockProfile != "" && *blockProfileRate >= 0 {
|
2013-06-12 18:13:34 -07:00
|
|
|
f, err := os.Create(toOutputDir(*blockProfile))
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 12:56:04 +04:00
|
|
|
if err != nil {
|
2013-06-12 18:13:34 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
|
|
|
|
|
os.Exit(2)
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 12:56:04 +04:00
|
|
|
}
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
if err = m.deps.WriteProfileTo("block", f, 0); err != nil {
|
2016-09-22 09:48:30 -04:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
|
|
|
|
|
os.Exit(2)
|
|
|
|
|
}
|
|
|
|
|
f.Close()
|
|
|
|
|
}
|
|
|
|
|
if *mutexProfile != "" && *mutexProfileFraction >= 0 {
|
|
|
|
|
f, err := os.Create(toOutputDir(*mutexProfile))
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
|
|
|
|
|
os.Exit(2)
|
|
|
|
|
}
|
testing: introduce testing/internal/testdeps for holding testmain dependencies
Currently, we don't have package testing to import package regexp directly,
because then regexp can't have internal tests (or at least they become more
difficult to write), for fear of an import cycle. The solution we've been using
is for the generated test main package (pseudo-import path "testmain", package main)
to import regexp and pass in a matchString function for use by testing when
implementing the -run flags. This lets testing use regexp but without depending
on regexp and creating unnecessary cycles.
We want to add a few dependencies to runtime/pprof, notably regexp
but also compress/gzip, without causing those packages to have to work
hard to write internal tests.
Restructure the (dare I say it) dependency injection of regexp.MatchString
to be more general, and use it for the runtime/pprof functionality in addition
to the regexp functionality. The new package testing/internal/testdeps is
the root for the testing dependencies handled this way.
Code using testing.MainStart will have to change from passing in a matchString
implementation to passing in testdeps.TestDeps{}. Users of 'go test' don't do this,
but other build systems that have recreated 'go test' (for example, Blaze/Bazel)
may need to be updated. The new testdeps setup should make future updates
unnecessary, but even so we keep the comment about MainStart not being
subject to Go 1 compatibility.
Change-Id: Iec821d2afde10c79f95f3b23de5e71b219f47b92
Reviewed-on: https://go-review.googlesource.com/32455
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-10-31 19:27:26 -04:00
|
|
|
if err = m.deps.WriteProfileTo("mutex", f, 0); err != nil {
|
2013-06-12 18:13:34 -07:00
|
|
|
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
|
|
|
|
|
os.Exit(2)
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 12:56:04 +04:00
|
|
|
}
|
|
|
|
|
f.Close()
|
|
|
|
|
}
|
2013-07-12 20:40:30 -04:00
|
|
|
if cover.Mode != "" {
|
2013-06-18 14:18:25 -07:00
|
|
|
coverReport()
|
|
|
|
|
}
|
2011-03-16 09:53:58 -07:00
|
|
|
}
|
2011-03-31 15:27:51 -07:00
|
|
|
|
2013-06-12 18:13:34 -07:00
|
|
|
// toOutputDir returns the file name relocated, if required, to outputDir.
|
|
|
|
|
// Simple implementation to avoid pulling in path/filepath.
|
|
|
|
|
func toOutputDir(path string) string {
|
|
|
|
|
if *outputDir == "" || path == "" {
|
|
|
|
|
return path
|
|
|
|
|
}
|
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
|
// On Windows, it's clumsy, but we can be almost always correct
|
|
|
|
|
// by just looking for a drive letter and a colon.
|
|
|
|
|
// Absolute paths always have a drive letter (ignoring UNC).
|
|
|
|
|
// Problem: if path == "C:A" and outputdir == "C:\Go" it's unclear
|
|
|
|
|
// what to do, but even then path/filepath doesn't help.
|
|
|
|
|
// TODO: Worth doing better? Probably not, because we're here only
|
|
|
|
|
// under the management of go test.
|
|
|
|
|
if len(path) >= 2 {
|
|
|
|
|
letter, colon := path[0], path[1]
|
|
|
|
|
if ('a' <= letter && letter <= 'z' || 'A' <= letter && letter <= 'Z') && colon == ':' {
|
|
|
|
|
// If path starts with a drive letter we're stuck with it regardless.
|
|
|
|
|
return path
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if os.IsPathSeparator(path[0]) {
|
|
|
|
|
return path
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%s%c%s", *outputDir, os.PathSeparator, path)
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-31 15:27:51 -07:00
|
|
|
var timer *time.Timer
|
|
|
|
|
|
|
|
|
|
// startAlarm starts an alarm if requested.
|
|
|
|
|
func startAlarm() {
|
|
|
|
|
if *timeout > 0 {
|
2013-08-01 17:24:24 +04:00
|
|
|
timer = time.AfterFunc(*timeout, func() {
|
2015-12-18 11:24:55 -05:00
|
|
|
debug.SetTraceback("all")
|
2013-08-01 17:24:24 +04:00
|
|
|
panic(fmt.Sprintf("test timed out after %v", *timeout))
|
|
|
|
|
})
|
2011-03-31 15:27:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 21:23:03 +00:00
|
|
|
// stopAlarm turns off the alarm.
|
|
|
|
|
func stopAlarm() {
|
|
|
|
|
if *timeout > 0 {
|
|
|
|
|
timer.Stop()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-27 13:31:40 -04:00
|
|
|
func parseCpuList() {
|
2013-08-02 13:51:45 -04:00
|
|
|
for _, val := range strings.Split(*cpuListStr, ",") {
|
|
|
|
|
val = strings.TrimSpace(val)
|
|
|
|
|
if val == "" {
|
|
|
|
|
continue
|
2011-06-27 13:31:40 -04:00
|
|
|
}
|
2013-08-02 13:51:45 -04:00
|
|
|
cpu, err := strconv.Atoi(val)
|
|
|
|
|
if err != nil || cpu <= 0 {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu\n", val)
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
2015-06-03 22:21:07 -04:00
|
|
|
for i := uint(0); i < *count; i++ {
|
|
|
|
|
cpuList = append(cpuList, cpu)
|
|
|
|
|
}
|
2013-08-02 13:51:45 -04:00
|
|
|
}
|
|
|
|
|
if cpuList == nil {
|
2015-06-03 22:21:07 -04:00
|
|
|
for i := uint(0); i < *count; i++ {
|
|
|
|
|
cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
|
|
|
|
|
}
|
2011-06-27 13:31:40 -04:00
|
|
|
}
|
|
|
|
|
}
|