Skip to content

Commit 508e24b

Browse files
authored
Merge branch 'main' into anvil-zksync
2 parents 15810a8 + 63eefaa commit 508e24b

File tree

4 files changed

+199
-113
lines changed

4 files changed

+199
-113
lines changed

tools/flakeguard/cmd/run.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ var RunTestsCmd = &cobra.Command{
184184
flushSummaryAndExit(0)
185185
}
186186

187+
fmt.Fprint(&summaryBuffer, "\nFailed Tests On The First Run:\n\n")
188+
reports.PrintTestResultsTable(&summaryBuffer, failedTests, false, false, true, false, false, false)
189+
fmt.Fprintln(&summaryBuffer)
190+
187191
rerunResults, rerunJsonOutputPaths, err := testRunner.RerunFailedTests(failedTests, rerunFailedCount)
188192
if err != nil {
189193
log.Fatal().Err(err).Msg("Error rerunning failed tests")
@@ -203,8 +207,8 @@ var RunTestsCmd = &cobra.Command{
203207
flushSummaryAndExit(ErrorExitCode)
204208
}
205209

206-
fmt.Fprint(&summaryBuffer, "\nFailed Tests That Were Rerun:\n\n")
207-
reports.PrintTestResultsTable(&summaryBuffer, rerunResults, false, false, true)
210+
fmt.Fprint(&summaryBuffer, "\nTests After Rerun:\n\n")
211+
reports.PrintTestResultsTable(&summaryBuffer, rerunResults, false, false, true, true, true, true)
208212
fmt.Fprintln(&summaryBuffer)
209213

210214
// Save the rerun test report to file
@@ -248,6 +252,9 @@ var RunTestsCmd = &cobra.Command{
248252
Int("count", len(flakyTests)).
249253
Str("stability threshold", fmt.Sprintf("%.0f%%", passRatioThreshold*100)).
250254
Msg("Found flaky tests")
255+
256+
fmt.Fprint(&summaryBuffer, "\nFlakeguard Summary\n")
257+
reports.RenderTestReport(&summaryBuffer, mainReport, false, false)
251258
flushSummaryAndExit(FlakyTestsExitCode)
252259
} else {
253260
log.Info().Msg("All tests passed stability requirements")

tools/flakeguard/reports/presentation.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,27 @@ func generateTestResultsTable(
7878
func generateShortTestResultsTable(
7979
results []TestResult,
8080
markdown bool,
81+
showEverPassed bool,
82+
showRuns bool,
83+
showSuccesses bool,
8184
filter func(TestResult) bool,
8285
) [][]string {
8386
p := message.NewPrinter(language.English)
8487

85-
headers := []string{"Name", "Ever Passed", "Runs", "Successes", "Code Owners", "Path"}
88+
// Build headers dynamically
89+
var headers []string
90+
headers = append(headers, "Name")
91+
if showEverPassed {
92+
headers = append(headers, "Ever Passed")
93+
}
94+
if showRuns {
95+
headers = append(headers, "Runs")
96+
}
97+
if showSuccesses {
98+
headers = append(headers, "Successes")
99+
}
100+
101+
headers = append(headers, "Code Owners", "Path")
86102

87103
// Optionally format the headers for Markdown
88104
if markdown {
@@ -112,14 +128,22 @@ func generateShortTestResultsTable(
112128
owners = strings.Join(r.CodeOwners, ", ")
113129
}
114130

115-
row := []string{
116-
r.TestName, // "Name"
117-
passed, // "Passed"
118-
p.Sprintf("%d", r.Runs), // "Runs"
119-
p.Sprintf("%d", r.Successes), // "Passes"
120-
owners, // "Code Owners"
121-
r.TestPath, // "Path"
131+
// Build row dynamically
132+
row := []string{r.TestName}
133+
if showEverPassed {
134+
row = append(row, passed)
122135
}
136+
if showRuns {
137+
row = append(row, p.Sprintf("%d", r.Runs))
138+
}
139+
if showSuccesses {
140+
row = append(row, p.Sprintf("%d", r.Successes))
141+
}
142+
143+
row = append(row,
144+
owners,
145+
r.TestPath,
146+
)
123147

124148
table = append(table, row)
125149
}
@@ -143,13 +167,16 @@ func PrintTestResultsTable(
143167
results []TestResult,
144168
markdown bool,
145169
collapsible bool,
146-
shortTable bool) {
170+
shortTable bool,
171+
showEverPassed bool,
172+
showRuns bool,
173+
showSuccesses bool) {
147174
filter := func(result TestResult) bool {
148175
return true // Include all tests
149176
}
150177
var table [][]string
151178
if shortTable {
152-
table = generateShortTestResultsTable(results, markdown, filter)
179+
table = generateShortTestResultsTable(results, markdown, showEverPassed, showRuns, showSuccesses, filter)
153180
} else {
154181
table = generateTestResultsTable(results, markdown, filter)
155182
}

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)