sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/plugins/mergecommitblocker/mergecommitblocker_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package mergecommitblocker 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/sirupsen/logrus" 24 "sigs.k8s.io/prow/pkg/commentpruner" 25 "sigs.k8s.io/prow/pkg/git/localgit" 26 "sigs.k8s.io/prow/pkg/github" 27 "sigs.k8s.io/prow/pkg/labels" 28 ) 29 30 var defaultBranch = localgit.DefaultBranch("") 31 32 type strSet map[string]struct{} 33 34 type fakeGHClient struct { 35 labels strSet 36 comments map[int]string 37 } 38 39 func (f *fakeGHClient) AddLabel(org, repo string, number int, label string) error { 40 f.labels[label] = struct{}{} 41 return nil 42 } 43 44 func (f *fakeGHClient) RemoveLabel(org, repo string, number int, label string) error { 45 delete(f.labels, label) 46 return nil 47 } 48 49 func (f *fakeGHClient) GetIssueLabels(org, repo string, number int) ([]github.Label, error) { 50 var labels []github.Label 51 for l := range f.labels { 52 labels = append(labels, github.Label{Name: l}) 53 } 54 return labels, nil 55 } 56 57 func (f *fakeGHClient) CreateComment(org, repo string, number int, comment string) error { 58 if _, ok := f.comments[number]; ok { 59 return fmt.Errorf("comment id %d already exists", number) 60 } 61 f.comments[number] = comment 62 return nil 63 } 64 65 func (f *fakeGHClient) DeleteComment(org, repo string, id int) error { 66 delete(f.comments, id) 67 return nil 68 } 69 70 func (f *fakeGHClient) BotUserChecker() (func(candidate string) bool, error) { 71 return func(candidate string) bool { 72 return candidate == "foo" 73 }, nil 74 } 75 76 func (f *fakeGHClient) ListIssueComments(org, repo string, number int) ([]github.IssueComment, error) { 77 var ghComments []github.IssueComment 78 for id, c := range f.comments { 79 ghComment := github.IssueComment{ 80 ID: id, 81 Body: c, 82 User: github.User{Login: "foo"}, 83 } 84 ghComments = append(ghComments, ghComment) 85 } 86 return ghComments, nil 87 } 88 89 func TestHandleV2(t *testing.T) { 90 testHandle(localgit.NewV2, t) 91 } 92 93 func testHandle(clients localgit.Clients, t *testing.T) { 94 lg, c, err := clients() 95 if err != nil { 96 t.Fatalf("Making localgit: %v", err) 97 } 98 defer func() { 99 if err := lg.Clean(); err != nil { 100 t.Errorf("Cleaning up localgit: %v", err) 101 } 102 if err := c.Clean(); err != nil { 103 t.Errorf("Cleaning up client: %v", err) 104 } 105 }() 106 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 107 t.Fatalf("Making fake repo: %v", err) 108 } 109 var ( 110 checkoutPR = func(prNum int) { 111 if err := lg.CheckoutNewBranch("foo", "bar", fmt.Sprintf("pull/%d/head", prNum)); err != nil { 112 t.Fatalf("Creating & checking out pull branch pull/%d/head: %v", prNum, err) 113 } 114 } 115 checkoutBranch = func(branch string) { 116 if err := lg.Checkout("foo", "bar", branch); err != nil { 117 t.Fatalf("Checking out branch %s: %v", branch, err) 118 } 119 } 120 addCommit = func(file string) { 121 if err := lg.AddCommit("foo", "bar", map[string][]byte{file: {}}); err != nil { 122 t.Fatalf("Adding commit: %v", err) 123 } 124 } 125 mergeMaster = func() { 126 if _, err := lg.Merge("foo", "bar", defaultBranch); err != nil { 127 t.Fatalf("Rebasing commit: %v", err) 128 } 129 } 130 rebaseMaster = func() { 131 if _, err := lg.Rebase("foo", "bar", defaultBranch); err != nil { 132 t.Fatalf("Rebasing commit: %v", err) 133 } 134 } 135 ) 136 137 type testCase struct { 138 name string 139 fakeGHClient *fakeGHClient 140 prNum int 141 checkout func() 142 mergeOrRebase func() 143 wantLabel bool 144 wantComment bool 145 } 146 testcases := []testCase{ 147 { 148 name: "merge commit label not exist, PR has merge commits", 149 fakeGHClient: &fakeGHClient{ 150 labels: strSet{}, 151 comments: make(map[int]string), 152 }, 153 prNum: 11, 154 checkout: func() { checkoutBranch("pull/11/head") }, 155 mergeOrRebase: mergeMaster, 156 wantLabel: true, 157 wantComment: true, 158 }, 159 { 160 name: "merge commit label exists, PR has merge commits", 161 fakeGHClient: &fakeGHClient{ 162 labels: strSet{labels.MergeCommits: struct{}{}}, 163 comments: map[int]string{12: commentBody}, 164 }, 165 prNum: 12, 166 checkout: func() { checkoutBranch("pull/12/head") }, 167 mergeOrRebase: mergeMaster, 168 wantLabel: true, 169 wantComment: true, 170 }, 171 { 172 name: "merge commit label not exists, PR doesn't have merge commits", 173 fakeGHClient: &fakeGHClient{ 174 labels: strSet{}, 175 comments: make(map[int]string), 176 }, 177 prNum: 13, 178 checkout: func() { checkoutBranch("pull/13/head") }, 179 mergeOrRebase: rebaseMaster, 180 wantLabel: false, 181 wantComment: false, 182 }, 183 { 184 name: "merge commit label exists, PR doesn't have merge commits", 185 fakeGHClient: &fakeGHClient{ 186 labels: strSet{labels.MergeCommits: struct{}{}}, 187 comments: map[int]string{14: commentBody}, 188 }, 189 prNum: 14, 190 checkout: func() { checkoutBranch("pull/14/head") }, 191 mergeOrRebase: rebaseMaster, 192 wantLabel: false, 193 wantComment: false, 194 }, 195 } 196 197 addCommit("wow") 198 // preparation work: branch off all prs upon commit 'wow' 199 for _, tt := range testcases { 200 checkoutPR(tt.prNum) 201 } 202 // switch back to master and create a new commit 'ouch' 203 checkoutBranch(defaultBranch) 204 addCommit("ouch") 205 masterSHA, err := lg.RevParse("foo", "bar", "HEAD") 206 if err != nil { 207 t.Fatalf("Fetching SHA: %v", err) 208 } 209 210 for _, tt := range testcases { 211 tt.checkout() 212 tt.mergeOrRebase() 213 prSHA, err := lg.RevParse("foo", "bar", "HEAD") 214 if err != nil { 215 t.Fatalf("Fetching SHA: %v", err) 216 } 217 pre := &github.PullRequestEvent{ 218 Action: github.PullRequestActionOpened, 219 PullRequest: github.PullRequest{ 220 Number: tt.prNum, 221 Base: github.PullRequestBranch{ 222 Repo: github.Repo{ 223 Owner: github.User{Login: "foo"}, 224 Name: "bar", 225 }, 226 SHA: masterSHA, 227 }, 228 Head: github.PullRequestBranch{ 229 Repo: github.Repo{ 230 Owner: github.User{Login: "foo"}, 231 Name: "bar", 232 }, 233 SHA: prSHA, 234 }, 235 }, 236 } 237 log := logrus.NewEntry(logrus.New()) 238 fakePruner := commentpruner.NewEventClient(tt.fakeGHClient, log, "foo", "bar", tt.prNum) 239 if err := handle(tt.fakeGHClient, c, fakePruner, log, pre); err != nil { 240 t.Errorf("Expect err is nil, but got %v", err) 241 } 242 // verify if MergeCommits label as expected 243 if _, got := tt.fakeGHClient.labels[labels.MergeCommits]; got != tt.wantLabel { 244 t.Errorf("Case: %v. Expect MergeCommits=%v, but got %v", tt.name, tt.wantLabel, got) 245 } 246 // verify if github comment is created/pruned as expected 247 if _, got := tt.fakeGHClient.comments[tt.prNum]; got != tt.wantComment { 248 t.Errorf("Case: %v. Expect wantComment=%v, but got %v", tt.name, tt.wantComment, got) 249 } 250 } 251 }