Skip to content

Commit 9685774

Browse files
wip
1 parent d4c1727 commit 9685774

File tree

9 files changed

+244
-73
lines changed

9 files changed

+244
-73
lines changed

internal/fileupload/client_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//go:generate go run github.com/golang/mock/mockgen -package=mocks -destination=./mocks/mock_http_client.go github.com/snyk/cli-extension-os-flows/internal/fileupload/lowlevel SealableClient
2+
package fileupload
3+
4+
import (
5+
"github.com/golang/mock/gomock"
6+
"github.com/google/uuid"
7+
"github.com/snyk/cli-extension-os-flows/internal/fileupload/lowlevel"
8+
"github.com/snyk/cli-extension-os-flows/internal/fileupload/mocks"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"os"
12+
"testing"
13+
)
14+
15+
type File struct {
16+
filename string
17+
content string
18+
}
19+
20+
type FileUploadClient struct {
21+
}
22+
23+
func (c FileUploadClient) UploadDir(dir os.File) (RevisionID, error) {
24+
25+
}
26+
27+
func Test_uploadingADirectory(t *testing.T) {
28+
ctrl := gomock.NewController(t)
29+
defer ctrl.Finish()
30+
sealableClientMock := mocks.NewMockSealableClient(ctrl)
31+
client := NewFileUploadClient(sealableClientMock)
32+
orgID := uuid.New()
33+
dir, files := createFlatDirWithFiles([]File{{
34+
filename: "file1",
35+
content: "content1",
36+
}})
37+
38+
expectRevisionUploaded(sealableClientMock, orgID, files)
39+
40+
revisionID, err := client.UploadDir(dir)
41+
42+
require.NoError(t, err)
43+
require.NotZero(t, revisionID)
44+
}
45+
46+
func expectRevisionUploaded(sealableClientMock *mocks.MockSealableClient, orgID uuid.UUID, files []lowlevel.UploadFile) {
47+
r := uuid.New()
48+
sealableClientMock.EXPECT().CreateRevision(gomock.Any(), gomock.Eq(orgID)).Return(lowlevel.UploadRevisionResponseBody{
49+
Data: lowlevel.UploadRevisionResponseData{
50+
ID: r,
51+
},
52+
})
53+
sealableClientMock.EXPECT().UploadFiles(gomock.Any(), gomock.Eq(orgID), gomock.Eq(r), gomock.Eq(files))
54+
sealableClientMock.EXPECT().SealRevision(gomock.Any(), gomock.Eq(orgID), gomock.Eq(r))
55+
}
56+
57+
func createTempFile() *os.File {
58+
file, err := os.Create(os.TempDir() + "/" + uuid.New().String())
59+
if err != nil {
60+
panic(err)
61+
}
62+
return file
63+
}
64+
65+
func createFlatDirWithFiles(filesContent []File) (dir *os.File, files []lowlevel.UploadFile) {
66+
tempDir, err := os.MkdirTemp("", "cliuploadtest*")
67+
if err != nil {
68+
panic(err)
69+
}
70+
dir, err = os.Open(tempDir)
71+
if err != nil {
72+
panic(err)
73+
}
74+
for _, file := range filesContent {
75+
f, err := os.Create(tempDir + "/" + file.filename)
76+
if err != nil {
77+
panic(err)
78+
}
79+
files = append(files, lowlevel.UploadFile{
80+
Path: file.filename,
81+
File: f,
82+
})
83+
}
84+
return dir, files
85+
}

internal/fileupload/lowlevel/client.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package lowlevel_fileupload //nolint:revive // underscore naming is intentional for this internal package
1+
package lowlevel
22

33
import (
44
"bytes"
55
"context"
66
"encoding/json"
77
"errors"
88
"fmt"
9+
"github.com/snyk/cli-extension-os-flows/internal/fileupload"
910
"io"
1011
"mime/multipart"
1112
"net/http"
@@ -14,23 +15,23 @@ import (
1415
"github.com/snyk/error-catalog-golang-public/snyk_errors"
1516
)
1617

17-
// Client defines the interface for file upload API operations.
18-
type Client interface {
18+
// SealableClient defines the interface for file upload API operations.
19+
type SealableClient interface {
1920
CreateRevision(ctx context.Context, orgID OrgID) (*UploadRevisionResponseBody, error)
20-
UploadFiles(ctx context.Context, orgID OrgID, revisionID RevisionID, files []UploadFile) error
21-
SealRevision(ctx context.Context, orgID OrgID, revisionID RevisionID) (*SealUploadRevisionResponseBody, error)
21+
UploadFiles(ctx context.Context, orgID OrgID, revisionID fileupload.RevisionID, files []UploadFile) error
22+
SealRevision(ctx context.Context, orgID OrgID, revisionID fileupload.RevisionID) (*SealUploadRevisionResponseBody, error)
2223
}
2324

2425
// This will force go to complain if the type doesn't satisfy the interface.
25-
var _ Client = (*HTTPClient)(nil)
26+
var _ SealableClient = (*HTTPSealableClient)(nil)
2627

2728
// Config contains configuration for the file upload client.
2829
type Config struct {
2930
BaseURL string
3031
}
3132

32-
// HTTPClient implements the Client interface for file upload operations via HTTP API.
33-
type HTTPClient struct {
33+
// HTTPSealableClient implements the SealableClient interface for file upload operations via HTTP API.
34+
type HTTPSealableClient struct {
3435
cfg Config
3536
httpClient *http.Client
3637
}
@@ -48,8 +49,8 @@ const FileCountLimit = 100 // arbitrary number, will need to be re-evaluated
4849
const ContentType = "Content-Type"
4950

5051
// NewClient creates a new file upload client with the given configuration and options.
51-
func NewClient(cfg Config, opts ...Opt) *HTTPClient {
52-
c := HTTPClient{cfg, http.DefaultClient}
52+
func NewClient(cfg Config, opts ...Opt) *HTTPSealableClient {
53+
c := HTTPSealableClient{cfg, http.DefaultClient}
5354

5455
for _, opt := range opts {
5556
opt(&c)
@@ -59,7 +60,7 @@ func NewClient(cfg Config, opts ...Opt) *HTTPClient {
5960
}
6061

6162
// CreateRevision creates a new upload revision for the specified organization.
62-
func (c *HTTPClient) CreateRevision(ctx context.Context, orgID OrgID) (*UploadRevisionResponseBody, error) {
63+
func (c *HTTPSealableClient) CreateRevision(ctx context.Context, orgID OrgID) (*UploadRevisionResponseBody, error) {
6364
if orgID == uuid.Nil {
6465
return nil, ErrEmptyOrgID
6566
}
@@ -103,7 +104,7 @@ func (c *HTTPClient) CreateRevision(ctx context.Context, orgID OrgID) (*UploadRe
103104
}
104105

105106
// UploadFiles uploads the provided files to the specified revision. It will not close the file descriptors.
106-
func (c *HTTPClient) UploadFiles(ctx context.Context, orgID OrgID, revisionID RevisionID, files []UploadFile) error {
107+
func (c *HTTPSealableClient) UploadFiles(ctx context.Context, orgID OrgID, revisionID fileupload.RevisionID, files []UploadFile) error {
107108
if orgID == uuid.Nil {
108109
return ErrEmptyOrgID
109110
}
@@ -165,7 +166,7 @@ func (c *HTTPClient) UploadFiles(ctx context.Context, orgID OrgID, revisionID Re
165166
return nil
166167
}
167168

168-
func (c *HTTPClient) streamFilesToPipe(pWriter *io.PipeWriter, mpartWriter *multipart.Writer, files []UploadFile) {
169+
func (c *HTTPSealableClient) streamFilesToPipe(pWriter *io.PipeWriter, mpartWriter *multipart.Writer, files []UploadFile) {
169170
var streamError error
170171
defer func() {
171172
pWriter.CloseWithError(streamError)
@@ -189,7 +190,7 @@ func (c *HTTPClient) streamFilesToPipe(pWriter *io.PipeWriter, mpartWriter *mult
189190
}
190191

191192
// SealRevision seals the specified upload revision, marking it as complete.
192-
func (c *HTTPClient) SealRevision(ctx context.Context, orgID OrgID, revisionID RevisionID) (*SealUploadRevisionResponseBody, error) {
193+
func (c *HTTPSealableClient) SealRevision(ctx context.Context, orgID OrgID, revisionID fileupload.RevisionID) (*SealUploadRevisionResponseBody, error) {
193194
if orgID == uuid.Nil {
194195
return nil, ErrEmptyOrgID
195196
}
@@ -237,7 +238,7 @@ func (c *HTTPClient) SealRevision(ctx context.Context, orgID OrgID, revisionID R
237238
return &respBody, nil
238239
}
239240

240-
func (c *HTTPClient) handleUnexpectedStatusCodes(body io.ReadCloser, statusCode int, status, operation string) error {
241+
func (c *HTTPSealableClient) handleUnexpectedStatusCodes(body io.ReadCloser, statusCode int, status, operation string) error {
241242
bts, err := io.ReadAll(body)
242243
if err != nil {
243244
return fmt.Errorf("failed to read response body: %w", err)

0 commit comments

Comments
 (0)