github.com/google/go-github/v74@v74.0.0/github/code_scanning_test.go (about) 1 // Copyright 2020 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "net/http" 13 "testing" 14 "time" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestCodeScanningService_Alert_ID(t *testing.T) { 20 t.Parallel() 21 // Test: nil Alert ID == 0 22 var a *Alert 23 id := a.ID() 24 var want int64 25 if id != want { 26 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 27 } 28 29 // Test: Valid HTMLURL 30 a = &Alert{ 31 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/88"), 32 } 33 id = a.ID() 34 want = 88 35 if !cmp.Equal(id, want) { 36 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 37 } 38 39 // Test: HTMLURL is nil 40 a = &Alert{} 41 id = a.ID() 42 want = 0 43 if !cmp.Equal(id, want) { 44 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 45 } 46 47 // Test: ID can't be parsed as an int 48 a = &Alert{ 49 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/bad88"), 50 } 51 id = a.ID() 52 want = 0 53 if !cmp.Equal(id, want) { 54 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 55 } 56 } 57 58 func TestCodeScanningService_UploadSarif(t *testing.T) { 59 t.Parallel() 60 client, mux, _ := setup(t) 61 62 expectedSarifID := &SarifID{ 63 ID: Ptr("testid"), 64 URL: Ptr("https://example.com/testurl"), 65 } 66 67 mux.HandleFunc("/repos/o/r/code-scanning/sarifs", func(w http.ResponseWriter, r *http.Request) { 68 v := new(SarifAnalysis) 69 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 70 testMethod(t, r, "POST") 71 want := &SarifAnalysis{CommitSHA: Ptr("abc"), Ref: Ptr("ref/head/main"), Sarif: Ptr("abc"), CheckoutURI: Ptr("uri"), StartedAt: &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, ToolName: Ptr("codeql-cli")} 72 if !cmp.Equal(v, want) { 73 t.Errorf("Request body = %+v, want %+v", v, want) 74 } 75 76 w.WriteHeader(http.StatusAccepted) 77 respBody, _ := json.Marshal(expectedSarifID) 78 _, _ = w.Write(respBody) 79 }) 80 81 ctx := context.Background() 82 sarifAnalysis := &SarifAnalysis{CommitSHA: Ptr("abc"), Ref: Ptr("ref/head/main"), Sarif: Ptr("abc"), CheckoutURI: Ptr("uri"), StartedAt: &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, ToolName: Ptr("codeql-cli")} 83 respSarifID, _, err := client.CodeScanning.UploadSarif(ctx, "o", "r", sarifAnalysis) 84 if err != nil { 85 t.Errorf("CodeScanning.UploadSarif returned error: %v", err) 86 } 87 if !cmp.Equal(expectedSarifID, respSarifID) { 88 t.Errorf("Sarif response = %+v, want %+v", respSarifID, expectedSarifID) 89 } 90 91 const methodName = "UploadSarif" 92 testBadOptions(t, methodName, func() (err error) { 93 _, _, err = client.CodeScanning.UploadSarif(ctx, "\n", "\n", sarifAnalysis) 94 return err 95 }) 96 97 testNewRequestAndDoFailureCategory(t, methodName, client, CodeScanningUploadCategory, func() (*Response, error) { 98 _, resp, err := client.CodeScanning.UploadSarif(ctx, "o", "r", sarifAnalysis) 99 return resp, err 100 }) 101 } 102 103 func TestCodeScanningService_GetSARIF(t *testing.T) { 104 t.Parallel() 105 client, mux, _ := setup(t) 106 107 mux.HandleFunc("/repos/o/r/code-scanning/sarifs/abc", func(w http.ResponseWriter, r *http.Request) { 108 testMethod(t, r, "GET") 109 fmt.Fprint(w, `{ 110 "processing_status": "s", 111 "analyses_url": "u" 112 }`) 113 }) 114 115 ctx := context.Background() 116 sarifUpload, _, err := client.CodeScanning.GetSARIF(ctx, "o", "r", "abc") 117 if err != nil { 118 t.Errorf("CodeScanning.GetSARIF returned error: %v", err) 119 } 120 121 want := &SARIFUpload{ 122 ProcessingStatus: Ptr("s"), 123 AnalysesURL: Ptr("u"), 124 } 125 if !cmp.Equal(sarifUpload, want) { 126 t.Errorf("CodeScanning.GetSARIF returned %+v, want %+v", sarifUpload, want) 127 } 128 129 const methodName = "GetSARIF" 130 testBadOptions(t, methodName, func() (err error) { 131 _, _, err = client.CodeScanning.GetSARIF(ctx, "\n", "\n", "\n") 132 return err 133 }) 134 135 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 136 got, resp, err := client.CodeScanning.GetSARIF(ctx, "o", "r", "abc") 137 if got != nil { 138 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 139 } 140 return resp, err 141 }) 142 } 143 144 func TestCodeScanningService_ListAlertsForOrg(t *testing.T) { 145 t.Parallel() 146 client, mux, _ := setup(t) 147 148 mux.HandleFunc("/orgs/o/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 149 testMethod(t, r, "GET") 150 testFormValues(t, r, values{"state": "open", "ref": "heads/master", "severity": "warning", "tool_name": "CodeQL", "tool_guid": "guid", "direction": "asc", "sort": "updated"}) 151 fmt.Fprint(w, `[{ 152 "repository": { 153 "id": 1, 154 "name": "n", 155 "url": "url" 156 }, 157 "rule_id":"js/trivial-conditional", 158 "rule_severity":"warning", 159 "rule_description":"Useless conditional", 160 "tool": { 161 "name": "CodeQL", 162 "guid": "guid", 163 "version": "1.4.0" 164 }, 165 "rule": { 166 "id": "js/trivial-conditional", 167 "severity": "warning", 168 "description": "Useless conditional", 169 "name": "js/trivial-conditional", 170 "full_description": "Expression has no effect", 171 "help": "Expression has no effect" 172 }, 173 "most_recent_instance": { 174 "ref": "refs/heads/main", 175 "state": "open", 176 "commit_sha": "abcdefg12345", 177 "message": { 178 "text": "This path depends on a user-provided value." 179 }, 180 "location": { 181 "path": "spec-main/api-session-spec.ts", 182 "start_line": 917, 183 "end_line": 917, 184 "start_column": 7, 185 "end_column": 18 186 }, 187 "classifications": [ 188 "test" 189 ] 190 }, 191 "created_at":"2020-05-06T12:00:00Z", 192 "state":"open", 193 "closed_by":null, 194 "closed_at":null, 195 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/25", 196 "html_url":"https://github.com/o/r/security/code-scanning/25" 197 }, 198 { 199 "rule_id":"js/useless-expression", 200 "rule_severity":"warning", 201 "rule_description":"Expression has no effect", 202 "tool": { 203 "name": "CodeQL", 204 "guid": null, 205 "version": "1.4.0" 206 }, 207 "rule": { 208 "id": "js/useless-expression", 209 "severity": "warning", 210 "description": "Expression has no effect", 211 "name": "js/useless-expression", 212 "full_description": "Expression has no effect", 213 "help": "Expression has no effect" 214 }, 215 "most_recent_instance": { 216 "ref": "refs/heads/main", 217 "state": "open", 218 "commit_sha": "abcdefg12345", 219 "message": { 220 "text": "This path depends on a user-provided value." 221 }, 222 "location": { 223 "path": "spec-main/api-session-spec.ts", 224 "start_line": 917, 225 "end_line": 917, 226 "start_column": 7, 227 "end_column": 18 228 }, 229 "classifications": [ 230 "test" 231 ] 232 }, 233 "created_at":"2020-05-06T12:00:00Z", 234 "state":"open", 235 "closed_by":null, 236 "closed_at":null, 237 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 238 "html_url":"https://github.com/o/r/security/code-scanning/88" 239 }]`) 240 }) 241 242 opts := &AlertListOptions{State: "open", Ref: "heads/master", Severity: "warning", ToolName: "CodeQL", ToolGUID: "guid", Direction: "asc", Sort: "updated"} 243 ctx := context.Background() 244 alerts, _, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts) 245 if err != nil { 246 t.Errorf("CodeScanning.ListAlertsForOrg returned error: %v", err) 247 } 248 249 date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)} 250 want := []*Alert{ 251 { 252 Repository: &Repository{ 253 ID: Ptr(int64(1)), 254 URL: Ptr("url"), 255 Name: Ptr("n"), 256 }, 257 RuleID: Ptr("js/trivial-conditional"), 258 RuleSeverity: Ptr("warning"), 259 RuleDescription: Ptr("Useless conditional"), 260 Tool: &Tool{Name: Ptr("CodeQL"), GUID: Ptr("guid"), Version: Ptr("1.4.0")}, 261 Rule: &Rule{ 262 ID: Ptr("js/trivial-conditional"), 263 Severity: Ptr("warning"), 264 Description: Ptr("Useless conditional"), 265 Name: Ptr("js/trivial-conditional"), 266 FullDescription: Ptr("Expression has no effect"), 267 Help: Ptr("Expression has no effect"), 268 }, 269 CreatedAt: &date, 270 State: Ptr("open"), 271 ClosedBy: nil, 272 ClosedAt: nil, 273 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/25"), 274 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/25"), 275 MostRecentInstance: &MostRecentInstance{ 276 Ref: Ptr("refs/heads/main"), 277 State: Ptr("open"), 278 CommitSHA: Ptr("abcdefg12345"), 279 Message: &Message{ 280 Text: Ptr("This path depends on a user-provided value."), 281 }, 282 Location: &Location{ 283 Path: Ptr("spec-main/api-session-spec.ts"), 284 StartLine: Ptr(917), 285 EndLine: Ptr(917), 286 StartColumn: Ptr(7), 287 EndColumn: Ptr(18), 288 }, 289 Classifications: []string{"test"}, 290 }, 291 }, 292 { 293 RuleID: Ptr("js/useless-expression"), 294 RuleSeverity: Ptr("warning"), 295 RuleDescription: Ptr("Expression has no effect"), 296 Tool: &Tool{Name: Ptr("CodeQL"), GUID: nil, Version: Ptr("1.4.0")}, 297 Rule: &Rule{ 298 ID: Ptr("js/useless-expression"), 299 Severity: Ptr("warning"), 300 Description: Ptr("Expression has no effect"), 301 Name: Ptr("js/useless-expression"), 302 FullDescription: Ptr("Expression has no effect"), 303 Help: Ptr("Expression has no effect"), 304 }, 305 CreatedAt: &date, 306 State: Ptr("open"), 307 ClosedBy: nil, 308 ClosedAt: nil, 309 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 310 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/88"), 311 MostRecentInstance: &MostRecentInstance{ 312 Ref: Ptr("refs/heads/main"), 313 State: Ptr("open"), 314 CommitSHA: Ptr("abcdefg12345"), 315 Message: &Message{ 316 Text: Ptr("This path depends on a user-provided value."), 317 }, 318 Location: &Location{ 319 Path: Ptr("spec-main/api-session-spec.ts"), 320 StartLine: Ptr(917), 321 EndLine: Ptr(917), 322 StartColumn: Ptr(7), 323 EndColumn: Ptr(18), 324 }, 325 Classifications: []string{"test"}, 326 }, 327 }, 328 } 329 if !cmp.Equal(alerts, want) { 330 t.Errorf("CodeScanning.ListAlertsForOrg returned %+v, want %+v", alerts, want) 331 } 332 333 const methodName = "ListAlertsForOrg" 334 testBadOptions(t, methodName, func() (err error) { 335 _, _, err = client.CodeScanning.ListAlertsForOrg(ctx, "\n", opts) 336 return err 337 }) 338 339 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 340 got, resp, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts) 341 if got != nil { 342 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 343 } 344 return resp, err 345 }) 346 } 347 348 func TestCodeScanningService_ListAlertsForOrgLisCursorOptions(t *testing.T) { 349 t.Parallel() 350 client, mux, _ := setup(t) 351 352 mux.HandleFunc("/orgs/o/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 353 testMethod(t, r, "GET") 354 testFormValues(t, r, values{"state": "open", "ref": "heads/master", "severity": "warning", "tool_name": "CodeQL", "per_page": "1", "before": "deadbeefb", "after": "deadbeefa"}) 355 fmt.Fprint(w, `[{ 356 "repository": { 357 "id": 1, 358 "name": "n", 359 "url": "url" 360 }, 361 "rule_id":"js/trivial-conditional", 362 "rule_severity":"warning", 363 "rule_description":"Useless conditional", 364 "tool": { 365 "name": "CodeQL", 366 "guid": null, 367 "version": "1.4.0" 368 }, 369 "rule": { 370 "id": "js/trivial-conditional", 371 "severity": "warning", 372 "description": "Useless conditional", 373 "name": "js/trivial-conditional", 374 "full_description": "Expression has no effect", 375 "help": "Expression has no effect" 376 }, 377 "most_recent_instance": { 378 "ref": "refs/heads/main", 379 "state": "open", 380 "commit_sha": "abcdefg12345", 381 "message": { 382 "text": "This path depends on a user-provided value." 383 }, 384 "location": { 385 "path": "spec-main/api-session-spec.ts", 386 "start_line": 917, 387 "end_line": 917, 388 "start_column": 7, 389 "end_column": 18 390 }, 391 "classifications": [ 392 "test" 393 ] 394 }, 395 "created_at":"2020-05-06T12:00:00Z", 396 "state":"open", 397 "closed_by":null, 398 "closed_at":null, 399 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/25", 400 "html_url":"https://github.com/o/r/security/code-scanning/25" 401 }]`) 402 }) 403 404 opts := &AlertListOptions{State: "open", Ref: "heads/master", Severity: "warning", ToolName: "CodeQL", ListCursorOptions: ListCursorOptions{PerPage: 1, Before: "deadbeefb", After: "deadbeefa"}} 405 ctx := context.Background() 406 alerts, _, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts) 407 if err != nil { 408 t.Errorf("CodeScanning.ListAlertsForOrg returned error: %v", err) 409 } 410 411 date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)} 412 want := []*Alert{ 413 { 414 Repository: &Repository{ 415 ID: Ptr(int64(1)), 416 URL: Ptr("url"), 417 Name: Ptr("n"), 418 }, 419 RuleID: Ptr("js/trivial-conditional"), 420 RuleSeverity: Ptr("warning"), 421 RuleDescription: Ptr("Useless conditional"), 422 Tool: &Tool{Name: Ptr("CodeQL"), GUID: nil, Version: Ptr("1.4.0")}, 423 Rule: &Rule{ 424 ID: Ptr("js/trivial-conditional"), 425 Severity: Ptr("warning"), 426 Description: Ptr("Useless conditional"), 427 Name: Ptr("js/trivial-conditional"), 428 FullDescription: Ptr("Expression has no effect"), 429 Help: Ptr("Expression has no effect"), 430 }, 431 CreatedAt: &date, 432 State: Ptr("open"), 433 ClosedBy: nil, 434 ClosedAt: nil, 435 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/25"), 436 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/25"), 437 MostRecentInstance: &MostRecentInstance{ 438 Ref: Ptr("refs/heads/main"), 439 State: Ptr("open"), 440 CommitSHA: Ptr("abcdefg12345"), 441 Message: &Message{ 442 Text: Ptr("This path depends on a user-provided value."), 443 }, 444 Location: &Location{ 445 Path: Ptr("spec-main/api-session-spec.ts"), 446 StartLine: Ptr(917), 447 EndLine: Ptr(917), 448 StartColumn: Ptr(7), 449 EndColumn: Ptr(18), 450 }, 451 Classifications: []string{"test"}, 452 }, 453 }, 454 } 455 if !cmp.Equal(alerts, want) { 456 t.Errorf("CodeScanning.ListAlertsForOrg returned %+v, want %+v", alerts, want) 457 } 458 459 const methodName = "ListAlertsForOrg" 460 testBadOptions(t, methodName, func() (err error) { 461 _, _, err = client.CodeScanning.ListAlertsForOrg(ctx, "\n", opts) 462 return err 463 }) 464 465 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 466 got, resp, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts) 467 if got != nil { 468 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 469 } 470 return resp, err 471 }) 472 } 473 474 func TestCodeScanningService_ListAlertsForRepo(t *testing.T) { 475 t.Parallel() 476 client, mux, _ := setup(t) 477 478 mux.HandleFunc("/repos/o/r/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 479 testMethod(t, r, "GET") 480 testFormValues(t, r, values{"state": "open", "ref": "heads/master", "severity": "warning", "tool_name": "CodeQL", "tool_guid": "guid", "direction": "asc", "sort": "updated"}) 481 fmt.Fprint(w, `[{ 482 "rule_id":"js/trivial-conditional", 483 "rule_severity":"warning", 484 "rule_description":"Useless conditional", 485 "tool": { 486 "name": "CodeQL", 487 "guid": "guid", 488 "version": "1.4.0" 489 }, 490 "rule": { 491 "id": "js/trivial-conditional", 492 "severity": "warning", 493 "description": "Useless conditional", 494 "name": "js/trivial-conditional", 495 "full_description": "Expression has no effect", 496 "help": "Expression has no effect" 497 }, 498 "most_recent_instance": { 499 "ref": "refs/heads/main", 500 "state": "open", 501 "commit_sha": "abcdefg12345", 502 "message": { 503 "text": "This path depends on a user-provided value." 504 }, 505 "location": { 506 "path": "spec-main/api-session-spec.ts", 507 "start_line": 917, 508 "end_line": 917, 509 "start_column": 7, 510 "end_column": 18 511 }, 512 "classifications": [ 513 "test" 514 ] 515 }, 516 "created_at":"2020-05-06T12:00:00Z", 517 "state":"open", 518 "closed_by":null, 519 "closed_at":null, 520 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/25", 521 "html_url":"https://github.com/o/r/security/code-scanning/25" 522 }, 523 { 524 "rule_id":"js/useless-expression", 525 "rule_severity":"warning", 526 "rule_description":"Expression has no effect", 527 "tool": { 528 "name": "CodeQL", 529 "guid": "guid", 530 "version": "1.4.0" 531 }, 532 "rule": { 533 "id": "js/useless-expression", 534 "severity": "warning", 535 "description": "Expression has no effect", 536 "name": "js/useless-expression", 537 "full_description": "Expression has no effect", 538 "help": "Expression has no effect" 539 }, 540 "most_recent_instance": { 541 "ref": "refs/heads/main", 542 "state": "open", 543 "commit_sha": "abcdefg12345", 544 "message": { 545 "text": "This path depends on a user-provided value." 546 }, 547 "location": { 548 "path": "spec-main/api-session-spec.ts", 549 "start_line": 917, 550 "end_line": 917, 551 "start_column": 7, 552 "end_column": 18 553 }, 554 "classifications": [ 555 "test" 556 ] 557 }, 558 "created_at":"2020-05-06T12:00:00Z", 559 "state":"open", 560 "closed_by":null, 561 "closed_at":null, 562 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 563 "html_url":"https://github.com/o/r/security/code-scanning/88" 564 }]`) 565 }) 566 567 opts := &AlertListOptions{State: "open", Ref: "heads/master", Severity: "warning", ToolName: "CodeQL", ToolGUID: "guid", Direction: "asc", Sort: "updated"} 568 ctx := context.Background() 569 alerts, _, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts) 570 if err != nil { 571 t.Errorf("CodeScanning.ListAlertsForRepo returned error: %v", err) 572 } 573 574 date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)} 575 want := []*Alert{ 576 { 577 RuleID: Ptr("js/trivial-conditional"), 578 RuleSeverity: Ptr("warning"), 579 RuleDescription: Ptr("Useless conditional"), 580 Tool: &Tool{Name: Ptr("CodeQL"), GUID: Ptr("guid"), Version: Ptr("1.4.0")}, 581 Rule: &Rule{ 582 ID: Ptr("js/trivial-conditional"), 583 Severity: Ptr("warning"), 584 Description: Ptr("Useless conditional"), 585 Name: Ptr("js/trivial-conditional"), 586 FullDescription: Ptr("Expression has no effect"), 587 Help: Ptr("Expression has no effect"), 588 }, 589 CreatedAt: &date, 590 State: Ptr("open"), 591 ClosedBy: nil, 592 ClosedAt: nil, 593 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/25"), 594 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/25"), 595 MostRecentInstance: &MostRecentInstance{ 596 Ref: Ptr("refs/heads/main"), 597 State: Ptr("open"), 598 CommitSHA: Ptr("abcdefg12345"), 599 Message: &Message{ 600 Text: Ptr("This path depends on a user-provided value."), 601 }, 602 Location: &Location{ 603 Path: Ptr("spec-main/api-session-spec.ts"), 604 StartLine: Ptr(917), 605 EndLine: Ptr(917), 606 StartColumn: Ptr(7), 607 EndColumn: Ptr(18), 608 }, 609 Classifications: []string{"test"}, 610 }, 611 }, 612 { 613 RuleID: Ptr("js/useless-expression"), 614 RuleSeverity: Ptr("warning"), 615 RuleDescription: Ptr("Expression has no effect"), 616 Tool: &Tool{Name: Ptr("CodeQL"), GUID: Ptr("guid"), Version: Ptr("1.4.0")}, 617 Rule: &Rule{ 618 ID: Ptr("js/useless-expression"), 619 Severity: Ptr("warning"), 620 Description: Ptr("Expression has no effect"), 621 Name: Ptr("js/useless-expression"), 622 FullDescription: Ptr("Expression has no effect"), 623 Help: Ptr("Expression has no effect"), 624 }, 625 CreatedAt: &date, 626 State: Ptr("open"), 627 ClosedBy: nil, 628 ClosedAt: nil, 629 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 630 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/88"), 631 MostRecentInstance: &MostRecentInstance{ 632 Ref: Ptr("refs/heads/main"), 633 State: Ptr("open"), 634 CommitSHA: Ptr("abcdefg12345"), 635 Message: &Message{ 636 Text: Ptr("This path depends on a user-provided value."), 637 }, 638 Location: &Location{ 639 Path: Ptr("spec-main/api-session-spec.ts"), 640 StartLine: Ptr(917), 641 EndLine: Ptr(917), 642 StartColumn: Ptr(7), 643 EndColumn: Ptr(18), 644 }, 645 Classifications: []string{"test"}, 646 }, 647 }, 648 } 649 if !cmp.Equal(alerts, want) { 650 t.Errorf("CodeScanning.ListAlertsForRepo returned %+v, want %+v", alerts, want) 651 } 652 653 const methodName = "ListAlertsForRepo" 654 testBadOptions(t, methodName, func() (err error) { 655 _, _, err = client.CodeScanning.ListAlertsForRepo(ctx, "\n", "\n", opts) 656 return err 657 }) 658 659 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 660 got, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts) 661 if got != nil { 662 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 663 } 664 return resp, err 665 }) 666 } 667 668 func TestCodeScanningService_UpdateAlert(t *testing.T) { 669 t.Parallel() 670 client, mux, _ := setup(t) 671 672 mux.HandleFunc("/repos/o/r/code-scanning/alerts/88", func(w http.ResponseWriter, r *http.Request) { 673 testMethod(t, r, "PATCH") 674 fmt.Fprint(w, `{"rule_id":"js/useless-expression", 675 "rule_severity":"warning", 676 "rule_description":"Expression has no effect", 677 "tool": { 678 "name": "CodeQL", 679 "guid": null, 680 "version": "1.4.0" 681 }, 682 "rule": { 683 "id": "useless expression", 684 "severity": "warning", 685 "description": "Expression has no effect", 686 "name": "useless expression", 687 "full_description": "Expression has no effect", 688 "help": "Expression has no effect" 689 }, 690 "most_recent_instance": { 691 "ref": "refs/heads/main", 692 "state": "dismissed", 693 "commit_sha": "abcdefg12345", 694 "message": { 695 "text": "This path depends on a user-provided value." 696 }, 697 "location": { 698 "path": "spec-main/api-session-spec.ts", 699 "start_line": 917, 700 "end_line": 917, 701 "start_column": 7, 702 "end_column": 18 703 }, 704 "classifications": [ 705 "test" 706 ] 707 }, 708 "created_at":"2019-01-02T15:04:05Z", 709 "state":"dismissed", 710 "dismissed_reason": "false positive", 711 "dismissed_comment": "This alert is not actually correct as sanitizer is used", 712 "closed_by":null, 713 "closed_at":null, 714 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 715 "html_url":"https://github.com/o/r/security/code-scanning/88"}`) 716 }) 717 718 ctx := context.Background() 719 dismissedComment := Ptr("This alert is not actually correct as sanitizer is used") 720 dismissedReason := Ptr("false positive") 721 state := Ptr("dismissed") 722 stateInfo := &CodeScanningAlertState{State: *state, DismissedReason: dismissedReason, DismissedComment: dismissedComment} 723 alert, _, err := client.CodeScanning.UpdateAlert(ctx, "o", "r", 88, stateInfo) 724 if err != nil { 725 t.Errorf("CodeScanning.UpdateAlert returned error: %v", err) 726 } 727 728 date := Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)} 729 want := &Alert{ 730 RuleID: Ptr("js/useless-expression"), 731 RuleSeverity: Ptr("warning"), 732 RuleDescription: Ptr("Expression has no effect"), 733 Tool: &Tool{Name: Ptr("CodeQL"), GUID: nil, Version: Ptr("1.4.0")}, 734 Rule: &Rule{ 735 ID: Ptr("useless expression"), 736 Severity: Ptr("warning"), 737 Description: Ptr("Expression has no effect"), 738 Name: Ptr("useless expression"), 739 FullDescription: Ptr("Expression has no effect"), 740 Help: Ptr("Expression has no effect"), 741 }, 742 CreatedAt: &date, 743 State: state, 744 DismissedReason: dismissedReason, 745 DismissedComment: dismissedComment, 746 ClosedBy: nil, 747 ClosedAt: nil, 748 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 749 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/88"), 750 MostRecentInstance: &MostRecentInstance{ 751 Ref: Ptr("refs/heads/main"), 752 State: Ptr("dismissed"), 753 CommitSHA: Ptr("abcdefg12345"), 754 Message: &Message{ 755 Text: Ptr("This path depends on a user-provided value."), 756 }, 757 Location: &Location{ 758 Path: Ptr("spec-main/api-session-spec.ts"), 759 StartLine: Ptr(917), 760 EndLine: Ptr(917), 761 StartColumn: Ptr(7), 762 EndColumn: Ptr(18), 763 }, 764 Classifications: []string{"test"}, 765 }, 766 } 767 if !cmp.Equal(alert, want) { 768 t.Errorf("CodeScanning.UpdateAlert returned %+v, want %+v", alert, want) 769 } 770 771 const methodName = "UpdateAlert" 772 testBadOptions(t, methodName, func() (err error) { 773 _, _, err = client.CodeScanning.UpdateAlert(ctx, "\n", "\n", -88, stateInfo) 774 return err 775 }) 776 777 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 778 got, resp, err := client.CodeScanning.UpdateAlert(ctx, "o", "r", 88, stateInfo) 779 if got != nil { 780 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 781 } 782 return resp, err 783 }) 784 } 785 786 func TestCodeScanningService_ListAlertInstances(t *testing.T) { 787 t.Parallel() 788 client, mux, _ := setup(t) 789 790 mux.HandleFunc("/repos/o/r/code-scanning/alerts/88/instances", func(w http.ResponseWriter, r *http.Request) { 791 testMethod(t, r, "GET") 792 fmt.Fprint(w, `[ 793 { 794 "ref": "refs/heads/main", 795 "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", 796 "environment": "", 797 "category": ".github/workflows/codeql-analysis.yml:analyze", 798 "state": "open", 799 "fixed_at": null, 800 "commit_sha": "abcdefg12345", 801 "message": { 802 "text": "This path depends on a user-provided value." 803 }, 804 "location": { 805 "path": "spec-main/api-session-spec.ts", 806 "start_line": 917, 807 "end_line": 917, 808 "start_column": 7, 809 "end_column": 18 810 }, 811 "classifications": [ 812 "test" 813 ] 814 } 815 ]`) 816 }) 817 818 opts := &AlertInstancesListOptions{Ref: "heads/main", ListOptions: ListOptions{Page: 1}} 819 ctx := context.Background() 820 instances, _, err := client.CodeScanning.ListAlertInstances(ctx, "o", "r", 88, opts) 821 if err != nil { 822 t.Errorf("CodeScanning.ListAlertInstances returned error: %v", err) 823 } 824 825 want := []*MostRecentInstance{ 826 { 827 Ref: Ptr("refs/heads/main"), 828 AnalysisKey: Ptr(".github/workflows/codeql-analysis.yml:analyze"), 829 Category: Ptr(".github/workflows/codeql-analysis.yml:analyze"), 830 Environment: Ptr(""), 831 State: Ptr("open"), 832 CommitSHA: Ptr("abcdefg12345"), 833 Message: &Message{ 834 Text: Ptr("This path depends on a user-provided value."), 835 }, 836 Location: &Location{ 837 Path: Ptr("spec-main/api-session-spec.ts"), 838 StartLine: Ptr(917), 839 EndLine: Ptr(917), 840 StartColumn: Ptr(7), 841 EndColumn: Ptr(18), 842 }, 843 Classifications: []string{"test"}, 844 }, 845 } 846 if !cmp.Equal(instances, want) { 847 t.Errorf("CodeScanning.ListAlertInstances returned %+v, want %+v", instances, want) 848 } 849 850 const methodName = "ListAlertInstances" 851 testBadOptions(t, methodName, func() (err error) { 852 _, _, err = client.CodeScanning.ListAlertInstances(ctx, "\n", "\n", -1, opts) 853 return err 854 }) 855 856 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 857 got, resp, err := client.CodeScanning.ListAlertInstances(ctx, "o", "r", 88, opts) 858 if got != nil { 859 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 860 } 861 return resp, err 862 }) 863 } 864 865 func TestCodeScanningService_GetAlert(t *testing.T) { 866 t.Parallel() 867 client, mux, _ := setup(t) 868 869 mux.HandleFunc("/repos/o/r/code-scanning/alerts/88", func(w http.ResponseWriter, r *http.Request) { 870 testMethod(t, r, "GET") 871 fmt.Fprint(w, `{ 872 "rule_id":"js/useless-expression", 873 "rule_severity":"warning", 874 "rule_description":"Expression has no effect", 875 "tool": { 876 "name": "CodeQL", 877 "guid": null, 878 "version": "1.4.0" 879 }, 880 "rule": { 881 "id": "useless expression", 882 "severity": "warning", 883 "description": "Expression has no effect", 884 "name": "useless expression", 885 "full_description": "Expression has no effect", 886 "help": "Expression has no effect" 887 }, 888 "most_recent_instance": { 889 "ref": "refs/heads/main", 890 "state": "open", 891 "commit_sha": "abcdefg12345", 892 "message": { 893 "text": "This path depends on a user-provided value." 894 }, 895 "location": { 896 "path": "spec-main/api-session-spec.ts", 897 "start_line": 917, 898 "end_line": 917, 899 "start_column": 7, 900 "end_column": 18 901 }, 902 "classifications": [ 903 "test" 904 ] 905 }, 906 "created_at":"2019-01-02T15:04:05Z", 907 "state":"open", 908 "closed_by":null, 909 "closed_at":null, 910 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 911 "html_url":"https://github.com/o/r/security/code-scanning/88" 912 }`) 913 }) 914 915 ctx := context.Background() 916 alert, _, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88) 917 if err != nil { 918 t.Errorf("CodeScanning.GetAlert returned error: %v", err) 919 } 920 921 date := Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)} 922 want := &Alert{ 923 RuleID: Ptr("js/useless-expression"), 924 RuleSeverity: Ptr("warning"), 925 RuleDescription: Ptr("Expression has no effect"), 926 Tool: &Tool{Name: Ptr("CodeQL"), GUID: nil, Version: Ptr("1.4.0")}, 927 Rule: &Rule{ 928 ID: Ptr("useless expression"), 929 Severity: Ptr("warning"), 930 Description: Ptr("Expression has no effect"), 931 Name: Ptr("useless expression"), 932 FullDescription: Ptr("Expression has no effect"), 933 Help: Ptr("Expression has no effect"), 934 }, 935 CreatedAt: &date, 936 State: Ptr("open"), 937 ClosedBy: nil, 938 ClosedAt: nil, 939 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 940 HTMLURL: Ptr("https://github.com/o/r/security/code-scanning/88"), 941 MostRecentInstance: &MostRecentInstance{ 942 Ref: Ptr("refs/heads/main"), 943 State: Ptr("open"), 944 CommitSHA: Ptr("abcdefg12345"), 945 Message: &Message{ 946 Text: Ptr("This path depends on a user-provided value."), 947 }, 948 Location: &Location{ 949 Path: Ptr("spec-main/api-session-spec.ts"), 950 StartLine: Ptr(917), 951 EndLine: Ptr(917), 952 StartColumn: Ptr(7), 953 EndColumn: Ptr(18), 954 }, 955 Classifications: []string{"test"}, 956 }, 957 } 958 if !cmp.Equal(alert, want) { 959 t.Errorf("CodeScanning.GetAlert returned %+v, want %+v", alert, want) 960 } 961 962 const methodName = "GetAlert" 963 testBadOptions(t, methodName, func() (err error) { 964 _, _, err = client.CodeScanning.GetAlert(ctx, "\n", "\n", -88) 965 return err 966 }) 967 968 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 969 got, resp, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88) 970 if got != nil { 971 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 972 } 973 return resp, err 974 }) 975 } 976 977 func TestAlert_Marshal(t *testing.T) { 978 t.Parallel() 979 testJSONMarshal(t, &Alert{}, "{}") 980 981 u := &Alert{ 982 RuleID: Ptr("rid"), 983 RuleSeverity: Ptr("rs"), 984 RuleDescription: Ptr("rd"), 985 Tool: &Tool{ 986 Name: Ptr("n"), 987 GUID: Ptr("g"), 988 Version: Ptr("v"), 989 }, 990 CreatedAt: &Timestamp{referenceTime}, 991 State: Ptr("fixed"), 992 ClosedBy: &User{ 993 Login: Ptr("l"), 994 ID: Ptr(int64(1)), 995 NodeID: Ptr("n"), 996 URL: Ptr("u"), 997 ReposURL: Ptr("r"), 998 EventsURL: Ptr("e"), 999 AvatarURL: Ptr("a"), 1000 }, 1001 ClosedAt: &Timestamp{referenceTime}, 1002 URL: Ptr("url"), 1003 HTMLURL: Ptr("hurl"), 1004 } 1005 1006 want := `{ 1007 "rule_id": "rid", 1008 "rule_severity": "rs", 1009 "rule_description": "rd", 1010 "tool": { 1011 "name": "n", 1012 "guid": "g", 1013 "version": "v" 1014 }, 1015 "created_at": ` + referenceTimeStr + `, 1016 "state": "fixed", 1017 "closed_by": { 1018 "login": "l", 1019 "id": 1, 1020 "node_id": "n", 1021 "avatar_url": "a", 1022 "url": "u", 1023 "events_url": "e", 1024 "repos_url": "r" 1025 }, 1026 "closed_at": ` + referenceTimeStr + `, 1027 "url": "url", 1028 "html_url": "hurl" 1029 }` 1030 1031 testJSONMarshal(t, u, want) 1032 } 1033 1034 func TestLocation_Marshal(t *testing.T) { 1035 t.Parallel() 1036 testJSONMarshal(t, &Location{}, "{}") 1037 1038 u := &Location{ 1039 Path: Ptr("path"), 1040 StartLine: Ptr(1), 1041 EndLine: Ptr(2), 1042 StartColumn: Ptr(3), 1043 EndColumn: Ptr(4), 1044 } 1045 1046 want := `{ 1047 "path": "path", 1048 "start_line": 1, 1049 "end_line": 2, 1050 "start_column": 3, 1051 "end_column": 4 1052 }` 1053 1054 testJSONMarshal(t, u, want) 1055 } 1056 1057 func TestRule_Marshal(t *testing.T) { 1058 t.Parallel() 1059 testJSONMarshal(t, &Rule{}, "{}") 1060 1061 u := &Rule{ 1062 ID: Ptr("1"), 1063 Severity: Ptr("3"), 1064 Description: Ptr("description"), 1065 Name: Ptr("first"), 1066 SecuritySeverityLevel: Ptr("2"), 1067 FullDescription: Ptr("summary"), 1068 Tags: []string{"tag1", "tag2"}, 1069 Help: Ptr("Help Text"), 1070 } 1071 1072 want := `{ 1073 "id": "1", 1074 "severity": "3", 1075 "description": "description", 1076 "name": "first", 1077 "security_severity_level": "2", 1078 "full_description": "summary", 1079 "tags": ["tag1", "tag2"], 1080 "help": "Help Text" 1081 }` 1082 1083 testJSONMarshal(t, u, want) 1084 } 1085 1086 func TestTool_Marshal(t *testing.T) { 1087 t.Parallel() 1088 testJSONMarshal(t, &Tool{}, "{}") 1089 1090 u := &Tool{ 1091 Name: Ptr("name"), 1092 GUID: Ptr("guid"), 1093 Version: Ptr("ver"), 1094 } 1095 1096 want := `{ 1097 "name": "name", 1098 "guid": "guid", 1099 "version": "ver" 1100 }` 1101 1102 testJSONMarshal(t, u, want) 1103 } 1104 1105 func TestMessage_Marshal(t *testing.T) { 1106 t.Parallel() 1107 testJSONMarshal(t, &Message{}, "{}") 1108 1109 u := &Message{ 1110 Text: Ptr("text"), 1111 } 1112 1113 want := `{ 1114 "text": "text" 1115 }` 1116 1117 testJSONMarshal(t, u, want) 1118 } 1119 1120 func TestCodeScanningService_ListAnalysesForRepo(t *testing.T) { 1121 t.Parallel() 1122 client, mux, _ := setup(t) 1123 1124 mux.HandleFunc("/repos/o/r/code-scanning/analyses", func(w http.ResponseWriter, r *http.Request) { 1125 testMethod(t, r, "GET") 1126 testFormValues(t, r, values{"sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", "ref": "heads/master"}) 1127 fmt.Fprint(w, `[ 1128 { 1129 "ref": "refs/heads/main", 1130 "commit_sha": "d99612c3e1f2970085cfbaeadf8f010ef69bad83", 1131 "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", 1132 "environment": "{\"language\":\"python\"}", 1133 "error": "", 1134 "category": ".github/workflows/codeql-analysis.yml:analyze/language:python", 1135 "created_at": "2020-08-27T15:05:21Z", 1136 "results_count": 17, 1137 "rules_count": 49, 1138 "id": 201, 1139 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/201", 1140 "sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", 1141 "tool": { 1142 "name": "CodeQL", 1143 "guid": null, 1144 "version": "2.4.0" 1145 }, 1146 "deletable": true, 1147 "warning": "" 1148 }, 1149 { 1150 "ref": "refs/heads/my-branch", 1151 "commit_sha": "c8cff6510d4d084fb1b4aa13b64b97ca12b07321", 1152 "analysis_key": ".github/workflows/shiftleft.yml:build", 1153 "environment": "{}", 1154 "error": "", 1155 "category": ".github/workflows/shiftleft.yml:build/", 1156 "created_at": "2020-08-27T15:05:21Z", 1157 "results_count": 17, 1158 "rules_count": 32, 1159 "id": 200, 1160 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/200", 1161 "sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", 1162 "tool": { 1163 "name": "Python Security ScanningAnalysis", 1164 "guid": null, 1165 "version": "1.2.0" 1166 }, 1167 "deletable": true, 1168 "warning": "" 1169 } 1170 ]`) 1171 }) 1172 1173 opts := &AnalysesListOptions{SarifID: Ptr("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), Ref: Ptr("heads/master")} 1174 ctx := context.Background() 1175 analyses, _, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts) 1176 if err != nil { 1177 t.Errorf("CodeScanning.ListAnalysesForRepo returned error: %v", err) 1178 } 1179 1180 date := &Timestamp{time.Date(2020, time.August, 27, 15, 05, 21, 0, time.UTC)} 1181 want := []*ScanningAnalysis{ 1182 { 1183 ID: Ptr(int64(201)), 1184 Ref: Ptr("refs/heads/main"), 1185 CommitSHA: Ptr("d99612c3e1f2970085cfbaeadf8f010ef69bad83"), 1186 AnalysisKey: Ptr(".github/workflows/codeql-analysis.yml:analyze"), 1187 Environment: Ptr("{\"language\":\"python\"}"), 1188 Error: Ptr(""), 1189 Category: Ptr(".github/workflows/codeql-analysis.yml:analyze/language:python"), 1190 CreatedAt: date, 1191 ResultsCount: Ptr(17), 1192 RulesCount: Ptr(49), 1193 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/analyses/201"), 1194 SarifID: Ptr("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), 1195 Tool: &Tool{ 1196 Name: Ptr("CodeQL"), 1197 GUID: nil, 1198 Version: Ptr("2.4.0"), 1199 }, 1200 Deletable: Ptr(true), 1201 Warning: Ptr(""), 1202 }, 1203 { 1204 ID: Ptr(int64(200)), 1205 Ref: Ptr("refs/heads/my-branch"), 1206 CommitSHA: Ptr("c8cff6510d4d084fb1b4aa13b64b97ca12b07321"), 1207 AnalysisKey: Ptr(".github/workflows/shiftleft.yml:build"), 1208 Environment: Ptr("{}"), 1209 Error: Ptr(""), 1210 Category: Ptr(".github/workflows/shiftleft.yml:build/"), 1211 CreatedAt: date, 1212 ResultsCount: Ptr(17), 1213 RulesCount: Ptr(32), 1214 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/analyses/200"), 1215 SarifID: Ptr("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), 1216 Tool: &Tool{ 1217 Name: Ptr("Python Security ScanningAnalysis"), 1218 GUID: nil, 1219 Version: Ptr("1.2.0"), 1220 }, 1221 Deletable: Ptr(true), 1222 Warning: Ptr(""), 1223 }, 1224 } 1225 if !cmp.Equal(analyses, want) { 1226 t.Errorf("CodeScanning.ListAnalysesForRepo returned %+v, want %+v", analyses, want) 1227 } 1228 1229 const methodName = "ListAnalysesForRepo" 1230 testBadOptions(t, methodName, func() (err error) { 1231 _, _, err = client.CodeScanning.ListAnalysesForRepo(ctx, "\n", "\n", opts) 1232 return err 1233 }) 1234 1235 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1236 got, resp, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts) 1237 if got != nil { 1238 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1239 } 1240 return resp, err 1241 }) 1242 } 1243 1244 func TestCodeScanningService_GetAnalysis(t *testing.T) { 1245 t.Parallel() 1246 client, mux, _ := setup(t) 1247 1248 mux.HandleFunc("/repos/o/r/code-scanning/analyses/3602840", func(w http.ResponseWriter, r *http.Request) { 1249 testMethod(t, r, "GET") 1250 fmt.Fprint(w, `{ 1251 "ref": "refs/heads/main", 1252 "commit_sha": "c18c69115654ff0166991962832dc2bd7756e655", 1253 "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", 1254 "environment": "{\"language\":\"javascript\"}", 1255 "error": "", 1256 "category": ".github/workflows/codeql-analysis.yml:analyze/language:javascript", 1257 "created_at": "2021-01-13T11:55:49Z", 1258 "results_count": 3, 1259 "rules_count": 67, 1260 "id": 3602840, 1261 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/201", 1262 "sarif_id": "47177e22-5596-11eb-80a1-c1e54ef945c6", 1263 "tool": { 1264 "name": "CodeQL", 1265 "guid": null, 1266 "version": "2.4.0" 1267 }, 1268 "deletable": true, 1269 "warning": "" 1270 }`) 1271 }) 1272 1273 ctx := context.Background() 1274 analysis, _, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840) 1275 if err != nil { 1276 t.Errorf("CodeScanning.GetAnalysis returned error: %v", err) 1277 } 1278 1279 date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} 1280 want := &ScanningAnalysis{ 1281 ID: Ptr(int64(3602840)), 1282 Ref: Ptr("refs/heads/main"), 1283 CommitSHA: Ptr("c18c69115654ff0166991962832dc2bd7756e655"), 1284 AnalysisKey: Ptr(".github/workflows/codeql-analysis.yml:analyze"), 1285 Environment: Ptr("{\"language\":\"javascript\"}"), 1286 Error: Ptr(""), 1287 Category: Ptr(".github/workflows/codeql-analysis.yml:analyze/language:javascript"), 1288 CreatedAt: date, 1289 ResultsCount: Ptr(3), 1290 RulesCount: Ptr(67), 1291 URL: Ptr("https://api.github.com/repos/o/r/code-scanning/analyses/201"), 1292 SarifID: Ptr("47177e22-5596-11eb-80a1-c1e54ef945c6"), 1293 Tool: &Tool{ 1294 Name: Ptr("CodeQL"), 1295 GUID: nil, 1296 Version: Ptr("2.4.0"), 1297 }, 1298 Deletable: Ptr(true), 1299 Warning: Ptr(""), 1300 } 1301 if !cmp.Equal(analysis, want) { 1302 t.Errorf("CodeScanning.GetAnalysis returned %+v, want %+v", analysis, want) 1303 } 1304 1305 const methodName = "GetAnalysis" 1306 testBadOptions(t, methodName, func() (err error) { 1307 _, _, err = client.CodeScanning.GetAnalysis(ctx, "\n", "\n", -123) 1308 return err 1309 }) 1310 1311 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1312 got, resp, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840) 1313 if got != nil { 1314 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1315 } 1316 return resp, err 1317 }) 1318 } 1319 1320 func TestCodeScanningService_DeleteAnalysis(t *testing.T) { 1321 t.Parallel() 1322 client, mux, _ := setup(t) 1323 1324 mux.HandleFunc("/repos/o/r/code-scanning/analyses/40", func(w http.ResponseWriter, r *http.Request) { 1325 testMethod(t, r, "DELETE") 1326 fmt.Fprint(w, `{ 1327 "next_analysis_url": "a", 1328 "confirm_delete_url": "b" 1329 }`) 1330 }) 1331 1332 ctx := context.Background() 1333 analysis, _, err := client.CodeScanning.DeleteAnalysis(ctx, "o", "r", 40) 1334 if err != nil { 1335 t.Errorf("CodeScanning.DeleteAnalysis returned error: %v", err) 1336 } 1337 1338 want := &DeleteAnalysis{ 1339 NextAnalysisURL: Ptr("a"), 1340 ConfirmDeleteURL: Ptr("b"), 1341 } 1342 if !cmp.Equal(analysis, want) { 1343 t.Errorf("CodeScanning.DeleteAnalysis returned %+v, want %+v", analysis, want) 1344 } 1345 1346 const methodName = "DeleteAnalysis" 1347 testBadOptions(t, methodName, func() (err error) { 1348 _, _, err = client.CodeScanning.DeleteAnalysis(ctx, "\n", "\n", -123) 1349 return err 1350 }) 1351 1352 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1353 got, resp, err := client.CodeScanning.DeleteAnalysis(ctx, "o", "r", 40) 1354 if got != nil { 1355 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1356 } 1357 return resp, err 1358 }) 1359 } 1360 1361 func TestCodeScanningService_ListCodeQLDatabases(t *testing.T) { 1362 t.Parallel() 1363 client, mux, _ := setup(t) 1364 1365 mux.HandleFunc("/repos/o/r/code-scanning/codeql/databases", func(w http.ResponseWriter, r *http.Request) { 1366 testMethod(t, r, "GET") 1367 fmt.Fprint(w, `[ 1368 { 1369 "id": 1, 1370 "name": "name", 1371 "language": "language", 1372 "uploader": { 1373 "login": "a", 1374 "id": 1, 1375 "node_id": "b", 1376 "avatar_url": "c", 1377 "gravatar_id": "d", 1378 "url": "e", 1379 "html_url": "f", 1380 "followers_url": "g", 1381 "following_url": "h", 1382 "gists_url": "i", 1383 "starred_url": "j", 1384 "subscriptions_url": "k", 1385 "organizations_url": "l", 1386 "repos_url": "m", 1387 "events_url": "n", 1388 "received_events_url": "o", 1389 "type": "p", 1390 "site_admin": false 1391 }, 1392 "content_type": "r", 1393 "size": 1024, 1394 "created_at": "2021-01-13T11:55:49Z", 1395 "updated_at": "2021-01-13T11:55:49Z", 1396 "url": "s" 1397 } 1398 ]`) 1399 }) 1400 1401 ctx := context.Background() 1402 databases, _, err := client.CodeScanning.ListCodeQLDatabases(ctx, "o", "r") 1403 if err != nil { 1404 t.Errorf("CodeScanning.ListCodeQLDatabases returned error: %v", err) 1405 } 1406 1407 date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} 1408 want := []*CodeQLDatabase{ 1409 { 1410 ID: Ptr(int64(1)), 1411 Name: Ptr("name"), 1412 Language: Ptr("language"), 1413 Uploader: &User{ 1414 Login: Ptr("a"), 1415 ID: Ptr(int64(1)), 1416 NodeID: Ptr("b"), 1417 AvatarURL: Ptr("c"), 1418 GravatarID: Ptr("d"), 1419 URL: Ptr("e"), 1420 HTMLURL: Ptr("f"), 1421 FollowersURL: Ptr("g"), 1422 FollowingURL: Ptr("h"), 1423 GistsURL: Ptr("i"), 1424 StarredURL: Ptr("j"), 1425 SubscriptionsURL: Ptr("k"), 1426 OrganizationsURL: Ptr("l"), 1427 ReposURL: Ptr("m"), 1428 EventsURL: Ptr("n"), 1429 ReceivedEventsURL: Ptr("o"), 1430 Type: Ptr("p"), 1431 SiteAdmin: Ptr(false), 1432 }, 1433 ContentType: Ptr("r"), 1434 Size: Ptr(int64(1024)), 1435 CreatedAt: date, 1436 UpdatedAt: date, 1437 URL: Ptr("s"), 1438 }, 1439 } 1440 1441 if !cmp.Equal(databases, want) { 1442 t.Errorf("CodeScanning.ListCodeQLDatabases returned %+v, want %+v", databases, want) 1443 } 1444 1445 const methodName = "ListCodeQLDatabases" 1446 testBadOptions(t, methodName, func() (err error) { 1447 _, _, err = client.CodeScanning.ListCodeQLDatabases(ctx, "\n", "\n") 1448 return err 1449 }) 1450 1451 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1452 got, resp, err := client.CodeScanning.ListCodeQLDatabases(ctx, "o", "r") 1453 if got != nil { 1454 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1455 } 1456 return resp, err 1457 }) 1458 } 1459 1460 func TestCodeScanningService_GetCodeQLDatabase(t *testing.T) { 1461 t.Parallel() 1462 client, mux, _ := setup(t) 1463 1464 mux.HandleFunc("/repos/o/r/code-scanning/codeql/databases/lang", func(w http.ResponseWriter, r *http.Request) { 1465 testMethod(t, r, "GET") 1466 fmt.Fprint(w, `{ 1467 "id": 1, 1468 "name": "name", 1469 "language": "language", 1470 "uploader": { 1471 "login": "a", 1472 "id": 1, 1473 "node_id": "b", 1474 "avatar_url": "c", 1475 "gravatar_id": "d", 1476 "url": "e", 1477 "html_url": "f", 1478 "followers_url": "g", 1479 "following_url": "h", 1480 "gists_url": "i", 1481 "starred_url": "j", 1482 "subscriptions_url": "k", 1483 "organizations_url": "l", 1484 "repos_url": "m", 1485 "events_url": "n", 1486 "received_events_url": "o", 1487 "type": "p", 1488 "site_admin": false 1489 }, 1490 "content_type": "r", 1491 "size": 1024, 1492 "created_at": "2021-01-13T11:55:49Z", 1493 "updated_at": "2021-01-13T11:55:49Z", 1494 "url": "s" 1495 }`) 1496 }) 1497 1498 ctx := context.Background() 1499 database, _, err := client.CodeScanning.GetCodeQLDatabase(ctx, "o", "r", "lang") 1500 if err != nil { 1501 t.Errorf("CodeScanning.GetCodeQLDatabase returned error: %v", err) 1502 } 1503 1504 date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} 1505 want := &CodeQLDatabase{ 1506 ID: Ptr(int64(1)), 1507 Name: Ptr("name"), 1508 Language: Ptr("language"), 1509 Uploader: &User{ 1510 Login: Ptr("a"), 1511 ID: Ptr(int64(1)), 1512 NodeID: Ptr("b"), 1513 AvatarURL: Ptr("c"), 1514 GravatarID: Ptr("d"), 1515 URL: Ptr("e"), 1516 HTMLURL: Ptr("f"), 1517 FollowersURL: Ptr("g"), 1518 FollowingURL: Ptr("h"), 1519 GistsURL: Ptr("i"), 1520 StarredURL: Ptr("j"), 1521 SubscriptionsURL: Ptr("k"), 1522 OrganizationsURL: Ptr("l"), 1523 ReposURL: Ptr("m"), 1524 EventsURL: Ptr("n"), 1525 ReceivedEventsURL: Ptr("o"), 1526 Type: Ptr("p"), 1527 SiteAdmin: Ptr(false), 1528 }, 1529 ContentType: Ptr("r"), 1530 Size: Ptr(int64(1024)), 1531 CreatedAt: date, 1532 UpdatedAt: date, 1533 URL: Ptr("s"), 1534 } 1535 1536 if !cmp.Equal(database, want) { 1537 t.Errorf("CodeScanning.GetCodeQLDatabase returned %+v, want %+v", database, want) 1538 } 1539 1540 const methodName = "GetCodeQLDatabase" 1541 testBadOptions(t, methodName, func() (err error) { 1542 _, _, err = client.CodeScanning.GetCodeQLDatabase(ctx, "\n", "\n", "\n") 1543 return err 1544 }) 1545 1546 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1547 got, resp, err := client.CodeScanning.GetCodeQLDatabase(ctx, "o", "r", "lang") 1548 if got != nil { 1549 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1550 } 1551 return resp, err 1552 }) 1553 } 1554 1555 func TestCodeScanningService_GetDefaultSetupConfiguration(t *testing.T) { 1556 t.Parallel() 1557 client, mux, _ := setup(t) 1558 1559 mux.HandleFunc("/repos/o/r/code-scanning/default-setup", func(w http.ResponseWriter, r *http.Request) { 1560 testMethod(t, r, "GET") 1561 _, err := fmt.Fprint(w, `{ 1562 "state": "configured", 1563 "languages": [ 1564 "javascript", 1565 "javascript-typescript", 1566 "typescript" 1567 ], 1568 "query_suite": "default", 1569 "updated_at": "2006-01-02T15:04:05Z" 1570 }`) 1571 if err != nil { 1572 t.Fatal(err) 1573 } 1574 }) 1575 1576 ctx := context.Background() 1577 cfg, _, err := client.CodeScanning.GetDefaultSetupConfiguration(ctx, "o", "r") 1578 if err != nil { 1579 t.Errorf("CodeScanning.GetDefaultSetupConfiguration returned error: %v", err) 1580 } 1581 1582 date := &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)} 1583 want := &DefaultSetupConfiguration{ 1584 State: Ptr("configured"), 1585 Languages: []string{"javascript", "javascript-typescript", "typescript"}, 1586 QuerySuite: Ptr("default"), 1587 UpdatedAt: date, 1588 } 1589 if !cmp.Equal(cfg, want) { 1590 t.Errorf("CodeScanning.GetDefaultSetupConfiguration returned %+v, want %+v", cfg, want) 1591 } 1592 1593 const methodName = "GetDefaultSetupConfiguration" 1594 testBadOptions(t, methodName, func() (err error) { 1595 _, _, err = client.CodeScanning.GetDefaultSetupConfiguration(ctx, "\n", "\n") 1596 return err 1597 }) 1598 1599 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1600 got, resp, err := client.CodeScanning.GetDefaultSetupConfiguration(ctx, "o", "r") 1601 if got != nil { 1602 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1603 } 1604 return resp, err 1605 }) 1606 } 1607 1608 func TestCodeScanningService_UpdateDefaultSetupConfiguration(t *testing.T) { 1609 t.Parallel() 1610 client, mux, _ := setup(t) 1611 1612 mux.HandleFunc("/repos/o/r/code-scanning/default-setup", func(w http.ResponseWriter, r *http.Request) { 1613 testMethod(t, r, "PATCH") 1614 _, err := fmt.Fprint(w, `{ 1615 "run_id": 5301214200, 1616 "run_url": "https://api.github.com/repos/o/r/actions/runs/5301214200" 1617 }`) 1618 if err != nil { 1619 t.Fatal(err) 1620 } 1621 }) 1622 1623 ctx := context.Background() 1624 options := &UpdateDefaultSetupConfigurationOptions{ 1625 State: "configured", 1626 Languages: []string{"go"}, 1627 QuerySuite: Ptr("default"), 1628 } 1629 got, _, err := client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "o", "r", options) 1630 if err != nil { 1631 t.Errorf("CodeScanning.UpdateDefaultSetupConfiguration returned error: %v", err) 1632 } 1633 1634 want := &UpdateDefaultSetupConfigurationResponse{ 1635 RunID: Ptr(int64(5301214200)), 1636 RunURL: Ptr("https://api.github.com/repos/o/r/actions/runs/5301214200"), 1637 } 1638 if !cmp.Equal(got, want) { 1639 t.Errorf("CodeScanning.UpdateDefaultSetupConfiguration returned %+v, want %+v", got, want) 1640 } 1641 1642 const methodName = "UpdateDefaultSetupConfiguration" 1643 testBadOptions(t, methodName, func() (err error) { 1644 _, _, err = client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "\n", "\n", nil) 1645 return err 1646 }) 1647 1648 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1649 got, resp, err := client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "o", "r", nil) 1650 if got != nil { 1651 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1652 } 1653 return resp, err 1654 }) 1655 }