github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/maintenance/migratestatus/migrator/migrator_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 migrator 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/google/go-github/github" 24 ) 25 26 type modeTest struct { 27 name string 28 start []github.RepoStatus 29 expectedDiffs []*github.RepoStatus 30 } 31 32 // compareDiffs checks if a list of status updates matches an expected list of status updates. 33 func compareDiffs(diffs []*github.RepoStatus, expectedDiffs []*github.RepoStatus) error { 34 if len(diffs) != len(expectedDiffs) { 35 return fmt.Errorf("failed because the returned diff had %d changes instead of %d.", len(diffs), len(expectedDiffs)) 36 } 37 for _, diff := range diffs { 38 if diff == nil { 39 return fmt.Errorf("failed because the returned diff contained a nil RepoStatus.") 40 } 41 if diff.Context == nil { 42 return fmt.Errorf("failed because the returned diff contained a RepoStatus with a nil Context field.") 43 } 44 if diff.Description == nil { 45 return fmt.Errorf("failed because the returned diff contained a RepoStatus with a nil Description field.") 46 } 47 if diff.State == nil { 48 return fmt.Errorf("failed because the returned diff contained a RepoStatus with a nil State field.") 49 } 50 var match *github.RepoStatus 51 for _, expected := range expectedDiffs { 52 if *expected.Context == *diff.Context { 53 match = expected 54 break 55 } 56 } 57 if match == nil { 58 return fmt.Errorf("failed because the returned diff contained an unexpected change to context '%s'.", *diff.Context) 59 } 60 // Found a matching context. Make sure that fields are equal. 61 if *match.Description != *diff.Description { 62 return fmt.Errorf("failed because the returned diff for context '%s' had Description '%s' instead of '%s'.", *diff.Context, *diff.Description, *match.Description) 63 } 64 if *match.State != *diff.State { 65 return fmt.Errorf("failed because the returned diff for context '%s' had State '%s' instead of '%s'.", *diff.Context, *diff.State, *match.State) 66 } 67 68 if match.TargetURL == nil { 69 if diff.TargetURL != nil { 70 return fmt.Errorf("failed because the returned diff for context '%s' had a non-nil TargetURL.", *diff.Context) 71 } 72 } else if diff.TargetURL == nil { 73 return fmt.Errorf("failed because the returned diff for context '%s' had a nil TargetURL.", *diff.Context) 74 } else if *match.TargetURL != *diff.TargetURL { 75 return fmt.Errorf("failed because the returned diff for context '%s' had TargetURL '%s' instead of '%s'.", *diff.Context, *diff.TargetURL, *match.TargetURL) 76 } 77 } 78 return nil 79 } 80 81 func TestMoveMode(t *testing.T) { 82 contextA := "context A" 83 contextB := "context B" 84 desc := "Context retired. Status moved to \"context B\"." 85 86 tests := []*modeTest{ 87 { 88 name: "simple", 89 start: []github.RepoStatus{ 90 *makeStatus(contextA, "failure", "description 1", "url 1"), 91 }, 92 expectedDiffs: []*github.RepoStatus{ 93 makeStatus(contextA, "success", desc, ""), 94 makeStatus(contextB, "failure", "description 1", "url 1"), 95 }, 96 }, 97 { 98 name: "unrelated contexts", 99 start: []github.RepoStatus{ 100 *makeStatus("also not related", "error", "description 4", "url 4"), 101 *makeStatus(contextA, "failure", "description 1", "url 1"), 102 *makeStatus("unrelated context", "success", "description 2", "url 2"), 103 }, 104 expectedDiffs: []*github.RepoStatus{ 105 makeStatus(contextA, "success", desc, ""), 106 makeStatus(contextB, "failure", "description 1", "url 1"), 107 }, 108 }, 109 { 110 name: "unrelated contexts; missing context A", 111 start: []github.RepoStatus{ 112 *makeStatus("also not related", "error", "description 4", "url 4"), 113 *makeStatus("unrelated context", "success", "description 2", "url 2"), 114 }, 115 expectedDiffs: []*github.RepoStatus{}, 116 }, 117 { 118 name: "unrelated contexts; already have context A and B", 119 start: []github.RepoStatus{ 120 *makeStatus("also not related", "error", "description 4", "url 4"), 121 *makeStatus(contextA, "failure", "description 1", "url 1"), 122 *makeStatus("unrelated context", "success", "description 2", "url 2"), 123 *makeStatus(contextB, "failure", "description 1", "url 1"), 124 }, 125 expectedDiffs: []*github.RepoStatus{}, 126 }, 127 { 128 name: "unrelated contexts; already have context B; no context A", 129 start: []github.RepoStatus{ 130 *makeStatus("also not related", "error", "description 4", "url 4"), 131 *makeStatus("unrelated context", "success", "description 2", "url 2"), 132 *makeStatus(contextB, "failure", "description 1", "url 1"), 133 }, 134 expectedDiffs: []*github.RepoStatus{}, 135 }, 136 { 137 name: "no contexts", 138 start: []github.RepoStatus{}, 139 expectedDiffs: []*github.RepoStatus{}, 140 }, 141 } 142 143 m := *MoveMode(contextA, contextB) 144 for _, test := range tests { 145 diff := m.ProcessStatuses(&github.CombinedStatus{Statuses: test.start}) 146 if err := compareDiffs(diff, test.expectedDiffs); err != nil { 147 t.Errorf("MoveMode test '%s' %v\n", test.name, err) 148 } 149 } 150 } 151 152 func TestCopyMode(t *testing.T) { 153 contextA := "context A" 154 contextB := "context B" 155 156 tests := []*modeTest{ 157 { 158 name: "simple", 159 start: []github.RepoStatus{ 160 *makeStatus(contextA, "failure", "description 1", "url 1"), 161 }, 162 expectedDiffs: []*github.RepoStatus{ 163 makeStatus(contextB, "failure", "description 1", "url 1"), 164 }, 165 }, 166 { 167 name: "unrelated contexts", 168 start: []github.RepoStatus{ 169 *makeStatus("unrelated context", "success", "description 2", "url 2"), 170 *makeStatus(contextA, "failure", "description 1", "url 1"), 171 *makeStatus("also not related", "error", "description 4", "url 4"), 172 }, 173 expectedDiffs: []*github.RepoStatus{ 174 makeStatus(contextB, "failure", "description 1", "url 1"), 175 }, 176 }, 177 { 178 name: "already have context B", 179 start: []github.RepoStatus{ 180 *makeStatus(contextA, "failure", "description 1", "url 1"), 181 *makeStatus(contextB, "failure", "description 1", "url 1"), 182 }, 183 expectedDiffs: []*github.RepoStatus{}, 184 }, 185 { 186 name: "already have updated context B", 187 start: []github.RepoStatus{ 188 *makeStatus(contextA, "failure", "description 1", "url 1"), 189 *makeStatus(contextB, "success", "description 2", "url 2"), 190 }, 191 expectedDiffs: []*github.RepoStatus{}, 192 }, 193 { 194 name: "unrelated contexts already have updated context B", 195 start: []github.RepoStatus{ 196 *makeStatus("unrelated context", "success", "description 2", "url 2"), 197 *makeStatus(contextA, "failure", "description 1", "url 1"), 198 *makeStatus("also not related", "error", "description 4", "url 4"), 199 *makeStatus(contextB, "error", "description 3", "url 3"), 200 }, 201 expectedDiffs: []*github.RepoStatus{}, 202 }, 203 { 204 name: "only have context B", 205 start: []github.RepoStatus{ 206 *makeStatus(contextB, "failure", "description 1", "url 1"), 207 }, 208 expectedDiffs: []*github.RepoStatus{}, 209 }, 210 { 211 name: "unrelated contexts; context B but not A", 212 start: []github.RepoStatus{ 213 *makeStatus("unrelated context", "success", "description 2", "url 2"), 214 *makeStatus(contextB, "failure", "description 1", "url 1"), 215 *makeStatus("also not related", "error", "description 4", "url 4"), 216 }, 217 expectedDiffs: []*github.RepoStatus{}, 218 }, 219 { 220 name: "no contexts", 221 start: []github.RepoStatus{}, 222 expectedDiffs: []*github.RepoStatus{}, 223 }, 224 } 225 226 m := *CopyMode(contextA, contextB) 227 for _, test := range tests { 228 diff := m.ProcessStatuses(&github.CombinedStatus{Statuses: test.start}) 229 if err := compareDiffs(diff, test.expectedDiffs); err != nil { 230 t.Errorf("CopyMode test '%s' %v\n", test.name, err) 231 } 232 } 233 } 234 235 func TestRetireModeReplacement(t *testing.T) { 236 contextA := "context A" 237 contextB := "context B" 238 desc := "Context retired. Status moved to \"context B\"." 239 240 tests := []*modeTest{ 241 { 242 name: "simple", 243 start: []github.RepoStatus{ 244 *makeStatus(contextA, "failure", "description 1", "url 1"), 245 *makeStatus(contextB, "failure", "description 1", "url 1"), 246 }, 247 expectedDiffs: []*github.RepoStatus{ 248 makeStatus(contextA, "success", desc, ""), 249 }, 250 }, 251 { 252 name: "unrelated contexts;updated context B", 253 start: []github.RepoStatus{ 254 *makeStatus("unrelated context", "success", "description 2", "url 2"), 255 *makeStatus(contextA, "failure", "description 1", "url 1"), 256 *makeStatus("also not related", "error", "description 4", "url 4"), 257 *makeStatus(contextB, "success", "description 3", "url 3"), 258 }, 259 expectedDiffs: []*github.RepoStatus{ 260 makeStatus(contextA, "success", desc, ""), 261 }, 262 }, 263 { 264 name: "missing context B", 265 start: []github.RepoStatus{ 266 *makeStatus(contextA, "failure", "description 1", "url 1"), 267 }, 268 expectedDiffs: []*github.RepoStatus{}, 269 }, 270 { 271 name: "unrelated contexts;missing context B", 272 start: []github.RepoStatus{ 273 *makeStatus("unrelated context", "success", "description 2", "url 2"), 274 *makeStatus(contextA, "failure", "description 1", "url 1"), 275 *makeStatus("also not related", "error", "description 4", "url 4"), 276 }, 277 expectedDiffs: []*github.RepoStatus{}, 278 }, 279 { 280 name: "missing context A", 281 start: []github.RepoStatus{ 282 *makeStatus(contextB, "failure", "description 1", "url 1"), 283 }, 284 expectedDiffs: []*github.RepoStatus{}, 285 }, 286 { 287 name: "unrelated contexts;missing context A", 288 start: []github.RepoStatus{ 289 *makeStatus("unrelated context", "success", "description 2", "url 2"), 290 *makeStatus("also not related", "error", "description 4", "url 4"), 291 *makeStatus(contextB, "success", "description 3", "url 3"), 292 }, 293 expectedDiffs: []*github.RepoStatus{}, 294 }, 295 { 296 name: "no contexts", 297 start: []github.RepoStatus{}, 298 expectedDiffs: []*github.RepoStatus{}, 299 }, 300 } 301 302 m := *RetireMode(contextA, contextB) 303 for _, test := range tests { 304 diff := m.ProcessStatuses(&github.CombinedStatus{Statuses: test.start}) 305 if err := compareDiffs(diff, test.expectedDiffs); err != nil { 306 t.Errorf("RetireMode(Replacement) test '%s' %v\n", test.name, err) 307 } 308 } 309 } 310 311 func TestRetireModeNoReplacement(t *testing.T) { 312 contextA := "context A" 313 desc := "Context retired without replacement." 314 315 tests := []*modeTest{ 316 { 317 name: "simple", 318 start: []github.RepoStatus{ 319 *makeStatus(contextA, "failure", "description 1", "url 1"), 320 }, 321 expectedDiffs: []*github.RepoStatus{ 322 makeStatus(contextA, "success", desc, ""), 323 }, 324 }, 325 { 326 name: "unrelated contexts", 327 start: []github.RepoStatus{ 328 *makeStatus("unrelated context", "success", "description 2", "url 2"), 329 *makeStatus(contextA, "failure", "description 1", "url 1"), 330 *makeStatus("also not related", "error", "description 4", "url 4"), 331 }, 332 expectedDiffs: []*github.RepoStatus{ 333 makeStatus(contextA, "success", desc, ""), 334 }, 335 }, 336 { 337 name: "missing context A", 338 start: []github.RepoStatus{}, 339 expectedDiffs: []*github.RepoStatus{}, 340 }, 341 { 342 name: "unrelated contexts;missing context A", 343 start: []github.RepoStatus{ 344 *makeStatus("unrelated context", "success", "description 2", "url 2"), 345 *makeStatus("also not related", "error", "description 4", "url 4"), 346 }, 347 expectedDiffs: []*github.RepoStatus{}, 348 }, 349 } 350 351 m := *RetireMode(contextA, "") 352 for _, test := range tests { 353 diff := m.ProcessStatuses(&github.CombinedStatus{Statuses: test.start}) 354 if err := compareDiffs(diff, test.expectedDiffs); err != nil { 355 t.Errorf("RetireMode(NoReplace) test '%s' %v\n", test.name, err) 356 } 357 } 358 } 359 360 // makeStatus returns a new RepoStatus struct with the specified fields. 361 // targetURL=="" means TargetURL==nil 362 func makeStatus(context, state, description, targetURL string) *github.RepoStatus { 363 var url *string 364 if targetURL != "" { 365 url = &targetURL 366 } 367 return &github.RepoStatus{ 368 Context: &context, 369 State: &state, 370 Description: &description, 371 TargetURL: url, 372 } 373 }