@@ -375,12 +375,13 @@ func (r *Runner) parseTestResults(runPrefix string, runCount int) ([]reports.Tes
375375 }
376376 }
377377
378+ // TODO: An argument could be made to check for entryLine.Action != "output" instead, but need to check edge cases
378379 if (panicDetectionMode || raceDetectionMode ) && entryLine .Action == "fail" { // End of panic or race output
380+ var outputs []string
381+ for _ , entry := range detectedEntries {
382+ outputs = append (outputs , entry .Output )
383+ }
379384 if panicDetectionMode {
380- var outputs []string
381- for _ , entry := range detectedEntries {
382- outputs = append (outputs , entry .Output )
383- }
384385 panicTest , timeout , err := attributePanicToTest (outputs )
385386 if err != nil {
386387 log .Warn ().Err (err ).Msg ("Unable to attribute panic to a test" )
@@ -418,9 +419,10 @@ func (r *Runner) parseTestResults(runPrefix string, runCount int) ([]reports.Tes
418419 }
419420 }
420421 } else if raceDetectionMode {
421- raceTest , err := attributeRaceToTest (entryLine . Package , detectedEntries )
422+ raceTest , err := attributeRaceToTest (outputs )
422423 if err != nil {
423- return nil , err
424+ log .Warn ().Err (err ).Msg ("Unable to attribute race to a test" )
425+ raceTest = "UnableToAttributeRaceTestPleaseInvestigate"
424426 }
425427 raceTestKey := fmt .Sprintf ("%s/%s" , entryLine .Package , raceTest )
426428
@@ -612,42 +614,46 @@ func (r *Runner) transformTestOutputFiles(filePaths []string) error {
612614 return nil
613615}
614616
617+ var (
618+ // Regex to extract a valid test function name from a panic or race message, e.g.
619+ // github.com/smartcontractkit/chainlink/deployment/keystone/changeset_test.TestDeployBalanceReader(0xc000583c00)
620+ nestedTestNameRe = regexp .MustCompile (`\.(Test[A-Z]\w+)(?:\.[^(]+)?\s*\(` )
621+
622+ ErrFailedToAttributePanic = errors .New ("failed to attribute panic to test" )
623+ ErrFailedToAttributeRace = errors .New ("failed to attribute race to test" )
624+ )
625+
615626// attributePanicToTest properly attributes panics to the test that caused them.
616627func attributePanicToTest (outputs []string ) (test string , timeout bool , err error ) {
617- // Regex to extract a valid test function name from a panic message, e.g.
618- // github.com/smartcontractkit/chainlink/deployment/keystone/changeset_test.TestDeployBalanceReader(0xc000583c00)
619- nestedTestNameRe := regexp .MustCompile (`\.(Test[A-Z]\w+)(?:\.[^(]+)?\s*\(` )
620628 // Regex to extract a valid test function name from a panic message if the panic is a timeout, e.g.
621629 // TestTimedOut (10m0s)
622630 timedOutTestNamRe := regexp .MustCompile (`^(Test\w+)\W+\(.*\)$` )
623631
624- for _ , o := range outputs {
625- outputs = append (outputs , o )
626- matchNestedTestName := nestedTestNameRe .FindStringSubmatch (o )
627- matchTimedOutTestName := timedOutTestNamRe .FindStringSubmatch (o )
632+ for _ , output := range outputs {
633+ matchNestedTestName := nestedTestNameRe .FindStringSubmatch (output )
634+ matchTimedOutTestName := timedOutTestNamRe .FindStringSubmatch (output )
628635 if len (matchNestedTestName ) > 1 {
629636 return strings .TrimSpace (matchNestedTestName [1 ]), false , nil
630637 } else if len (matchTimedOutTestName ) > 1 {
631638 return strings .TrimSpace (matchTimedOutTestName [1 ]), true , nil
632639 }
633640 }
634- return "" , false , fmt .Errorf ("failed to attribute panic to test, using regex '%s' and '%s' on these strings:\n \n %s" ,
635- nestedTestNameRe .String (), timedOutTestNamRe .String (), strings .Join (outputs , "" ))
641+ return "" , false , fmt .Errorf ("%w, using regex '%s' and '%s' on these strings:\n \n %s" ,
642+ ErrFailedToAttributePanic , nestedTestNameRe .String (), timedOutTestNamRe .String (), strings .Join (outputs , "" ),
643+ )
636644}
637645
638646// attributeRaceToTest properly attributes races to the test that caused them.
639- func attributeRaceToTest (racePackage string , raceEntries []entry ) (string , error ) {
640- regexSanitizeRacePackage := filepath .Base (racePackage )
641- raceAttributionRe := regexp .MustCompile (fmt .Sprintf (`%s\.(Test[^\.\(]+)` , regexSanitizeRacePackage ))
642- entriesOutputs := []string {}
643- for _ , entry := range raceEntries {
644- entriesOutputs = append (entriesOutputs , entry .Output )
645- if matches := raceAttributionRe .FindStringSubmatch (entry .Output ); len (matches ) > 1 {
646- testName := strings .TrimSpace (matches [1 ])
647- return testName , nil
647+ func attributeRaceToTest (outputs []string ) (string , error ) {
648+ for _ , output := range outputs {
649+ match := nestedTestNameRe .FindStringSubmatch (output )
650+ if len (match ) > 1 {
651+ return strings .TrimSpace (match [1 ]), nil
648652 }
649653 }
650- return "" , fmt .Errorf ("failed to attribute race to test, using regex: %s on these strings:\n %s" , raceAttributionRe .String (), strings .Join (entriesOutputs , "" ))
654+ return "" , fmt .Errorf ("%w, using regex '%s' on these strings:\n \n %s" ,
655+ ErrFailedToAttributeRace , nestedTestNameRe .String (), strings .Join (outputs , "" ),
656+ )
651657}
652658
653659// parseSubTest checks if a test name is a subtest and returns the parent and sub names.
0 commit comments