@@ -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,10 +117,11 @@ 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 ))
@@ -134,8 +143,20 @@ func parseReport(t *testing.T, reporter *Reporter, fn string) *ParseTest {
134143 test .Log = append (test .Log , '\n' )
135144 }
136145 case phaseReport :
137- test .Report = append (test .Report , s .Bytes ()... )
138- test .Report = append (test .Report , '\n' )
146+ if string (s .Bytes ()) == "TAIL REPORTS:" {
147+ test .TailReports = [][]byte {{}}
148+ phase = phaseTailReports
149+ } else {
150+ test .Report = append (test .Report , s .Bytes ()... )
151+ test .Report = append (test .Report , '\n' )
152+ }
153+ case phaseTailReports :
154+ if string (s .Bytes ()) == reportSeparator {
155+ test .TailReports = append (test .TailReports , []byte {})
156+ continue
157+ }
158+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], s .Bytes ()... )
159+ test .TailReports [len (test .TailReports )- 1 ] = append (test .TailReports [len (test .TailReports )- 1 ], []byte {'\n' }... )
139160 }
140161 prevEmptyLine = len (s .Bytes ()) == 0
141162 }
@@ -160,6 +181,7 @@ func parseHeaderLine(t *testing.T, test *ParseTest, ln string) {
160181 corruptedPrefix = "CORRUPTED: "
161182 suppressedPrefix = "SUPPRESSED: "
162183 executorPrefix = "EXECUTOR: "
184+ contextidPrefix = "CONTEXTS: "
163185 )
164186 switch {
165187 case strings .HasPrefix (ln , "#" ):
@@ -195,60 +217,72 @@ func parseHeaderLine(t *testing.T, test *ParseTest, ln string) {
195217 }
196218 case strings .HasPrefix (ln , executorPrefix ):
197219 test .Executor = ln [len (executorPrefix ):]
220+ case strings .HasPrefix (ln , contextidPrefix ):
221+ test .ContextIDs = strings .Split (ln [len (contextidPrefix ):], ", " )
198222 default :
199223 t .Fatalf ("unknown header field %q" , ln )
200224 }
201225}
202226
203- func testFromReport ( rep * Report ) * ParseTest {
204- if rep == nil {
227+ func testFromReports ( reps ... * Report ) * ParseTest {
228+ if reps == nil || len ( reps ) > 0 && reps [ 0 ] == nil {
205229 return & ParseTest {}
206230 }
207231 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 )
232+ Title : reps [ 0 ] .Title ,
233+ AltTitles : reps [ 0 ] .AltTitles ,
234+ Corrupted : reps [ 0 ] .Corrupted ,
235+ corruptedReason : reps [ 0 ] .CorruptedReason ,
236+ Suppressed : reps [ 0 ] .Suppressed ,
237+ Type : TitleToCrashType (reps [ 0 ] .Title ),
238+ Frame : reps [ 0 ] .Frame ,
239+ Report : reps [ 0 ] .Report ,
240+ }
241+ if reps [ 0 ] .Executor != nil {
242+ ret .Executor = fmt .Sprintf ("proc=%d, id=%d" , reps [ 0 ] .Executor .ProcID , reps [ 0 ] .Executor .ExecID )
219243 }
220244 sort .Strings (ret .AltTitles )
245+ ret .ContextIDs = append (ret .ContextIDs , reps [0 ].ContextID )
246+ for i := 1 ; i < len (reps ); i ++ {
247+ ret .TailReports = append (ret .TailReports , reps [i ].Report )
248+ ret .ContextIDs = append (ret .ContextIDs , reps [i ].ContextID )
249+ }
221250 return ret
222251}
223252
224253func testParseImpl (t * testing.T , reporter * Reporter , test * ParseTest ) {
225- rep := reporter .Parse (test .Log )
254+ gotReports := ParseAll (reporter , test .Log , 0 )
255+
256+ var firstReport * Report
257+ if len (gotReports ) > 0 {
258+ firstReport = gotReports [0 ]
259+ }
226260 containsCrash := reporter .ContainsCrash (test .Log )
227261 expectCrash := (test .Title != "" )
228262 if expectCrash && ! containsCrash {
229263 t .Fatalf ("did not find crash" )
230264 }
231265 if ! expectCrash && containsCrash {
232- t .Fatalf ("found unexpected crash" )
266+ t .Fatalf ("found unexpected crash: %s" , firstReport . Title )
233267 }
234- if rep != nil && rep .Title == "" {
268+ if firstReport != nil && firstReport .Title == "" {
235269 t .Fatalf ("found crash, but title is empty" )
236270 }
237- parsed := testFromReport ( rep )
271+ parsed := testFromReports ( gotReports ... )
238272 if ! test .Equal (parsed ) {
239273 if * flagUpdate && test .StartLine + test .EndLine == "" {
240274 updateReportTest (t , test , parsed )
241275 }
242276 t .Fatalf ("want:\n %s\n got:\n %sCorrupted reason: %q" ,
243277 test .Headers (), parsed .Headers (), parsed .corruptedReason )
244278 }
245- if parsed .Title != "" && len (rep .Report ) == 0 {
279+ if parsed .Title != "" && len (firstReport .Report ) == 0 {
246280 t .Fatalf ("found crash message but report is empty" )
247281 }
248- if rep == nil {
282+ if firstReport == nil {
249283 return
250284 }
251- checkReport (t , reporter , rep , test )
285+ checkReport (t , reporter , firstReport , test )
252286}
253287
254288func checkReport (t * testing.T , reporter * Reporter , rep * Report , test * ParseTest ) {
@@ -285,11 +319,6 @@ func checkReport(t *testing.T, reporter *Reporter, rep *Report, test *ParseTest)
285319 if rep1 == nil || rep1 .Title != rep .Title || rep1 .StartPos != rep .StartPos {
286320 t .Fatalf ("did not find the same report from rep.StartPos=%v" , rep .StartPos )
287321 }
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- }
293322 }
294323}
295324
@@ -303,7 +332,13 @@ func updateReportTest(t *testing.T, test, parsed *ParseTest) {
303332 fmt .Fprintf (buf , "\n %s" , test .Log )
304333 if test .HasReport {
305334 fmt .Fprintf (buf , "REPORT:\n %s" , parsed .Report )
335+
336+ if len (parsed .TailReports ) > 0 {
337+ fmt .Fprintf (buf , "TAIL REPORTS:\n " )
338+ buf .Write (bytes .Join (parsed .TailReports , []byte (reportSeparator + "\n " )))
339+ }
306340 }
341+
307342 if err := os .WriteFile (test .FileName , buf .Bytes (), 0640 ); err != nil {
308343 t .Logf ("failed to update test file: %v" , err )
309344 }
@@ -395,7 +430,7 @@ func testSymbolizeFile(t *testing.T, reporter *Reporter, fn string) {
395430 if err != nil {
396431 t .Fatalf ("failed to symbolize: %v" , err )
397432 }
398- parsed := testFromReport (rep )
433+ parsed := testFromReports (rep )
399434 if ! test .Equal (parsed ) {
400435 if * flagUpdate {
401436 updateReportTest (t , test , parsed )
0 commit comments