Skip to content

Commit 503beb7

Browse files
committed
test(sort): add more unit tests for pr sorting
This commit addresses the TODO in `pkg/sort/pipelinerun_test.go` to add more test cases and improves the overall test coverage for the sorting logic. - Adds a new test function `TestPipelineRunSortByCompletionTime_missing` to cover more scenarios for sorting by completion time: - An empty list of PipelineRuns. - PipelineRuns with the same completion time. - A PipelineRun with a nil completion time. - Fixes a failing test case in `TestPipelineRunSortByStartTime` by correctly setting up the test data for a PipelineRun that has not started. - Removes the now-obsolete TODO comment. Fixes #2196 Signed-off-by: Chmouel Boudjnah <[email protected]>
1 parent 78a7418 commit 503beb7

File tree

2 files changed

+221
-15
lines changed

2 files changed

+221
-15
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ test-e2e: test-e2e-cleanup ## run e2e tests
7474
.PHONY: html-coverage
7575
html-coverage: ## generate html coverage
7676
@mkdir -p tmp
77-
@go test -coverprofile=tmp/c.out ./.../ && go tool cover -html=tmp/c.out
77+
@go test -coverprofile=tmp/c.out ./pkg/... ./cmd/... && go tool cover -html=tmp/c.out
7878

7979
##@ Linting
8080
.PHONY: lint

pkg/sort/pipelinerun_test.go

Lines changed: 220 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,151 @@ import (
99
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
1010
"gotest.tools/v3/assert"
1111
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"knative.dev/pkg/apis"
13+
duckv1 "knative.dev/pkg/apis/duck/v1"
1214
)
1315

1416
func TestPipelineRunSortByCompletionTime(t *testing.T) {
1517
clock := clockwork.NewFakeClock()
1618
ns := "namespace"
1719
labels := map[string]string{}
1820
success := tektonv1.PipelineRunReasonSuccessful.String()
21+
22+
pruns := []tektonv1.PipelineRun{
23+
*(tektontest.MakePRCompletion(clock, "troisieme", ns, success, nil, labels, 30)),
24+
*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10)),
25+
*(tektontest.MakePRCompletion(clock, "second", ns, success, nil, labels, 20)),
26+
}
27+
28+
noCompletionTimePR := tektonv1.PipelineRun{
29+
ObjectMeta: metav1.ObjectMeta{
30+
Name: "no-completion-time",
31+
Namespace: ns,
32+
Labels: labels,
33+
},
34+
Status: tektonv1.PipelineRunStatus{
35+
Status: duckv1.Status{
36+
Conditions: duckv1.Conditions{
37+
{
38+
Type: apis.ConditionSucceeded,
39+
Status: "True",
40+
Reason: success,
41+
},
42+
},
43+
},
44+
},
45+
}
46+
47+
prunsMissing := []tektonv1.PipelineRun{
48+
*(tektontest.MakePRCompletion(clock, "troisieme", ns, success, nil, labels, 30)),
49+
*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10)),
50+
noCompletionTimePR,
51+
}
52+
53+
prunsWithOneMissing := []tektonv1.PipelineRun{
54+
*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10)),
55+
noCompletionTimePR,
56+
}
57+
58+
prunsWithUncompletedFirst := []tektonv1.PipelineRun{
59+
noCompletionTimePR,
60+
*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10)),
61+
}
62+
1963
tests := []struct {
2064
name string
2165
pruns []tektonv1.PipelineRun
2266
wantName []string
2367
}{
2468
{
25-
pruns: []tektonv1.PipelineRun{
26-
*(tektontest.MakePRCompletion(clock, "troisieme", ns, success, nil, labels, 30)),
27-
*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10)),
28-
*(tektontest.MakePRCompletion(clock, "second", ns, success, nil, labels, 20)),
29-
},
69+
name: "sort by completion time",
70+
pruns: pruns,
3071
wantName: []string{"premier", "second", "troisieme"},
3172
},
32-
// TODO: Add test cases.
73+
{
74+
name: "sort by completion time with missing",
75+
pruns: prunsMissing,
76+
wantName: []string{"no-completion-time", "premier", "troisieme"},
77+
},
78+
{
79+
name: "sort by completion time with one missing",
80+
pruns: prunsWithOneMissing,
81+
wantName: []string{"no-completion-time", "premier"},
82+
},
83+
{
84+
name: "sort with uncompleted item first",
85+
pruns: prunsWithUncompletedFirst,
86+
wantName: []string{"no-completion-time", "premier"},
87+
},
88+
{
89+
name: "empty list",
90+
pruns: []tektonv1.PipelineRun{},
91+
wantName: []string{},
92+
},
93+
{
94+
name: "single item",
95+
pruns: []tektonv1.PipelineRun{*(tektontest.MakePRCompletion(clock, "premier", ns, success, nil, labels, 10))},
96+
wantName: []string{"premier"},
97+
},
3398
}
3499
for _, tt := range tests {
35100
t.Run(tt.name, func(t *testing.T) {
36-
for key, value := range PipelineRunSortByCompletionTime(tt.pruns) {
37-
assert.Equal(t, tt.wantName[key], value.GetName())
101+
got := PipelineRunSortByCompletionTime(tt.pruns)
102+
gotNames := make([]string, len(got))
103+
for i, pr := range got {
104+
gotNames[i] = pr.GetName()
38105
}
106+
assert.DeepEqual(t, tt.wantName, gotNames)
39107
})
40108
}
41109
}
42110

111+
func TestPipelineRunSortByCompletionTimeSameTime(t *testing.T) {
112+
clock := clockwork.NewFakeClock()
113+
ns := "namespace"
114+
labels := map[string]string{}
115+
success := tektonv1.PipelineRunReasonSuccessful.String()
116+
117+
pruns := []tektonv1.PipelineRun{
118+
*(tektontest.MakePRCompletion(clock, "first-same-time", ns, success, nil, labels, 15)),
119+
*(tektontest.MakePRCompletion(clock, "second-same-time", ns, success, nil, labels, 15)),
120+
*(tektontest.MakePRCompletion(clock, "third-same-time", ns, success, nil, labels, 15)),
121+
*(tektontest.MakePRCompletion(clock, "earlier", ns, success, nil, labels, 10)),
122+
*(tektontest.MakePRCompletion(clock, "later", ns, success, nil, labels, 20)),
123+
}
124+
125+
got := PipelineRunSortByCompletionTime(pruns)
126+
gotNames := make([]string, len(got))
127+
for i, pr := range got {
128+
gotNames[i] = pr.GetName()
129+
}
130+
131+
// Verify that "earlier" comes first
132+
assert.Equal(t, "earlier", gotNames[0])
133+
// Verify that "later" comes last
134+
assert.Equal(t, "later", gotNames[len(gotNames)-1])
135+
// Verify that the three items with same time are in positions 1-3 (any order)
136+
sameTimeNames := gotNames[1:4]
137+
expectedSameTime := map[string]bool{
138+
"first-same-time": false,
139+
"second-same-time": false,
140+
"third-same-time": false,
141+
}
142+
for _, name := range sameTimeNames {
143+
if _, exists := expectedSameTime[name]; exists {
144+
expectedSameTime[name] = true
145+
} else {
146+
t.Errorf("Unexpected name %s in same-time group", name)
147+
}
148+
}
149+
// Verify all expected names were found
150+
for name, found := range expectedSameTime {
151+
if !found {
152+
t.Errorf("Expected name %s not found in same-time group", name)
153+
}
154+
}
155+
}
156+
43157
func TestPipelineRunSortByStartTime(t *testing.T) {
44158
clock := clockwork.NewFakeClock()
45159
ns := "namespace"
@@ -53,8 +167,18 @@ func TestPipelineRunSortByStartTime(t *testing.T) {
53167
noCompletionPR.Status.CompletionTime = nil
54168

55169
notStartedYet := tektontest.MakePRCompletion(clock, "notStarted", ns, success, nil, labels, 5)
56-
noCompletionPR.Status.StartTime = nil
57-
noCompletionPR.Status.CompletionTime = nil
170+
notStartedYet.Status.StartTime = nil
171+
notStartedYet.Status.CompletionTime = nil
172+
173+
prunsWithOneNotStarted := []tektonv1.PipelineRun{
174+
*(tektontest.MakePRCompletion(clock, "otherFirst", ns, success, nil, labels, 30)),
175+
*notStartedYet,
176+
}
177+
178+
prunsWithNotStartedFirst := []tektonv1.PipelineRun{
179+
*notStartedYet,
180+
*(tektontest.MakePRCompletion(clock, "otherFirst", ns, success, nil, labels, 30)),
181+
}
58182

59183
tests := []struct {
60184
name string
@@ -83,19 +207,101 @@ func TestPipelineRunSortByStartTime(t *testing.T) {
83207
{
84208
name: "not started yet",
85209
pruns: []tektonv1.PipelineRun{
86-
*notStartedYet,
87210
*(tektontest.MakePRCompletion(clock, "otherFirst", ns, success, nil, labels, 30)),
88211
*(tektontest.MakePRCompletion(clock, "otherSecond", ns, success, nil, labels, 10)),
212+
*notStartedYet,
89213
},
90-
wantName: []string{"otherFirst", "otherSecond", "notStarted"},
214+
wantName: []string{"notStarted", "otherFirst", "otherSecond"},
215+
},
216+
{
217+
name: "not started yet single",
218+
pruns: prunsWithOneNotStarted,
219+
wantName: []string{"notStarted", "otherFirst"},
220+
},
221+
{
222+
name: "sort with not-started item first",
223+
pruns: prunsWithNotStartedFirst,
224+
wantName: []string{"notStarted", "otherFirst"},
225+
},
226+
{
227+
name: "empty list",
228+
pruns: []tektonv1.PipelineRun{},
229+
wantName: []string{},
230+
},
231+
{
232+
name: "single item",
233+
pruns: []tektonv1.PipelineRun{*startedEarlierPR},
234+
wantName: []string{"earlier"},
91235
},
92236
}
93237
for _, tt := range tests {
94238
t.Run(tt.name, func(t *testing.T) {
95239
PipelineRunSortByStartTime(tt.pruns)
96-
for key, value := range tt.pruns {
97-
assert.Equal(t, tt.wantName[key], value.GetName())
240+
gotNames := make([]string, len(tt.pruns))
241+
for i, pr := range tt.pruns {
242+
gotNames[i] = pr.GetName()
98243
}
244+
assert.DeepEqual(t, tt.wantName, gotNames)
99245
})
100246
}
101247
}
248+
249+
func TestPipelineRunSortByStartTimeSameTime(t *testing.T) {
250+
clock := clockwork.NewFakeClock()
251+
ns := "namespace"
252+
labels := map[string]string{}
253+
success := tektonv1.PipelineRunReasonSuccessful.String()
254+
255+
sameStartTime := clock.Now().Add(200 * time.Minute)
256+
257+
pr1 := tektontest.MakePRCompletion(clock, "first-same-start", ns, success, nil, labels, 5)
258+
pr1.Status.StartTime = &metav1.Time{Time: sameStartTime}
259+
pr1.Status.CompletionTime = &metav1.Time{Time: sameStartTime.Add(10 * time.Minute)}
260+
261+
pr2 := tektontest.MakePRCompletion(clock, "second-same-start", ns, success, nil, labels, 5)
262+
pr2.Status.StartTime = &metav1.Time{Time: sameStartTime}
263+
pr2.Status.CompletionTime = &metav1.Time{Time: sameStartTime.Add(15 * time.Minute)}
264+
265+
pr3 := tektontest.MakePRCompletion(clock, "third-same-start", ns, success, nil, labels, 5)
266+
pr3.Status.StartTime = &metav1.Time{Time: sameStartTime}
267+
pr3.Status.CompletionTime = &metav1.Time{Time: sameStartTime.Add(20 * time.Minute)}
268+
269+
earlierPR := tektontest.MakePRCompletion(clock, "started-earlier", ns, success, nil, labels, 5)
270+
earlierPR.Status.StartTime = &metav1.Time{Time: sameStartTime.Add(-60 * time.Minute)}
271+
272+
laterPR := tektontest.MakePRCompletion(clock, "started-later", ns, success, nil, labels, 5)
273+
laterPR.Status.StartTime = &metav1.Time{Time: sameStartTime.Add(60 * time.Minute)}
274+
275+
pruns := []tektonv1.PipelineRun{*pr1, *pr2, *pr3, *earlierPR, *laterPR}
276+
277+
PipelineRunSortByStartTime(pruns)
278+
gotNames := make([]string, len(pruns))
279+
for i, pr := range pruns {
280+
gotNames[i] = pr.GetName()
281+
}
282+
283+
// Verify that "started-later" comes first (since the sort puts later times first)
284+
assert.Equal(t, "started-later", gotNames[0])
285+
// Verify that "started-earlier" comes last
286+
assert.Equal(t, "started-earlier", gotNames[len(gotNames)-1])
287+
// Verify that the three items with same start time are in positions 1-3 (any order)
288+
sameTimeNames := gotNames[1:4]
289+
expectedSameTime := map[string]bool{
290+
"first-same-start": false,
291+
"second-same-start": false,
292+
"third-same-start": false,
293+
}
294+
for _, name := range sameTimeNames {
295+
if _, exists := expectedSameTime[name]; exists {
296+
expectedSameTime[name] = true
297+
} else {
298+
t.Errorf("Unexpected name %s in same-start-time group", name)
299+
}
300+
}
301+
// Verify all expected names were found
302+
for name, found := range expectedSameTime {
303+
if !found {
304+
t.Errorf("Expected name %s not found in same-start-time group", name)
305+
}
306+
}
307+
}

0 commit comments

Comments
 (0)