Skip to content

Commit 1ed7511

Browse files
Yaroslav Kravtsovviktigpetterr
authored andcommitted
fix the failing on the conditional skip scan
1 parent 1a839d8 commit 1ed7511

File tree

8 files changed

+209
-30
lines changed

8 files changed

+209
-30
lines changed

pkg/client/testdata/deb_client_mock.go

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,44 @@ package testdata
22

33
import (
44
"bytes"
5+
"github.com/debricked/cli/pkg/client"
56
"io"
67
"net/http"
8+
"net/url"
79
)
810

911
type DebClientMock struct {
10-
responseQueue []MockResponse
12+
realDebClient *client.DebClient
13+
responseQueue []MockResponse
14+
responseUriQueue map[string]MockResponse
1115
}
1216

1317
func NewDebClientMock() *DebClientMock {
14-
return &DebClientMock{responseQueue: []MockResponse{}}
18+
debClient := client.NewDebClient(nil)
19+
return &DebClientMock{
20+
realDebClient: debClient,
21+
responseQueue: []MockResponse{},
22+
responseUriQueue: map[string]MockResponse{}}
1523
}
1624

17-
func (mock *DebClientMock) Get(_ string, _ string) (*http.Response, error) {
18-
return mock.popResponse()
25+
func (mock *DebClientMock) Get(uri string, format string) (*http.Response, error) {
26+
response, err := mock.popResponse(mock.RemoveQueryParamsFromUri(uri))
27+
28+
if response != nil {
29+
return response, err
30+
}
31+
32+
return mock.realDebClient.Get(uri, format)
1933
}
2034

21-
func (mock *DebClientMock) Post(_ string, _ string, _ *bytes.Buffer) (*http.Response, error) {
22-
return mock.popResponse()
35+
func (mock *DebClientMock) Post(uri string, format string, body *bytes.Buffer) (*http.Response, error) {
36+
response, err := mock.popResponse(mock.RemoveQueryParamsFromUri(uri))
37+
38+
if response != nil {
39+
return response, err
40+
}
41+
42+
return mock.realDebClient.Post(uri, format, body)
2343
}
2444

2545
type MockResponse struct {
@@ -32,25 +52,56 @@ func (mock *DebClientMock) AddMockResponse(response MockResponse) {
3252
mock.responseQueue = append(mock.responseQueue, response)
3353
}
3454

35-
func (mock *DebClientMock) popResponse() (*http.Response, error) {
36-
responseMock := mock.responseQueue[0] // The first element is the one to be dequeued.
37-
mock.responseQueue = mock.responseQueue[1:] // Slice off the element once it is dequeued.
38-
39-
res := http.Response{
40-
Status: "",
41-
StatusCode: responseMock.StatusCode,
42-
Proto: "",
43-
ProtoMajor: 0,
44-
ProtoMinor: 0,
45-
Header: nil,
46-
Body: responseMock.ResponseBody,
47-
ContentLength: 0,
48-
TransferEncoding: nil,
49-
Close: false,
50-
Uncompressed: false,
51-
Trailer: nil,
52-
Request: nil,
53-
TLS: nil,
55+
func (mock *DebClientMock) AddMockUriResponse(uri string, response MockResponse) {
56+
mock.responseUriQueue[uri] = response
57+
}
58+
59+
func (mock *DebClientMock) RemoveQueryParamsFromUri(uri string) string {
60+
u, err := url.Parse(uri)
61+
if err != nil {
62+
return uri
63+
}
64+
q := u.Query()
65+
for s := range q {
66+
q.Del(s)
67+
}
68+
u.RawQuery = q.Encode()
69+
return u.String()
70+
}
71+
72+
func (mock *DebClientMock) popResponse(uri string) (*http.Response, error) {
73+
var responseMock MockResponse
74+
_, existsInUriQueue := mock.responseUriQueue[uri]
75+
existsInQueue := len(mock.responseQueue) != 0
76+
if existsInUriQueue {
77+
responseMock = mock.responseUriQueue[uri]
78+
delete(mock.responseUriQueue, uri)
79+
} else if existsInQueue {
80+
responseMock = mock.responseQueue[0] // The first element is the one to be dequeued.
81+
mock.responseQueue = mock.responseQueue[1:] // Slice off the element once it is dequeued.
82+
}
83+
84+
var res http.Response
85+
86+
if existsInUriQueue || existsInQueue {
87+
res = http.Response{
88+
Status: "",
89+
StatusCode: responseMock.StatusCode,
90+
Proto: "",
91+
ProtoMajor: 0,
92+
ProtoMinor: 0,
93+
Header: nil,
94+
Body: responseMock.ResponseBody,
95+
ContentLength: 0,
96+
TransferEncoding: nil,
97+
Close: false,
98+
Uncompressed: false,
99+
Trailer: nil,
100+
Request: nil,
101+
TLS: nil,
102+
}
103+
} else {
104+
return nil, nil
54105
}
55106

56107
return &res, responseMock.Error

pkg/scan/scanner.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ func (dScanner *DebrickedScanner) Scan(o IOptions) error {
100100
return err
101101
}
102102

103+
if result == nil {
104+
fmt.Println("Progress polling terminated due to long scan times. Please try again later")
105+
return nil
106+
}
107+
103108
fmt.Printf("\n%d vulnerabilities found\n", result.VulnerabilitiesFound)
104109
fmt.Println("")
105110
failPipeline := false

pkg/scan/scanner_test.go

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package scan
22

33
import (
4+
"bytes"
5+
"encoding/json"
46
"github.com/debricked/cli/pkg/ci"
57
"github.com/debricked/cli/pkg/ci/argo"
68
"github.com/debricked/cli/pkg/ci/azure"
@@ -12,8 +14,12 @@ import (
1214
"github.com/debricked/cli/pkg/ci/gitlab"
1315
"github.com/debricked/cli/pkg/ci/travis"
1416
"github.com/debricked/cli/pkg/client"
17+
"github.com/debricked/cli/pkg/client/testdata"
18+
"github.com/debricked/cli/pkg/file"
1519
"github.com/debricked/cli/pkg/git"
1620
"github.com/debricked/cli/pkg/upload"
21+
"io"
22+
"net/http"
1723
"os"
1824
"path/filepath"
1925
"strings"
@@ -166,6 +172,85 @@ func TestScanBadOpts(t *testing.T) {
166172
}
167173
}
168174

175+
func TestScanEmptyResult(t *testing.T) {
176+
var debClient client.IDebClient
177+
clientMock := testdata.NewDebClientMock()
178+
179+
// Create mocked formats response
180+
formats := []file.Format{{
181+
Regex: "",
182+
LockFileRegexes: []string{"yarn\\.lock"},
183+
}}
184+
formatsBytes, _ := json.Marshal(formats)
185+
formatsMockRes := testdata.MockResponse{
186+
StatusCode: http.StatusOK,
187+
ResponseBody: io.NopCloser(bytes.NewReader(formatsBytes)),
188+
}
189+
clientMock.AddMockUriResponse("/api/1.0/open/files/supported-formats", formatsMockRes)
190+
191+
// Create mocked file upload response
192+
uploadMockRes := testdata.MockResponse{
193+
StatusCode: http.StatusOK,
194+
ResponseBody: io.NopCloser(strings.NewReader("{\"ciUploadId\": 1}")),
195+
}
196+
clientMock.AddMockUriResponse("/api/1.0/open/uploads/dependencies/files", uploadMockRes)
197+
198+
// Create a mocked finish response
199+
finishMockRes := testdata.MockResponse{
200+
StatusCode: http.StatusNoContent,
201+
ResponseBody: io.NopCloser(strings.NewReader("{}")),
202+
}
203+
clientMock.AddMockUriResponse("/api/1.0/open/finishes/dependencies/files/uploads", finishMockRes)
204+
205+
// Create mocked scan result response, 201 is returned when the queue time are too long
206+
scanMockRes := testdata.MockResponse{
207+
StatusCode: http.StatusCreated,
208+
ResponseBody: io.NopCloser(strings.NewReader("{}")),
209+
}
210+
clientMock.AddMockUriResponse("/api/1.0/open/ci/upload/status", scanMockRes)
211+
212+
debClient = clientMock
213+
214+
var ciService ci.IService
215+
ciService = ci.NewService(nil)
216+
scanner, _ := NewDebrickedScanner(&debClient, ciService)
217+
path := "testdata/yarn"
218+
repositoryName := path
219+
commitName := "testdata/yarn-commit"
220+
cwd, _ := os.Getwd()
221+
opts := DebrickedOptions{
222+
Path: path,
223+
Exclusions: nil,
224+
RepositoryName: repositoryName,
225+
CommitName: commitName,
226+
BranchName: "",
227+
CommitAuthor: "",
228+
RepositoryUrl: "",
229+
IntegrationName: "",
230+
}
231+
232+
rescueStdout := os.Stdout
233+
r, w, _ := os.Pipe()
234+
os.Stdout = w
235+
236+
err := scanner.Scan(opts)
237+
238+
_ = w.Close()
239+
out, _ := io.ReadAll(r)
240+
os.Stdout = rescueStdout
241+
242+
existsMessageInCMDOutput := strings.Contains(
243+
string(out),
244+
"Progress polling terminated due to long scan times. Please try again later")
245+
246+
if err != nil || !existsMessageInCMDOutput {
247+
t.Error("failed to assert that scan ran without errors. Error:", err)
248+
}
249+
250+
// reset working directory that has been manipulated in scanner.Scan
251+
_ = os.Chdir(cwd)
252+
}
253+
169254
func TestMapEnvToOptions(t *testing.T) {
170255
dOptionsTemplate := DebrickedOptions{
171256
Path: "path",
@@ -328,7 +413,12 @@ func TestSetWorkingDirectory(t *testing.T) {
328413
for _, c := range cases {
329414
t.Run(c.name, func(t *testing.T) {
330415
err := SetWorkingDirectory(&c.opts)
331-
defer os.Chdir(cwd)
416+
defer func(dir string) {
417+
err := os.Chdir(dir)
418+
if err != nil {
419+
t.Fatal("Can not read the directory: ", dir)
420+
}
421+
}(cwd)
332422

333423
if len(c.errMessages) > 0 {
334424
containsCorrectErrMsg := false

pkg/upload/batch.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import (
2222
)
2323

2424
var (
25-
NoFilesErr = errors.New("failed to find dependency files")
25+
NoFilesErr = errors.New("failed to find dependency files")
26+
PollingTerminatedErr = errors.New("progress polling terminated due to long queue times")
2627
)
2728

2829
type uploadBatch struct {
@@ -182,9 +183,9 @@ func (uploadBatch *uploadBatch) wait() (*UploadResult, error) {
182183
if res.StatusCode == http.StatusCreated {
183184
err := bar.Finish()
184185
if err != nil {
185-
return nil, err
186+
return resultStatus, err
186187
}
187-
return nil, errors.New("progress polling terminated due to long queue times")
188+
return resultStatus, PollingTerminatedErr
188189
}
189190
status, err := newUploadStatus(res)
190191
if err != nil {

pkg/upload/batch_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/debricked/cli/pkg/client/testdata"
99
"github.com/debricked/cli/pkg/file"
1010
"github.com/debricked/cli/pkg/git"
11+
"io"
1112
"log"
1213
"net/http"
1314
"os"
@@ -65,3 +66,29 @@ func captureOutput(f func()) string {
6566
log.SetOutput(os.Stderr)
6667
return buf.String()
6768
}
69+
70+
func TestWaitWithPollingTerminatedError(t *testing.T) {
71+
group := file.NewGroup("package.json", nil, []string{"yarn.lock"})
72+
var groups file.Groups
73+
groups.Add(*group)
74+
metaObj, err := git.NewMetaObject("", "repository-name", "commit-name", "", "", "")
75+
if err != nil {
76+
t.Fatal("failed to create new MetaObject")
77+
}
78+
79+
var c client.IDebClient
80+
clientMock := testdata.NewDebClientMock()
81+
mockRes := testdata.MockResponse{
82+
StatusCode: http.StatusCreated,
83+
ResponseBody: io.NopCloser(strings.NewReader("{}")),
84+
}
85+
clientMock.AddMockResponse(mockRes)
86+
c = clientMock
87+
batch := newUploadBatch(&c, groups, metaObj, "CLI")
88+
89+
uploadResult, err := batch.wait()
90+
91+
if uploadResult != nil && err != PollingTerminatedErr {
92+
t.Fatal("Upload result must be nil and err must be PollingTerminatedErr")
93+
}
94+
}

pkg/upload/uploader.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ func (uploader *Uploader) Upload(o IOptions) (*UploadResult, error) {
4040
}
4141

4242
result, err := batch.wait()
43+
4344
if err != nil {
45+
// the command should not fail because some file can't be scanned
46+
if err == PollingTerminatedErr {
47+
return result, nil
48+
}
4449
return nil, err
4550
}
4651

scripts/test_cli.sh

100644100755
File mode changed.

scripts/test_docker.sh

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ case $type in
1313
docker build -f build/docker/Dockerfile -t debricked/cli-scan:latest --target scan .
1414
;;
1515
*)
16-
echo "${type} type is not supported!"
16+
echo -e "Please use the following type dev, cli, scan. For example ./test_docker.sh dev"
1717
exit 1
1818
;;
1919
esac

0 commit comments

Comments
 (0)