Skip to content

Commit 5852034

Browse files
fixup! roachprod-microbench: post GitHub issues for performance regressions
1 parent be14bbe commit 5852034

File tree

1 file changed

+226
-0
lines changed

1 file changed

+226
-0
lines changed

pkg/cmd/roachprod-microbench/github_test.go

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,232 @@ func TestCreatePostRequest(t *testing.T) {
5555
}
5656

5757
// formatPostRequest emulates the behavior of the githubpost package.
58+
func TestCreateRegressionPostRequestBasic(t *testing.T) {
59+
regressions := []regressionInfo{
60+
{
61+
benchmarkName: "BenchmarkScan",
62+
metricUnit: "ns/op",
63+
percentChange: 25.5,
64+
formattedDelta: "+1.2ms",
65+
},
66+
{
67+
benchmarkName: "BenchmarkInsert",
68+
metricUnit: "ns/op",
69+
percentChange: 30.0,
70+
formattedDelta: "+500µs",
71+
},
72+
}
73+
74+
formatter, req := createRegressionPostRequest(
75+
"pkg/sql",
76+
regressions,
77+
"https://docs.google.com/spreadsheets/d/test123",
78+
"master -> release-24.1",
79+
)
80+
81+
// Verify labels
82+
expectedLabels := []string{"O-microbench", "C-performance"}
83+
for _, label := range expectedLabels {
84+
found := false
85+
for _, l := range req.Labels {
86+
if l == label {
87+
found = true
88+
break
89+
}
90+
}
91+
if !found {
92+
t.Errorf("Expected label %q not found in %v", label, req.Labels)
93+
}
94+
}
95+
96+
// Verify title contains package name
97+
data := issues.TemplateData{
98+
PostRequest: req,
99+
Parameters: req.ExtraParams,
100+
CondensedMessage: issues.CondensedMessage(req.Message),
101+
PackageNameShort: req.PackageName,
102+
}
103+
title := formatter.Title(data)
104+
if !strings.Contains(title, "pkg/sql") {
105+
t.Errorf("Title should contain package name: %s", title)
106+
}
107+
if !strings.Contains(title, "performance regression") {
108+
t.Errorf("Title should contain 'performance regression': %s", title)
109+
}
110+
111+
// Verify message contains key information
112+
if !strings.Contains(req.Message, "pkg/sql") {
113+
t.Error("Message should contain package name")
114+
}
115+
if !strings.Contains(req.Message, "BenchmarkScan") {
116+
t.Error("Message should contain benchmark name")
117+
}
118+
if !strings.Contains(req.Message, "25.5%") {
119+
t.Error("Message should contain percentage")
120+
}
121+
if !strings.Contains(req.Message, "https://docs.google.com/spreadsheets/d/test123") {
122+
t.Error("Message should contain sheet link")
123+
}
124+
if !strings.Contains(req.Message, "master -> release-24.1") {
125+
t.Error("Message should contain comparison description")
126+
}
127+
}
128+
129+
func TestCreateRegressionPostRequestMultiple(t *testing.T) {
130+
// Test with multiple regressions
131+
regressions := make([]regressionInfo, 15)
132+
for i := 0; i < 15; i++ {
133+
regressions[i] = regressionInfo{
134+
benchmarkName: fmt.Sprintf("Benchmark%d", i),
135+
metricUnit: "ns/op",
136+
percentChange: 20.0 + float64(i),
137+
formattedDelta: fmt.Sprintf("+%dµs", i*100),
138+
}
139+
}
140+
141+
_, req := createRegressionPostRequest(
142+
"pkg/kv",
143+
regressions,
144+
"https://docs.google.com/spreadsheets/d/test456",
145+
"baseline -> experiment",
146+
)
147+
148+
// Should mention total count
149+
if !strings.Contains(req.Message, "15 benchmark(s)") {
150+
t.Error("Message should contain total regression count")
151+
}
152+
153+
// Should truncate to 10 and show "... and 5 more"
154+
if !strings.Contains(req.Message, "5 more regression(s)") {
155+
t.Errorf("Message should indicate truncation. Got: %s", req.Message)
156+
}
157+
158+
// First regression should be present
159+
if !strings.Contains(req.Message, "Benchmark0") {
160+
t.Error("Message should contain first benchmark")
161+
}
162+
163+
// 11th regression should not be listed individually
164+
if strings.Contains(req.Message, "Benchmark10") {
165+
t.Error("Message should not list 11th benchmark individually")
166+
}
167+
}
168+
169+
func TestCreateRegressionPostRequestTruncation(t *testing.T) {
170+
// Test the exact boundary at 10 regressions
171+
regressions := make([]regressionInfo, 10)
172+
for i := 0; i < 10; i++ {
173+
regressions[i] = regressionInfo{
174+
benchmarkName: fmt.Sprintf("Benchmark%d", i),
175+
metricUnit: "ns/op",
176+
percentChange: 20.0,
177+
formattedDelta: "+100µs",
178+
}
179+
}
180+
181+
_, req := createRegressionPostRequest(
182+
"pkg/storage",
183+
regressions,
184+
"https://docs.google.com/spreadsheets/d/test",
185+
"test comparison",
186+
)
187+
188+
// All 10 should be listed
189+
for i := 0; i < 10; i++ {
190+
if !strings.Contains(req.Message, fmt.Sprintf("Benchmark%d", i)) {
191+
t.Errorf("Message should contain Benchmark%d", i)
192+
}
193+
}
194+
195+
// Should not show truncation message for exactly 10
196+
if strings.Contains(req.Message, "more regression(s)") {
197+
t.Error("Should not show truncation message for exactly 10 regressions")
198+
}
199+
}
200+
201+
func TestCreateRegressionPostRequestFormat(t *testing.T) {
202+
// Test the full formatted output of a regression issue
203+
regressions := []regressionInfo{
204+
{
205+
benchmarkName: "BenchmarkScan/rows=1000",
206+
metricUnit: "ns/op",
207+
percentChange: 25.5,
208+
formattedDelta: "+1.2ms",
209+
},
210+
{
211+
benchmarkName: "BenchmarkInsert/batch=100",
212+
metricUnit: "B/op",
213+
percentChange: 30.0,
214+
formattedDelta: "+5.0KB",
215+
},
216+
}
217+
218+
formatter, req := createRegressionPostRequest(
219+
"pkg/sql/exec",
220+
regressions,
221+
"https://docs.google.com/spreadsheets/d/example123",
222+
"v24.1.0 -> v24.2.0",
223+
)
224+
225+
// Verify the full formatted message structure
226+
output, err := formatPostRequest(formatter, req)
227+
if err != nil {
228+
t.Fatalf("Failed to format post request: %v", err)
229+
}
230+
231+
// Check title format
232+
data := issues.TemplateData{
233+
PostRequest: req,
234+
Parameters: req.ExtraParams,
235+
CondensedMessage: issues.CondensedMessage(req.Message),
236+
PackageNameShort: req.PackageName,
237+
}
238+
title := formatter.Title(data)
239+
240+
// Verify title structure
241+
if !strings.Contains(title, "pkg/sql/exec") {
242+
t.Errorf("Title should contain package name, got: %s", title)
243+
}
244+
if !strings.Contains(title, "performance regression") {
245+
t.Errorf("Title should contain 'performance regression', got: %s", title)
246+
}
247+
248+
// Verify formatted output contains all key elements
249+
expectedElements := []string{
250+
"Performance regressions detected in package pkg/sql/exec",
251+
"Comparison: v24.1.0 -> v24.2.0",
252+
"Found 2 benchmark(s) with regressions ≥20%",
253+
"BenchmarkScan/rows=1000",
254+
"(ns/op): +1.2ms (25.5%)",
255+
"BenchmarkInsert/batch=100",
256+
"(B/op): +5.0KB (30.0%)",
257+
"Detailed comparison: https://docs.google.com/spreadsheets/d/example123",
258+
}
259+
260+
for _, expected := range expectedElements {
261+
if !strings.Contains(output, expected) {
262+
t.Errorf("Formatted output should contain %q\nGot:\n%s", expected, output)
263+
}
264+
}
265+
266+
// Verify labels are correct
267+
if !containsLabel(req.Labels, "O-microbench") {
268+
t.Errorf("Should have O-microbench label, got: %v", req.Labels)
269+
}
270+
if !containsLabel(req.Labels, "C-performance") {
271+
t.Errorf("Should have C-performance label, got: %v", req.Labels)
272+
}
273+
}
274+
275+
func containsLabel(labels []string, label string) bool {
276+
for _, l := range labels {
277+
if l == label {
278+
return true
279+
}
280+
}
281+
return false
282+
}
283+
58284
func formatPostRequest(formatter issues.IssueFormatter, req issues.PostRequest) (string, error) {
59285
// These fields can vary based on the test env so we set them to arbitrary
60286
// values here.

0 commit comments

Comments
 (0)