github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/github/client_test.go (about) 1 /* 2 Copyright 2016 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 github 18 19 import ( 20 "crypto/tls" 21 "encoding/base64" 22 "encoding/json" 23 "fmt" 24 "io/ioutil" 25 "net/http" 26 "net/http/httptest" 27 "strconv" 28 "strings" 29 "testing" 30 "time" 31 ) 32 33 func getClient(url string) *Client { 34 return &Client{ 35 client: &http.Client{ 36 Transport: &http.Transport{ 37 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 38 }, 39 }, 40 base: url, 41 } 42 } 43 44 func TestRequestRateLimit(t *testing.T) { 45 var slept time.Duration 46 timeSleep = func(d time.Duration) { slept = d } 47 defer func() { timeSleep = time.Sleep }() 48 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 49 if slept == 0 { 50 w.Header().Set("X-RateLimit-Remaining", "0") 51 w.Header().Set("X-RateLimit-Reset", strconv.Itoa(int(time.Now().Add(time.Second).Unix()))) 52 http.Error(w, "403 Forbidden", http.StatusForbidden) 53 } 54 })) 55 defer ts.Close() 56 c := getClient(ts.URL) 57 resp, err := c.requestRetry(http.MethodGet, c.base, "", nil) 58 if err != nil { 59 t.Errorf("Error from request: %v", err) 60 } else if resp.StatusCode != 200 { 61 t.Errorf("Expected status code 200, got %d", resp.StatusCode) 62 } else if slept < time.Second { 63 t.Errorf("Expected to sleep for at least a second, got %v", slept) 64 } 65 } 66 67 func TestRetry404(t *testing.T) { 68 var slept int 69 timeSleep = func(d time.Duration) { slept++ } 70 defer func() { timeSleep = time.Sleep }() 71 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 72 if slept == 0 { 73 http.Error(w, "404 Not Found", http.StatusNotFound) 74 } 75 })) 76 defer ts.Close() 77 c := getClient(ts.URL) 78 resp, err := c.requestRetry(http.MethodGet, c.base, "", nil) 79 if err != nil { 80 t.Errorf("Error from request: %v", err) 81 } else if resp.StatusCode != 200 { 82 t.Errorf("Expected status code 200, got %d", resp.StatusCode) 83 } 84 } 85 86 func TestBotName(t *testing.T) { 87 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 88 if r.Method != http.MethodGet { 89 t.Errorf("Bad method: %s", r.Method) 90 } 91 if r.URL.Path != "/user" { 92 t.Errorf("Bad request path: %s", r.URL.Path) 93 } 94 fmt.Fprint(w, "{\"login\": \"wowza\"}") 95 })) 96 c := getClient(ts.URL) 97 botName, err := c.BotName() 98 if err != nil { 99 t.Errorf("Didn't expect error: %v", err) 100 } else if botName != "wowza" { 101 t.Errorf("Wrong bot name. Got %s, expected wowza.", botName) 102 } 103 ts.Close() 104 botName, err = c.BotName() 105 if err != nil { 106 t.Errorf("Didn't expect error: %v", err) 107 } else if botName != "wowza" { 108 t.Errorf("Wrong bot name. Got %s, expected wowza.", botName) 109 } 110 } 111 112 func TestIsMember(t *testing.T) { 113 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 114 if r.Method != http.MethodGet { 115 t.Errorf("Bad method: %s", r.Method) 116 } 117 if r.URL.Path != "/orgs/k8s/members/person" { 118 t.Errorf("Bad request path: %s", r.URL.Path) 119 } 120 http.Error(w, "204 No Content", http.StatusNoContent) 121 })) 122 defer ts.Close() 123 c := getClient(ts.URL) 124 mem, err := c.IsMember("k8s", "person") 125 if err != nil { 126 t.Errorf("Didn't expect error: %v", err) 127 } else if !mem { 128 t.Errorf("Should be member.") 129 } 130 } 131 132 func TestCreateComment(t *testing.T) { 133 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 134 if r.Method != http.MethodPost { 135 t.Errorf("Bad method: %s", r.Method) 136 } 137 if r.URL.Path != "/repos/k8s/kuber/issues/5/comments" { 138 t.Errorf("Bad request path: %s", r.URL.Path) 139 } 140 b, err := ioutil.ReadAll(r.Body) 141 if err != nil { 142 t.Fatalf("Could not read request body: %v", err) 143 } 144 var ic IssueComment 145 if err := json.Unmarshal(b, &ic); err != nil { 146 t.Errorf("Could not unmarshal request: %v", err) 147 } else if ic.Body != "hello" { 148 t.Errorf("Wrong body: %s", ic.Body) 149 } 150 http.Error(w, "201 Created", http.StatusCreated) 151 })) 152 defer ts.Close() 153 c := getClient(ts.URL) 154 if err := c.CreateComment("k8s", "kuber", 5, "hello"); err != nil { 155 t.Errorf("Didn't expect error: %v", err) 156 } 157 } 158 159 func TestCreateCommentReaction(t *testing.T) { 160 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 161 if r.Method != http.MethodPost { 162 t.Errorf("Bad method: %s", r.Method) 163 } 164 if r.URL.Path != "/repos/k8s/kuber/issues/comments/5/reactions" { 165 t.Errorf("Bad request path: %s", r.URL.Path) 166 } 167 if r.Header.Get("Accept") != "application/vnd.github.squirrel-girl-preview" { 168 t.Errorf("Bad Accept header: %s", r.Header.Get("Accept")) 169 } 170 http.Error(w, "201 Created", http.StatusCreated) 171 })) 172 defer ts.Close() 173 c := getClient(ts.URL) 174 if err := c.CreateCommentReaction("k8s", "kuber", 5, "+1"); err != nil { 175 t.Errorf("Didn't expect error: %v", err) 176 } 177 } 178 179 func TestDeleteComment(t *testing.T) { 180 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 181 if r.Method != http.MethodDelete { 182 t.Errorf("Bad method: %s", r.Method) 183 } 184 if r.URL.Path != "/repos/k8s/kuber/issues/comments/123" { 185 t.Errorf("Bad request path: %s", r.URL.Path) 186 } 187 http.Error(w, "204 No Content", http.StatusNoContent) 188 })) 189 defer ts.Close() 190 c := getClient(ts.URL) 191 if err := c.DeleteComment("k8s", "kuber", 123); err != nil { 192 t.Errorf("Didn't expect error: %v", err) 193 } 194 } 195 196 func TestGetPullRequest(t *testing.T) { 197 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 198 if r.Method != http.MethodGet { 199 t.Errorf("Bad method: %s", r.Method) 200 } 201 if r.URL.Path != "/repos/k8s/kuber/pulls/12" { 202 t.Errorf("Bad request path: %s", r.URL.Path) 203 } 204 pr := PullRequest{ 205 User: User{Login: "bla"}, 206 } 207 b, err := json.Marshal(&pr) 208 if err != nil { 209 t.Fatalf("Didn't expect error: %v", err) 210 } 211 fmt.Fprint(w, string(b)) 212 })) 213 defer ts.Close() 214 c := getClient(ts.URL) 215 pr, err := c.GetPullRequest("k8s", "kuber", 12) 216 if err != nil { 217 t.Errorf("Didn't expect error: %v", err) 218 } else if pr.User.Login != "bla" { 219 t.Errorf("Wrong user: %s", pr.User.Login) 220 } 221 } 222 223 func TestGetPullRequestChanges(t *testing.T) { 224 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 225 if r.Method != http.MethodGet { 226 t.Errorf("Bad method: %s", r.Method) 227 } 228 if r.URL.Path != "/repos/k8s/kuber/pulls/12/files" { 229 t.Errorf("Bad request path: %s", r.URL.Path) 230 } 231 changes := []PullRequestChange{ 232 {Filename: "foo.txt"}, 233 } 234 b, err := json.Marshal(&changes) 235 if err != nil { 236 t.Fatalf("Didn't expect error: %v", err) 237 } 238 fmt.Fprint(w, string(b)) 239 })) 240 defer ts.Close() 241 c := getClient(ts.URL) 242 cs, err := c.GetPullRequestChanges("k8s", "kuber", 12) 243 if err != nil { 244 t.Errorf("Didn't expect error: %v", err) 245 } 246 if len(cs) != 1 || cs[0].Filename != "foo.txt" { 247 t.Errorf("Wrong result: %#v", cs) 248 } 249 } 250 251 func TestGetRef(t *testing.T) { 252 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 253 if r.Method != http.MethodGet { 254 t.Errorf("Bad method: %s", r.Method) 255 } 256 if r.URL.Path != "/repos/k8s/kuber/git/refs/heads/mastah" { 257 t.Errorf("Bad request path: %s", r.URL.Path) 258 } 259 fmt.Fprint(w, `{"object": {"sha":"abcde"}}`) 260 })) 261 defer ts.Close() 262 c := getClient(ts.URL) 263 sha, err := c.GetRef("k8s", "kuber", "heads/mastah") 264 if err != nil { 265 t.Errorf("Didn't expect error: %v", err) 266 } else if sha != "abcde" { 267 t.Errorf("Wrong sha: %s", sha) 268 } 269 } 270 271 func TestCreateStatus(t *testing.T) { 272 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 273 if r.Method != http.MethodPost { 274 t.Errorf("Bad method: %s", r.Method) 275 } 276 if r.URL.Path != "/repos/k8s/kuber/statuses/abcdef" { 277 t.Errorf("Bad request path: %s", r.URL.Path) 278 } 279 b, err := ioutil.ReadAll(r.Body) 280 if err != nil { 281 t.Fatalf("Could not read request body: %v", err) 282 } 283 var s Status 284 if err := json.Unmarshal(b, &s); err != nil { 285 t.Errorf("Could not unmarshal request: %v", err) 286 } else if s.Context != "c" { 287 t.Errorf("Wrong context: %s", s.Context) 288 } 289 http.Error(w, "201 Created", http.StatusCreated) 290 })) 291 defer ts.Close() 292 c := getClient(ts.URL) 293 if err := c.CreateStatus("k8s", "kuber", "abcdef", Status{ 294 Context: "c", 295 }); err != nil { 296 t.Errorf("Didn't expect error: %v", err) 297 } 298 } 299 300 func TestListIssueComments(t *testing.T) { 301 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 302 if r.Method != http.MethodGet { 303 t.Errorf("Bad method: %s", r.Method) 304 } 305 if r.URL.Path == "/repos/k8s/kuber/issues/15/comments" { 306 ics := []IssueComment{{ID: 1}} 307 b, err := json.Marshal(ics) 308 if err != nil { 309 t.Fatalf("Didn't expect error: %v", err) 310 } 311 w.Header().Set("Link", fmt.Sprintf(`<blorp>; rel="first", <https://%s/someotherpath>; rel="next"`, r.Host)) 312 fmt.Fprint(w, string(b)) 313 } else if r.URL.Path == "/someotherpath" { 314 ics := []IssueComment{{ID: 2}} 315 b, err := json.Marshal(ics) 316 if err != nil { 317 t.Fatalf("Didn't expect error: %v", err) 318 } 319 fmt.Fprint(w, string(b)) 320 } else { 321 t.Errorf("Bad request path: %s", r.URL.Path) 322 } 323 })) 324 defer ts.Close() 325 c := getClient(ts.URL) 326 ics, err := c.ListIssueComments("k8s", "kuber", 15) 327 if err != nil { 328 t.Errorf("Didn't expect error: %v", err) 329 } else if len(ics) != 2 { 330 t.Errorf("Expected two issues, found %d: %v", len(ics), ics) 331 } else if ics[0].ID != 1 || ics[1].ID != 2 { 332 t.Errorf("Wrong issue IDs: %v", ics) 333 } 334 } 335 336 func TestAddLabel(t *testing.T) { 337 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 338 if r.Method != http.MethodPost { 339 t.Errorf("Bad method: %s", r.Method) 340 } 341 if r.URL.Path != "/repos/k8s/kuber/issues/5/labels" { 342 t.Errorf("Bad request path: %s", r.URL.Path) 343 } 344 b, err := ioutil.ReadAll(r.Body) 345 if err != nil { 346 t.Fatalf("Could not read request body: %v", err) 347 } 348 var ls []string 349 if err := json.Unmarshal(b, &ls); err != nil { 350 t.Errorf("Could not unmarshal request: %v", err) 351 } else if len(ls) != 1 { 352 t.Errorf("Wrong length labels: %v", ls) 353 } else if ls[0] != "yay" { 354 t.Errorf("Wrong label: %s", ls[0]) 355 } 356 })) 357 defer ts.Close() 358 c := getClient(ts.URL) 359 if err := c.AddLabel("k8s", "kuber", 5, "yay"); err != nil { 360 t.Errorf("Didn't expect error: %v", err) 361 } 362 } 363 364 func TestRemoveLabel(t *testing.T) { 365 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 366 if r.Method != http.MethodDelete { 367 t.Errorf("Bad method: %s", r.Method) 368 } 369 if r.URL.Path != "/repos/k8s/kuber/issues/5/labels/yay" { 370 t.Errorf("Bad request path: %s", r.URL.Path) 371 } 372 http.Error(w, "204 No Content", http.StatusNoContent) 373 })) 374 defer ts.Close() 375 c := getClient(ts.URL) 376 if err := c.RemoveLabel("k8s", "kuber", 5, "yay"); err != nil { 377 t.Errorf("Didn't expect error: %v", err) 378 } 379 } 380 381 func TestAssignIssue(t *testing.T) { 382 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 383 if r.Method != http.MethodPost { 384 t.Errorf("Bad method: %s", r.Method) 385 } 386 if r.URL.Path != "/repos/k8s/kuber/issues/5/assignees" { 387 t.Errorf("Bad request path: %s", r.URL.Path) 388 } 389 b, err := ioutil.ReadAll(r.Body) 390 if err != nil { 391 t.Fatalf("Could not read request body: %v", err) 392 } 393 var ps map[string][]string 394 if err := json.Unmarshal(b, &ps); err != nil { 395 t.Errorf("Could not unmarshal request: %v", err) 396 } else if len(ps) != 1 { 397 t.Errorf("Wrong length patch: %v", ps) 398 } else if len(ps["assignees"]) == 3 { 399 if ps["assignees"][0] != "george" || ps["assignees"][1] != "jungle" || ps["assignees"][2] != "not-in-the-org" { 400 t.Errorf("Wrong assignees: %v", ps) 401 } 402 } else if len(ps["assignees"]) == 2 { 403 if ps["assignees"][0] != "george" || ps["assignees"][1] != "jungle" { 404 t.Errorf("Wrong assignees: %v", ps) 405 } 406 407 } else { 408 t.Errorf("Wrong assignees length: %v", ps) 409 } 410 w.WriteHeader(http.StatusCreated) 411 json.NewEncoder(w).Encode(Issue{ 412 Assignees: []User{{Login: "george"}, {Login: "jungle"}, {Login: "ignore-other"}}, 413 }) 414 })) 415 defer ts.Close() 416 c := getClient(ts.URL) 417 if err := c.AssignIssue("k8s", "kuber", 5, []string{"george", "jungle"}); err != nil { 418 t.Errorf("Unexpected error: %v", err) 419 } 420 if err := c.AssignIssue("k8s", "kuber", 5, []string{"george", "jungle", "not-in-the-org"}); err == nil { 421 t.Errorf("Expected an error") 422 } else if merr, ok := err.(MissingUsers); ok { 423 if len(merr.Users) != 1 || merr.Users[0] != "not-in-the-org" { 424 t.Errorf("Expected [not-in-the-org], not %v", merr.Users) 425 } 426 } else { 427 t.Errorf("Expected MissingUsers error") 428 } 429 } 430 431 func TestUnassignIssue(t *testing.T) { 432 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 433 if r.Method != http.MethodDelete { 434 t.Errorf("Bad method: %s", r.Method) 435 } 436 if r.URL.Path != "/repos/k8s/kuber/issues/5/assignees" { 437 t.Errorf("Bad request path: %s", r.URL.Path) 438 } 439 b, err := ioutil.ReadAll(r.Body) 440 if err != nil { 441 t.Fatalf("Could not read request body: %v", err) 442 } 443 var ps map[string][]string 444 if err := json.Unmarshal(b, &ps); err != nil { 445 t.Errorf("Could not unmarshal request: %v", err) 446 } else if len(ps) != 1 { 447 t.Errorf("Wrong length patch: %v", ps) 448 } else if len(ps["assignees"]) == 3 { 449 if ps["assignees"][0] != "george" || ps["assignees"][1] != "jungle" || ps["assignees"][2] != "perma-assignee" { 450 t.Errorf("Wrong assignees: %v", ps) 451 } 452 } else if len(ps["assignees"]) == 2 { 453 if ps["assignees"][0] != "george" || ps["assignees"][1] != "jungle" { 454 t.Errorf("Wrong assignees: %v", ps) 455 } 456 457 } else { 458 t.Errorf("Wrong assignees length: %v", ps) 459 } 460 json.NewEncoder(w).Encode(Issue{ 461 Assignees: []User{{Login: "perma-assignee"}, {Login: "ignore-other"}}, 462 }) 463 })) 464 defer ts.Close() 465 c := getClient(ts.URL) 466 if err := c.UnassignIssue("k8s", "kuber", 5, []string{"george", "jungle"}); err != nil { 467 t.Errorf("Unexpected error: %v", err) 468 } 469 if err := c.UnassignIssue("k8s", "kuber", 5, []string{"george", "jungle", "perma-assignee"}); err == nil { 470 t.Errorf("Expected an error") 471 } else if merr, ok := err.(ExtraUsers); ok { 472 if len(merr.Users) != 1 || merr.Users[0] != "perma-assignee" { 473 t.Errorf("Expected [perma-assignee], not %v", merr.Users) 474 } 475 } else { 476 t.Errorf("Expected ExtraUsers error") 477 } 478 } 479 480 func TestReadPaginatedResults(t *testing.T) { 481 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 482 if r.Method != http.MethodGet { 483 t.Errorf("Bad method: %s", r.Method) 484 } 485 if r.URL.Path == "/label/foo" { 486 objects := []Label{{Name: "foo"}} 487 b, err := json.Marshal(objects) 488 if err != nil { 489 t.Fatalf("Didn't expect error: %v", err) 490 } 491 w.Header().Set("Link", fmt.Sprintf(`<blorp>; rel="first", <https://%s/label/bar>; rel="next"`, r.Host)) 492 fmt.Fprint(w, string(b)) 493 } else if r.URL.Path == "/label/bar" { 494 objects := []Label{{Name: "bar"}} 495 b, err := json.Marshal(objects) 496 if err != nil { 497 t.Fatalf("Didn't expect error: %v", err) 498 } 499 fmt.Fprint(w, string(b)) 500 } else { 501 t.Errorf("Bad request path: %s", r.URL.Path) 502 } 503 })) 504 defer ts.Close() 505 c := getClient(ts.URL) 506 path := "/label/foo" 507 var labels []Label 508 err := c.readPaginatedResults(path, 509 func() interface{} { 510 return &[]Label{} 511 }, 512 func(obj interface{}) { 513 labels = append(labels, *(obj.(*[]Label))...) 514 }, 515 ) 516 if err != nil { 517 t.Errorf("Didn't expect error: %v", err) 518 } else if len(labels) != 2 { 519 t.Errorf("Expected two labels, found %d: %v", len(labels), labels) 520 } else if labels[0].Name != "foo" || labels[1].Name != "bar" { 521 t.Errorf("Wrong label names: %v", labels) 522 } 523 } 524 525 func TestListPullRequestComments(t *testing.T) { 526 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 527 if r.Method != http.MethodGet { 528 t.Errorf("Bad method: %s", r.Method) 529 } 530 if r.URL.Path == "/repos/k8s/kuber/pulls/15/comments" { 531 prcs := []ReviewComment{{ID: 1}} 532 b, err := json.Marshal(prcs) 533 if err != nil { 534 t.Fatalf("Didn't expect error: %v", err) 535 } 536 w.Header().Set("Link", fmt.Sprintf(`<blorp>; rel="first", <https://%s/someotherpath>; rel="next"`, r.Host)) 537 fmt.Fprint(w, string(b)) 538 } else if r.URL.Path == "/someotherpath" { 539 prcs := []ReviewComment{{ID: 2}} 540 b, err := json.Marshal(prcs) 541 if err != nil { 542 t.Fatalf("Didn't expect error: %v", err) 543 } 544 fmt.Fprint(w, string(b)) 545 } else { 546 t.Errorf("Bad request path: %s", r.URL.Path) 547 } 548 })) 549 defer ts.Close() 550 c := getClient(ts.URL) 551 prcs, err := c.ListPullRequestComments("k8s", "kuber", 15) 552 if err != nil { 553 t.Errorf("Didn't expect error: %v", err) 554 } else if len(prcs) != 2 { 555 t.Errorf("Expected two comments, found %d: %v", len(prcs), prcs) 556 } else if prcs[0].ID != 1 || prcs[1].ID != 2 { 557 t.Errorf("Wrong issue IDs: %v", prcs) 558 } 559 } 560 561 func TestRequestReview(t *testing.T) { 562 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 563 if r.Method != http.MethodPost { 564 t.Errorf("Bad method: %s", r.Method) 565 } 566 if r.URL.Path != "/repos/k8s/kuber/pulls/5/requested_reviewers" { 567 t.Errorf("Bad request path: %s", r.URL.Path) 568 } 569 b, err := ioutil.ReadAll(r.Body) 570 if err != nil { 571 t.Fatalf("Could not read request body: %v", err) 572 } 573 var ps map[string][]string 574 if err := json.Unmarshal(b, &ps); err != nil { 575 t.Fatalf("Could not unmarshal request: %v", err) 576 } 577 if len(ps) != 1 { 578 t.Fatalf("Wrong length patch: %v", ps) 579 } 580 switch len(ps["reviewers"]) { 581 case 3: 582 if ps["reviewers"][0] != "george" || ps["reviewers"][1] != "jungle" || ps["reviewers"][2] != "not-a-collaborator" { 583 t.Errorf("Wrong reviewers: %v", ps) 584 } 585 //fall out of switch statement to bad reviewer case 586 case 2: 587 if ps["reviewers"][0] != "george" || ps["reviewers"][1] != "jungle" { 588 t.Errorf("Wrong reviewers: %v", ps) 589 } 590 w.WriteHeader(http.StatusCreated) 591 json.NewEncoder(w).Encode(PullRequest{ 592 RequestedReviewers: []User{{Login: "george"}, {Login: "jungle"}, {Login: "ignore-other"}}, 593 }) 594 return 595 case 1: 596 if ps["reviewers"][0] != "not-a-collaborator" { 597 w.WriteHeader(http.StatusCreated) 598 json.NewEncoder(w).Encode(PullRequest{ 599 RequestedReviewers: []User{{Login: ps["reviewers"][0]}, {Login: "ignore-other"}}, 600 }) 601 return 602 } 603 //fall out of switch statement to bad reviewer case 604 default: 605 t.Errorf("Wrong reviewers length: %v", ps) 606 } 607 //bad reviewer case 608 w.WriteHeader(http.StatusUnprocessableEntity) 609 })) 610 defer ts.Close() 611 c := getClient(ts.URL) 612 if err := c.RequestReview("k8s", "kuber", 5, []string{"george", "jungle"}); err != nil { 613 t.Errorf("Unexpected error: %v", err) 614 } 615 if err := c.RequestReview("k8s", "kuber", 5, []string{"george", "jungle", "not-a-collaborator"}); err == nil { 616 t.Errorf("Expected an error") 617 } else if merr, ok := err.(MissingUsers); ok { 618 if len(merr.Users) != 1 || merr.Users[0] != "not-a-collaborator" { 619 t.Errorf("Expected [not-a-collaborator], not %v", merr.Users) 620 } 621 } else { 622 t.Errorf("Expected MissingUsers error") 623 } 624 } 625 626 func TestUnrequestReview(t *testing.T) { 627 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 628 if r.Method != http.MethodDelete { 629 t.Errorf("Bad method: %s", r.Method) 630 } 631 if r.URL.Path != "/repos/k8s/kuber/pulls/5/requested_reviewers" { 632 t.Errorf("Bad request path: %s", r.URL.Path) 633 } 634 b, err := ioutil.ReadAll(r.Body) 635 if err != nil { 636 t.Fatalf("Could not read request body: %v", err) 637 } 638 var ps map[string][]string 639 if err := json.Unmarshal(b, &ps); err != nil { 640 t.Errorf("Could not unmarshal request: %v", err) 641 } else if len(ps) != 1 { 642 t.Errorf("Wrong length patch: %v", ps) 643 } else if len(ps["reviewers"]) == 3 { 644 if ps["reviewers"][0] != "george" || ps["reviewers"][1] != "jungle" || ps["reviewers"][2] != "perma-reviewer" { 645 t.Errorf("Wrong reviewers: %v", ps) 646 } 647 } else if len(ps["reviewers"]) == 2 { 648 if ps["reviewers"][0] != "george" || ps["reviewers"][1] != "jungle" { 649 t.Errorf("Wrong reviewers: %v", ps) 650 } 651 } else { 652 t.Errorf("Wrong reviewers length: %v", ps) 653 } 654 json.NewEncoder(w).Encode(PullRequest{ 655 RequestedReviewers: []User{{Login: "perma-reviewer"}, {Login: "ignore-other"}}, 656 }) 657 })) 658 defer ts.Close() 659 c := getClient(ts.URL) 660 if err := c.UnrequestReview("k8s", "kuber", 5, []string{"george", "jungle"}); err != nil { 661 t.Errorf("Unexpected error: %v", err) 662 } 663 if err := c.UnrequestReview("k8s", "kuber", 5, []string{"george", "jungle", "perma-reviewer"}); err == nil { 664 t.Errorf("Expected an error") 665 } else if merr, ok := err.(ExtraUsers); ok { 666 if len(merr.Users) != 1 || merr.Users[0] != "perma-reviewer" { 667 t.Errorf("Expected [perma-reviewer], not %v", merr.Users) 668 } 669 } else { 670 t.Errorf("Expected ExtraUsers error") 671 } 672 } 673 674 func TestCloseIssue(t *testing.T) { 675 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 676 if r.Method != http.MethodPatch { 677 t.Errorf("Bad method: %s", r.Method) 678 } 679 if r.URL.Path != "/repos/k8s/kuber/issues/5" { 680 t.Errorf("Bad request path: %s", r.URL.Path) 681 } 682 b, err := ioutil.ReadAll(r.Body) 683 if err != nil { 684 t.Fatalf("Could not read request body: %v", err) 685 } 686 var ps map[string]string 687 if err := json.Unmarshal(b, &ps); err != nil { 688 t.Errorf("Could not unmarshal request: %v", err) 689 } else if len(ps) != 1 { 690 t.Errorf("Wrong length patch: %v", ps) 691 } else if ps["state"] != "closed" { 692 t.Errorf("Wrong state: %s", ps["state"]) 693 } 694 })) 695 defer ts.Close() 696 c := getClient(ts.URL) 697 if err := c.CloseIssue("k8s", "kuber", 5); err != nil { 698 t.Errorf("Didn't expect error: %v", err) 699 } 700 } 701 702 func TestReopenIssue(t *testing.T) { 703 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 704 if r.Method != http.MethodPatch { 705 t.Errorf("Bad method: %s", r.Method) 706 } 707 if r.URL.Path != "/repos/k8s/kuber/issues/5" { 708 t.Errorf("Bad request path: %s", r.URL.Path) 709 } 710 b, err := ioutil.ReadAll(r.Body) 711 if err != nil { 712 t.Fatalf("Could not read request body: %v", err) 713 } 714 var ps map[string]string 715 if err := json.Unmarshal(b, &ps); err != nil { 716 t.Errorf("Could not unmarshal request: %v", err) 717 } else if len(ps) != 1 { 718 t.Errorf("Wrong length patch: %v", ps) 719 } else if ps["state"] != "open" { 720 t.Errorf("Wrong state: %s", ps["state"]) 721 } 722 })) 723 defer ts.Close() 724 c := getClient(ts.URL) 725 if err := c.ReopenIssue("k8s", "kuber", 5); err != nil { 726 t.Errorf("Didn't expect error: %v", err) 727 } 728 } 729 730 func TestClosePR(t *testing.T) { 731 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 732 if r.Method != http.MethodPatch { 733 t.Errorf("Bad method: %s", r.Method) 734 } 735 if r.URL.Path != "/repos/k8s/kuber/pulls/5" { 736 t.Errorf("Bad request path: %s", r.URL.Path) 737 } 738 b, err := ioutil.ReadAll(r.Body) 739 if err != nil { 740 t.Fatalf("Could not read request body: %v", err) 741 } 742 var ps map[string]string 743 if err := json.Unmarshal(b, &ps); err != nil { 744 t.Errorf("Could not unmarshal request: %v", err) 745 } else if len(ps) != 1 { 746 t.Errorf("Wrong length patch: %v", ps) 747 } else if ps["state"] != "closed" { 748 t.Errorf("Wrong state: %s", ps["state"]) 749 } 750 })) 751 defer ts.Close() 752 c := getClient(ts.URL) 753 if err := c.ClosePR("k8s", "kuber", 5); err != nil { 754 t.Errorf("Didn't expect error: %v", err) 755 } 756 } 757 758 func TestReopenPR(t *testing.T) { 759 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 760 if r.Method != http.MethodPatch { 761 t.Errorf("Bad method: %s", r.Method) 762 } 763 if r.URL.Path != "/repos/k8s/kuber/pulls/5" { 764 t.Errorf("Bad request path: %s", r.URL.Path) 765 } 766 b, err := ioutil.ReadAll(r.Body) 767 if err != nil { 768 t.Fatalf("Could not read request body: %v", err) 769 } 770 var ps map[string]string 771 if err := json.Unmarshal(b, &ps); err != nil { 772 t.Errorf("Could not unmarshal request: %v", err) 773 } else if len(ps) != 1 { 774 t.Errorf("Wrong length patch: %v", ps) 775 } else if ps["state"] != "open" { 776 t.Errorf("Wrong state: %s", ps["state"]) 777 } 778 })) 779 defer ts.Close() 780 c := getClient(ts.URL) 781 if err := c.ReopenPR("k8s", "kuber", 5); err != nil { 782 t.Errorf("Didn't expect error: %v", err) 783 } 784 } 785 786 func TestFindIssues(t *testing.T) { 787 cases := []struct { 788 name string 789 sort bool 790 order bool 791 }{ 792 { 793 name: "simple query", 794 }, 795 { 796 name: "sort no order", 797 sort: true, 798 }, 799 { 800 name: "sort and order", 801 sort: true, 802 order: true, 803 }, 804 } 805 806 issueNum := 5 807 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 808 if r.Method != http.MethodGet { 809 t.Errorf("Bad method: %s", r.Method) 810 } 811 if r.URL.Path != "/search/issues" { 812 t.Errorf("Bad request path: %s", r.URL.Path) 813 } 814 issueList := IssuesSearchResult{ 815 Total: 1, 816 Issues: []Issue{ 817 { 818 Number: issueNum, 819 Title: r.URL.RawQuery, 820 }, 821 }, 822 } 823 b, err := json.Marshal(&issueList) 824 if err != nil { 825 t.Fatalf("Didn't expect error: %v", err) 826 } 827 fmt.Fprint(w, string(b)) 828 })) 829 defer ts.Close() 830 c := getClient(ts.URL) 831 832 for _, tc := range cases { 833 var result []Issue 834 var err error 835 sort := "" 836 if tc.sort { 837 sort = "sort-strategy" 838 } 839 if result, err = c.FindIssues("commit_hash", sort, tc.order); err != nil { 840 t.Errorf("%s: didn't expect error: %v", tc.name, err) 841 } 842 if len(result) != 1 { 843 t.Errorf("%s: unexpected number of results: %v", tc.name, len(result)) 844 } 845 if result[0].Number != issueNum { 846 t.Errorf("%s: expected issue number %+v, got %+v", tc.name, issueNum, result[0].Number) 847 } 848 if tc.sort && !strings.Contains(result[0].Title, "sort="+sort) { 849 t.Errorf("%s: missing sort=%s from query: %s", tc.name, sort, result[0].Title) 850 } 851 if tc.order && !strings.Contains(result[0].Title, "order=asc") { 852 t.Errorf("%s: missing order=asc from query: %s", tc.name, result[0].Title) 853 } 854 } 855 } 856 857 func TestGetFile(t *testing.T) { 858 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 859 if r.Method != http.MethodGet { 860 t.Errorf("Bad method: %s", r.Method) 861 } 862 if r.URL.Path != "/repos/k8s/kuber/contents/foo.txt" { 863 t.Errorf("Bad request path: %s", r.URL.Path) 864 } 865 if r.URL.RawQuery != "" { 866 t.Errorf("Bad request query: %s", r.URL.RawQuery) 867 } 868 c := &Content{ 869 Content: base64.StdEncoding.EncodeToString([]byte("abcde")), 870 } 871 b, err := json.Marshal(&c) 872 if err != nil { 873 t.Fatalf("Didn't expect error: %v", err) 874 } 875 fmt.Fprint(w, string(b)) 876 })) 877 defer ts.Close() 878 c := getClient(ts.URL) 879 if content, err := c.GetFile("k8s", "kuber", "foo.txt", ""); err != nil { 880 t.Errorf("Didn't expect error: %v", err) 881 } else if string(content) != "abcde" { 882 t.Errorf("Wrong content -- expect: abcde, got: %s", string(content)) 883 } 884 } 885 886 func TestGetFileRef(t *testing.T) { 887 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 888 if r.Method != http.MethodGet { 889 t.Errorf("Bad method: %s", r.Method) 890 } 891 if r.URL.Path != "/repos/k8s/kuber/contents/foo/bar.txt" { 892 t.Errorf("Bad request path: %s", r.URL) 893 } 894 if r.URL.RawQuery != "ref=12345" { 895 t.Errorf("Bad request query: %s", r.URL.RawQuery) 896 } 897 c := &Content{ 898 Content: base64.StdEncoding.EncodeToString([]byte("abcde")), 899 } 900 b, err := json.Marshal(&c) 901 if err != nil { 902 t.Fatalf("Didn't expect error: %v", err) 903 } 904 fmt.Fprint(w, string(b)) 905 })) 906 defer ts.Close() 907 c := getClient(ts.URL) 908 if content, err := c.GetFile("k8s", "kuber", "foo/bar.txt", "12345"); err != nil { 909 t.Errorf("Didn't expect error: %v", err) 910 } else if string(content) != "abcde" { 911 t.Errorf("Wrong content -- expect: abcde, got: %s", string(content)) 912 } 913 } 914 915 // TestGetLabels tests both GetRepoLabels and GetIssueLabels. 916 func TestGetLabels(t *testing.T) { 917 ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 918 if r.Method != http.MethodGet { 919 t.Errorf("Bad method: %s", r.Method) 920 } 921 var labels []Label 922 switch r.URL.Path { 923 case "/repos/k8s/kuber/issues/5/labels": 924 labels = []Label{{Name: "issue-label"}} 925 w.Header().Set("Link", fmt.Sprintf(`<blorp>; rel="first", <https://%s/someotherpath>; rel="next"`, r.Host)) 926 case "/repos/k8s/kuber/labels": 927 labels = []Label{{Name: "repo-label"}} 928 w.Header().Set("Link", fmt.Sprintf(`<blorp>; rel="first", <https://%s/someotherpath>; rel="next"`, r.Host)) 929 case "/someotherpath": 930 labels = []Label{{Name: "label2"}} 931 default: 932 t.Errorf("Bad request path: %s", r.URL.Path) 933 return 934 } 935 b, err := json.Marshal(labels) 936 if err != nil { 937 t.Fatalf("Didn't expect error: %v", err) 938 } 939 fmt.Fprint(w, string(b)) 940 })) 941 defer ts.Close() 942 c := getClient(ts.URL) 943 labels, err := c.GetIssueLabels("k8s", "kuber", 5) 944 if err != nil { 945 t.Errorf("Didn't expect error: %v", err) 946 } else if len(labels) != 2 { 947 t.Errorf("Expected two labels, found %d: %v", len(labels), labels) 948 } else if labels[0].Name != "issue-label" || labels[1].Name != "label2" { 949 t.Errorf("Wrong label names: %v", labels) 950 } 951 952 labels, err = c.GetRepoLabels("k8s", "kuber") 953 if err != nil { 954 t.Errorf("Didn't expect error: %v", err) 955 } else if len(labels) != 2 { 956 t.Errorf("Expected two labels, found %d: %v", len(labels), labels) 957 } else if labels[0].Name != "repo-label" || labels[1].Name != "label2" { 958 t.Errorf("Wrong label names: %v", labels) 959 } 960 } 961 962 func simpleTestServer(t *testing.T, path string, v interface{}) *httptest.Server { 963 return httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 964 if r.URL.Path == path { 965 b, err := json.Marshal(v) 966 if err != nil { 967 t.Fatalf("Didn't expect error: %v", err) 968 } 969 fmt.Fprint(w, string(b)) 970 } else { 971 t.Fatalf("Bad request path: %s", r.URL.Path) 972 } 973 })) 974 } 975 976 func TestListTeams(t *testing.T) { 977 ts := simpleTestServer(t, "/orgs/foo/teams", []Team{{ID: 1}}) 978 defer ts.Close() 979 c := getClient(ts.URL) 980 teams, err := c.ListTeams("foo") 981 if err != nil { 982 t.Errorf("Didn't expect error: %v", err) 983 } else if len(teams) != 1 { 984 t.Errorf("Expected one team, found %d: %v", len(teams), teams) 985 } else if teams[0].ID != 1 { 986 t.Errorf("Wrong team names: %v", teams) 987 } 988 } 989 990 func TestListTeamMembers(t *testing.T) { 991 ts := simpleTestServer(t, "/teams/1/members", []TeamMember{{Login: "foo"}}) 992 defer ts.Close() 993 c := getClient(ts.URL) 994 teamMembers, err := c.ListTeamMembers(1) 995 if err != nil { 996 t.Errorf("Didn't expect error: %v", err) 997 } else if len(teamMembers) != 1 { 998 t.Errorf("Expected one team member, found %d: %v", len(teamMembers), teamMembers) 999 } else if teamMembers[0].Login != "foo" { 1000 t.Errorf("Wrong team names: %v", teamMembers) 1001 } 1002 }