Skip to content

Commit 97dc520

Browse files
committed
Improve panic attribution logic in Flakeguard test runner
1 parent af19bb9 commit 97dc520

File tree

2 files changed

+153
-101
lines changed

2 files changed

+153
-101
lines changed

tools/flakeguard/runner/runner.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,11 @@ func (r *Runner) parseTestResults(jsonOutputPaths []string, runPrefix string, ru
381381

382382
if (panicDetectionMode || raceDetectionMode) && entryLine.Action == "fail" { // End of panic or race output
383383
if panicDetectionMode {
384-
panicTest, timeout, err := attributePanicToTest(entryLine.Package, detectedEntries)
384+
var outputs []string
385+
for _, entry := range detectedEntries {
386+
outputs = append(outputs, entry.Output)
387+
}
388+
panicTest, timeout, err := attributePanicToTest(outputs)
385389
if err != nil {
386390
return nil, err
387391
}
@@ -614,23 +618,23 @@ func (r *Runner) transformTestOutputFiles(filePaths []string) ([]string, error)
614618
}
615619

616620
// attributePanicToTest properly attributes panics to the test that caused them.
617-
func attributePanicToTest(panicPackage string, panicEntries []entry) (test string, timeout bool, err error) {
618-
regexSanitizePanicPackage := filepath.Base(panicPackage)
619-
panicAttributionRe := regexp.MustCompile(fmt.Sprintf(`%s\.(Test[^\.\(]+)`, regexSanitizePanicPackage))
620-
timeoutAttributionRe := regexp.MustCompile(`(Test.*?)\W+\(.*\)`)
621-
entriesOutputs := []string{}
622-
for _, entry := range panicEntries {
623-
entriesOutputs = append(entriesOutputs, entry.Output)
624-
if matches := panicAttributionRe.FindStringSubmatch(entry.Output); len(matches) > 1 {
621+
func attributePanicToTest(outputs []string) (test string, timeout bool, err error) {
622+
// Regex to extract a valid test function name.
623+
testNameRe := regexp.MustCompile(`(?:.*\.)?(Test[A-Z]\w+)(?:\.[^(]+)?\s*\(`)
624+
// Regex to detect timeout messages (accepting "timeout", "timedout", or "timed out", case-insensitive).
625+
timeoutRe := regexp.MustCompile(`(?i)(timeout|timedout|timed\s*out)`)
626+
for _, o := range outputs {
627+
outputs = append(outputs, o)
628+
if matches := testNameRe.FindStringSubmatch(o); len(matches) > 1 {
625629
testName := strings.TrimSpace(matches[1])
630+
if timeoutRe.MatchString(o) {
631+
return testName, true, nil
632+
}
626633
return testName, false, nil
627634
}
628-
if matches := timeoutAttributionRe.FindStringSubmatch(entry.Output); len(matches) > 1 {
629-
testName := strings.TrimSpace(matches[1])
630-
return testName, true, nil
631-
}
632635
}
633-
return "", false, fmt.Errorf("failed to attribute panic to test, using regex %s on these strings:\n%s", panicAttributionRe.String(), strings.Join(entriesOutputs, ""))
636+
return "", false, fmt.Errorf("failed to attribute panic to test, using regex %s on these strings:\n%s",
637+
testNameRe.String(), strings.Join(outputs, ""))
634638
}
635639

636640
// attributeRaceToTest properly attributes races to the test that caused them.

0 commit comments

Comments
 (0)