Skip to content

Commit 94b54b2

Browse files
committed
initial unit & integration test
1 parent 83be4ab commit 94b54b2

File tree

12 files changed

+294
-12
lines changed

12 files changed

+294
-12
lines changed

cmd/common.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,3 @@ func fail(err error) {
1111
fmt.Println(prettyFmt.Error(err))
1212
os.Exit(1)
1313
}
14-
15-
func success(message string) {
16-
fmt.Println(prettyFmt.Success(message))
17-
os.Exit(0)
18-
}

etc/run-test.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
#!/usr/bin/env sh
22

3-
golangci-lint run --fix ./... && go test -coverprofile=coverage.out -v -p 1 ./...
3+
docker run --rm -v $(pwd):/app -w /app golangci/golangci-lint:v1.49.0 golangci-lint run --fix ./... && \
4+
go test -coverprofile=coverage.out -v -p 1 ./...

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/enescakir/emoji v1.0.0
99
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
1010
github.com/golang/mock v1.6.0
11+
github.com/google/uuid v1.1.2
1112
github.com/spf13/cobra v1.5.0
1213
github.com/spf13/viper v1.13.0
1314
)
@@ -17,6 +18,7 @@ require (
1718
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
1819
github.com/acomagu/bufpipe v1.0.3 // indirect
1920
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
21+
github.com/davecgh/go-spew v1.1.1 // indirect
2022
github.com/emirpasic/gods v1.12.0 // indirect
2123
github.com/fatih/color v1.13.0 // indirect
2224
github.com/go-git/gcfg v1.5.0 // indirect
@@ -31,6 +33,7 @@ require (
3133
github.com/mattn/go-runewidth v0.0.13 // indirect
3234
github.com/mitchellh/go-homedir v1.1.0 // indirect
3335
github.com/oklog/ulid v1.3.1 // indirect
36+
github.com/pmezard/go-difflib v1.0.0 // indirect
3437
github.com/rivo/uniseg v0.2.0 // indirect
3538
github.com/sergi/go-diff v1.1.0 // indirect
3639
github.com/xanzy/ssh-agent v0.3.0 // indirect
@@ -41,6 +44,7 @@ require (
4144
)
4245

4346
require (
47+
github.com/brianvoe/gofakeit/v6 v6.19.0
4448
github.com/fsnotify/fsnotify v1.5.4 // indirect
4549
github.com/go-git/go-git/v5 v5.4.2
4650
github.com/hashicorp/hcl v1.0.0 // indirect
@@ -54,6 +58,7 @@ require (
5458
github.com/spf13/cast v1.5.0 // indirect
5559
github.com/spf13/jwalterweatherman v1.1.0 // indirect
5660
github.com/spf13/pflag v1.0.5 // indirect
61+
github.com/stretchr/testify v1.8.0
5762
github.com/subosito/gotenv v1.4.1 // indirect
5863
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
5964
golang.org/x/text v0.3.7 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGL
5454
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
5555
github.com/briandowns/spinner v1.19.0 h1:s8aq38H+Qju89yhp89b4iIiMzMm8YN3p6vGpwyh/a8E=
5656
github.com/briandowns/spinner v1.19.0/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU=
57+
github.com/brianvoe/gofakeit/v6 v6.19.0 h1:g+yJ+meWVEsAmR+bV4mNM/eXI0N+0pZ3D+Mi+G5+YQo=
58+
github.com/brianvoe/gofakeit/v6 v6.19.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8=
5759
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
5860
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
5961
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"idScan": "3cd76071-f869-4b7e-bcc7-568a2004ecdb",
3+
"type": "CLI",
4+
"branch": "fix-cve",
5+
"sha": "7797b477716310ceff32aa705a97ea0fcd03011a",
6+
"ok": false,
7+
"results": {
8+
"count": {
9+
"total": 7,
10+
"new": 7,
11+
"open": 7,
12+
"resolved": 0,
13+
"fixed": 0,
14+
"findings": 0
15+
},
16+
"rules": [
17+
{
18+
"rule": {
19+
"idRule": 7,
20+
"title": "Vulnerable Libraries",
21+
"name": "GR0013",
22+
"docs": "using_vulnerable_libraries.html"
23+
},
24+
"languages": ["javascript"],
25+
"count": {
26+
"total": 3,
27+
"open": 3,
28+
"resolved": 0,
29+
"fixed": 0,
30+
"findings": 0
31+
},
32+
"vulnerabilities": [
33+
{
34+
"idFinding": "eda2569d-020e-4ff7-bd8d-874d7d4359d1",
35+
"status": "VULNERABILITY",
36+
"language": "javascript",
37+
"branch": "refs/tags/v1.21.3",
38+
"path": "package-lock.json",
39+
"lineNumber": 24788,
40+
"introducedBy": "yamilfrich",
41+
"type": "sca",
42+
"metadata": {
43+
"dependencyName": "pkg:npm/hoek@6.1.3",
44+
"currentVersion": "6.1.3",
45+
"patchedVersions": "<0.0.0",
46+
"references": [
47+
"https://ossindex.sonatype.org/vulnerability/sonatype-2020-0074?component-type=npm&component-name=hoek&utm_source=go-http-client&utm_medium=integration&utm_content=1.1"
48+
],
49+
"cvssSeverity": "Medium",
50+
"cvssScore": "5.60",
51+
"cvssVector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L"
52+
},
53+
"severity": {
54+
"idSeverity": 1003,
55+
"name": "Medium"
56+
},
57+
"engineRule": {
58+
"idEngineRule": 5893,
59+
"title": "Vulnerable Dependency",
60+
"name": "SBOM001",
61+
"docs": null,
62+
"engineName": "sbom",
63+
"cvssSeverity": null,
64+
"cvssScore": 0,
65+
"cvssVector": null
66+
}
67+
}
68+
]
69+
}
70+
]
71+
},
72+
"repository": {
73+
"idRepository": 28909,
74+
"name": "core-api",
75+
"defaultBranch": "develop",
76+
"provider": "GITHUB",
77+
"isPrivate": true,
78+
"isEnabled": true,
79+
"createdAt": "2019-11-15T12:52:51.727+00:00",
80+
"updatedAt": "2019-11-15T12:52:51.727+00:00",
81+
"fullName": "guardrailsio/core-api",
82+
"description": "⚡ GuardRails Core API",
83+
"language": "JavaScript"
84+
},
85+
"report": "https://dashboard.guardrails.io/gh/guardrailsio/scans?sha=3cd76071-f869-4b7e-bcc7-568a2004ecdb&type=CLI",
86+
"queuedAt": "2022-09-13T02:55:04.97+00:00",
87+
"scanningAt": "2022-09-13T02:55:07.203+00:00",
88+
"finishedAt": "2022-09-13T02:55:33.534+00:00"
89+
}

internal/command/scan/args_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package scan
2+
3+
import (
4+
"testing"
5+
6+
"github.com/brianvoe/gofakeit/v6"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestScanCommandArgsValidationFailed(t *testing.T) {
11+
type testCase struct {
12+
name string
13+
input Args
14+
}
15+
16+
testCases := []testCase{
17+
{
18+
name: "missing_token",
19+
input: Args{},
20+
},
21+
{
22+
name: "invalid_format",
23+
input: Args{
24+
Token: gofakeit.HexUint32(),
25+
Format: "invalid-format",
26+
},
27+
},
28+
}
29+
30+
for _, tc := range testCases {
31+
err := tc.input.Validate()
32+
assert.NotNil(t, err)
33+
}
34+
}

internal/command/scan/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (h *Handler) Execute(ctx context.Context) error {
154154
}
155155

156156
if h.Args.Output != "" {
157-
if err := outputter.SaveToFile(h.Args.Output, getScanDataResp); err != nil {
157+
if err := outputter.SaveScanDataToFile(h.Args.Output, getScanDataResp); err != nil {
158158
return fmt.Errorf("Couldn't save output, %s", err.Error())
159159
} else if !h.Args.Quiet {
160160
fmt.Printf("\n%s\n", prettyFmt.Success("Output saved"))
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package scan
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"crypto/sha1"
7+
"encoding/json"
8+
"fmt"
9+
"os"
10+
"testing"
11+
12+
"github.com/brianvoe/gofakeit/v6"
13+
"github.com/golang/mock/gomock"
14+
"github.com/google/uuid"
15+
mockarchiver "github.com/guardrailsio/guardrails-cli/internal/archiver/mock"
16+
grclient "github.com/guardrailsio/guardrails-cli/internal/client/guardrails"
17+
mockgrclient "github.com/guardrailsio/guardrails-cli/internal/client/guardrails/mock"
18+
"github.com/guardrailsio/guardrails-cli/internal/config"
19+
"github.com/guardrailsio/guardrails-cli/internal/repository"
20+
mockrepository "github.com/guardrailsio/guardrails-cli/internal/repository/mock"
21+
"github.com/guardrailsio/guardrails-cli/internal/tools/spinner"
22+
"github.com/stretchr/testify/assert"
23+
"github.com/stretchr/testify/require"
24+
)
25+
26+
func TestScanCommandExecuteSuccess(t *testing.T) {
27+
ctx := context.Background()
28+
args := &Args{
29+
Token: "test-token",
30+
Path: "/var/www/guardrails-cli",
31+
Format: "pretty",
32+
Output: "",
33+
Quiet: true,
34+
}
35+
cfg := config.New()
36+
spinner := spinner.New()
37+
38+
mockCtrl := gomock.NewController(t)
39+
defer mockCtrl.Finish()
40+
41+
mockRepo := mockrepository.NewMockRepository(mockCtrl)
42+
mockArc := mockarchiver.NewMockArchiver(mockCtrl)
43+
mockGrClient := mockgrclient.NewMockGuardRailsClient(mockCtrl)
44+
45+
commitMessage := gofakeit.Sentence(5)
46+
sha := sha1.New()
47+
sha.Write([]byte(commitMessage))
48+
encrypted := sha.Sum(nil)
49+
commitHash := fmt.Sprintf("%x", encrypted)
50+
51+
repoMetadata := &repository.Metadata{
52+
Path: args.Path,
53+
Protocol: "https",
54+
Provider: "github",
55+
Name: gofakeit.AppName(),
56+
Branch: gofakeit.Word(),
57+
CommitHash: commitHash,
58+
}
59+
listOfFiles := []string{
60+
".gitignore",
61+
"LICENSE",
62+
"Makefile",
63+
"README.md",
64+
"bin/.gitignore",
65+
"cmd/common.go",
66+
"cmd/root.go",
67+
"cmd/scan.go",
68+
"etc/run-test.sh",
69+
"go.mod",
70+
"go.sum",
71+
"internal/archiver/archiver.go",
72+
"internal/archiver/mock/archiver.go",
73+
"internal/client/client.go",
74+
"internal/client/errors.go",
75+
"internal/client/guardrails/client.go",
76+
"internal/client/guardrails/message.go",
77+
"internal/client/guardrails/mock/client.go",
78+
"internal/command/scan/args.go",
79+
"internal/command/scan/handler.go",
80+
"internal/command/scan/message.go",
81+
"internal/config/config.go",
82+
"internal/formatter/csv/csv.go",
83+
"internal/formatter/json/json.go",
84+
"internal/formatter/pretty/pretty.go",
85+
"internal/formatter/sarif/sarif.go",
86+
"internal/outputter/outputter.go",
87+
"internal/repository/ignorelist.go",
88+
"internal/repository/mock/repository.go",
89+
"internal/repository/repository.go",
90+
"internal/tools/spinner/spinner.go",
91+
"main.go",
92+
}
93+
fileZipName := fmt.Sprintf("%s.zip", repoMetadata.Name)
94+
fileZipByte := bytes.NewReader([]byte{})
95+
createUploadURLReq := &grclient.CreateUploadURLReq{
96+
File: fileZipName,
97+
}
98+
createUploadURLResp := &grclient.CreateUploadURLResp{
99+
SignedURL: gofakeit.URL(),
100+
}
101+
uploadProjectReq := &grclient.UploadProjectReq{
102+
UploadURL: createUploadURLResp.SignedURL,
103+
File: fileZipByte,
104+
}
105+
triggerScanReq := &grclient.TriggerScanReq{
106+
Repository: repoMetadata.Name,
107+
SHA: repoMetadata.CommitHash,
108+
Branch: repoMetadata.Branch,
109+
FileName: fileZipName,
110+
}
111+
triggerScanResp := &grclient.TriggerScanResp{
112+
ScanID: uuid.New().String(),
113+
DashboardURL: gofakeit.URL(),
114+
}
115+
getScanDataReq := &grclient.GetScanDataReq{
116+
ScanID: triggerScanResp.ScanID,
117+
}
118+
119+
file, err := os.Open("../../client/guardrails/mock/get_scan_data.json")
120+
require.NoError(t, err)
121+
defer file.Close()
122+
123+
getScanDataResp := new(grclient.GetScanDataResp)
124+
err = json.NewDecoder(file).Decode(getScanDataResp)
125+
require.NoError(t, err)
126+
127+
gomock.InOrder(
128+
mockRepo.EXPECT().GetMetadataFromRemoteURL().Return(repoMetadata, nil),
129+
mockRepo.EXPECT().ListFiles().Return(listOfFiles, nil),
130+
mockArc.EXPECT().OutputZipToIOReader(repoMetadata.Path, listOfFiles).Return(fileZipByte, nil),
131+
mockGrClient.EXPECT().CreateUploadURL(ctx, createUploadURLReq).Return(createUploadURLResp, nil),
132+
mockGrClient.EXPECT().UploadProject(ctx, uploadProjectReq).Return(nil),
133+
mockGrClient.EXPECT().TriggerScan(ctx, triggerScanReq).Return(triggerScanResp, nil),
134+
mockGrClient.EXPECT().GetScanData(ctx, getScanDataReq).Return(getScanDataResp, nil),
135+
)
136+
137+
cmd := New(args, spinner, cfg, mockRepo, mockArc, mockGrClient)
138+
err = cmd.Execute(ctx)
139+
assert.Nil(t, err)
140+
}

internal/formatter/csv/csv.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func ScanResult(result *guardrailsclient.GetScanDataResp) error {
3838
return err
3939
}
4040

41-
fmt.Printf("%s", string(buf.Bytes()))
41+
fmt.Printf("%s", buf.String())
4242

4343
return nil
4444
}

internal/formatter/pretty/pretty.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func ScanResult(result *guardrailsclient.GetScanDataResp) {
5050

5151
fmt.Println("Not sure how to fix this ?")
5252
for _, l := range r.Languages {
53-
fmt.Printf(text.FgBlue.Sprintf("https://docs.guardrails.io/docs/vulnerabilities/%s/%s\n", l, r.Rule.Docs))
53+
fmt.Println(text.FgBlue.Sprintf("https://docs.guardrails.io/docs/vulnerabilities/%s/%s\n", l, r.Rule.Docs))
5454
}
5555
}
5656
}

0 commit comments

Comments
 (0)