github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/report/report_test.go (about) 1 /* 2 Copyright 2017 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 report 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 "k8s.io/test-infra/prow/github" 25 "k8s.io/test-infra/prow/kube" 26 ) 27 28 func TestParseIssueComment(t *testing.T) { 29 var testcases = []struct { 30 name string 31 context string 32 state string 33 ics []github.IssueComment 34 expectedDeletes []int 35 expectedContexts []string 36 expectedUpdate int 37 }{ 38 { 39 name: "should delete old style comments", 40 context: "Jenkins foo test", 41 state: github.StatusSuccess, 42 ics: []github.IssueComment{ 43 { 44 User: github.User{Login: "k8s-ci-robot"}, 45 Body: "Jenkins foo test **failed** for such-and-such.", 46 ID: 12345, 47 }, 48 { 49 User: github.User{Login: "someone-else"}, 50 Body: "Jenkins foo test **failed**!? Why?", 51 ID: 12356, 52 }, 53 { 54 User: github.User{Login: "k8s-ci-robot"}, 55 Body: "Jenkins foo test **failed** for so-and-so.", 56 ID: 12367, 57 }, 58 { 59 User: github.User{Login: "k8s-ci-robot"}, 60 Body: "Jenkins bar test **failed** for something-or-other.", 61 ID: 12378, 62 }, 63 }, 64 expectedDeletes: []int{12345, 12367}, 65 }, 66 { 67 name: "should create a new comment", 68 context: "bla test", 69 state: github.StatusFailure, 70 expectedContexts: []string{"bla test"}, 71 }, 72 { 73 name: "should not delete an up-to-date comment", 74 context: "bla test", 75 state: github.StatusSuccess, 76 ics: []github.IssueComment{ 77 { 78 User: github.User{Login: "k8s-ci-robot"}, 79 Body: "--- | --- | ---\nfoo test | something | or other\n\n", 80 }, 81 }, 82 }, 83 { 84 name: "should delete when all tests pass", 85 context: "bla test", 86 state: github.StatusSuccess, 87 ics: []github.IssueComment{ 88 { 89 User: github.User{Login: "k8s-ci-robot"}, 90 Body: "--- | --- | ---\nbla test | something | or other\n\n" + commentTag, 91 ID: 123, 92 }, 93 }, 94 expectedDeletes: []int{123}, 95 expectedContexts: []string{}, 96 }, 97 { 98 name: "should delete a passing test with \\r", 99 context: "bla test", 100 state: github.StatusSuccess, 101 ics: []github.IssueComment{ 102 { 103 User: github.User{Login: "k8s-ci-robot"}, 104 Body: "--- | --- | ---\r\nbla test | something | or other\r\n\r\n" + commentTag, 105 ID: 123, 106 }, 107 }, 108 expectedDeletes: []int{123}, 109 expectedContexts: []string{}, 110 }, 111 112 { 113 name: "should update a failed test", 114 context: "bla test", 115 state: github.StatusFailure, 116 ics: []github.IssueComment{ 117 { 118 User: github.User{Login: "k8s-ci-robot"}, 119 Body: "--- | --- | ---\nbla test | something | or other\n\n" + commentTag, 120 ID: 123, 121 }, 122 }, 123 expectedDeletes: []int{123}, 124 expectedContexts: []string{"bla test"}, 125 }, 126 { 127 name: "should preserve old results when updating", 128 context: "bla test", 129 state: github.StatusFailure, 130 ics: []github.IssueComment{ 131 { 132 User: github.User{Login: "k8s-ci-robot"}, 133 Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow | aye\n\n" + commentTag, 134 ID: 123, 135 }, 136 }, 137 expectedDeletes: []int{123}, 138 expectedContexts: []string{"bla test", "foo test"}, 139 }, 140 { 141 name: "should merge duplicates", 142 context: "bla test", 143 state: github.StatusFailure, 144 ics: []github.IssueComment{ 145 { 146 User: github.User{Login: "k8s-ci-robot"}, 147 Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow such\n\n" + commentTag, 148 ID: 123, 149 }, 150 { 151 User: github.User{Login: "k8s-ci-robot"}, 152 Body: "--- | --- | ---\nfoo test | beep | boop\n\n" + commentTag, 153 ID: 124, 154 }, 155 }, 156 expectedDeletes: []int{123, 124}, 157 expectedContexts: []string{"bla test", "foo test"}, 158 }, 159 { 160 name: "should update an old comment when a test passes", 161 context: "bla test", 162 state: github.StatusSuccess, 163 ics: []github.IssueComment{ 164 { 165 User: github.User{Login: "k8s-ci-robot"}, 166 Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow | aye\n\n" + commentTag, 167 ID: 123, 168 }, 169 }, 170 expectedDeletes: []int{}, 171 expectedContexts: []string{"foo test"}, 172 expectedUpdate: 123, 173 }, 174 } 175 for _, tc := range testcases { 176 pj := kube.ProwJob{ 177 Spec: kube.ProwJobSpec{ 178 Context: tc.context, 179 Refs: kube.Refs{Pulls: []kube.Pull{{}}}, 180 }, 181 Status: kube.ProwJobStatus{ 182 State: kube.ProwJobState(tc.state), 183 }, 184 } 185 deletes, entries, update := parseIssueComments(pj, "k8s-ci-robot", tc.ics) 186 if len(deletes) != len(tc.expectedDeletes) { 187 t.Errorf("It %s: wrong number of deletes. Got %v, expected %v", tc.name, deletes, tc.expectedDeletes) 188 } else { 189 for _, edel := range tc.expectedDeletes { 190 found := false 191 for _, del := range deletes { 192 if del == edel { 193 found = true 194 break 195 } 196 } 197 if !found { 198 t.Errorf("It %s: expected to find %d in %v", tc.name, edel, deletes) 199 } 200 } 201 } 202 if len(entries) != len(tc.expectedContexts) { 203 t.Errorf("It %s: wrong number of entries. Got %v, expected %v", tc.name, entries, tc.expectedContexts) 204 } else { 205 for _, econt := range tc.expectedContexts { 206 found := false 207 for _, ent := range entries { 208 if strings.Contains(ent, econt) { 209 found = true 210 break 211 } 212 } 213 if !found { 214 t.Errorf("It %s: expected to find %s in %v", tc.name, econt, entries) 215 } 216 } 217 } 218 if tc.expectedUpdate != update { 219 t.Errorf("It %s: expected update %d, got %d", tc.name, tc.expectedUpdate, update) 220 } 221 } 222 } 223 224 type fakeGhClient struct { 225 status []github.Status 226 } 227 228 func (gh fakeGhClient) BotName() (string, error) { 229 return "BotName", nil 230 } 231 func (gh *fakeGhClient) CreateStatus(org, repo, ref string, s github.Status) error { 232 gh.status = append(gh.status, s) 233 return nil 234 235 } 236 func (gh fakeGhClient) ListIssueComments(org, repo string, number int) ([]github.IssueComment, error) { 237 return nil, nil 238 } 239 func (gh fakeGhClient) CreateComment(org, repo string, number int, comment string) error { 240 return nil 241 } 242 func (gh fakeGhClient) DeleteComment(org, repo string, ID int) error { 243 return nil 244 } 245 func (gh fakeGhClient) EditComment(org, repo string, ID int, comment string) error { 246 return nil 247 } 248 249 func createChildren(pjs *kube.ProwJobSpec, d int) int { 250 count := 0 251 for i := 0; i < d; i++ { 252 report := false 253 if d%2 == 0 { 254 report = true 255 count++ 256 } 257 npjs := &kube.ProwJobSpec{ 258 Report: report, 259 Context: fmt.Sprintf("%s/child_%d", pjs.Context, i), 260 } 261 count += createChildren(npjs, d-1) 262 pjs.RunAfterSuccess = append(pjs.RunAfterSuccess, *npjs) 263 } 264 return count 265 } 266 267 func TestReportStatus(t *testing.T) { 268 type tc struct { 269 name string 270 pj kube.ProwJob 271 statusCount int 272 } 273 children := 3 274 createTc := func(n string, state kube.ProwJobState, report bool) tc { 275 276 pj := kube.ProwJob{ 277 Status: kube.ProwJobStatus{ 278 State: state, 279 Description: "message", 280 URL: "http://mytest.com", 281 }, 282 Spec: kube.ProwJobSpec{ 283 Context: "parent", 284 Report: report, 285 Refs: kube.Refs{ 286 Org: "k8s", 287 Repo: "test-infra", 288 Pulls: []kube.Pull{{ 289 Author: "me", 290 Number: 1, 291 SHA: "abcdef", 292 }}, 293 }, 294 }, 295 } 296 297 statusCount := createChildren(&pj.Spec, children) 298 if report { 299 statusCount++ 300 } 301 302 return tc{ 303 name: n, 304 pj: pj, 305 statusCount: statusCount, 306 } 307 } 308 for _, tc := range []tc{ 309 createTc("successful job", kube.SuccessState, true), 310 createTc("successful job", kube.SuccessState, false), 311 createTc("pending jobs", kube.PendingState, true), 312 createTc("pending jobs", kube.PendingState, false), 313 } { 314 ghc := &fakeGhClient{} 315 if err := reportStatus(ghc, tc.pj, parentJobChanged); err != nil { 316 t.Error(err) 317 } 318 if tc.pj.Status.State == kube.SuccessState { 319 if tc.pj.Spec.Report { 320 if len(ghc.status) != 1 { 321 t.Errorf("There should only be one status sent, found %d", len(ghc.status)) 322 } 323 } else { 324 if len(ghc.status) != 0 { 325 t.Errorf("There should only no status sent, found %d", len(ghc.status)) 326 } 327 } 328 } else { 329 if len(ghc.status) != tc.statusCount { 330 t.Errorf("There should be %d status, found %d", tc.statusCount, len(ghc.status)) 331 } 332 for i := 1; i < tc.statusCount; i++ { 333 if !strings.HasPrefix(ghc.status[i].Description, parentJobChanged) { 334 t.Errorf("Description should start with prefix %s", parentJobChanged) 335 } 336 } 337 } 338 } 339 }