mirror of
https://github.com/versity/versitygw.git
synced 2026-01-10 13:27:21 +00:00
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/versity/scoutgw/s3err"
|
||||
)
|
||||
|
||||
//go:generate moq -out backend_moq_test.go . Backend
|
||||
//go:generate moq -out ../s3api/controllers/backend_moq_test.go . Backend
|
||||
type Backend interface {
|
||||
fmt.Stringer
|
||||
GetIAMConfig() ([]byte, error)
|
||||
|
||||
1794
backend/backend_moq_test.go
Normal file
1794
backend/backend_moq_test.go
Normal file
File diff suppressed because it is too large
Load Diff
204
backend/backend_test.go
Normal file
204
backend/backend_test.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/versity/scoutgw/s3err"
|
||||
)
|
||||
|
||||
func TestBackend_ListBuckets(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
c Backend
|
||||
args args
|
||||
wantErr bool
|
||||
}
|
||||
var tests []test
|
||||
tests = append(tests, test{
|
||||
name: "list-Bucket",
|
||||
c: &BackendMock{
|
||||
ListBucketsFunc: func() (*s3.ListBucketsOutput, error) {
|
||||
return &s3.ListBucketsOutput{
|
||||
Buckets: []types.Bucket{
|
||||
{
|
||||
Name: aws.String("t1"),
|
||||
},
|
||||
},
|
||||
}, s3err.GetAPIError(0)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
wantErr: false,
|
||||
}, test{
|
||||
name: "list-Bucket-error",
|
||||
c: &BackendMock{
|
||||
ListBucketsFunc: func() (*s3.ListBucketsOutput, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
wantErr: true,
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := tt.c.ListBuckets(); (err.(s3err.APIError).Code != "") != tt.wantErr {
|
||||
t.Errorf("Backend.ListBuckets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestBackend_HeadBucket(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
BucketName string
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
c Backend
|
||||
args args
|
||||
wantErr bool
|
||||
}
|
||||
var tests []test
|
||||
tests = append(tests, test{
|
||||
name: "head-buckets-error",
|
||||
c: &BackendMock{
|
||||
HeadBucketFunc: func(bucket string) (*s3.HeadBucketOutput, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
BucketName: "b1",
|
||||
},
|
||||
wantErr: true,
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := tt.c.HeadBucket(tt.args.BucketName); (err.(s3err.APIError).Code != "") != tt.wantErr {
|
||||
t.Errorf("Backend.HeadBucket() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestBackend_GetBucketAcl(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
bucketName string
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
c Backend
|
||||
args args
|
||||
wantErr bool
|
||||
}
|
||||
var tests []test
|
||||
tests = append(tests, test{
|
||||
name: "get bucket acl error",
|
||||
c: &BackendMock{
|
||||
GetBucketAclFunc: func(bucket string) (*s3.GetBucketAclOutput, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
bucketName: "b1",
|
||||
},
|
||||
wantErr: true,
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := tt.c.GetBucketAcl(tt.args.bucketName); (err.(s3err.APIError).Code != "") != tt.wantErr {
|
||||
t.Errorf("Backend.GetBucketAcl() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestBackend_PutBucket(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
bucketName string
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
c Backend
|
||||
args args
|
||||
wantErr bool
|
||||
}
|
||||
var tests []test
|
||||
tests = append(tests, test{
|
||||
name: "put bucket ",
|
||||
c: &BackendMock{
|
||||
PutBucketFunc: func(bucket string) error {
|
||||
return s3err.GetAPIError(0)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
bucketName: "b1",
|
||||
},
|
||||
wantErr: false,
|
||||
}, test{
|
||||
name: "put bucket error",
|
||||
c: &BackendMock{
|
||||
PutBucketFunc: func(bucket string) error {
|
||||
return s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
bucketName: "b2",
|
||||
},
|
||||
wantErr: true,
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.PutBucket(tt.args.bucketName); (err.(s3err.APIError).Code != "") != tt.wantErr {
|
||||
t.Errorf("Backend.PutBucket() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestBackend_DeleteBucket(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
bucketName string
|
||||
}
|
||||
type test struct {
|
||||
name string
|
||||
c Backend
|
||||
args args
|
||||
wantErr bool
|
||||
}
|
||||
var tests []test
|
||||
tests = append(tests, test{
|
||||
name: "Delete Bucket Error",
|
||||
c: &BackendMock{
|
||||
DeleteBucketFunc: func(bucket string) error {
|
||||
return s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
bucketName: "b1",
|
||||
},
|
||||
wantErr: true,
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.DeleteBucket(tt.args.bucketName); (err.(s3err.APIError).Code != "") != tt.wantErr {
|
||||
t.Errorf("Backend.DeleteBucket() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.0
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.33.1
|
||||
github.com/gofiber/fiber/v2 v2.45.0
|
||||
github.com/valyala/fasthttp v1.47.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/pkg/xattr v0.4.9
|
||||
golang.org/x/sys v0.8.0
|
||||
@@ -32,6 +33,5 @@ require (
|
||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
||||
github.com/tinylib/msgp v1.1.8 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.47.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
)
|
||||
|
||||
1796
s3api/controllers/backend_moq_test.go
Normal file
1796
s3api/controllers/backend_moq_test.go
Normal file
File diff suppressed because it is too large
Load Diff
715
s3api/controllers/base_test.go
Normal file
715
s3api/controllers/base_test.go
Normal file
@@ -0,0 +1,715 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/versity/scoutgw/backend"
|
||||
"github.com/versity/scoutgw/s3err"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
type args struct {
|
||||
be backend.Backend
|
||||
}
|
||||
|
||||
be := backend.BackendUnsupported{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want S3ApiController
|
||||
}{
|
||||
{
|
||||
name: "Initialize S3 api controller",
|
||||
args: args{
|
||||
be: be,
|
||||
},
|
||||
want: S3ApiController{
|
||||
be: be,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := New(tt.args.be); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("New() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_ListBuckets(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "List-bucket-not-implemented",
|
||||
c: S3ApiController{
|
||||
be: backend.BackendUnsupported{},
|
||||
},
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 501,
|
||||
},
|
||||
{
|
||||
name: "list-bucket-success",
|
||||
c: S3ApiController{
|
||||
be: &BackendMock{
|
||||
ListBucketsFunc: func() (*s3.ListBucketsOutput, error) {
|
||||
return &s3.ListBucketsOutput{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.c.ListBuckets(tt.args.ctx)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.ListBuckets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
statusCode := tt.args.ctx.Response().StatusCode()
|
||||
|
||||
if statusCode != tt.statusCode {
|
||||
t.Errorf("S3ApiController.ListBuckets() code = %v, wantErr %v", statusCode, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_GetActions(t *testing.T) {
|
||||
type args struct {
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
s3ApiController := S3ApiController{be: &BackendMock{
|
||||
ListObjectPartsFunc: func(bucket, object, uploadID string, partNumberMarker int, maxParts int) (*s3.ListPartsOutput, error) {
|
||||
return &s3.ListPartsOutput{}, nil
|
||||
},
|
||||
GetObjectAclFunc: func(bucket, object string) (*s3.GetObjectAclOutput, error) {
|
||||
return &s3.GetObjectAclOutput{}, nil
|
||||
},
|
||||
GetObjectAttributesFunc: func(bucket, object string, attributes []string) (*s3.GetObjectAttributesOutput, error) {
|
||||
return &s3.GetObjectAttributesOutput{}, nil
|
||||
},
|
||||
GetObjectFunc: func(bucket, object string, startOffset, length int64, writer io.Writer, etag string) (*s3.GetObjectOutput, error) {
|
||||
return &s3.GetObjectOutput{Metadata: nil}, nil
|
||||
},
|
||||
}}
|
||||
app.Get("/:bucket/:key/*", s3ApiController.GetActions)
|
||||
|
||||
// GetObjectACL
|
||||
getObjectACLReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil)
|
||||
getObjectACLReq.Header.Set("X-Amz-Object-Attributes", "attrs")
|
||||
|
||||
// GetObject error case
|
||||
getObjectReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil)
|
||||
getObjectReq.Header.Set("Range", "hello=")
|
||||
|
||||
// GetObject success case
|
||||
getObjectSuccessReq := httptest.NewRequest(http.MethodGet, "/my-bucket/key", nil)
|
||||
getObjectReq.Header.Set("Range", "range=13-invalid")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
app *fiber.App
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Get-actions-invalid-max-parts",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=InvalidMaxParts", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Get-actions-invalid-part-number",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=200&part-number-marker=InvalidPartNumber", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Get-actions-list-object-parts-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket/key?uploadId=hello&max-parts=200&part-number-marker=23", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Get-actions-get-object-acl-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: getObjectACLReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Get-actions-invalid-range-header",
|
||||
app: app,
|
||||
args: args{
|
||||
req: getObjectReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Get-actions-get-object-error",
|
||||
app: app,
|
||||
args: args{
|
||||
req: getObjectSuccessReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resp, err := tt.app.Test(tt.args.req)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.GetActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if resp.StatusCode != tt.statusCode {
|
||||
t.Errorf("S3ApiController.GetActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_ListActions(t *testing.T) {
|
||||
type args struct {
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
s3ApiController := S3ApiController{be: &BackendMock{
|
||||
GetBucketAclFunc: func(bucket string) (*s3.GetBucketAclOutput, error) {
|
||||
return &s3.GetBucketAclOutput{}, nil
|
||||
},
|
||||
ListMultipartUploadsFunc: func(output *s3.ListMultipartUploadsInput) (*s3.ListMultipartUploadsOutput, error) {
|
||||
return &s3.ListMultipartUploadsOutput{}, nil
|
||||
},
|
||||
ListObjectsV2Func: func(bucket, prefix, marker, delim string, maxkeys int) (*s3.ListBucketsOutput, error) {
|
||||
return &s3.ListBucketsOutput{}, nil
|
||||
},
|
||||
ListObjectsFunc: func(bucket, prefix, marker, delim string, maxkeys int) (*s3.ListBucketsOutput, error) {
|
||||
return &s3.ListBucketsOutput{}, nil
|
||||
},
|
||||
}}
|
||||
app.Get("/:bucket", s3ApiController.ListActions)
|
||||
|
||||
//Error case
|
||||
s3ApiControllerError := S3ApiController{be: &BackendMock{
|
||||
ListObjectsFunc: func(bucket, prefix, marker, delim string, maxkeys int) (*s3.ListBucketsOutput, error) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNotImplemented)
|
||||
},
|
||||
}}
|
||||
appError := fiber.New()
|
||||
appError.Get("/:bucket", s3ApiControllerError.ListActions)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
app *fiber.App
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Get-bucket-acl-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket?acl=acl", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "List-Multipart-Upload-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket?uploads=uploads", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "List-Objects-V2-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket?list-type=2", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "List-Objects-V1-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "List-actions-error-case",
|
||||
app: appError,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodGet, "/my-bucket", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 501,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resp, err := tt.app.Test(tt.args.req)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.GetActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if resp.StatusCode != tt.statusCode {
|
||||
t.Errorf("S3ApiController.GetActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_PutBucketActions(t *testing.T) {
|
||||
type args struct {
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
s3ApiController := S3ApiController{be: &BackendMock{
|
||||
PutBucketAclFunc: func(*s3.PutBucketAclInput) error {
|
||||
return nil
|
||||
},
|
||||
PutBucketFunc: func(bucket string) error {
|
||||
return nil
|
||||
},
|
||||
}}
|
||||
app.Put("/:bucket", s3ApiController.PutBucketActions)
|
||||
|
||||
// Error case
|
||||
errorReq := httptest.NewRequest(http.MethodPut, "/my-bucket", nil)
|
||||
errorReq.Header.Set("X-Amz-Acl", "restricted")
|
||||
errorReq.Header.Set("X-Amz-Grant-Read", "read")
|
||||
|
||||
// PutBucketAcl success
|
||||
aclReq := httptest.NewRequest(http.MethodPut, "/my-bucket", nil)
|
||||
errorReq.Header.Set("X-Amz-Acl", "full")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
app *fiber.App
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Put-bucket-acl-error",
|
||||
app: app,
|
||||
args: args{
|
||||
req: errorReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Put-object-acl-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: aclReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Put-bucket-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodPut, "/my-bucket", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
resp, err := tt.app.Test(tt.args.req)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.GetActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if resp.StatusCode != tt.statusCode {
|
||||
t.Errorf("S3ApiController.GetActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_PutActions(t *testing.T) {
|
||||
type args struct {
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
s3ApiController := S3ApiController{be: &BackendMock{
|
||||
UploadPartCopyFunc: func(*s3.UploadPartCopyInput) (*s3.UploadPartCopyOutput, error) {
|
||||
return &s3.UploadPartCopyOutput{}, nil
|
||||
},
|
||||
UploadPartFunc: func(bucket, object, uploadId string, Body io.ReadSeeker) (*s3.UploadPartOutput, error) {
|
||||
return &s3.UploadPartOutput{}, nil
|
||||
},
|
||||
PutObjectAclFunc: func(*s3.PutObjectAclInput) error {
|
||||
return nil
|
||||
},
|
||||
CopyObjectFunc: func(srcBucket, srcObject, DstBucket, dstObject string) (*s3.CopyObjectOutput, error) {
|
||||
return &s3.CopyObjectOutput{}, nil
|
||||
},
|
||||
PutObjectFunc: func(bucket, object string, r io.Reader) (string, error) {
|
||||
return "hello", nil
|
||||
},
|
||||
}}
|
||||
app.Put("/:bucket/:key/*", s3ApiController.PutActions)
|
||||
|
||||
//PutObjectAcl error
|
||||
aclReqErr := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil)
|
||||
aclReqErr.Header.Set("X-Amz-Acl", "acl")
|
||||
aclReqErr.Header.Set("X-Amz-Grant-Write", "write")
|
||||
|
||||
//PutObjectAcl success
|
||||
aclReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil)
|
||||
aclReq.Header.Set("X-Amz-Acl", "acl")
|
||||
|
||||
//CopyObject success
|
||||
cpySrcReq := httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil)
|
||||
cpySrcReq.Header.Set("X-Amz-Copy-Source", "srcBucket/srcObject")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
app *fiber.App
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Upload-copy-part-error-case",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?partNumber=invalid", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Upload-copy-part-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?partNumber=3", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Upload-part-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key?uploadId=234234", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Put-object-acl-error",
|
||||
app: app,
|
||||
args: args{
|
||||
req: aclReqErr,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Put-object-acl-error",
|
||||
app: app,
|
||||
args: args{
|
||||
req: aclReqErr,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Put-object-acl-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: aclReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Copy-object-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: cpySrcReq,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Put-object-success",
|
||||
app: app,
|
||||
args: args{
|
||||
req: httptest.NewRequest(http.MethodPut, "/my-bucket/my-key", nil),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
resp, err := tt.app.Test(tt.args.req)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.GetActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
if resp.StatusCode != tt.statusCode {
|
||||
t.Errorf("S3ApiController.GetActions() statusCode = %v, wantStatusCode = %v", resp.StatusCode, tt.statusCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_DeleteBucket(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.DeleteBucket(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.DeleteBucket() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_DeleteObjects(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.DeleteObjects(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.DeleteObjects() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_DeleteActions(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.DeleteActions(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.DeleteActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_HeadBucket(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.HeadBucket(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.HeadBucket() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_HeadObject(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.HeadObject(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.HeadObject() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiController_CreateActions(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
c S3ApiController
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.c.CreateActions(tt.args.ctx); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiController.CreateActions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_responce(t *testing.T) {
|
||||
type args struct {
|
||||
ctx *fiber.Ctx
|
||||
resp any
|
||||
err error
|
||||
}
|
||||
app := fiber.New()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
statusCode int
|
||||
}{
|
||||
{
|
||||
name: "Internal-server-error",
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
resp: nil,
|
||||
err: s3err.GetAPIError(16),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 500,
|
||||
},
|
||||
{
|
||||
name: "Error-not-implemented",
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
resp: nil,
|
||||
err: s3err.GetAPIError(50),
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 501,
|
||||
},
|
||||
{
|
||||
name: "Invalid-request-body",
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
resp: make(chan int),
|
||||
err: nil,
|
||||
},
|
||||
wantErr: true,
|
||||
statusCode: 200,
|
||||
},
|
||||
{
|
||||
name: "Successful-response",
|
||||
args: args{
|
||||
ctx: app.AcquireCtx(&fasthttp.RequestCtx{}),
|
||||
resp: "Valid response",
|
||||
err: nil,
|
||||
},
|
||||
wantErr: false,
|
||||
statusCode: 200,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := responce(tt.args.ctx, tt.args.resp, tt.args.err); (err != nil) != tt.wantErr {
|
||||
t.Errorf("responce() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
statusCode := tt.args.ctx.Response().StatusCode()
|
||||
|
||||
if statusCode != tt.statusCode {
|
||||
t.Errorf("responce() code = %v, wantErr %v", statusCode, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
34
s3api/router_test.go
Normal file
34
s3api/router_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package s3api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/versity/scoutgw/backend"
|
||||
)
|
||||
|
||||
func TestS3ApiRouter_Init(t *testing.T) {
|
||||
type args struct {
|
||||
app *fiber.App
|
||||
be backend.Backend
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
sa *S3ApiRouter
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "Initialize S3 api router",
|
||||
sa: &S3ApiRouter{},
|
||||
args: args{
|
||||
app: fiber.New(),
|
||||
be: backend.BackendUnsupported{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.sa.Init(tt.args.app, tt.args.be)
|
||||
})
|
||||
}
|
||||
}
|
||||
83
s3api/server_test.go
Normal file
83
s3api/server_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package s3api
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/versity/scoutgw/backend"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
type args struct {
|
||||
app *fiber.App
|
||||
be backend.Backend
|
||||
port string
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
be := backend.BackendUnsupported{}
|
||||
router := S3ApiRouter{}
|
||||
port := ":7070"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantS3ApiServer *S3ApiServer
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Create S3 api server",
|
||||
args: args{
|
||||
app: app,
|
||||
be: be,
|
||||
port: port,
|
||||
},
|
||||
wantS3ApiServer: &S3ApiServer{
|
||||
app: app,
|
||||
port: port,
|
||||
router: &router,
|
||||
backend: be,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotS3ApiServer, err := New(tt.args.app, tt.args.be, tt.args.port)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("New() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotS3ApiServer, tt.wantS3ApiServer) {
|
||||
t.Errorf("New() = %v, want %v", gotS3ApiServer, tt.wantS3ApiServer)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3ApiServer_Serve(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
sa *S3ApiServer
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Return error when serving S3 api server with invalid address",
|
||||
wantErr: true,
|
||||
sa: &S3ApiServer{
|
||||
app: fiber.New(),
|
||||
backend: backend.BackendUnsupported{},
|
||||
port: "Wrong address",
|
||||
router: &S3ApiRouter{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.sa.Serve(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("S3ApiServer.Serve() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user