Skip to content

Commit 9700ce4

Browse files
committed
cmd,internal: replace fakeClient with mock test setup
Previously, issue.Client was an interface, so that we could use a fake client for testing. This made it difficult to jump to definition, when debugging issues with the client. Additionally, the tests weren't very effective, since they didn't traverse the githubClient code path at all. Replace the test setup with a mock http server, and make issues.Client to a struct. Change-Id: I878846ce69c2979b45ff6e8494bc0f7c020055ea Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/458203 Run-TryBot: Julie Qiu <[email protected]> Reviewed-by: Julie Qiu <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Tatiana Bradley <[email protected]>
1 parent 38d73a0 commit 9700ce4

File tree

11 files changed

+329
-209
lines changed

11 files changed

+329
-209
lines changed

cmd/issue/main.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func main() {
5050
if err != nil {
5151
log.Fatal(err)
5252
}
53-
c := issues.NewGitHubClient(owner, repoName, *githubToken)
53+
c := issues.NewClient(&issues.Config{Owner: owner, Repo: repoName, Token: *githubToken})
5454
switch cmd {
5555
case "triage":
5656
err = createIssueToTriage(ctx, c, *githubToken, filename)
@@ -64,7 +64,7 @@ func main() {
6464
}
6565
}
6666

67-
func createIssueToTriage(ctx context.Context, c issues.Client, ghToken, filename string) (err error) {
67+
func createIssueToTriage(ctx context.Context, c *issues.Client, ghToken, filename string) (err error) {
6868
aliases, err := parseAliases(filename)
6969
if err != nil {
7070
return err
@@ -77,7 +77,7 @@ func createIssueToTriage(ctx context.Context, c issues.Client, ghToken, filename
7777
return nil
7878
}
7979

80-
func createExcluded(ctx context.Context, c issues.Client, ghToken, filename string) (err error) {
80+
func createExcluded(ctx context.Context, c *issues.Client, ghToken, filename string) (err error) {
8181
records, err := parseExcluded(filename)
8282
if err != nil {
8383
return err
@@ -90,7 +90,7 @@ func createExcluded(ctx context.Context, c issues.Client, ghToken, filename stri
9090
return nil
9191
}
9292

93-
func constructIssue(ctx context.Context, c issues.Client, alias, ghToken string, labels []string) (err error) {
93+
func constructIssue(ctx context.Context, c *issues.Client, alias, ghToken string, labels []string) (err error) {
9494
var ghsas []*ghsa.SecurityAdvisory
9595
if strings.HasPrefix(alias, "GHSA") {
9696
sa, err := ghsa.FetchGHSA(ctx, ghToken, alias)

cmd/vulnreport/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ func parseArgsToGithubIDs(args []string, existingByIssue map[int]*report.Report)
235235
type createCfg struct {
236236
ghToken string
237237
repo *git.Repository
238-
issuesClient issues.Client
238+
issuesClient *issues.Client
239239
existingByFile map[string]*report.Report
240240
existingByIssue map[int]*report.Report
241241
allowClosed bool
@@ -272,7 +272,7 @@ func setupCreate(ctx context.Context, args []string) ([]int, *createCfg, error)
272272
return githubIDs, &createCfg{
273273
ghToken: *githubToken,
274274
repo: repo,
275-
issuesClient: issues.NewGitHubClient(owner, repoName, *githubToken),
275+
issuesClient: issues.NewClient(&issues.Config{Owner: owner, Repo: repoName, Token: *githubToken}),
276276
existingByFile: existingByFile,
277277
existingByIssue: existingByIssue,
278278
allowClosed: *closedOk,

cmd/worker/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ func createIssuesCommand(ctx context.Context) error {
255255
if err != nil {
256256
return err
257257
}
258-
client := issues.NewGitHubClient(owner, repoName, cfg.GitHubAccessToken)
258+
client := issues.NewClient(&issues.Config{Owner: owner, Repo: repoName, Token: cfg.GitHubAccessToken})
259259
repo, err := gitrepo.Clone(ctx, "https://github.com/golang/vulndb")
260260
if err != nil {
261261
return err

internal/issues/fake.go

Lines changed: 0 additions & 75 deletions
This file was deleted.

internal/issues/githubtest/setup.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package githubtest provides a test client and server for testing the GitHub API
6+
// client.
7+
package githubtest
8+
9+
import (
10+
"net/http"
11+
"net/http/httptest"
12+
"net/url"
13+
"testing"
14+
15+
"golang.org/x/vulndb/internal/issues"
16+
)
17+
18+
const (
19+
TestOwner = "test-owner"
20+
TestRepo = "test-repo"
21+
TestToken = "test-token"
22+
23+
testBaseURLPath = "/api-test"
24+
)
25+
26+
// Setup sets up a test HTTP server along with a issues.Client that is
27+
// configured to talk to that test server.
28+
func Setup(t *testing.T, cfg *issues.Config) (*issues.Client, *http.ServeMux) {
29+
mux := http.NewServeMux()
30+
apiHandler := http.NewServeMux()
31+
32+
apiHandler.Handle(testBaseURLPath+"/", http.StripPrefix(testBaseURLPath, mux))
33+
server := httptest.NewServer(apiHandler)
34+
35+
url, _ := url.Parse(server.URL + testBaseURLPath + "/")
36+
client := issues.NewTestClient(cfg, url)
37+
t.Cleanup(server.Close)
38+
return client, mux
39+
}

internal/issues/issues.go

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package issues
99
import (
1010
"context"
1111
"fmt"
12+
"net/url"
1213
"time"
1314

1415
"github.com/google/go-github/v41/github"
@@ -37,56 +38,60 @@ type GetIssuesOptions struct {
3738
}
3839

3940
// Client is a client that can create and retrieve issues.
40-
type Client interface {
41-
// Destination describes where issues will be created.
42-
Destination() string
43-
44-
// Reference returns a string that refers to the issue with number.
45-
Reference(number int) string
46-
47-
// IssueExists reports whether an issue with the given ID exists.
48-
IssueExists(ctx context.Context, number int) (bool, error)
49-
50-
// CreateIssue creates a new issue.
51-
CreateIssue(ctx context.Context, iss *Issue) (number int, err error)
52-
53-
// GetIssue returns an issue with the given issue number.
54-
GetIssue(ctx context.Context, number int) (iss *Issue, err error)
55-
56-
GetIssues(ctx context.Context, opts GetIssuesOptions) (issues []*Issue, err error)
57-
}
58-
59-
type githubClient struct {
41+
type Client struct {
6042
client *github.Client
6143
owner string
6244
repo string
6345
}
6446

65-
// NewGitHubClient creates a Client that will create issues in
47+
// Config is used to initialize a new Client.
48+
type Config struct {
49+
// Owner is the owner of a GitHub repo. For example, "golang" is the owner
50+
// for github.com/golang/vulndb.
51+
Owner string
52+
53+
// Repo is the name of a GitHub repo. For example, "vulndb" is the repo
54+
// name for github.com/golang/vulndb.
55+
Repo string
56+
57+
// Token is access token that authorizes and authenticates
58+
// requests to the GitHub API.
59+
Token string
60+
}
61+
62+
// NewClient creates a Client that will create issues in
6663
// the a GitHub repo.
67-
// A GitHub access token is required to create issues.
68-
func NewGitHubClient(owner, repo, accessToken string) *githubClient {
69-
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken})
64+
func NewClient(cfg *Config) *Client {
65+
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: cfg.Token})
7066
tc := oauth2.NewClient(context.Background(), ts)
71-
return &githubClient{
72-
client: github.NewClient(tc),
73-
owner: owner,
74-
repo: repo,
67+
c := github.NewClient(tc)
68+
return &Client{
69+
client: c,
70+
owner: cfg.Owner,
71+
repo: cfg.Repo,
7572
}
7673
}
7774

75+
// NewTestClient creates a Client for use in tests.
76+
func NewTestClient(cfg *Config, baseURL *url.URL) *Client {
77+
c := NewClient(cfg)
78+
c.client.BaseURL = baseURL
79+
c.client.UploadURL = baseURL
80+
return c
81+
}
82+
7883
// Destination implements Client.Destination.
79-
func (c *githubClient) Destination() string {
84+
func (c *Client) Destination() string {
8085
return fmt.Sprintf("https://github.com/%s/%s", c.owner, c.repo)
8186
}
8287

8388
// Reference implements Client.Reference.
84-
func (c *githubClient) Reference(num int) string {
89+
func (c *Client) Reference(num int) string {
8590
return fmt.Sprintf("%s/issues/%d", c.Destination(), num)
8691
}
8792

8893
// IssueExists implements Client.IssueExists.
89-
func (c *githubClient) IssueExists(ctx context.Context, number int) (_ bool, err error) {
94+
func (c *Client) IssueExists(ctx context.Context, number int) (_ bool, err error) {
9095
defer derrors.Wrap(&err, "IssueExists(%d)", number)
9196

9297
iss, _, err := c.client.Issues.Get(ctx, c.owner, c.repo, number)
@@ -131,7 +136,7 @@ func convertGithubIssueToIssue(ghIss *github.Issue) *Issue {
131136
}
132137

133138
// GetIssue implements Client.GetIssue.
134-
func (c *githubClient) GetIssue(ctx context.Context, number int) (_ *Issue, err error) {
139+
func (c *Client) GetIssue(ctx context.Context, number int) (_ *Issue, err error) {
135140
defer derrors.Wrap(&err, "GetIssue(%d)", number)
136141
ghIss, _, err := c.client.Issues.Get(ctx, c.owner, c.repo, number)
137142
if err != nil {
@@ -143,7 +148,7 @@ func (c *githubClient) GetIssue(ctx context.Context, number int) (_ *Issue, err
143148
}
144149

145150
// GetIssues implements Client.GetIssues
146-
func (c *githubClient) GetIssues(ctx context.Context, opts GetIssuesOptions) (_ []*Issue, err error) {
151+
func (c *Client) GetIssues(ctx context.Context, opts GetIssuesOptions) (_ []*Issue, err error) {
147152
defer derrors.Wrap(&err, "GetIssues()")
148153
clientOpts := &github.IssueListByRepoOptions{
149154
State: opts.State,
@@ -175,7 +180,7 @@ func (c *githubClient) GetIssues(ctx context.Context, opts GetIssuesOptions) (_
175180
}
176181

177182
// CreateIssue implements Client.CreateIssue.
178-
func (c *githubClient) CreateIssue(ctx context.Context, iss *Issue) (number int, err error) {
183+
func (c *Client) CreateIssue(ctx context.Context, iss *Issue) (number int, err error) {
179184
defer derrors.Wrap(&err, "CreateIssue(%s)", iss.Title)
180185

181186
req := &github.IssueRequest{

0 commit comments

Comments
 (0)