aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing.go
diff options
context:
space:
mode:
authorChangkun Ou <hi@changkun.us>2020-02-16 14:42:29 +0100
committerIan Lance Taylor <iant@golang.org>2020-03-17 00:45:15 +0000
commit2f54081adfc967836842c96619d241378400ece6 (patch)
treef60d3f67c7ca1c815b2a4a8e8456fce4264c76f1 /src/testing/testing.go
parent2fbca94db7e14fc1d18162cd203d7afc19b520e8 (diff)
downloadgo-2f54081adfc967836842c96619d241378400ece6.tar.gz
go-2f54081adfc967836842c96619d241378400ece6.zip
testing: do not require os.Exit in TestMain
If TestMain reports a wrong exit code to os.Exit, the test will be exited with exist code inconsist with test results. This CL eliminates the requirement of calling os.Exit in TestMain. Now, m.Run records the execution status of its test, the outer main func will call os.Exit with that exit code if TestMain does not call os.Exit. If TestMain does not call m.Run, the outer main func remain calls os.Exit(0) as before. Fixes #34129 Change-Id: I9598023e03b0a6260f0217f34df41c231c7d6489 Reviewed-on: https://go-review.googlesource.com/c/go/+/219639 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/testing/testing.go')
-rw-r--r--src/testing/testing.go31
1 files changed, 22 insertions, 9 deletions
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 83cd72fff3..039d3e6209 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -217,10 +217,11 @@
//
// 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
-// 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.
+// and teardown is necessary around a call to m.Run. m.Run will return an exit
+// status that may be passed to os.Exit. If TestMain returns, the test wrapper
+// will pass the result of m.Run to os.Exit itself. 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.
//
// A simple implementation of TestMain is:
//
@@ -1148,6 +1149,10 @@ type M struct {
afterOnce sync.Once
numRun int
+
+ // value to pass to os.Exit, the outer test func main
+ // harness calls os.Exit with this code. See #34129.
+ exitCode int
}
// testDeps is an internal interface of functionality that is
@@ -1178,7 +1183,11 @@ func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchma
}
// Run runs the tests. It returns an exit code to pass to os.Exit.
-func (m *M) Run() int {
+func (m *M) Run() (code int) {
+ defer func() {
+ code = m.exitCode
+ }()
+
// Count the number of calls to m.Run.
// We only ever expected 1, but we didn't enforce that,
// and now there are tests in the wild that call m.Run multiple times.
@@ -1193,12 +1202,14 @@ func (m *M) Run() int {
if *parallel < 1 {
fmt.Fprintln(os.Stderr, "testing: -parallel can only be given a positive integer")
flag.Usage()
- return 2
+ m.exitCode = 2
+ return
}
if len(*matchList) != 0 {
listTests(m.deps.MatchString, m.tests, m.benchmarks, m.examples)
- return 0
+ m.exitCode = 0
+ return
}
parseCpuList()
@@ -1215,11 +1226,13 @@ func (m *M) Run() int {
}
if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
fmt.Println("FAIL")
- return 1
+ m.exitCode = 1
+ return
}
fmt.Println("PASS")
- return 0
+ m.exitCode = 0
+ return
}
func (t *T) report() {