From 71042b949a84ae275660f45b8da9499a5877bb9c Mon Sep 17 00:00:00 2001 From: Robbert van Ginkel Date: Fri, 7 May 2021 16:38:23 -0700 Subject: Update test2json.go (#2873) There have been some updates to test2json.go since d47526ed777958aa4a2542382e931eb7b3c4c6a9, most notably a fix for https://github.com/golang/go/issues/40132 that was important enough to recevie a backport. Update rules_go's copy of test2json.go to the latest. --- go/tools/bzltestutil/test2json.go | 67 +++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/go/tools/bzltestutil/test2json.go b/go/tools/bzltestutil/test2json.go index 92375d57..331773d0 100644 --- a/go/tools/bzltestutil/test2json.go +++ b/go/tools/bzltestutil/test2json.go @@ -9,7 +9,7 @@ // // The file test2json.go was copied from upstream go at // src/cmd/internal/test2json/test2json.go, revision -// d47526ed777958aa4a2542382e931eb7b3c4c6a9. At the time of writing this was +// 1b86bdbdc3991c13c6ed156100a5f4918fdd9c6b. At the time of writing this was // deemed the best way of depending on this code that is otherwise not exposed // outside of the go toolchain. These files should be kept in sync. @@ -52,10 +52,10 @@ type textBytes []byte func (b textBytes) MarshalText() ([]byte, error) { return b, nil } -// A converter holds the state of a test-to-JSON conversion. +// A Converter holds the state of a test-to-JSON conversion. // It implements io.WriteCloser; the caller writes test output in, // and the converter writes JSON output to w. -type converter struct { +type Converter struct { w io.Writer // JSON output stream pkg string // package to name in events mode Mode // mode bits @@ -107,9 +107,9 @@ var ( // // The pkg string, if present, specifies the import path to // report in the JSON stream. -func NewConverter(w io.Writer, pkg string, mode Mode) io.WriteCloser { - c := new(converter) - *c = converter{ +func NewConverter(w io.Writer, pkg string, mode Mode) *Converter { + c := new(Converter) + *c = Converter{ w: w, pkg: pkg, mode: mode, @@ -129,15 +129,31 @@ func NewConverter(w io.Writer, pkg string, mode Mode) io.WriteCloser { } // Write writes the test input to the converter. -func (c *converter) Write(b []byte) (int, error) { +func (c *Converter) Write(b []byte) (int, error) { c.input.write(b) return len(b), nil } +// Exited marks the test process as having exited with the given error. +func (c *Converter) Exited(err error) { + if err == nil { + c.result = "pass" + } else { + c.result = "fail" + } +} + var ( + // printed by test on successful run. bigPass = []byte("PASS\n") + + // printed by test after a normal test failure. bigFail = []byte("FAIL\n") + // printed by 'go test' along with an error if the test binary terminates + // with an error. + bigFailErrorPrefix = []byte("FAIL\t") + updates = [][]byte{ []byte("=== RUN "), []byte("=== PAUSE "), @@ -160,9 +176,9 @@ var ( // handleInputLine handles a single whole test output line. // It must write the line to c.output but may choose to do so // before or after emitting other events. -func (c *converter) handleInputLine(line []byte) { +func (c *Converter) handleInputLine(line []byte) { // Final PASS or FAIL. - if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) { + if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) || bytes.HasPrefix(line, bigFailErrorPrefix) { c.flushReport(0) c.output.write(line) if bytes.Equal(line, bigPass) { @@ -211,8 +227,18 @@ func (c *converter) handleInputLine(line []byte) { } } + // Not a special test output line. if !ok { - // Not a special test output line. + // Lookup the name of the test which produced the output using the + // indentation of the output as an index into the stack of the current + // subtests. + // If the indentation is greater than the number of current subtests + // then the output must have included extra indentation. We can't + // determine which subtest produced this output, so we default to the + // old behaviour of assuming the most recently run subtest produced it. + if indent > 0 && indent <= len(c.report) { + c.testName = c.report[indent-1].Test + } c.output.write(origLine) return } @@ -276,7 +302,7 @@ func (c *converter) handleInputLine(line []byte) { } // flushReport flushes all pending PASS/FAIL reports at levels >= depth. -func (c *converter) flushReport(depth int) { +func (c *Converter) flushReport(depth int) { c.testName = "" for len(c.report) > depth { e := c.report[len(c.report)-1] @@ -288,23 +314,22 @@ func (c *converter) flushReport(depth int) { // Close marks the end of the go test output. // It flushes any pending input and then output (only partial lines at this point) // and then emits the final overall package-level pass/fail event. -func (c *converter) Close() error { +func (c *Converter) Close() error { c.input.flush() c.output.flush() - e := &event{Action: "pass"} if c.result != "" { - e.Action = c.result - } - if c.mode&Timestamp != 0 { - dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() - e.Elapsed = &dt + e := &event{Action: c.result} + if c.mode&Timestamp != 0 { + dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() + e.Elapsed = &dt + } + c.writeEvent(e) } - c.writeEvent(e) return nil } // writeOutputEvent writes a single output event with the given bytes. -func (c *converter) writeOutputEvent(out []byte) { +func (c *Converter) writeOutputEvent(out []byte) { c.writeEvent(&event{ Action: "output", Output: (*textBytes)(&out), @@ -313,7 +338,7 @@ func (c *converter) writeOutputEvent(out []byte) { // writeEvent writes a single event. // It adds the package, time (if requested), and test name (if needed). -func (c *converter) writeEvent(e *event) { +func (c *Converter) writeEvent(e *event) { e.Package = c.pkg if c.mode&Timestamp != 0 { t := time.Now() -- cgit v1.2.3