...

Source file src/github.com/google/go-github/v47/github/code-scanning_test.go

Documentation: github.com/google/go-github/v47/github

     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_ListAlertsForOrg(t *testing.T) {
    93  	client, mux, _, teardown := setup()
    94  	defer teardown()
    95  
    96  	mux.HandleFunc("/orgs/o/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  				"repository": {
   101  					"id": 1,
   102  					"name": "n",
   103  					"url": "url"
   104  				},
   105  				"rule_id":"js/trivial-conditional",
   106  				"rule_severity":"warning",
   107  				"rule_description":"Useless conditional",
   108  				"tool": {
   109  					"name": "CodeQL",
   110  					"guid": null,
   111  					"version": "1.4.0"
   112  				},
   113  				"rule": {
   114  					"id": "js/trivial-conditional",
   115  					"severity": "warning",
   116  					"description": "Useless conditional",
   117  					"name": "js/trivial-conditional",
   118  					"full_description": "Expression has no effect",
   119  					"help": "Expression has no effect"
   120  				},
   121  				"most_recent_instance": {
   122  					"ref": "refs/heads/main",
   123  					"state": "open",
   124  					"commit_sha": "abcdefg12345",
   125  					"message": {
   126  						"text": "This path depends on a user-provided value."
   127  					},
   128  					"location": {
   129  						"path": "spec-main/api-session-spec.ts",
   130  						"start_line": 917,
   131  						"end_line": 917,
   132  						"start_column": 7,
   133  						"end_column": 18
   134  					},
   135  					"classifications": [
   136  						"test"
   137  					]
   138  				},
   139  				"created_at":"2020-05-06T12:00:00Z",
   140  				"state":"open",
   141  				"closed_by":null,
   142  				"closed_at":null,
   143  				"url":"https://api.github.com/repos/o/r/code-scanning/alerts/25",
   144  				"html_url":"https://github.com/o/r/security/code-scanning/25"
   145  				},
   146  				{
   147  				"rule_id":"js/useless-expression",
   148  				"rule_severity":"warning",
   149  				"rule_description":"Expression has no effect",
   150  				"tool": {
   151  					"name": "CodeQL",
   152  					"guid": null,
   153  					"version": "1.4.0"
   154  				},
   155  				"rule": {
   156  					"id": "js/useless-expression",
   157  					"severity": "warning",
   158  					"description": "Expression has no effect",
   159  					"name": "js/useless-expression",
   160  					"full_description": "Expression has no effect",
   161  					"help": "Expression has no effect"
   162  				},
   163  				"most_recent_instance": {
   164  					"ref": "refs/heads/main",
   165  					"state": "open",
   166  					"commit_sha": "abcdefg12345",
   167  					"message": {
   168  						"text": "This path depends on a user-provided value."
   169  					},
   170  					"location": {
   171  						"path": "spec-main/api-session-spec.ts",
   172  						"start_line": 917,
   173  						"end_line": 917,
   174  						"start_column": 7,
   175  						"end_column": 18
   176  					},
   177  					"classifications": [
   178  						"test"
   179  					]
   180  				},
   181  				"created_at":"2020-05-06T12:00:00Z",
   182  				"state":"open",
   183  				"closed_by":null,
   184  				"closed_at":null,
   185  				"url":"https://api.github.com/repos/o/r/code-scanning/alerts/88",
   186  				"html_url":"https://github.com/o/r/security/code-scanning/88"
   187  				}]`)
   188  	})
   189  
   190  	opts := &AlertListOptions{State: "open", Ref: "heads/master"}
   191  	ctx := context.Background()
   192  	alerts, _, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
   193  	if err != nil {
   194  		t.Errorf("CodeScanning.ListAlertsForOrg returned error: %v", err)
   195  	}
   196  
   197  	date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)}
   198  	want := []*Alert{
   199  		{
   200  			Repository: &Repository{
   201  				ID:   Int64(1),
   202  				URL:  String("url"),
   203  				Name: String("n"),
   204  			},
   205  			RuleID:          String("js/trivial-conditional"),
   206  			RuleSeverity:    String("warning"),
   207  			RuleDescription: String("Useless conditional"),
   208  			Tool:            &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
   209  			Rule: &Rule{
   210  				ID:              String("js/trivial-conditional"),
   211  				Severity:        String("warning"),
   212  				Description:     String("Useless conditional"),
   213  				Name:            String("js/trivial-conditional"),
   214  				FullDescription: String("Expression has no effect"),
   215  				Help:            String("Expression has no effect"),
   216  			},
   217  			CreatedAt: &date,
   218  			State:     String("open"),
   219  			ClosedBy:  nil,
   220  			ClosedAt:  nil,
   221  			URL:       String("https://api.github.com/repos/o/r/code-scanning/alerts/25"),
   222  			HTMLURL:   String("https://github.com/o/r/security/code-scanning/25"),
   223  			MostRecentInstance: &MostRecentInstance{
   224  				Ref:       String("refs/heads/main"),
   225  				State:     String("open"),
   226  				CommitSHA: String("abcdefg12345"),
   227  				Message: &Message{
   228  					Text: String("This path depends on a user-provided value."),
   229  				},
   230  				Location: &Location{
   231  					Path:        String("spec-main/api-session-spec.ts"),
   232  					StartLine:   Int(917),
   233  					EndLine:     Int(917),
   234  					StartColumn: Int(7),
   235  					EndColumn:   Int(18),
   236  				},
   237  				Classifications: []string{"test"},
   238  			},
   239  		},
   240  		{
   241  			RuleID:          String("js/useless-expression"),
   242  			RuleSeverity:    String("warning"),
   243  			RuleDescription: String("Expression has no effect"),
   244  			Tool:            &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
   245  			Rule: &Rule{
   246  				ID:              String("js/useless-expression"),
   247  				Severity:        String("warning"),
   248  				Description:     String("Expression has no effect"),
   249  				Name:            String("js/useless-expression"),
   250  				FullDescription: String("Expression has no effect"),
   251  				Help:            String("Expression has no effect"),
   252  			},
   253  			CreatedAt: &date,
   254  			State:     String("open"),
   255  			ClosedBy:  nil,
   256  			ClosedAt:  nil,
   257  			URL:       String("https://api.github.com/repos/o/r/code-scanning/alerts/88"),
   258  			HTMLURL:   String("https://github.com/o/r/security/code-scanning/88"),
   259  			MostRecentInstance: &MostRecentInstance{
   260  				Ref:       String("refs/heads/main"),
   261  				State:     String("open"),
   262  				CommitSHA: String("abcdefg12345"),
   263  				Message: &Message{
   264  					Text: String("This path depends on a user-provided value."),
   265  				},
   266  				Location: &Location{
   267  					Path:        String("spec-main/api-session-spec.ts"),
   268  					StartLine:   Int(917),
   269  					EndLine:     Int(917),
   270  					StartColumn: Int(7),
   271  					EndColumn:   Int(18),
   272  				},
   273  				Classifications: []string{"test"},
   274  			},
   275  		},
   276  	}
   277  	if !cmp.Equal(alerts, want) {
   278  		t.Errorf("CodeScanning.ListAlertsForOrg returned %+v, want %+v", *&alerts, *&want)
   279  	}
   280  
   281  	const methodName = "ListAlertsForOrg"
   282  	testBadOptions(t, methodName, func() (err error) {
   283  		_, _, err = client.CodeScanning.ListAlertsForOrg(ctx, "\n", opts)
   284  		return err
   285  	})
   286  
   287  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   288  		got, resp, err := client.CodeScanning.ListAlertsForOrg(ctx, "o", opts)
   289  		if got != nil {
   290  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   291  		}
   292  		return resp, err
   293  	})
   294  }
   295  
   296  func TestCodeScanningService_ListAlertsForRepo(t *testing.T) {
   297  	client, mux, _, teardown := setup()
   298  	defer teardown()
   299  
   300  	mux.HandleFunc("/repos/o/r/code-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
   301  		testMethod(t, r, "GET")
   302  		testFormValues(t, r, values{"state": "open", "ref": "heads/master"})
   303  		fmt.Fprint(w, `[{
   304  				"rule_id":"js/trivial-conditional",
   305  				"rule_severity":"warning",
   306  				"rule_description":"Useless conditional",
   307  				"tool": {
   308  					"name": "CodeQL",
   309  					"guid": null,
   310  					"version": "1.4.0"
   311  				},
   312  				"rule": {
   313  					"id": "js/trivial-conditional",
   314  					"severity": "warning",
   315  					"description": "Useless conditional",
   316  					"name": "js/trivial-conditional",
   317  					"full_description": "Expression has no effect",
   318  					"help": "Expression has no effect"
   319  				},
   320  				"most_recent_instance": {
   321  					"ref": "refs/heads/main",
   322  					"state": "open",
   323  					"commit_sha": "abcdefg12345",
   324  					"message": {
   325  						"text": "This path depends on a user-provided value."
   326  					},
   327  					"location": {
   328  						"path": "spec-main/api-session-spec.ts",
   329  						"start_line": 917,
   330  						"end_line": 917,
   331  						"start_column": 7,
   332  						"end_column": 18
   333  					},
   334  					"classifications": [
   335  						"test"
   336  					]
   337  				},
   338  				"created_at":"2020-05-06T12:00:00Z",
   339  				"state":"open",
   340  				"closed_by":null,
   341  				"closed_at":null,
   342  				"url":"https://api.github.com/repos/o/r/code-scanning/alerts/25",
   343  				"html_url":"https://github.com/o/r/security/code-scanning/25"
   344  				},
   345  				{
   346  				"rule_id":"js/useless-expression",
   347  				"rule_severity":"warning",
   348  				"rule_description":"Expression has no effect",
   349  				"tool": {
   350  					"name": "CodeQL",
   351  					"guid": null,
   352  					"version": "1.4.0"
   353  				},
   354  				"rule": {
   355  					"id": "js/useless-expression",
   356  					"severity": "warning",
   357  					"description": "Expression has no effect",
   358  					"name": "js/useless-expression",
   359  					"full_description": "Expression has no effect",
   360  					"help": "Expression has no effect"
   361  				},
   362  				"most_recent_instance": {
   363  					"ref": "refs/heads/main",
   364  					"state": "open",
   365  					"commit_sha": "abcdefg12345",
   366  					"message": {
   367  						"text": "This path depends on a user-provided value."
   368  					},
   369  					"location": {
   370  						"path": "spec-main/api-session-spec.ts",
   371  						"start_line": 917,
   372  						"end_line": 917,
   373  						"start_column": 7,
   374  						"end_column": 18
   375  					},
   376  					"classifications": [
   377  						"test"
   378  					]
   379  				},
   380  				"created_at":"2020-05-06T12:00:00Z",
   381  				"state":"open",
   382  				"closed_by":null,
   383  				"closed_at":null,
   384  				"url":"https://api.github.com/repos/o/r/code-scanning/alerts/88",
   385  				"html_url":"https://github.com/o/r/security/code-scanning/88"
   386  				}]`)
   387  	})
   388  
   389  	opts := &AlertListOptions{State: "open", Ref: "heads/master"}
   390  	ctx := context.Background()
   391  	alerts, _, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts)
   392  	if err != nil {
   393  		t.Errorf("CodeScanning.ListAlertsForRepo returned error: %v", err)
   394  	}
   395  
   396  	date := Timestamp{time.Date(2020, time.May, 06, 12, 00, 00, 0, time.UTC)}
   397  	want := []*Alert{
   398  		{
   399  			RuleID:          String("js/trivial-conditional"),
   400  			RuleSeverity:    String("warning"),
   401  			RuleDescription: String("Useless conditional"),
   402  			Tool:            &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
   403  			Rule: &Rule{
   404  				ID:              String("js/trivial-conditional"),
   405  				Severity:        String("warning"),
   406  				Description:     String("Useless conditional"),
   407  				Name:            String("js/trivial-conditional"),
   408  				FullDescription: String("Expression has no effect"),
   409  				Help:            String("Expression has no effect"),
   410  			},
   411  			CreatedAt: &date,
   412  			State:     String("open"),
   413  			ClosedBy:  nil,
   414  			ClosedAt:  nil,
   415  			URL:       String("https://api.github.com/repos/o/r/code-scanning/alerts/25"),
   416  			HTMLURL:   String("https://github.com/o/r/security/code-scanning/25"),
   417  			MostRecentInstance: &MostRecentInstance{
   418  				Ref:       String("refs/heads/main"),
   419  				State:     String("open"),
   420  				CommitSHA: String("abcdefg12345"),
   421  				Message: &Message{
   422  					Text: String("This path depends on a user-provided value."),
   423  				},
   424  				Location: &Location{
   425  					Path:        String("spec-main/api-session-spec.ts"),
   426  					StartLine:   Int(917),
   427  					EndLine:     Int(917),
   428  					StartColumn: Int(7),
   429  					EndColumn:   Int(18),
   430  				},
   431  				Classifications: []string{"test"},
   432  			},
   433  		},
   434  		{
   435  			RuleID:          String("js/useless-expression"),
   436  			RuleSeverity:    String("warning"),
   437  			RuleDescription: String("Expression has no effect"),
   438  			Tool:            &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
   439  			Rule: &Rule{
   440  				ID:              String("js/useless-expression"),
   441  				Severity:        String("warning"),
   442  				Description:     String("Expression has no effect"),
   443  				Name:            String("js/useless-expression"),
   444  				FullDescription: String("Expression has no effect"),
   445  				Help:            String("Expression has no effect"),
   446  			},
   447  			CreatedAt: &date,
   448  			State:     String("open"),
   449  			ClosedBy:  nil,
   450  			ClosedAt:  nil,
   451  			URL:       String("https://api.github.com/repos/o/r/code-scanning/alerts/88"),
   452  			HTMLURL:   String("https://github.com/o/r/security/code-scanning/88"),
   453  			MostRecentInstance: &MostRecentInstance{
   454  				Ref:       String("refs/heads/main"),
   455  				State:     String("open"),
   456  				CommitSHA: String("abcdefg12345"),
   457  				Message: &Message{
   458  					Text: String("This path depends on a user-provided value."),
   459  				},
   460  				Location: &Location{
   461  					Path:        String("spec-main/api-session-spec.ts"),
   462  					StartLine:   Int(917),
   463  					EndLine:     Int(917),
   464  					StartColumn: Int(7),
   465  					EndColumn:   Int(18),
   466  				},
   467  				Classifications: []string{"test"},
   468  			},
   469  		},
   470  	}
   471  	if !cmp.Equal(alerts, want) {
   472  		t.Errorf("CodeScanning.ListAlertsForRepo returned %+v, want %+v", alerts, want)
   473  	}
   474  
   475  	const methodName = "ListAlertsForRepo"
   476  	testBadOptions(t, methodName, func() (err error) {
   477  		_, _, err = client.CodeScanning.ListAlertsForRepo(ctx, "\n", "\n", opts)
   478  		return err
   479  	})
   480  
   481  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   482  		got, resp, err := client.CodeScanning.ListAlertsForRepo(ctx, "o", "r", opts)
   483  		if got != nil {
   484  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   485  		}
   486  		return resp, err
   487  	})
   488  }
   489  
   490  func TestCodeScanningService_GetAlert(t *testing.T) {
   491  	client, mux, _, teardown := setup()
   492  	defer teardown()
   493  
   494  	mux.HandleFunc("/repos/o/r/code-scanning/alerts/88", func(w http.ResponseWriter, r *http.Request) {
   495  		testMethod(t, r, "GET")
   496  		fmt.Fprint(w, `{"rule_id":"js/useless-expression",
   497  				"rule_severity":"warning",
   498  				"rule_description":"Expression has no effect",
   499  				"tool": {
   500  					"name": "CodeQL",
   501  					"guid": null,
   502  					"version": "1.4.0"
   503  				},
   504  				"rule": {
   505  					"id": "useless expression",
   506  					"severity": "warning",
   507  					"description": "Expression has no effect",
   508  					"name": "useless expression",
   509  					"full_description": "Expression has no effect",
   510  					"help": "Expression has no effect"
   511  				},
   512  				"most_recent_instance": {
   513  					"ref": "refs/heads/main",
   514  					"state": "open",
   515  					"commit_sha": "abcdefg12345",
   516  					"message": {
   517  						"text": "This path depends on a user-provided value."
   518  					},
   519  					"location": {
   520  						"path": "spec-main/api-session-spec.ts",
   521  						"start_line": 917,
   522  						"end_line": 917,
   523  						"start_column": 7,
   524  						"end_column": 18
   525  					},
   526  					"classifications": [
   527  						"test"
   528  					]
   529  				},
   530  				"created_at":"2019-01-02T15:04:05Z",
   531  				"state":"open",
   532  				"closed_by":null,
   533  				"closed_at":null,
   534  				"url":"https://api.github.com/repos/o/r/code-scanning/alerts/88",
   535  				"html_url":"https://github.com/o/r/security/code-scanning/88"}`)
   536  	})
   537  
   538  	ctx := context.Background()
   539  	alert, _, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88)
   540  	if err != nil {
   541  		t.Errorf("CodeScanning.GetAlert returned error: %v", err)
   542  	}
   543  
   544  	date := Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}
   545  	want := &Alert{
   546  		RuleID:          String("js/useless-expression"),
   547  		RuleSeverity:    String("warning"),
   548  		RuleDescription: String("Expression has no effect"),
   549  		Tool:            &Tool{Name: String("CodeQL"), GUID: nil, Version: String("1.4.0")},
   550  		Rule: &Rule{
   551  			ID:              String("useless expression"),
   552  			Severity:        String("warning"),
   553  			Description:     String("Expression has no effect"),
   554  			Name:            String("useless expression"),
   555  			FullDescription: String("Expression has no effect"),
   556  			Help:            String("Expression has no effect"),
   557  		},
   558  		CreatedAt: &date,
   559  		State:     String("open"),
   560  		ClosedBy:  nil,
   561  		ClosedAt:  nil,
   562  		URL:       String("https://api.github.com/repos/o/r/code-scanning/alerts/88"),
   563  		HTMLURL:   String("https://github.com/o/r/security/code-scanning/88"),
   564  		MostRecentInstance: &MostRecentInstance{
   565  			Ref:       String("refs/heads/main"),
   566  			State:     String("open"),
   567  			CommitSHA: String("abcdefg12345"),
   568  			Message: &Message{
   569  				Text: String("This path depends on a user-provided value."),
   570  			},
   571  			Location: &Location{
   572  				Path:        String("spec-main/api-session-spec.ts"),
   573  				StartLine:   Int(917),
   574  				EndLine:     Int(917),
   575  				StartColumn: Int(7),
   576  				EndColumn:   Int(18),
   577  			},
   578  			Classifications: []string{"test"},
   579  		},
   580  	}
   581  	if !cmp.Equal(alert, want) {
   582  		t.Errorf("CodeScanning.GetAlert returned %+v, want %+v", alert, want)
   583  	}
   584  
   585  	const methodName = "GetAlert"
   586  	testBadOptions(t, methodName, func() (err error) {
   587  		_, _, err = client.CodeScanning.GetAlert(ctx, "\n", "\n", -88)
   588  		return err
   589  	})
   590  
   591  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   592  		got, resp, err := client.CodeScanning.GetAlert(ctx, "o", "r", 88)
   593  		if got != nil {
   594  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   595  		}
   596  		return resp, err
   597  	})
   598  }
   599  
   600  func TestAlert_Marshal(t *testing.T) {
   601  	testJSONMarshal(t, &Alert{}, "{}")
   602  
   603  	u := &Alert{
   604  		RuleID:          String("rid"),
   605  		RuleSeverity:    String("rs"),
   606  		RuleDescription: String("rd"),
   607  		Tool: &Tool{
   608  			Name:    String("n"),
   609  			GUID:    String("g"),
   610  			Version: String("v"),
   611  		},
   612  		CreatedAt: &Timestamp{referenceTime},
   613  		State:     String("fixed"),
   614  		ClosedBy: &User{
   615  			Login:     String("l"),
   616  			ID:        Int64(1),
   617  			NodeID:    String("n"),
   618  			URL:       String("u"),
   619  			ReposURL:  String("r"),
   620  			EventsURL: String("e"),
   621  			AvatarURL: String("a"),
   622  		},
   623  		ClosedAt: &Timestamp{referenceTime},
   624  		URL:      String("url"),
   625  		HTMLURL:  String("hurl"),
   626  	}
   627  
   628  	want := `{
   629  		"rule_id": "rid",
   630  		"rule_severity": "rs",
   631  		"rule_description": "rd",
   632  		"tool": {
   633  			"name": "n",
   634  			"guid": "g",
   635  			"version": "v"
   636  		},
   637  		"created_at": ` + referenceTimeStr + `,
   638  		"state": "fixed",
   639  		"closed_by": {
   640  			"login": "l",
   641  			"id": 1,
   642  			"node_id": "n",
   643  			"avatar_url": "a",
   644  			"url": "u",
   645  			"events_url": "e",
   646  			"repos_url": "r"
   647  		},
   648  		"closed_at": ` + referenceTimeStr + `,
   649  		"url": "url",
   650  		"html_url": "hurl"
   651  	}`
   652  
   653  	testJSONMarshal(t, u, want)
   654  }
   655  
   656  func TestLocation_Marshal(t *testing.T) {
   657  	testJSONMarshal(t, &Location{}, "{}")
   658  
   659  	u := &Location{
   660  		Path:        String("path"),
   661  		StartLine:   Int(1),
   662  		EndLine:     Int(2),
   663  		StartColumn: Int(3),
   664  		EndColumn:   Int(4),
   665  	}
   666  
   667  	want := `{
   668  		"path": "path",
   669  		"start_line": 1,
   670  		"end_line": 2,
   671  		"start_column": 3,
   672  		"end_column": 4
   673  	}`
   674  
   675  	testJSONMarshal(t, u, want)
   676  }
   677  
   678  func TestRule_Marshal(t *testing.T) {
   679  	testJSONMarshal(t, &Rule{}, "{}")
   680  
   681  	u := &Rule{
   682  		ID:                    String("1"),
   683  		Severity:              String("3"),
   684  		Description:           String("description"),
   685  		Name:                  String("first"),
   686  		SecuritySeverityLevel: String("2"),
   687  		FullDescription:       String("summary"),
   688  		Tags:                  []string{"tag1", "tag2"},
   689  		Help:                  String("Help Text"),
   690  	}
   691  
   692  	want := `{
   693  		"id":                      "1",
   694  		"severity":                "3",
   695  		"description":             "description",
   696  		"name":                    "first",
   697  		"security_severity_level": "2",
   698  		"full_description":        "summary",
   699  		"tags":                    ["tag1", "tag2"],
   700  		"help":                    "Help Text"
   701  	}`
   702  
   703  	testJSONMarshal(t, u, want)
   704  }
   705  
   706  func TestTool_Marshal(t *testing.T) {
   707  	testJSONMarshal(t, &Tool{}, "{}")
   708  
   709  	u := &Tool{
   710  		Name:    String("name"),
   711  		GUID:    String("guid"),
   712  		Version: String("ver"),
   713  	}
   714  
   715  	want := `{
   716  		"name": "name",
   717  		"guid": "guid",
   718  		"version": "ver"
   719  	}`
   720  
   721  	testJSONMarshal(t, u, want)
   722  }
   723  
   724  func TestMessage_Marshal(t *testing.T) {
   725  	testJSONMarshal(t, &Message{}, "{}")
   726  
   727  	u := &Message{
   728  		Text: String("text"),
   729  	}
   730  
   731  	want := `{
   732  		"text": "text"
   733  	}`
   734  
   735  	testJSONMarshal(t, u, want)
   736  }
   737  
   738  func TestCodeScanningService_ListAnalysesForRepo(t *testing.T) {
   739  	client, mux, _, teardown := setup()
   740  	defer teardown()
   741  
   742  	mux.HandleFunc("/repos/o/r/code-scanning/analyses", func(w http.ResponseWriter, r *http.Request) {
   743  		testMethod(t, r, "GET")
   744  		testFormValues(t, r, values{"sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582", "ref": "heads/master"})
   745  		fmt.Fprint(w, `[
   746  			  {
   747  				"ref": "refs/heads/main",
   748  				"commit_sha": "d99612c3e1f2970085cfbaeadf8f010ef69bad83",
   749  				"analysis_key": ".github/workflows/codeql-analysis.yml:analyze",
   750  				"environment": "{\"language\":\"python\"}",
   751  				"error": "",
   752  				"category": ".github/workflows/codeql-analysis.yml:analyze/language:python",
   753  				"created_at": "2020-08-27T15:05:21Z",
   754  				"results_count": 17,
   755  				"rules_count": 49,
   756  				"id": 201,
   757  				"url": "https://api.github.com/repos/o/r/code-scanning/analyses/201",
   758  				"sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582",
   759  				"tool": {
   760  				  "name": "CodeQL",
   761  				  "guid": null,
   762  				  "version": "2.4.0"
   763  				},
   764  				"deletable": true,
   765  				"warning": ""
   766  			  },
   767  			  {
   768  				"ref": "refs/heads/my-branch",
   769  				"commit_sha": "c8cff6510d4d084fb1b4aa13b64b97ca12b07321",
   770  				"analysis_key": ".github/workflows/shiftleft.yml:build",
   771  				"environment": "{}",
   772  				"error": "",
   773  				"category": ".github/workflows/shiftleft.yml:build/",
   774  				"created_at": "2020-08-27T15:05:21Z",
   775  				"results_count": 17,
   776  				"rules_count": 32,
   777  				"id": 200,
   778  				"url": "https://api.github.com/repos/o/r/code-scanning/analyses/200",
   779  				"sarif_id": "8981cd8e-b078-4ac3-a3be-1dad7dbd0b582",
   780  				"tool": {
   781  				  "name": "Python Security ScanningAnalysis",
   782  				  "guid": null,
   783  				  "version": "1.2.0"
   784  				},
   785  				"deletable": true,
   786  				"warning": ""
   787  			  }
   788  			]`)
   789  	})
   790  
   791  	opts := &AnalysesListOptions{SarifID: String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"), Ref: String("heads/master")}
   792  	ctx := context.Background()
   793  	analyses, _, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts)
   794  	if err != nil {
   795  		t.Errorf("CodeScanning.ListAnalysesForRepo returned error: %v", err)
   796  	}
   797  
   798  	date := &Timestamp{time.Date(2020, time.August, 27, 15, 05, 21, 0, time.UTC)}
   799  	want := []*ScanningAnalysis{
   800  		{
   801  			ID:           Int64(201),
   802  			Ref:          String("refs/heads/main"),
   803  			CommitSHA:    String("d99612c3e1f2970085cfbaeadf8f010ef69bad83"),
   804  			AnalysisKey:  String(".github/workflows/codeql-analysis.yml:analyze"),
   805  			Environment:  String("{\"language\":\"python\"}"),
   806  			Error:        String(""),
   807  			Category:     String(".github/workflows/codeql-analysis.yml:analyze/language:python"),
   808  			CreatedAt:    date,
   809  			ResultsCount: Int(17),
   810  			RulesCount:   Int(49),
   811  			URL:          String("https://api.github.com/repos/o/r/code-scanning/analyses/201"),
   812  			SarifID:      String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"),
   813  			Tool: &Tool{
   814  				Name:    String("CodeQL"),
   815  				GUID:    nil,
   816  				Version: String("2.4.0"),
   817  			},
   818  			Deletable: Bool(true),
   819  			Warning:   String(""),
   820  		},
   821  		{
   822  			ID:           Int64(200),
   823  			Ref:          String("refs/heads/my-branch"),
   824  			CommitSHA:    String("c8cff6510d4d084fb1b4aa13b64b97ca12b07321"),
   825  			AnalysisKey:  String(".github/workflows/shiftleft.yml:build"),
   826  			Environment:  String("{}"),
   827  			Error:        String(""),
   828  			Category:     String(".github/workflows/shiftleft.yml:build/"),
   829  			CreatedAt:    date,
   830  			ResultsCount: Int(17),
   831  			RulesCount:   Int(32),
   832  			URL:          String("https://api.github.com/repos/o/r/code-scanning/analyses/200"),
   833  			SarifID:      String("8981cd8e-b078-4ac3-a3be-1dad7dbd0b582"),
   834  			Tool: &Tool{
   835  				Name:    String("Python Security ScanningAnalysis"),
   836  				GUID:    nil,
   837  				Version: String("1.2.0"),
   838  			},
   839  			Deletable: Bool(true),
   840  			Warning:   String(""),
   841  		},
   842  	}
   843  	if !cmp.Equal(analyses, want) {
   844  		t.Errorf("CodeScanning.ListAnalysesForRepo returned %+v, want %+v", analyses, want)
   845  	}
   846  
   847  	const methodName = "ListAnalysesForRepo"
   848  	testBadOptions(t, methodName, func() (err error) {
   849  		_, _, err = client.CodeScanning.ListAnalysesForRepo(ctx, "\n", "\n", opts)
   850  		return err
   851  	})
   852  
   853  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   854  		got, resp, err := client.CodeScanning.ListAnalysesForRepo(ctx, "o", "r", opts)
   855  		if got != nil {
   856  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   857  		}
   858  		return resp, err
   859  	})
   860  }
   861  
   862  func TestCodeScanningService_GetAnalysis(t *testing.T) {
   863  	client, mux, _, teardown := setup()
   864  	defer teardown()
   865  
   866  	mux.HandleFunc("/repos/o/r/code-scanning/analyses/3602840", func(w http.ResponseWriter, r *http.Request) {
   867  		testMethod(t, r, "GET")
   868  		fmt.Fprint(w, `{
   869  			  "ref": "refs/heads/main",
   870  			  "commit_sha": "c18c69115654ff0166991962832dc2bd7756e655",
   871  			  "analysis_key": ".github/workflows/codeql-analysis.yml:analyze",
   872  			  "environment": "{\"language\":\"javascript\"}",
   873  			  "error": "",
   874  			  "category": ".github/workflows/codeql-analysis.yml:analyze/language:javascript",
   875  			  "created_at": "2021-01-13T11:55:49Z",
   876  			  "results_count": 3,
   877  			  "rules_count": 67,
   878  			  "id": 3602840,
   879  			  "url": "https://api.github.com/repos/o/r/code-scanning/analyses/201",
   880  			  "sarif_id": "47177e22-5596-11eb-80a1-c1e54ef945c6",
   881  			  "tool": {
   882  				"name": "CodeQL",
   883  				"guid": null,
   884  				"version": "2.4.0"
   885  			  },
   886  			  "deletable": true,
   887  			  "warning": ""
   888  			}`)
   889  	})
   890  
   891  	ctx := context.Background()
   892  	analysis, _, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840)
   893  	if err != nil {
   894  		t.Errorf("CodeScanning.GetAnalysis returned error: %v", err)
   895  	}
   896  
   897  	date := &Timestamp{time.Date(2021, time.January, 13, 11, 55, 49, 0, time.UTC)}
   898  	want := &ScanningAnalysis{
   899  		ID:           Int64(3602840),
   900  		Ref:          String("refs/heads/main"),
   901  		CommitSHA:    String("c18c69115654ff0166991962832dc2bd7756e655"),
   902  		AnalysisKey:  String(".github/workflows/codeql-analysis.yml:analyze"),
   903  		Environment:  String("{\"language\":\"javascript\"}"),
   904  		Error:        String(""),
   905  		Category:     String(".github/workflows/codeql-analysis.yml:analyze/language:javascript"),
   906  		CreatedAt:    date,
   907  		ResultsCount: Int(3),
   908  		RulesCount:   Int(67),
   909  		URL:          String("https://api.github.com/repos/o/r/code-scanning/analyses/201"),
   910  		SarifID:      String("47177e22-5596-11eb-80a1-c1e54ef945c6"),
   911  		Tool: &Tool{
   912  			Name:    String("CodeQL"),
   913  			GUID:    nil,
   914  			Version: String("2.4.0"),
   915  		},
   916  		Deletable: Bool(true),
   917  		Warning:   String(""),
   918  	}
   919  	if !cmp.Equal(analysis, want) {
   920  		t.Errorf("CodeScanning.GetAnalysis returned %+v, want %+v", analysis, want)
   921  	}
   922  
   923  	const methodName = "GetAnalysis"
   924  	testBadOptions(t, methodName, func() (err error) {
   925  		_, _, err = client.CodeScanning.GetAnalysis(ctx, "\n", "\n", -123)
   926  		return err
   927  	})
   928  
   929  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   930  		got, resp, err := client.CodeScanning.GetAnalysis(ctx, "o", "r", 3602840)
   931  		if got != nil {
   932  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   933  		}
   934  		return resp, err
   935  	})
   936  }
   937  

View as plain text