github.com/google/go-github/v42@v42.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 // Test: nil Alert ID == 0 21 var a *Alert 22 id := a.ID() 23 var want int64 24 if id != want { 25 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 26 } 27 28 // Test: Valid HTMLURL 29 a = &Alert{ 30 HTMLURL: String("https://github.com/o/r/security/code-scanning/88"), 31 } 32 id = a.ID() 33 want = 88 34 if !cmp.Equal(id, want) { 35 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 36 } 37 38 // Test: HTMLURL is nil 39 a = &Alert{} 40 id = a.ID() 41 want = 0 42 if !cmp.Equal(id, want) { 43 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 44 } 45 46 // Test: ID can't be parsed as an int 47 a = &Alert{ 48 HTMLURL: String("https://github.com/o/r/security/code-scanning/bad88"), 49 } 50 id = a.ID() 51 want = 0 52 if !cmp.Equal(id, want) { 53 t.Errorf("Alert.ID error returned %+v, want %+v", id, want) 54 } 55 } 56 57 func TestCodeScanningService_UploadSarif(t *testing.T) { 58 client, mux, _, teardown := setup() 59 defer teardown() 60 61 mux.HandleFunc("/repos/o/r/code-scanning/sarifs", func(w http.ResponseWriter, r *http.Request) { 62 v := new(SarifAnalysis) 63 json.NewDecoder(r.Body).Decode(v) 64 testMethod(t, r, "POST") 65 want := &SarifAnalysis{CommitSHA: String("abc"), Ref: String("ref/head/main"), Sarif: String("abc"), CheckoutURI: String("uri"), StartedAt: &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, ToolName: String("codeql-cli")} 66 if !cmp.Equal(v, want) { 67 t.Errorf("Request body = %+v, want %+v", v, want) 68 } 69 70 fmt.Fprint(w, `{"commit_sha":"abc","ref":"ref/head/main","sarif":"abc"}`) 71 }) 72 73 ctx := context.Background() 74 sarifAnalysis := &SarifAnalysis{CommitSHA: String("abc"), Ref: String("ref/head/main"), Sarif: String("abc"), CheckoutURI: String("uri"), StartedAt: &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}, ToolName: String("codeql-cli")} 75 _, _, err := client.CodeScanning.UploadSarif(ctx, "o", "r", sarifAnalysis) 76 if err != nil { 77 t.Errorf("CodeScanning.UploadSarif returned error: %v", err) 78 } 79 80 const methodName = "UploadSarif" 81 testBadOptions(t, methodName, func() (err error) { 82 _, _, err = client.CodeScanning.UploadSarif(ctx, "\n", "\n", sarifAnalysis) 83 return err 84 }) 85 86 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 87 _, resp, err := client.CodeScanning.UploadSarif(ctx, "o", "r", sarifAnalysis) 88 return resp, err 89 }) 90 } 91 92 func TestCodeScanningService_ListAlertsForRepo(t *testing.T) { 93 client, mux, _, teardown := setup() 94 defer teardown() 95 96 mux.HandleFunc("/repos/o/r/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 97 testMethod(t, r, "GET") 98 testFormValues(t, r, values{"state": "open", "ref": "heads/master"}) 99 fmt.Fprint(w, `[{ 100 "rule_id":"js/trivial-conditional", 101 "rule_severity":"warning", 102 "rule_description":"Useless conditional", 103 "tool": { 104 "name": "CodeQL", 105 "guid": null, 106 "version": "1.4.0" 107 }, 108 "rule": { 109 "id": "js/trivial-conditional", 110 "severity": "warning", 111 "description": "Useless conditional", 112 "name": "js/trivial-conditional", 113 "full_description": "Expression has no effect", 114 "help": "Expression has no effect" 115 }, 116 "most_recent_instance": { 117 "ref": "refs/heads/main", 118 "state": "open", 119 "commit_sha": "abcdefg12345", 120 "message": { 121 "text": "This path depends on a user-provided value." 122 }, 123 "location": { 124 "path": "spec-main/api-session-spec.ts", 125 "start_line": 917, 126 "end_line": 917, 127 "start_column": 7, 128 "end_column": 18 129 }, 130 "classifications": [ 131 "test" 132 ] 133 }, 134 "created_at":"2020-05-06T12:00:00Z", 135 "state":"open", 136 "closed_by":null, 137 "closed_at":null, 138 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/25", 139 "html_url":"https://github.com/o/r/security/code-scanning/25" 140 }, 141 { 142 "rule_id":"js/useless-expression", 143 "rule_severity":"warning", 144 "rule_description":"Expression has no effect", 145 "tool": { 146 "name": "CodeQL", 147 "guid": null, 148 "version": "1.4.0" 149 }, 150 "rule": { 151 "id": "js/useless-expression", 152 "severity": "warning", 153 "description": "Expression has no effect", 154 "name": "js/useless-expression", 155 "full_description": "Expression has no effect", 156 "help": "Expression has no effect" 157 }, 158 "most_recent_instance": { 159 "ref": "refs/heads/main", 160 "state": "open", 161 "commit_sha": "abcdefg12345", 162 "message": { 163 "text": "This path depends on a user-provided value." 164 }, 165 "location": { 166 "path": "spec-main/api-session-spec.ts", 167 "start_line": 917, 168 "end_line": 917, 169 "start_column": 7, 170 "end_column": 18 171 }, 172 "classifications": [ 173 "test" 174 ] 175 }, 176 "created_at":"2020-05-06T12:00:00Z", 177 "state":"open", 178 "closed_by":null, 179 "closed_at":null, 180 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 181 "html_url":"https://github.com/o/r/security/code-scanning/88" 182 }]`) 183 }) 184 185 opts := &AlertListOptions{State: "open", Ref: "heads/master"} 186 ctx := context.Background() 187 alerts, _, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts) 188 if err != nil { 189 t.Errorf("CodeScanning.ListAlertsForRepo returned error: %v", err) 190 } 191 192 date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)} 193 want := []*Alert{ 194 { 195 RuleID: String("js/trivial-conditional"), 196 RuleSeverity: String("warning"), 197 RuleDescription: String("Useless conditional"), 198 Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, 199 Rule: &Rule{ 200 ID: String("js/trivial-conditional"), 201 Severity: String("warning"), 202 Description: String("Useless conditional"), 203 Name: String("js/trivial-conditional"), 204 FullDescription: String("Expression has no effect"), 205 Help: String("Expression has no effect"), 206 }, 207 CreatedAt: &date, 208 State: String("open"), 209 ClosedBy: nil, 210 ClosedAt: nil, 211 URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/25"), 212 HTMLURL: String("https://github.com/o/r/security/code-scanning/25"), 213 MostRecentInstance: &MostRecentInstance{ 214 Ref: String("refs/heads/main"), 215 State: String("open"), 216 CommitSHA: String("abcdefg12345"), 217 Message: &Message{ 218 Text: String("This path depends on a user-provided value."), 219 }, 220 Location: &Location{ 221 Path: String("spec-main/api-session-spec.ts"), 222 StartLine: Int(917), 223 EndLine: Int(917), 224 StartColumn: Int(7), 225 EndColumn: Int(18), 226 }, 227 Classifications: []string{"test"}, 228 }, 229 }, 230 { 231 RuleID: String("js/useless-expression"), 232 RuleSeverity: String("warning"), 233 RuleDescription: String("Expression has no effect"), 234 Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, 235 Rule: &Rule{ 236 ID: String("js/useless-expression"), 237 Severity: String("warning"), 238 Description: String("Expression has no effect"), 239 Name: String("js/useless-expression"), 240 FullDescription: String("Expression has no effect"), 241 Help: String("Expression has no effect"), 242 }, 243 CreatedAt: &date, 244 State: String("open"), 245 ClosedBy: nil, 246 ClosedAt: nil, 247 URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 248 HTMLURL: String("https://github.com/o/r/security/code-scanning/88"), 249 MostRecentInstance: &MostRecentInstance{ 250 Ref: String("refs/heads/main"), 251 State: String("open"), 252 CommitSHA: String("abcdefg12345"), 253 Message: &Message{ 254 Text: String("This path depends on a user-provided value."), 255 }, 256 Location: &Location{ 257 Path: String("spec-main/api-session-spec.ts"), 258 StartLine: Int(917), 259 EndLine: Int(917), 260 StartColumn: Int(7), 261 EndColumn: Int(18), 262 }, 263 Classifications: []string{"test"}, 264 }, 265 }, 266 } 267 if !cmp.Equal(alerts, want) { 268 t.Errorf("CodeScanning.ListAlertsForRepo returned %+v, want %+v", alerts, want) 269 } 270 271 const methodName = "ListAlertsForRepo" 272 testBadOptions(t, methodName, func() (err error) { 273 _, _, err = client.CodeScanning.ListAlertsForRepo(ctx, "\n", "\n", opts) 274 return err 275 }) 276 277 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 278 got, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts) 279 if got != nil { 280 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 281 } 282 return resp, err 283 }) 284 } 285 286 func TestCodeScanningService_GetAlert(t *testing.T) { 287 client, mux, _, teardown := setup() 288 defer teardown() 289 290 mux.HandleFunc("/repos/o/r/code-scanning/alerts/88", func(w http.ResponseWriter, r *http.Request) { 291 testMethod(t, r, "GET") 292 fmt.Fprint(w, `{"rule_id":"js/useless-expression", 293 "rule_severity":"warning", 294 "rule_description":"Expression has no effect", 295 "tool": { 296 "name": "CodeQL", 297 "guid": null, 298 "version": "1.4.0" 299 }, 300 "rule": { 301 "id": "useless expression", 302 "severity": "warning", 303 "description": "Expression has no effect", 304 "name": "useless expression", 305 "full_description": "Expression has no effect", 306 "help": "Expression has no effect" 307 }, 308 "most_recent_instance": { 309 "ref": "refs/heads/main", 310 "state": "open", 311 "commit_sha": "abcdefg12345", 312 "message": { 313 "text": "This path depends on a user-provided value." 314 }, 315 "location": { 316 "path": "spec-main/api-session-spec.ts", 317 "start_line": 917, 318 "end_line": 917, 319 "start_column": 7, 320 "end_column": 18 321 }, 322 "classifications": [ 323 "test" 324 ] 325 }, 326 "created_at":"2019-01-02T15:04:05Z", 327 "state":"open", 328 "closed_by":null, 329 "closed_at":null, 330 "url":"https://api.github.com/repos/o/r/code-scanning/alerts/88", 331 "html_url":"https://github.com/o/r/security/code-scanning/88"}`) 332 }) 333 334 ctx := context.Background() 335 alert, _, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88) 336 if err != nil { 337 t.Errorf("CodeScanning.GetAlert returned error: %v", err) 338 } 339 340 date := Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)} 341 want := &Alert{ 342 RuleID: String("js/useless-expression"), 343 RuleSeverity: String("warning"), 344 RuleDescription: String("Expression has no effect"), 345 Tool: &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")}, 346 Rule: &Rule{ 347 ID: String("useless expression"), 348 Severity: String("warning"), 349 Description: String("Expression has no effect"), 350 Name: String("useless expression"), 351 FullDescription: String("Expression has no effect"), 352 Help: String("Expression has no effect"), 353 }, 354 CreatedAt: &date, 355 State: String("open"), 356 ClosedBy: nil, 357 ClosedAt: nil, 358 URL: String("https://api.github.com/repos/o/r/code-scanning/alerts/88"), 359 HTMLURL: String("https://github.com/o/r/security/code-scanning/88"), 360 MostRecentInstance: &MostRecentInstance{ 361 Ref: String("refs/heads/main"), 362 State: String("open"), 363 CommitSHA: String("abcdefg12345"), 364 Message: &Message{ 365 Text: String("This path depends on a user-provided value."), 366 }, 367 Location: &Location{ 368 Path: String("spec-main/api-session-spec.ts"), 369 StartLine: Int(917), 370 EndLine: Int(917), 371 StartColumn: Int(7), 372 EndColumn: Int(18), 373 }, 374 Classifications: []string{"test"}, 375 }, 376 } 377 if !cmp.Equal(alert, want) { 378 t.Errorf("CodeScanning.GetAlert returned %+v, want %+v", alert, want) 379 } 380 381 const methodName = "GetAlert" 382 testBadOptions(t, methodName, func() (err error) { 383 _, _, err = client.CodeScanning.GetAlert(ctx, "\n", "\n", -88) 384 return err 385 }) 386 387 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 388 got, resp, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88) 389 if got != nil { 390 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 391 } 392 return resp, err 393 }) 394 } 395 396 func TestAlert_Marshal(t *testing.T) { 397 testJSONMarshal(t, &Alert{}, "{}") 398 399 u := &Alert{ 400 RuleID: String("rid"), 401 RuleSeverity: String("rs"), 402 RuleDescription: String("rd"), 403 Tool: &Tool{ 404 Name: String("n"), 405 GUID: String("g"), 406 Version: String("v"), 407 }, 408 CreatedAt: &Timestamp{referenceTime}, 409 State: String("fixed"), 410 ClosedBy: &User{ 411 Login: String("l"), 412 ID: Int64(1), 413 NodeID: String("n"), 414 URL: String("u"), 415 ReposURL: String("r"), 416 EventsURL: String("e"), 417 AvatarURL: String("a"), 418 }, 419 ClosedAt: &Timestamp{referenceTime}, 420 URL: String("url"), 421 HTMLURL: String("hurl"), 422 } 423 424 want := `{ 425 "rule_id": "rid", 426 "rule_severity": "rs", 427 "rule_description": "rd", 428 "tool": { 429 "name": "n", 430 "guid": "g", 431 "version": "v" 432 }, 433 "created_at": ` + referenceTimeStr + `, 434 "state": "fixed", 435 "closed_by": { 436 "login": "l", 437 "id": 1, 438 "node_id": "n", 439 "avatar_url": "a", 440 "url": "u", 441 "events_url": "e", 442 "repos_url": "r" 443 }, 444 "closed_at": ` + referenceTimeStr + `, 445 "url": "url", 446 "html_url": "hurl" 447 }` 448 449 testJSONMarshal(t, u, want) 450 } 451 452 func TestLocation_Marshal(t *testing.T) { 453 testJSONMarshal(t, &Location{}, "{}") 454 455 u := &Location{ 456 Path: String("path"), 457 StartLine: Int(1), 458 EndLine: Int(2), 459 StartColumn: Int(3), 460 EndColumn: Int(4), 461 } 462 463 want := `{ 464 "path": "path", 465 "start_line": 1, 466 "end_line": 2, 467 "start_column": 3, 468 "end_column": 4 469 }` 470 471 testJSONMarshal(t, u, want) 472 } 473 474 func TestRule_Marshal(t *testing.T) { 475 testJSONMarshal(t, &Rule{}, "{}") 476 477 u := &Rule{ 478 ID: String("1"), 479 Severity: String("3"), 480 Description: String("description"), 481 Name: String("first"), 482 SecuritySeverityLevel: String("2"), 483 FullDescription: String("summary"), 484 Tags: []string{"tag1", "tag2"}, 485 Help: String("Help Text"), 486 } 487 488 want := `{ 489 "id": "1", 490 "severity": "3", 491 "description": "description", 492 "name": "first", 493 "security_severity_level": "2", 494 "full_description": "summary", 495 "tags": ["tag1", "tag2"], 496 "help": "Help Text" 497 }` 498 499 testJSONMarshal(t, u, want) 500 } 501 502 func TestTool_Marshal(t *testing.T) { 503 testJSONMarshal(t, &Tool{}, "{}") 504 505 u := &Tool{ 506 Name: String("name"), 507 GUID: String("guid"), 508 Version: String("ver"), 509 } 510 511 want := `{ 512 "name": "name", 513 "guid": "guid", 514 "version": "ver" 515 }` 516 517 testJSONMarshal(t, u, want) 518 } 519 520 func TestMessage_Marshal(t *testing.T) { 521 testJSONMarshal(t, &Message{}, "{}") 522 523 u := &Message{ 524 Text: String("text"), 525 } 526 527 want := `{ 528 "text": "text" 529 }` 530 531 testJSONMarshal(t, u, want) 532 } 533 534 func TestCodeScanningService_ListAnalysesForRepo(t *testing.T) { 535 client, mux, _, teardown := setup() 536 defer teardown() 537 538 mux.HandleFunc("/repos/o/r/code-scanning/analyses", func(w http.ResponseWriter, r *http.Request) { 539 testMethod(t, r, "GET") 540 testFormValues(t, r, values{"sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", "ref": "heads/master"}) 541 fmt.Fprint(w, `[ 542 { 543 "ref": "refs/heads/main", 544 "commit_sha": "d99612c3e1f2970085cfbaeadf8f010ef69bad83", 545 "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", 546 "environment": "{\"language\":\"python\"}", 547 "error": "", 548 "category": ".github/workflows/codeql-analysis.yml:analyze/language:python", 549 "created_at": "2020-08-27T15:05:21Z", 550 "results_count": 17, 551 "rules_count": 49, 552 "id": 201, 553 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/201", 554 "sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", 555 "tool": { 556 "name": "CodeQL", 557 "guid": null, 558 "version": "2.4.0" 559 }, 560 "deletable": true, 561 "warning": "" 562 }, 563 { 564 "ref": "refs/heads/my-branch", 565 "commit_sha": "c8cff6510d4d084fb1b4aa13b64b97ca12b07321", 566 "analysis_key": ".github/workflows/shiftleft.yml:build", 567 "environment": "{}", 568 "error": "", 569 "category": ".github/workflows/shiftleft.yml:build/", 570 "created_at": "2020-08-27T15:05:21Z", 571 "results_count": 17, 572 "rules_count": 32, 573 "id": 200, 574 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/200", 575 "sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", 576 "tool": { 577 "name": "Python Security ScanningAnalysis", 578 "guid": null, 579 "version": "1.2.0" 580 }, 581 "deletable": true, 582 "warning": "" 583 } 584 ]`) 585 }) 586 587 opts := &AnalysesListOptions{SarifID: String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), Ref: String("heads/master")} 588 ctx := context.Background() 589 analyses, _, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts) 590 if err != nil { 591 t.Errorf("CodeScanning.ListAnalysesForRepo returned error: %v", err) 592 } 593 594 date := &Timestamp{time.Date(2020, time.August, 27, 15, 05, 21, 0, time.UTC)} 595 want := []*ScanningAnalysis{ 596 { 597 ID: Int64(201), 598 Ref: String("refs/heads/main"), 599 CommitSHA: String("d99612c3e1f2970085cfbaeadf8f010ef69bad83"), 600 AnalysisKey: String(".github/workflows/codeql-analysis.yml:analyze"), 601 Environment: String("{\"language\":\"python\"}"), 602 Error: String(""), 603 Category: String(".github/workflows/codeql-analysis.yml:analyze/language:python"), 604 CreatedAt: date, 605 ResultsCount: Int(17), 606 RulesCount: Int(49), 607 URL: String("https://api.github.com/repos/o/r/code-scanning/analyses/201"), 608 SarifID: String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), 609 Tool: &Tool{ 610 Name: String("CodeQL"), 611 GUID: nil, 612 Version: String("2.4.0"), 613 }, 614 Deletable: Bool(true), 615 Warning: String(""), 616 }, 617 { 618 ID: Int64(200), 619 Ref: String("refs/heads/my-branch"), 620 CommitSHA: String("c8cff6510d4d084fb1b4aa13b64b97ca12b07321"), 621 AnalysisKey: String(".github/workflows/shiftleft.yml:build"), 622 Environment: String("{}"), 623 Error: String(""), 624 Category: String(".github/workflows/shiftleft.yml:build/"), 625 CreatedAt: date, 626 ResultsCount: Int(17), 627 RulesCount: Int(32), 628 URL: String("https://api.github.com/repos/o/r/code-scanning/analyses/200"), 629 SarifID: String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), 630 Tool: &Tool{ 631 Name: String("Python Security ScanningAnalysis"), 632 GUID: nil, 633 Version: String("1.2.0"), 634 }, 635 Deletable: Bool(true), 636 Warning: String(""), 637 }, 638 } 639 if !cmp.Equal(analyses, want) { 640 t.Errorf("CodeScanning.ListAnalysesForRepo returned %+v, want %+v", analyses, want) 641 } 642 643 const methodName = "ListAnalysesForRepo" 644 testBadOptions(t, methodName, func() (err error) { 645 _, _, err = client.CodeScanning.ListAnalysesForRepo(ctx, "\n", "\n", opts) 646 return err 647 }) 648 649 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 650 got, resp, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts) 651 if got != nil { 652 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 653 } 654 return resp, err 655 }) 656 } 657 658 func TestCodeScanningService_GetAnalysis(t *testing.T) { 659 client, mux, _, teardown := setup() 660 defer teardown() 661 662 mux.HandleFunc("/repos/o/r/code-scanning/analyses/3602840", func(w http.ResponseWriter, r *http.Request) { 663 testMethod(t, r, "GET") 664 fmt.Fprint(w, `{ 665 "ref": "refs/heads/main", 666 "commit_sha": "c18c69115654ff0166991962832dc2bd7756e655", 667 "analysis_key": ".github/workflows/codeql-analysis.yml:analyze", 668 "environment": "{\"language\":\"javascript\"}", 669 "error": "", 670 "category": ".github/workflows/codeql-analysis.yml:analyze/language:javascript", 671 "created_at": "2021-01-13T11:55:49Z", 672 "results_count": 3, 673 "rules_count": 67, 674 "id": 3602840, 675 "url": "https://api.github.com/repos/o/r/code-scanning/analyses/201", 676 "sarif_id": "47177e22-5596-11eb-80a1-c1e54ef945c6", 677 "tool": { 678 "name": "CodeQL", 679 "guid": null, 680 "version": "2.4.0" 681 }, 682 "deletable": true, 683 "warning": "" 684 }`) 685 }) 686 687 ctx := context.Background() 688 analysis, _, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840) 689 if err != nil { 690 t.Errorf("CodeScanning.GetAnalysis returned error: %v", err) 691 } 692 693 date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)} 694 want := &ScanningAnalysis{ 695 ID: Int64(3602840), 696 Ref: String("refs/heads/main"), 697 CommitSHA: String("c18c69115654ff0166991962832dc2bd7756e655"), 698 AnalysisKey: String(".github/workflows/codeql-analysis.yml:analyze"), 699 Environment: String("{\"language\":\"javascript\"}"), 700 Error: String(""), 701 Category: String(".github/workflows/codeql-analysis.yml:analyze/language:javascript"), 702 CreatedAt: date, 703 ResultsCount: Int(3), 704 RulesCount: Int(67), 705 URL: String("https://api.github.com/repos/o/r/code-scanning/analyses/201"), 706 SarifID: String("47177e22-5596-11eb-80a1-c1e54ef945c6"), 707 Tool: &Tool{ 708 Name: String("CodeQL"), 709 GUID: nil, 710 Version: String("2.4.0"), 711 }, 712 Deletable: Bool(true), 713 Warning: String(""), 714 } 715 if !cmp.Equal(analysis, want) { 716 t.Errorf("CodeScanning.GetAnalysis returned %+v, want %+v", analysis, want) 717 } 718 719 const methodName = "GetAnalysis" 720 testBadOptions(t, methodName, func() (err error) { 721 _, _, err = client.CodeScanning.GetAnalysis(ctx, "\n", "\n", -123) 722 return err 723 }) 724 725 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 726 got, resp, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840) 727 if got != nil { 728 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 729 } 730 return resp, err 731 }) 732 }