pkg/report: add Report.SkipPos

SkipPos is what pkg/instance needs,
but also will be needed for ParseAll.
This commit is contained in:
Dmitry Vyukov 2020-05-13 17:51:56 +02:00
parent b3fe7470a4
commit 3d789641a3
4 changed files with 58 additions and 26 deletions

View File

@ -6,7 +6,6 @@
package instance
import (
"bytes"
"encoding/json"
"fmt"
"net"
@ -245,11 +244,7 @@ func (inst *inst) test() error {
rep := inst.reporter.Parse(testErr.Output)
if rep != nil && rep.Type == report.UnexpectedReboot {
// Avoid detecting any boot crash as "unexpected kernel reboot".
output := testErr.Output[rep.EndPos:]
if pos := bytes.IndexByte(testErr.Output[rep.StartPos:], '\n'); pos != -1 {
output = testErr.Output[rep.StartPos+pos:]
}
rep = inst.reporter.Parse(output)
rep = inst.reporter.Parse(testErr.Output[rep.SkipPos:])
}
if rep == nil {
rep = &report.Report{

View File

@ -11,7 +11,7 @@ import (
func Fuzz(data []byte) int {
res := 0
for _, reporter := range fuzzReporters {
for os, reporter := range fuzzReporters {
typ := reporter.(*reporterWrapper).typ
containsCrash := reporter.ContainsCrash(data)
rep := reporter.Parse(data)
@ -32,18 +32,41 @@ func Fuzz(data []byte) int {
if len(rep.Output) == 0 {
panic(fmt.Sprintf("%v: len(Output) == 0", typ))
}
switch os {
case "openbsd", "netbsd", "fuchsia":
// openbsd/netbsd has Start/End/SkipPos set incorrectly due to messing with /r/n.
// fuchsia because it symbolizes before parsing.
continue
}
if rep.StartPos != 0 && rep.EndPos != 0 && rep.StartPos >= rep.EndPos {
panic(fmt.Sprintf("%v: StartPos=%v >= EndPos=%v", typ, rep.StartPos, rep.EndPos))
panic(fmt.Sprintf("%v: bad StartPos\nStartPos=%v >= EndPos=%v",
typ, rep.StartPos, rep.EndPos))
}
if rep.EndPos > len(rep.Output) {
panic(fmt.Sprintf("%v: EndPos=%v > len(Output)=%v", typ, rep.EndPos, len(rep.Output)))
panic(fmt.Sprintf("%v: bad EndPos\nEndPos=%v > len(Output)=%v",
typ, rep.EndPos, len(rep.Output)))
}
if rep.SkipPos <= rep.StartPos || rep.SkipPos > rep.EndPos {
panic(fmt.Sprintf("%v: bad SkipPos\nSkipPos=%v: StartPos=%v EndPos=%v",
typ, rep.SkipPos, rep.StartPos, rep.EndPos))
}
// If we parse from StartPos, we must find the same report.
rep1 := reporter.Parse(data[rep.StartPos:])
if rep1 == nil || rep1.Title != rep.Title || rep1.StartPos != 0 {
title, startPos := "", -1
if rep1 != nil {
title, startPos = rep1.Title, rep1.StartPos
}
panic(fmt.Sprintf("%v: did not find the same reports at StartPos\n"+
"StartPos=%v/%v\nTitle0=%q\nTitle1=%q",
typ, rep.StartPos, startPos, rep.Title, title))
}
}
return res
}
var fuzzReporters = func() []Reporter {
var reporters []Reporter
var fuzzReporters = func() map[string]Reporter {
reporters := make(map[string]Reporter)
for os := range ctors {
if os == "windows" {
continue
@ -59,7 +82,7 @@ var fuzzReporters = func() []Reporter {
if _, ok := reporter.(*stub); ok {
continue
}
reporters = append(reporters, reporter)
reporters[os] = reporter
}
return reporters
}()

View File

@ -42,6 +42,8 @@ type Report struct {
// StartPos/EndPos denote region of output with oops message(s).
StartPos int
EndPos int
// SkipPos is position in output where parsing for the next report should start.
SkipPos int
// Suppressed indicates whether the report should not be reported to user.
Suppressed bool
// Corrupted indicates whether the report is truncated of corrupted in some other way.
@ -184,6 +186,15 @@ func (wrap *reporterWrapper) Parse(output []byte) *Report {
if pos := bytes.Index(rep.Report, []byte(VMDiagnosisStart)); pos != -1 {
rep.Report = rep.Report[:pos]
}
rep.SkipPos = len(output)
if pos := bytes.IndexByte(output[rep.StartPos:], '\n'); pos != -1 {
rep.SkipPos = rep.StartPos + pos
}
if rep.EndPos < rep.SkipPos {
// This generally should not happen.
// But openbsd does some hacks with /r/n which may lead to off-by-one EndPos.
rep.EndPos = rep.SkipPos
}
return rep
}

View File

@ -186,22 +186,10 @@ func testParseImpl(t *testing.T, reporter Reporter, test *ParseTest) {
if rep == nil {
return
}
checkReport(t, rep, test)
if rep.StartPos != 0 {
// If we parse from StartPos, we must find the same report.
rep1 := reporter.Parse(test.Log[rep.StartPos:])
if rep1 == nil || rep1.Title != rep.Title {
t.Fatalf("did not find the same report from rep.StartPos=%v", rep.StartPos)
}
// If we parse from EndPos, we must not find the same report.
rep2 := reporter.Parse(test.Log[rep.EndPos:])
if rep2 != nil && rep2.Title == rep.Title {
t.Fatalf("found the same report after rep.EndPos=%v", rep.EndPos)
}
}
checkReport(t, reporter, rep, test)
}
func checkReport(t *testing.T, rep *Report, test *ParseTest) {
func checkReport(t *testing.T, reporter Reporter, rep *Report, test *ParseTest) {
if test.HasReport && !bytes.Equal(rep.Report, test.Report) {
t.Fatalf("extracted wrong report:\n%s\nwant:\n%s", rep.Report, test.Report)
}
@ -214,6 +202,9 @@ func checkReport(t *testing.T, rep *Report, test *ParseTest) {
if rep.EndPos > len(rep.Output) {
t.Fatalf("EndPos=%v > len(Output)=%v", rep.EndPos, len(rep.Output))
}
if rep.SkipPos <= rep.StartPos || rep.SkipPos > rep.EndPos {
t.Fatalf("bad SkipPos=%v: StartPos=%v EndPos=%v", rep.SkipPos, rep.StartPos, rep.EndPos)
}
if test.StartLine != "" {
if test.EndLine == "" {
test.EndLine = test.StartLine
@ -226,6 +217,18 @@ func checkReport(t *testing.T, rep *Report, test *ParseTest) {
string(test.Log[rep.StartPos:rep.EndPos]))
}
}
if rep.StartPos != 0 {
// If we parse from StartPos, we must find the same report.
rep1 := reporter.Parse(test.Log[rep.StartPos:])
if rep1 == nil || rep1.Title != rep.Title || rep1.StartPos != 0 {
t.Fatalf("did not find the same report from rep.StartPos=%v", rep.StartPos)
}
// If we parse from EndPos, we must not find the same report.
rep2 := reporter.Parse(test.Log[rep.EndPos:])
if rep2 != nil && rep2.Title == rep.Title {
t.Fatalf("found the same report after rep.EndPos=%v", rep.EndPos)
}
}
}
func updateReportTest(t *testing.T, test *ParseTest, title string, corrupted, suppressed bool,