Skip to content

Commit 76a6adc

Browse files
Jay Conroddmitshur
Jay Conrod
authored andcommitted
[release-branch.go1.14] cmd/go: make go test -json report failures for panicking/exiting tests
'go test -json' should report that a test failed if the test binary did not exit normally with status 0. This covers panics, non-zero exits, and abnormal terminations. These tests don't print a final result when run with -test.v (which is used by 'go test -json'). The final result should be "PASS" or "FAIL" on a line by itself. 'go test' prints "FAIL" in this case, but includes error information. test2json was changed in CL 192104 to report that a test passed if it does not report a final status. This caused 'go test -json' to report that a test passed after a panic or non-zero exit. With this change, test2json treats "FAIL" with error information the same as "FAIL" on a line by itself. This is intended to be a minimal fix for backporting, but it will likely be replaced by a complete solution for #29062. Fixes #37671 Updates #37555 Updates #29062 Updates #31969 Change-Id: Icb67bcd36bed97e6a8d51f4d14bf71f73c83ac3d Reviewed-on: https://go-review.googlesource.com/c/go/+/222243 Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com> (cherry picked from commit 5ea58c6) Reviewed-on: https://go-review.googlesource.com/c/go/+/222658 Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
1 parent 0e9f7ac commit 76a6adc

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

src/cmd/go/internal/test/test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,14 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
12241224
if len(out) == 0 {
12251225
fmt.Fprintf(cmd.Stdout, "%s\n", err)
12261226
}
1227+
// NOTE(golang.org/issue/37555): test2json reports that a test passes
1228+
// unless "FAIL" is printed at the beginning of a line. The test may not
1229+
// actually print that if it panics, exits, or terminates abnormally,
1230+
// so we print it here. We can't always check whether it was printed
1231+
// because some tests need stdout to be a terminal (golang.org/issue/34791),
1232+
// not a pipe.
1233+
// TODO(golang.org/issue/29062): tests that exit with status 0 without
1234+
// printing a final result should fail.
12271235
fmt.Fprintf(cmd.Stdout, "FAIL\t%s\t%s\n", a.Package.ImportPath, t)
12281236
}
12291237

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Verifies golang.org/issue/37555.
2+
3+
[short] skip
4+
5+
# 'go test -json' should say a test passes if it says it passes.
6+
go test -json ./pass
7+
stdout '"Action":"pass".*\n\z'
8+
! stdout '"Test":.*\n\z'
9+
10+
# 'go test -json' should say a test passes if it exits 0 and prints nothing.
11+
# TODO(golang.org/issue/29062): this should fail in the future.
12+
go test -json ./exit0main
13+
stdout '"Action":"pass".*\n\z'
14+
! stdout '"Test":.*\n\z'
15+
16+
# 'go test -json' should say a test fails if it exits 1 and prints nothing.
17+
! go test -json ./exit1main
18+
stdout '"Action":"fail".*\n\z'
19+
! stdout '"Test":.*\n\z'
20+
21+
# 'go test -json' should say a test fails if it panics.
22+
! go test -json ./panic
23+
stdout '"Action":"fail".*\n\z'
24+
! stdout '"Test":.*\n\z'
25+
26+
-- go.mod --
27+
module example.com/test
28+
29+
go 1.14
30+
31+
-- pass/pass_test.go --
32+
package pass_test
33+
34+
import "testing"
35+
36+
func TestPass(t *testing.T) {}
37+
38+
-- exit0main/exit0main_test.go --
39+
package exit0_test
40+
41+
import (
42+
"os"
43+
"testing"
44+
)
45+
46+
func TestMain(m *testing.M) {
47+
os.Exit(0)
48+
}
49+
50+
-- exit1main/exit1main_test.go --
51+
package exit1_test
52+
53+
import (
54+
"os"
55+
"testing"
56+
)
57+
58+
func TestMain(m *testing.M) {
59+
os.Exit(1)
60+
}
61+
62+
-- panic/panic_test.go --
63+
package panic_test
64+
65+
import "testing"
66+
67+
func TestPanic(t *testing.T) {
68+
panic("oh no")
69+
}

src/cmd/internal/test2json/test2json.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,16 @@ func (c *converter) Write(b []byte) (int, error) {
128128
}
129129

130130
var (
131+
// printed by test on successful run.
131132
bigPass = []byte("PASS\n")
133+
134+
// printed by test after a normal test failure.
132135
bigFail = []byte("FAIL\n")
133136

137+
// printed by 'go test' along with an error if the test binary terminates
138+
// with an error.
139+
bigFailErrorPrefix = []byte("FAIL\t")
140+
134141
updates = [][]byte{
135142
[]byte("=== RUN "),
136143
[]byte("=== PAUSE "),
@@ -155,7 +162,7 @@ var (
155162
// before or after emitting other events.
156163
func (c *converter) handleInputLine(line []byte) {
157164
// Final PASS or FAIL.
158-
if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) {
165+
if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) || bytes.HasPrefix(line, bigFailErrorPrefix) {
159166
c.flushReport(0)
160167
c.output.write(line)
161168
if bytes.Equal(line, bigPass) {

src/cmd/internal/test2json/testdata/panic.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
{"Action":"output","Test":"TestPanic","Output":"\tgo/src/testing/testing.go:909 +0xc9\n"}
1414
{"Action":"output","Test":"TestPanic","Output":"created by testing.(*T).Run\n"}
1515
{"Action":"output","Test":"TestPanic","Output":"\tgo/src/testing/testing.go:960 +0x350\n"}
16-
{"Action":"output","Test":"TestPanic","Output":"FAIL\tcommand-line-arguments\t0.042s\n"}
1716
{"Action":"fail","Test":"TestPanic"}
17+
{"Action":"output","Output":"FAIL\tcommand-line-arguments\t0.042s\n"}
1818
{"Action":"output","Output":"FAIL\n"}
1919
{"Action":"fail"}

0 commit comments

Comments
 (0)