@@ -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 .Error ().Msg ("Unable to attribute panic to a test" )
@@ -419,9 +420,11 @@ func (r *Runner) parseTestResults(runPrefix string, runCount int) ([]reports.Tes
419420 }
420421 }
421422 } else if raceDetectionMode {
422- raceTest , err := attributeRaceToTest (entryLine . Package , detectedEntries )
423+ raceTest , err := attributeRaceToTest (outputs )
423424 if err != nil {
424- return nil , err
425+ log .Warn ().Msg ("Unable to attribute race to a test" )
426+ fmt .Println (err .Error ())
427+ raceTest = "UnableToAttributeRaceTestPleaseInvestigate"
425428 }
426429 raceTestKey := fmt .Sprintf ("%s/%s" , entryLine .Package , raceTest )
427430
@@ -614,7 +617,13 @@ func (r *Runner) transformTestOutputFiles(filePaths []string) error {
614617}
615618
616619var (
620+ // Regex to extract a valid test function name from a panic message.
621+ // This is the most common situation for test panics, e.g.
622+ // github.com/smartcontractkit/chainlink/deployment/keystone/changeset_test.TestDeployBalanceReader(0xc000583c00)
623+ nestedTestNameRe = regexp .MustCompile (`\.(Test[^\s]+?)(?:\.[^(]+)?\s*\(` )
624+
617625 ErrFailedToAttributePanicToTest = errors .New ("failed to attribute panic to test" )
626+ ErrFailedToAttributeRaceToTest = errors .New ("failed to attribute race to test" )
618627 ErrFailedToParseTimeoutDuration = errors .New ("failed to parse timeout duration" )
619628 ErrFailedToExtractTimeoutDuration = errors .New ("failed to extract timeout duration" )
620629 ErrDetectedLogAfterCompleteFailedAttribution = errors .New ("detected a log after test has completed panic, but failed to properly attribute it" )
@@ -626,11 +635,6 @@ var (
626635// There are a lot of edge cases and strange behavior in Go test output when it comes to panics.
627636func attributePanicToTest (outputs []string ) (test string , timeout bool , err error ) {
628637 var (
629- // Regex to extract a valid test function name from a panic message.
630- // This is the most common situation for test panics, e.g.
631- // github.com/smartcontractkit/chainlink/deployment/keystone/changeset_test.TestDeployBalanceReader(0xc000583c00)
632- nestedTestNameRe = regexp .MustCompile (`\.(Test[^\s]+?)(?:\.[^(]+)?\s*\(` )
633-
634638 // Regex to check if the panic is from a log after a goroutine, e.g.
635639 // panic: Log in goroutine after Test_workflowRegisteredHandler/skips_fetch_if_secrets_url_is_missing has completed: <Log line>
636640 testLogAfterTestRe = regexp .MustCompile (`^panic: Log in goroutine after (Test[^\s]+) has completed:` )
@@ -716,18 +720,16 @@ func attributePanicToTest(outputs []string) (test string, timeout bool, err erro
716720}
717721
718722// attributeRaceToTest properly attributes races to the test that caused them.
719- func attributeRaceToTest (racePackage string , raceEntries []entry ) (string , error ) {
720- regexSanitizeRacePackage := filepath .Base (racePackage )
721- raceAttributionRe := regexp .MustCompile (fmt .Sprintf (`%s\.(Test[^\.\(]+)` , regexSanitizeRacePackage ))
722- entriesOutputs := []string {}
723- for _ , entry := range raceEntries {
724- entriesOutputs = append (entriesOutputs , entry .Output )
725- if matches := raceAttributionRe .FindStringSubmatch (entry .Output ); len (matches ) > 1 {
726- testName := strings .TrimSpace (matches [1 ])
727- return testName , nil
723+ func attributeRaceToTest (outputs []string ) (string , error ) {
724+ for _ , output := range outputs {
725+ match := nestedTestNameRe .FindStringSubmatch (output )
726+ if len (match ) > 1 {
727+ return strings .TrimSpace (match [1 ]), nil
728728 }
729729 }
730- return "" , fmt .Errorf ("failed to attribute race to test, using regex: %s on these strings:\n %s" , raceAttributionRe .String (), strings .Join (entriesOutputs , "" ))
730+ return "" , fmt .Errorf ("%w, using this output:\n \n %s" ,
731+ ErrFailedToAttributeRaceToTest , strings .Join (outputs , "" ),
732+ )
731733}
732734
733735// parseSubTest checks if a test name is a subtest and returns the parent and sub names.
0 commit comments