parser/gotest: Create JSONEventReader in internal reader package

The JSONEventReader implements reading lines with metadata and replaces
the gotest.jsonReader struct.
This commit is contained in:
Joël Stemmer
2022-08-11 23:58:06 +01:00
parent bd21d54501
commit 85f2715ac9
4 changed files with 87 additions and 115 deletions

View File

@ -3,7 +3,10 @@ package reader
import (
"bufio"
"bytes"
"encoding/json"
"io"
"strings"
"time"
)
// LineReader is an interface to read lines with optional Metadata.
@ -68,3 +71,52 @@ func (r *LimitedLineReader) ReadLine() (string, *Metadata, error) {
}
return buf.String(), nil, nil
}
// Event represents a JSON event emitted by `go test -json`.
type Event struct {
Time time.Time
Action string
Package string
Test string
Elapsed float64 // seconds
Output string
}
// JSONEventReader reads JSON events from an io.Reader object.
type JSONEventReader struct {
r *LimitedLineReader
}
var _ LineReader = &JSONEventReader{}
// jsonLineLimit is the maximum size of a single JSON line emitted by `go test
// -json`.
const jsonLineLimit = 64 * 1024
// NewJSONEventReader returns a JSONEventReader to read the data in JSON
// events from r.
func NewJSONEventReader(r io.Reader) *JSONEventReader {
return &JSONEventReader{NewLimitedLineReader(r, jsonLineLimit)}
}
// ReadLine returns the next line from the underlying reader.
func (r *JSONEventReader) ReadLine() (string, *Metadata, error) {
for {
line, _, err := r.r.ReadLine()
if err != nil {
return "", nil, err
}
if len(line) == 0 || line[0] != '{' {
return line, nil, nil
}
event := &Event{}
if err := json.Unmarshal([]byte(line), event); err != nil {
return "", nil, err
}
if event.Output == "" {
// Skip events without output
continue
}
return strings.TrimSuffix(event.Output, "\n"), &Metadata{Package: event.Package}, nil
}
}