@@ -31,19 +31,21 @@ func TestParse(t *testing.T) {
3131}
3232
3333type ParseTest struct {
34- FileName string
35- Log []byte
36- Title string
37- AltTitles []string
38- Type crash.Type
39- Frame string
40- StartLine string
41- EndLine string
42- Corrupted bool
43- Suppressed bool
44- HasReport bool
45- Report []byte
46- Executor string
34+ FileName string
35+ Log []byte
36+ Title string
37+ AltTitles []string
38+ Type crash.Type
39+ Frame string
40+ StartLine string
41+ EndLine string
42+ Corrupted bool
43+ Suppressed bool
44+ HasReport bool
45+ Report []byte
46+ TailReports [][]byte
47+ Executor string
48+ ContextIDs []string
4749 // Only used in report parsing:
4850 corruptedReason string
4951}
@@ -64,6 +66,9 @@ func (test *ParseTest) Equal(other *ParseTest) bool {
6466 if test .HasReport && ! bytes .Equal (test .Report , other .Report ) {
6567 return false
6668 }
69+ if test .HasReport && ! reflect .DeepEqual (test .TailReports , other .TailReports ) {
70+ return false
71+ }
6772 return test .Executor == other .Executor
6873}
6974
@@ -90,6 +95,9 @@ func (test *ParseTest) Headers() []byte {
9095 if test .Executor != "" {
9196 fmt .Fprintf (buf , "EXECUTOR: %s\n " , test .Executor )
9297 }
98+ if len (test .ContextIDs ) != 0 {
99+ fmt .Fprintf (buf , "CONTEXTS: %v\n " , test .ContextIDs )
100+ }
93101 return buf .Bytes ()
94102}
95103
@@ -98,8 +106,8 @@ func testParseFile(t *testing.T, reporter *Reporter, fn string) {
98106 testParseImpl (t , reporter , test )
99107}
100108
101- func parseReport (t * testing.T , reporter * Reporter , fn string ) * ParseTest {
102- data , err := os .ReadFile (fn )
109+ func parseReport (t * testing.T , reporter * Reporter , testFileName string ) * ParseTest {
110+ data , err := os .ReadFile (testFileName )
103111 if err != nil {
104112 t .Fatal (err )
105113 }
@@ -109,14 +117,22 @@ func parseReport(t *testing.T, reporter *Reporter, fn string) *ParseTest {
109117 phaseHeaders = iota
110118 phaseLog
111119 phaseReport
120+ phaseTailReports
112121 )
113122 phase := phaseHeaders
114123 test := & ParseTest {
115- FileName : fn ,
124+ FileName : testFileName ,
116125 }
117126 prevEmptyLine := false
118127 s := bufio .NewScanner (bytes .NewReader (data ))
119128 for s .Scan () {
129+ if string (s .Bytes ()) == "TAIL REPORTS:" {
130+ test .HasReport = true // we want both, REPORT and TAIL REPORT to be present
131+ test .TailReports = [][]byte {{}}
132+ phase = phaseTailReports
133+ continue
134+ }
135+
120136 switch phase {
121137 case phaseHeaders :
122138 ln := s .Text ()
@@ -136,6 +152,13 @@ func parseReport(t *testing.T, reporter *Reporter, fn string) *ParseTest {
136152 case phaseReport :
137153 test .Report = append (test .Report , s .Bytes ()... )
138154 test .Report = append (test .Report , '\n' )
155+ case phaseTailReports :
156+ if string (s .Bytes ()) == reportSeparator {
157+ test .TailReports = append (test .TailReports , []byte {})
158+ continue
159+ }
160+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], s .Bytes ()... )
161+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], []byte {'\n' }... )
139162 }
140163 prevEmptyLine = len (s .Bytes ()) == 0
141164 }
@@ -160,6 +183,7 @@ func parseHeaderLine(t *testing.T, test *ParseTest, ln string) {
160183 corruptedPrefix = "CORRUPTED: "
161184 suppressedPrefix = "SUPPRESSED: "
162185 executorPrefix = "EXECUTOR: "
186+ contextidPrefix = "CONTEXTS: "
163187 )
164188 switch {
165189 case strings .HasPrefix (ln , "#" ):
@@ -195,60 +219,72 @@ func parseHeaderLine(t *testing.T, test *ParseTest, ln string) {
195219 }
196220 case strings .HasPrefix (ln , executorPrefix ):
197221 test .Executor = ln [len (executorPrefix ):]
222+ case strings .HasPrefix (ln , contextidPrefix ):
223+ test .ContextIDs = strings .Split (ln [len (contextidPrefix ):], ", " )
198224 default :
199225 t .Fatalf ("unknown header field %q" , ln )
200226 }
201227}
202228
203- func testFromReport ( rep * Report ) * ParseTest {
204- if rep == nil {
229+ func testFromReports ( reps ... * Report ) * ParseTest {
230+ if reps == nil || len ( reps ) > 0 && reps [ 0 ] == nil {
205231 return & ParseTest {}
206232 }
207233 ret := & ParseTest {
208- Title : rep .Title ,
209- AltTitles : rep .AltTitles ,
210- Corrupted : rep .Corrupted ,
211- corruptedReason : rep .CorruptedReason ,
212- Suppressed : rep .Suppressed ,
213- Type : TitleToCrashType (rep .Title ),
214- Frame : rep .Frame ,
215- Report : rep .Report ,
216- }
217- if rep .Executor != nil {
218- ret .Executor = fmt .Sprintf ("proc=%d, id=%d" , rep .Executor .ProcID , rep .Executor .ExecID )
234+ Title : reps [ 0 ] .Title ,
235+ AltTitles : reps [ 0 ] .AltTitles ,
236+ Corrupted : reps [ 0 ] .Corrupted ,
237+ corruptedReason : reps [ 0 ] .CorruptedReason ,
238+ Suppressed : reps [ 0 ] .Suppressed ,
239+ Type : TitleToCrashType (reps [ 0 ] .Title ),
240+ Frame : reps [ 0 ] .Frame ,
241+ Report : reps [ 0 ] .Report ,
242+ }
243+ if reps [ 0 ] .Executor != nil {
244+ ret .Executor = fmt .Sprintf ("proc=%d, id=%d" , reps [ 0 ] .Executor .ProcID , reps [ 0 ] .Executor .ExecID )
219245 }
220246 sort .Strings (ret .AltTitles )
247+ ret .ContextIDs = append (ret .ContextIDs , reps [0 ].ContextID )
248+ for i := 1 ; i < len (reps ); i ++ {
249+ ret .TailReports = append (ret .TailReports , reps [i ].Report )
250+ ret .ContextIDs = append (ret .ContextIDs , reps [i ].ContextID )
251+ }
221252 return ret
222253}
223254
224255func testParseImpl (t * testing.T , reporter * Reporter , test * ParseTest ) {
225- rep := reporter .Parse (test .Log )
256+ gotReports := ParseAll (reporter , test .Log , 0 )
257+
258+ var firstReport * Report
259+ if len (gotReports ) > 0 {
260+ firstReport = gotReports [0 ]
261+ }
226262 containsCrash := reporter .ContainsCrash (test .Log )
227263 expectCrash := (test .Title != "" )
228264 if expectCrash && ! containsCrash {
229265 t .Fatalf ("did not find crash" )
230266 }
231267 if ! expectCrash && containsCrash {
232- t .Fatalf ("found unexpected crash" )
268+ t .Fatalf ("found unexpected crash: %s" , firstReport . Title )
233269 }
234- if rep != nil && rep .Title == "" {
270+ if firstReport != nil && firstReport .Title == "" {
235271 t .Fatalf ("found crash, but title is empty" )
236272 }
237- parsed := testFromReport ( rep )
273+ parsed := testFromReports ( gotReports ... )
238274 if ! test .Equal (parsed ) {
239275 if * flagUpdate && test .StartLine + test .EndLine == "" {
240276 updateReportTest (t , test , parsed )
241277 }
242278 t .Fatalf ("want:\n %s\n got:\n %sCorrupted reason: %q" ,
243279 test .Headers (), parsed .Headers (), parsed .corruptedReason )
244280 }
245- if parsed .Title != "" && len (rep .Report ) == 0 {
281+ if parsed .Title != "" && len (firstReport .Report ) == 0 {
246282 t .Fatalf ("found crash message but report is empty" )
247283 }
248- if rep == nil {
284+ if firstReport == nil {
249285 return
250286 }
251- checkReport (t , reporter , rep , test )
287+ checkReport (t , reporter , firstReport , test )
252288}
253289
254290func checkReport (t * testing.T , reporter * Reporter , rep * Report , test * ParseTest ) {
@@ -285,11 +321,6 @@ func checkReport(t *testing.T, reporter *Reporter, rep *Report, test *ParseTest)
285321 if rep1 == nil || rep1 .Title != rep .Title || rep1 .StartPos != rep .StartPos {
286322 t .Fatalf ("did not find the same report from rep.StartPos=%v" , rep .StartPos )
287323 }
288- // If we parse from EndPos, we must not find the same report.
289- rep2 := reporter .ParseFrom (test .Log , rep .EndPos )
290- if rep2 != nil && rep2 .Title == rep .Title {
291- t .Fatalf ("found the same report after rep.EndPos=%v" , rep .EndPos )
292- }
293324 }
294325}
295326
@@ -303,7 +334,13 @@ func updateReportTest(t *testing.T, test, parsed *ParseTest) {
303334 fmt .Fprintf (buf , "\n %s" , test .Log )
304335 if test .HasReport {
305336 fmt .Fprintf (buf , "REPORT:\n %s" , parsed .Report )
337+
338+ if len (parsed .TailReports ) > 0 {
339+ fmt .Fprintf (buf , "TAIL REPORTS:\n " )
340+ buf .Write (bytes .Join (parsed .TailReports , []byte (reportSeparator + "\n " )))
341+ }
306342 }
343+
307344 if err := os .WriteFile (test .FileName , buf .Bytes (), 0640 ); err != nil {
308345 t .Logf ("failed to update test file: %v" , err )
309346 }
@@ -395,7 +432,7 @@ func testSymbolizeFile(t *testing.T, reporter *Reporter, fn string) {
395432 if err != nil {
396433 t .Fatalf ("failed to symbolize: %v" , err )
397434 }
398- parsed := testFromReport (rep )
435+ parsed := testFromReports (rep )
399436 if ! test .Equal (parsed ) {
400437 if * flagUpdate {
401438 updateReportTest (t , test , parsed )
0 commit comments