@@ -31,20 +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
47- ContextIDs 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
4849 // Only used in report parsing:
4950 corruptedReason string
5051}
@@ -59,12 +60,18 @@ func (test *ParseTest) Equal(other *ParseTest) bool {
5960 if ! reflect .DeepEqual (test .AltTitles , other .AltTitles ) {
6061 return false
6162 }
63+ // Check frame only if it was present in the test file.
6264 if test .Frame != "" && test .Frame != other .Frame {
6365 return false
6466 }
67+ // Check report only if it was present in the test file.
6568 if test .HasReport && ! bytes .Equal (test .Report , other .Report ) {
6669 return false
6770 }
71+ // Check tail reports only if they were present in the test file.
72+ if test .HasReport && ! reflect .DeepEqual (test .TailReports , other .TailReports ) {
73+ return false
74+ }
6875 return test .Executor == other .Executor
6976}
7077
@@ -91,8 +98,8 @@ func (test *ParseTest) Headers() []byte {
9198 if test .Executor != "" {
9299 fmt .Fprintf (buf , "EXECUTOR: %s\n " , test .Executor )
93100 }
94- if test .ContextIDs != "" {
95- fmt .Fprintf (buf , "CONTEXTS: %s \n " , test .ContextIDs )
101+ if len ( test .ContextIDs ) != 0 {
102+ fmt .Fprintf (buf , "CONTEXTS: %v \n " , test .ContextIDs )
96103 }
97104 return buf .Bytes ()
98105}
@@ -113,6 +120,7 @@ func parseReport(t *testing.T, reporter *Reporter, testFileName string) *ParseTe
113120 phaseHeaders = iota
114121 phaseLog
115122 phaseReport
123+ phaseTailReports
116124 )
117125 phase := phaseHeaders
118126 test := & ParseTest {
@@ -121,6 +129,14 @@ func parseReport(t *testing.T, reporter *Reporter, testFileName string) *ParseTe
121129 prevEmptyLine := false
122130 s := bufio .NewScanner (bytes .NewReader (data ))
123131 for s .Scan () {
132+
133+ if string (s .Bytes ()) == "TAIL REPORTS:" {
134+ test .HasReport = true // we want both, REPORT and TAIL REPORT to be present
135+ test .TailReports = [][]byte {{}}
136+ phase = phaseTailReports
137+ continue
138+ }
139+
124140 switch phase {
125141 case phaseHeaders :
126142 ln := s .Text ()
@@ -140,11 +156,18 @@ func parseReport(t *testing.T, reporter *Reporter, testFileName string) *ParseTe
140156 case phaseReport :
141157 test .Report = append (test .Report , s .Bytes ()... )
142158 test .Report = append (test .Report , '\n' )
159+ case phaseTailReports :
160+ if string (s .Bytes ()) == reportSeparator {
161+ test .TailReports = append (test .TailReports , []byte {})
162+ continue
163+ }
164+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], s .Bytes ()... )
165+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], []byte {'\n' }... )
143166 }
144167 prevEmptyLine = len (s .Bytes ()) == 0
145168 }
146169 if s .Err () != nil {
147- t .Fatalf ("file scanning error : %v" , s .Err ())
170+ t .Fatalf ("file scanningerror : %v" , s .Err ())
148171 }
149172 if len (test .Log ) == 0 {
150173 t .Fatalf ("can't find log in input file" )
@@ -201,61 +224,87 @@ func parseHeaderLine(t *testing.T, test *ParseTest, ln string) {
201224 case strings .HasPrefix (ln , executorPrefix ):
202225 test .Executor = ln [len (executorPrefix ):]
203226 case strings .HasPrefix (ln , contextidPrefix ):
204- test .ContextIDs = ln [len (contextidPrefix ):]
227+ test .ContextIDs = strings . Split ( ln [len (contextidPrefix ):], ", " )
205228 default :
206229 t .Fatalf ("unknown header field %q" , ln )
207230 }
208231}
209232
210- func testFromReport ( rep * Report ) * ParseTest {
211- if rep == nil {
233+ func testFromReports ( reps ... * Report ) * ParseTest {
234+ if reps == nil || len ( reps ) > 0 && reps [ 0 ] == nil {
212235 return & ParseTest {}
213236 }
214237 ret := & ParseTest {
215- Title : rep .Title ,
216- AltTitles : rep .AltTitles ,
217- Corrupted : rep .Corrupted ,
218- corruptedReason : rep .CorruptedReason ,
219- Suppressed : rep .Suppressed ,
220- Type : TitleToCrashType (rep .Title ),
221- Frame : rep .Frame ,
222- Report : rep .Report ,
223- }
224- if rep .Executor != nil {
225- ret .Executor = fmt .Sprintf ("proc=%d, id=%d" , rep .Executor .ProcID , rep .Executor .ExecID )
238+ Title : reps [ 0 ] .Title ,
239+ AltTitles : reps [ 0 ] .AltTitles ,
240+ Corrupted : reps [ 0 ] .Corrupted ,
241+ corruptedReason : reps [ 0 ] .CorruptedReason ,
242+ Suppressed : reps [ 0 ] .Suppressed ,
243+ Type : TitleToCrashType (reps [ 0 ] .Title ),
244+ Frame : reps [ 0 ] .Frame ,
245+ Report : reps [ 0 ] .Report ,
246+ }
247+ if reps [ 0 ] .Executor != nil {
248+ ret .Executor = fmt .Sprintf ("proc=%d, id=%d" , reps [ 0 ] .Executor .ProcID , reps [ 0 ] .Executor .ExecID )
226249 }
227250 sort .Strings (ret .AltTitles )
251+ ret .ContextIDs = append (ret .ContextIDs , reps [0 ].ContextID )
252+ for i := 1 ; i < len (reps ); i ++ {
253+ ret .TailReports = append (ret .TailReports , reps [i ].Report )
254+ ret .ContextIDs = append (ret .ContextIDs , reps [i ].ContextID )
255+ }
228256 return ret
229257}
230258
259+ /*func testParseAll(t *testing.T, reporter *Reporter, testFileName string) {
260+ test := parseReport(t, reporter, testFileName)
261+ gotReports := ParseAll(reporter, test.Log, 0)
262+ gotIDs := mergeReportContextIDs(gotReports)
263+ mergedReport := MergeReportBytes(gotReports)
264+ if !bytes.Equal(mergedReport, test.Report) || gotIDs != test.ContextIDs {
265+ if *flagUpdate {
266+ updateReportTest(t, test, &ParseTest{
267+ ContextIDs: gotIDs,
268+ Report: mergedReport})
269+ }
270+ assert.Equal(t, test.ContextIDs, gotIDs, "extracted wrong Thread or CPU ids")
271+ assert.Equal(t, string(test.Report), string(mergedReport), "extracted wrong reports")
272+ }
273+ }*/
274+
231275func testParseImpl (t * testing.T , reporter * Reporter , test * ParseTest ) {
232- rep := reporter .Parse (test .Log )
276+ gotReports := ParseAll (reporter , test .Log , 0 )
277+
278+ var firstReport * Report
279+ if len (gotReports ) > 0 {
280+ firstReport = gotReports [0 ]
281+ }
233282 containsCrash := reporter .ContainsCrash (test .Log )
234283 expectCrash := (test .Title != "" )
235284 if expectCrash && ! containsCrash {
236285 t .Fatalf ("did not find crash" )
237286 }
238287 if ! expectCrash && containsCrash {
239- t .Fatalf ("found unexpected crash" )
288+ t .Fatalf ("found unexpected crash: %s" , firstReport . Title )
240289 }
241- if rep != nil && rep .Title == "" {
290+ if firstReport != nil && firstReport .Title == "" {
242291 t .Fatalf ("found crash, but title is empty" )
243292 }
244- parsed := testFromReport ( rep )
293+ parsed := testFromReports ( gotReports ... )
245294 if ! test .Equal (parsed ) {
246295 if * flagUpdate && test .StartLine + test .EndLine == "" {
247296 updateReportTest (t , test , parsed )
248297 }
249298 t .Fatalf ("want:\n %s\n got:\n %sCorrupted reason: %q" ,
250299 test .Headers (), parsed .Headers (), parsed .corruptedReason )
251300 }
252- if parsed .Title != "" && len (rep .Report ) == 0 {
301+ if parsed .Title != "" && len (firstReport .Report ) == 0 {
253302 t .Fatalf ("found crash message but report is empty" )
254303 }
255- if rep == nil {
304+ if firstReport == nil {
256305 return
257306 }
258- checkReport (t , reporter , rep , test )
307+ checkReport (t , reporter , firstReport , test )
259308}
260309
261310func checkReport (t * testing.T , reporter * Reporter , rep * Report , test * ParseTest ) {
@@ -292,11 +341,6 @@ func checkReport(t *testing.T, reporter *Reporter, rep *Report, test *ParseTest)
292341 if rep1 == nil || rep1 .Title != rep .Title || rep1 .StartPos != rep .StartPos {
293342 t .Fatalf ("did not find the same report from rep.StartPos=%v" , rep .StartPos )
294343 }
295- // If we parse from EndPos, we must not find the same report.
296- rep2 := reporter .ParseFrom (test .Log , rep .EndPos )
297- if rep2 != nil && rep2 .Title == rep .Title {
298- t .Fatalf ("found the same report after rep.EndPos=%v" , rep .EndPos )
299- }
300344 }
301345}
302346
@@ -310,7 +354,13 @@ func updateReportTest(t *testing.T, test, parsed *ParseTest) {
310354 fmt .Fprintf (buf , "\n %s" , test .Log )
311355 if test .HasReport {
312356 fmt .Fprintf (buf , "REPORT:\n %s" , parsed .Report )
357+
358+ if len (parsed .TailReports ) > 0 {
359+ fmt .Fprintf (buf , "TAIL REPORTS:\n " )
360+ buf .Write (bytes .Join (parsed .TailReports , []byte (reportSeparator + "\n " )))
361+ }
313362 }
363+
314364 if err := os .WriteFile (test .FileName , buf .Bytes (), 0640 ); err != nil {
315365 t .Logf ("failed to update test file: %v" , err )
316366 }
@@ -402,7 +452,7 @@ func testSymbolizeFile(t *testing.T, reporter *Reporter, fn string) {
402452 if err != nil {
403453 t .Fatalf ("failed to symbolize: %v" , err )
404454 }
405- parsed := testFromReport (rep )
455+ parsed := testFromReports (rep )
406456 if ! test .Equal (parsed ) {
407457 if * flagUpdate {
408458 updateReportTest (t , test , parsed )
@@ -558,26 +608,3 @@ func TestSplitReportBytes(t *testing.T) {
558608 })
559609 }
560610}
561-
562- // TestParseAll's focus points are the ability to:
563- // 1. parse multiple reports
564- // 2. extract correct ThreadID/CpuID.
565- func TestParseAll (t * testing.T ) {
566- forEachFile (t , "parse_all" , testParseAll )
567- }
568-
569- func testParseAll (t * testing.T , reporter * Reporter , testFileName string ) {
570- test := parseReport (t , reporter , testFileName )
571- gotReports := ParseAll (reporter , test .Log , 0 )
572- gotIDs := mergeReportContextIDs (gotReports )
573- mergedReport := MergeReportBytes (gotReports )
574- if ! bytes .Equal (mergedReport , test .Report ) || gotIDs != test .ContextIDs {
575- if * flagUpdate {
576- updateReportTest (t , test , & ParseTest {
577- ContextIDs : gotIDs ,
578- Report : mergedReport })
579- }
580- assert .Equal (t , test .ContextIDs , gotIDs , "extracted wrong Thread or CPU ids" )
581- assert .Equal (t , string (test .Report ), string (mergedReport ), "extracted wrong reports" )
582- }
583- }
0 commit comments