Commit 7ef9f725 authored by Russ Cox's avatar Russ Cox

cmd/go: fix missing conversions in -json output

1. Apply JSON conversion when -bench is in use.
2. Apply JSON conversion to "no test files" result.
3. Apply JSON conversion to test case-ending SKIP status.

Fixes #22769.
Fixes #22790.

Change-Id: I67ad656fc58bacae8c51d23b1e6d543cad190f08
Reviewed-on: https://go-review.googlesource.com/81535
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 232b2e33
...@@ -5237,13 +5237,20 @@ func TestGoTestJSON(t *testing.T) { ...@@ -5237,13 +5237,20 @@ func TestGoTestJSON(t *testing.T) {
// It would be nice to test that the output is interlaced // It would be nice to test that the output is interlaced
// but it seems to be impossible to do that in a short test // but it seems to be impossible to do that in a short test
// that isn't also flaky. Just check that we get JSON output. // that isn't also flaky. Just check that we get JSON output.
tg.run("test", "-json", "-short", "-v", "errors") tg.run("test", "-json", "-short", "-v", "errors", "empty/pkg", "skipper")
for _, line := range strings.Split(tg.getStdout(), "\n") { tg.grepStdout(`"Package":"errors"`, "did not see JSON output")
if strings.Contains(line, `"Package":"errors"`) { tg.grepStdout(`"Action":"run"`, "did not see JSON output")
return
} tg.grepStdout(`"Action":"output","Package":"empty/pkg","Output":".*no test files`, "did not see no test files print")
} tg.grepStdout(`"Action":"skip","Package":"empty/pkg"`, "did not see skip")
t.Fatalf("did not see JSON output")
tg.grepStdout(`"Action":"output","Package":"skipper","Test":"Test","Output":"--- SKIP:`, "did not see SKIP output")
tg.grepStdout(`"Action":"skip","Package":"skipper","Test":"Test"`, "did not see skip result for Test")
tg.run("test", "-json", "-bench=NONE", "-short", "-v", "errors")
tg.grepStdout(`"Package":"errors"`, "did not see JSON output")
tg.grepStdout(`"Action":"run"`, "did not see JSON output")
} }
func TestFailFast(t *testing.T) { func TestFailFast(t *testing.T) {
......
...@@ -1283,7 +1283,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error { ...@@ -1283,7 +1283,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
// Stream test output (no buffering) when no package has // Stream test output (no buffering) when no package has
// been given on the command line (implicit current directory) // been given on the command line (implicit current directory)
// or when benchmarking. // or when benchmarking.
cmd.Stdout = os.Stdout cmd.Stdout = stdout
} else { } else {
// If we're only running a single package under test or if parallelism is // If we're only running a single package under test or if parallelism is
// set to 1, and if we're displaying all output (testShowPass), we can // set to 1, and if we're displaying all output (testShowPass), we can
...@@ -1547,7 +1547,13 @@ func builderPrintTest(b *work.Builder, a *work.Action) error { ...@@ -1547,7 +1547,13 @@ func builderPrintTest(b *work.Builder, a *work.Action) error {
// builderNoTest is the action for testing a package with no test files. // builderNoTest is the action for testing a package with no test files.
func builderNoTest(b *work.Builder, a *work.Action) error { func builderNoTest(b *work.Builder, a *work.Action) error {
fmt.Printf("? \t%s\t[no test files]\n", a.Package.ImportPath) var stdout io.Writer = os.Stdout
if testJSON {
json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp)
defer json.Close()
stdout = json
}
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", a.Package.ImportPath)
return nil return nil
} }
......
package skipper
import "testing"
func Test(t *testing.T) {
t.Skip("skipping")
}
...@@ -54,7 +54,7 @@ type converter struct { ...@@ -54,7 +54,7 @@ type converter struct {
start time.Time // time converter started start time.Time // time converter started
testName string // name of current test, for output attribution testName string // name of current test, for output attribution
report []*event // pending test result reports (nested for subtests) report []*event // pending test result reports (nested for subtests)
passed bool // whether we've seen the final whole-package PASS line result string // overall test result if seen
input lineBuffer // input buffer input lineBuffer // input buffer
output lineBuffer // output buffer output lineBuffer // output buffer
} }
...@@ -139,9 +139,13 @@ var ( ...@@ -139,9 +139,13 @@ var (
reports = [][]byte{ reports = [][]byte{
[]byte("--- PASS: "), []byte("--- PASS: "),
[]byte("--- FAIL: "), []byte("--- FAIL: "),
[]byte("--- SKIP: "),
} }
fourSpace = []byte(" ") fourSpace = []byte(" ")
skipLinePrefix = []byte("? \t")
skipLineSuffix = []byte("\t[no test files]\n")
) )
// handleInputLine handles a single whole test output line. // handleInputLine handles a single whole test output line.
...@@ -152,10 +156,20 @@ func (c *converter) handleInputLine(line []byte) { ...@@ -152,10 +156,20 @@ func (c *converter) handleInputLine(line []byte) {
if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) { if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) {
c.flushReport(0) c.flushReport(0)
c.output.write(line) c.output.write(line)
c.passed = bytes.Equal(line, bigPass) if bytes.Equal(line, bigPass) {
c.result = "pass"
} else {
c.result = "fail"
}
return return
} }
// Special case for entirely skipped test binary: "? \tpkgname\t[no test files]\n" is only line.
// Report it as plain output but remember to say skip in the final summary.
if bytes.HasPrefix(line, skipLinePrefix) && bytes.HasSuffix(line, skipLineSuffix) && len(c.report) == 0 {
c.result = "skip"
}
// "=== RUN " // "=== RUN "
// "=== PAUSE " // "=== PAUSE "
// "=== CONT " // "=== CONT "
...@@ -171,6 +185,7 @@ func (c *converter) handleInputLine(line []byte) { ...@@ -171,6 +185,7 @@ func (c *converter) handleInputLine(line []byte) {
if !ok { if !ok {
// "--- PASS: " // "--- PASS: "
// "--- FAIL: " // "--- FAIL: "
// "--- SKIP: "
// but possibly indented. // but possibly indented.
for bytes.HasPrefix(line, fourSpace) { for bytes.HasPrefix(line, fourSpace) {
line = line[4:] line = line[4:]
...@@ -257,8 +272,8 @@ func (c *converter) Close() error { ...@@ -257,8 +272,8 @@ func (c *converter) Close() error {
c.input.flush() c.input.flush()
c.output.flush() c.output.flush()
e := &event{Action: "fail"} e := &event{Action: "fail"}
if c.passed { if c.result != "" {
e.Action = "pass" e.Action = c.result
} }
if c.mode&Timestamp != 0 { if c.mode&Timestamp != 0 {
dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds()
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// //
// type TestEvent struct { // type TestEvent struct {
// Time time.Time // encodes as an RFC3339-format string // Time time.Time // encodes as an RFC3339-format string
// Event string // Action string
// Package string // Package string
// Test string // Test string
// Elapsed float64 // seconds // Elapsed float64 // seconds
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
// The Time field holds the time the event happened. // The Time field holds the time the event happened.
// It is conventionally omitted for cached test results. // It is conventionally omitted for cached test results.
// //
// The Event field is one of a fixed set of event descriptions: // The Action field is one of a fixed set of action descriptions:
// //
// run - the test has started running // run - the test has started running
// pause - the test has been paused // pause - the test has been paused
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment