feat: Closes #189, added utility functions for testing, restructured tests for CreateBucket, DeleteBucket... and 5 more actions

This commit is contained in:
jonaustin09
2023-08-11 02:13:01 +04:00
parent a325dd6834
commit 2cc0c7203c
4 changed files with 1790 additions and 1543 deletions

View File

@@ -67,114 +67,6 @@ func initTestFlags() []cli.Flag {
func initTestCommands() []*cli.Command {
return []*cli.Command{
{
Name: "bucket-actions",
Usage: "Test bucket creation, checking the existence, deletes it.",
Description: `Calls s3 gateway create-bucket action to create a new bucket,
calls head-bucket action to check the existence, then calls delete-bucket action to delete the bucket.`,
Action: getAction(integration.TestMakeBucket),
},
{
Name: "object-actions",
Usage: "Test put/get/delete/copy objects.",
Description: `Creates a bucket with s3 gateway action, puts an object in it,
tries to copy into another bucket, that doesn't exist, creates the destination bucket for copying,
copies the object, get's the object to check the length and content,
get's the copied object to check the length and content, deletes all the objects inside the source bucket,
deletes both the objects and buckets.`,
Action: getAction(integration.TestPutGetObject),
},
{
Name: "put-get-mp-object",
Usage: "Test put & get multipart object.",
Description: `Creates a bucket with s3 gateway action, puts an object in it with multipart upload,
gets the object from the bucket, deletes both the object and bucket.`,
Action: getAction(integration.TestPutGetMPObject),
},
{
Name: "put-dir-object",
Usage: "Test put directory object.",
Description: `Creates a bucket with s3 gateway action, puts a directory object in it,
lists the bucket's objects, deletes both the objects and bucket.`,
Action: getAction(integration.TestPutDirObject),
},
{
Name: "list-objects",
Usage: "Test list-objects action.",
Description: `Creates a bucket with s3 gateway action, puts 2 directory objects in it,
lists the bucket's objects, deletes both the objects and bucket.`,
Action: getAction(integration.TestListObject),
},
{
Name: "abort-mp",
Usage: "Tests abort-multipart-upload action.",
Description: `Creates a bucket with s3 gateway action, creates a multipart upload,
lists the multipart upload, aborts the multipart upload, lists the multipart upload again,
deletes both the objects and bucket.`,
Action: getAction(integration.TestListAbortMultiPartObject),
},
{
Name: "list-parts",
Usage: "Tests list-parts action.",
Description: `Creates a bucket with s3 gateway action, creates a multipart upload,
lists the upload parts, deletes both the objects and bucket.`,
Action: getAction(integration.TestListMultiParts),
},
{
Name: "incorrect-mp",
Usage: "Tests incorrect multipart case.",
Description: `Creates a bucket with s3 gateway action, creates a multipart upload,
uploads different parts, completes the multipart upload with incorrect part numbers,
calls the head-object action, compares the content length, removes both the object and bucket`,
Action: getAction(integration.TestIncorrectMultiParts),
},
{
Name: "incomplete-mp",
Usage: "Tests incomplete multi parts.",
Description: `Creates a bucket with s3 gateway action, creates a multipart upload,
upload a part, lists the parts, checks if the uploaded part is in the list,
removes both the object and the bucket`,
Action: getAction(integration.TestIncompleteMultiParts),
},
{
Name: "incomplete-put-object",
Usage: "Tests incomplete put objects case.",
Description: `Creates a bucket with s3 gateway action, puts an object in it,
gets the object with head-object action, expects the object to be got,
removes both the object and bucket`,
Action: getAction(integration.TestIncompletePutObject),
},
{
Name: "get-range",
Usage: "Tests get object by range.",
Description: `Creates a bucket with s3 gateway action, puts an object in it,
gets the object by specifying the object range, compares the range with the original one,
removes both the object and the bucket`,
Action: getAction(integration.TestRangeGet),
},
{
Name: "invalid-mp",
Usage: "Tests invalid multi part case.",
Description: `Creates a bucket with s3 gateway action, creates a multi part upload,
uploads an invalid part, gets the object with head-object action, expects to get error,
removes both the object and bucket`,
Action: getAction(integration.TestInvalidMultiParts),
},
{
Name: "object-tag-actions",
Usage: "Tests get/put/delete object tag actions.",
Description: `Creates a bucket with s3 gateway action, puts an object in it,
puts some tags for the object, gets the tags, compares the results, removes the tags,
gets the tags again, checks it to be empty, then removes both the object and bucket`,
Action: getAction(integration.TestPutGetRemoveTags),
},
{
Name: "bucket-acl-actions",
Usage: "Tests put/get bucket actions.",
Description: `Creates a bucket with s3 gateway action, puts some bucket acls
gets the acl, verifies it, then removes the bucket`,
Action: getAction(integration.TestAclActions),
},
{
Name: "full-flow",
Usage: "Tests the full flow of gateway.",

View File

@@ -0,0 +1,58 @@
package integration
func TestCreateBucket(s *S3Conf) {
CreateBucket_invalid_bucket_name(s)
CreateBucket_existing_bucket(s)
CreateDeleteBucket_success(s)
}
func TestDeleteBucket(s *S3Conf) {
DeleteBucket_non_existing_bucket(s)
DeleteBucket_non_empty_bucket(s)
}
func TestPutObject(s *S3Conf) {
PutObject_non_existing_bucket(s)
PutObject_special_chars(s)
PutObject_existing_dir_obj(s)
PutObject_obj_parent_is_file(s)
PutObject_success(s)
}
func TestGetObject(s *S3Conf) {
GetObject_non_existing_key(s)
GetObject_invalid_ranges(s)
GetObject_with_meta(s)
GetObject_success(s)
GetObject_by_range_success(s)
}
func TestCopyObject(s *S3Conf) {
CopyObject_non_existing_dst_bucket(s)
CopyObject_success(s)
}
func TestPutObjectTagging(s *S3Conf) {
PutObjectTagging_non_existing_object(s)
PutObjectTagging_success(s)
}
func TestGetObjectTagging(s *S3Conf) {
GetObjectTagging_non_existing_object(s)
GetObjectTagging_success(s)
}
func TestDeleteObjectTagging(s *S3Conf) {
DeleteObjectTagging_non_existing_object(s)
DeleteObjectTagging_success(s)
}
func TestFullFlow(s *S3Conf) {
TestCreateBucket(s)
TestDeleteBucket(s)
TestPutObject(s)
TestGetObject(s)
TestCopyObject(s)
TestPutObjectTagging(s)
TestDeleteObjectTagging(s)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,30 @@
package integration
import (
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
"errors"
"fmt"
"os/exec"
"strings"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/smithy-go"
"github.com/versity/versitygw/s3err"
)
var (
bcktCount = 0
)
func getBucketName() string {
bcktCount++
return fmt.Sprintf("test-bucket-%v", bcktCount)
}
func setup(s *S3Conf, bucket string) error {
s3client := s3.NewFromConfig(s.Config())
@@ -69,6 +84,78 @@ func teardown(s *S3Conf, bucket string) error {
return err
}
func actionHandler(s *S3Conf, testName string, handler func(s3client *s3.Client, bucket string) error) {
runF(testName)
bucketName := getBucketName()
err := setup(s, bucketName)
if err != nil {
failF("%v: failed to create a bucket: %v", testName, err.Error())
return
}
client := s3.NewFromConfig(s.Config())
handlerErr := handler(client, bucketName)
if handlerErr != nil {
failF("%v: %v", testName, handlerErr.Error())
}
err = teardown(s, bucketName)
if err != nil {
if handlerErr == nil {
failF("%v: failed to delete the bucket: %v", testName, err.Error())
} else {
fmt.Printf(colorRed+"%v: failed to delete the bucket: %v", testName, err.Error())
}
}
if handlerErr == nil {
passF(testName)
}
}
func putObjects(client *s3.Client, objs []string, bucket string) error {
for _, key := range objs {
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := client.PutObject(ctx, &s3.PutObjectInput{
Key: &key,
Bucket: &bucket,
})
cancel()
if err != nil {
return err
}
}
return nil
}
func checkApiErr(err error, apiErr s3err.APIError) error {
if err == nil {
return fmt.Errorf("expected %v, instead got nil", apiErr.Code)
}
var ae smithy.APIError
if errors.As(err, &ae) {
if ae.ErrorCode() == apiErr.Code && ae.ErrorMessage() == apiErr.Description {
return nil
}
return fmt.Errorf("expected %v, instead got %v", apiErr.Code, ae.ErrorCode())
} else {
return fmt.Errorf("expected aws api error, instead got: %v", err.Error())
}
}
func putObjectWithData(lgth int64, input *s3.PutObjectInput, client *s3.Client) (csum [32]byte, data []byte, err error) {
data = make([]byte, lgth)
rand.Read(data)
csum = sha256.Sum256(data)
r := bytes.NewReader(data)
input.Body = r
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err = client.PutObject(ctx, input)
cancel()
return
}
func isEqual(a, b []byte) bool {
if len(a) != len(b) {
return false
@@ -162,6 +249,10 @@ func getString(str *string) string {
return *str
}
func getPtr(str string) *string {
return &str
}
func areMapsSame(mp1, mp2 map[string]string) bool {
if len(mp1) != len(mp2) {
return false