mirror of
https://github.com/versity/versitygw.git
synced 2026-08-19 05:36:19 +00:00
Integration test cases for HeadBucket, CopyObject, DeleteObject actions (#117)
* feat: Added integration test cases for HeadBucket, CopyObject, DeleteObjects * feat: Added logger for debugging
This commit is contained in:
@@ -979,6 +979,7 @@ func (p *Posix) HeadObject(bucket, object string) (*s3.HeadObjectOutput, error)
|
||||
}
|
||||
|
||||
func (p *Posix) CopyObject(srcBucket, srcObject, DstBucket, dstObject string) (*s3.CopyObjectOutput, error) {
|
||||
fmt.Println(srcBucket, srcObject, DstBucket, dstObject)
|
||||
_, err := os.Stat(srcBucket)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNoSuchBucket)
|
||||
@@ -1005,7 +1006,12 @@ func (p *Posix) CopyObject(srcBucket, srcObject, DstBucket, dstObject string) (*
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
etag, err := p.PutObject(&s3.PutObjectInput{Bucket: &DstBucket, Key: &dstObject, Body: f})
|
||||
fInfo, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stat object: %w", err)
|
||||
}
|
||||
|
||||
etag, err := p.PutObject(&s3.PutObjectInput{Bucket: &DstBucket, Key: &dstObject, Body: f, ContentLength: fInfo.Size()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -68,17 +68,20 @@ func initTestFlags() []cli.Flag {
|
||||
func initTestCommands() []*cli.Command {
|
||||
return []*cli.Command{
|
||||
{
|
||||
Name: "make-bucket",
|
||||
Usage: "Test bucket creation.",
|
||||
Name: "bucket-actions",
|
||||
Usage: "Test bucket creation, checking the existence, deletes it.",
|
||||
Description: `Calls s3 gateway create-bucket action to create a new bucket,
|
||||
then calls delete-bucket action to delete the bucket.`,
|
||||
calls head-bucket action to check the existence, then calls delete-bucket action to delete the bucket.`,
|
||||
Action: getAction(integration.TestMakeBucket),
|
||||
},
|
||||
{
|
||||
Name: "put-get-object",
|
||||
Usage: "Test put & get object.",
|
||||
Name: "object-actions",
|
||||
Usage: "Test put/get/delete/copy objects.",
|
||||
Description: `Creates a bucket with s3 gateway action, puts an object in it,
|
||||
gets the object from the bucket, deletes both the object and bucket.`,
|
||||
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),
|
||||
},
|
||||
{
|
||||
|
||||
+130
-11
@@ -22,20 +22,34 @@ var (
|
||||
)
|
||||
|
||||
func TestMakeBucket(s *S3Conf) {
|
||||
testname := "test make bucket"
|
||||
testname := "test make/head/delete bucket"
|
||||
runF(testname)
|
||||
|
||||
s3client := s3.NewFromConfig(s.Config())
|
||||
|
||||
bucket := "testbucket"
|
||||
|
||||
err := setup(s, bucket)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err := s3client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: &bucket})
|
||||
cancel()
|
||||
if err == nil {
|
||||
failF("%v: expected error, instead got success response", testname)
|
||||
return
|
||||
}
|
||||
|
||||
err = setup(s, bucket)
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
passF(testname)
|
||||
|
||||
testname = "test delete empty bucket"
|
||||
runF(testname)
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: &bucket})
|
||||
cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = teardown(s, bucket)
|
||||
if err != nil {
|
||||
@@ -46,10 +60,16 @@ func TestMakeBucket(s *S3Conf) {
|
||||
}
|
||||
|
||||
func TestPutGetObject(s *S3Conf) {
|
||||
testname := "test put/get object"
|
||||
testname := "test put/get/delete/copy objects"
|
||||
runF(testname)
|
||||
|
||||
bucket := "testbucket1"
|
||||
dstBucket := "testdstbucket"
|
||||
obj := "myobject"
|
||||
obj2 := "myobject2"
|
||||
copySource := bucket + "/" + obj
|
||||
|
||||
s3client := s3.NewFromConfig(s.Config())
|
||||
|
||||
err := setup(s, bucket)
|
||||
if err != nil {
|
||||
@@ -64,13 +84,22 @@ func TestPutGetObject(s *S3Conf) {
|
||||
csum := sha256.Sum256(data)
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
name := "myobject"
|
||||
s3client := s3.NewFromConfig(s.Config())
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &name,
|
||||
Key: &obj,
|
||||
Body: r,
|
||||
})
|
||||
cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &obj2,
|
||||
Body: r,
|
||||
})
|
||||
cancel()
|
||||
@@ -82,7 +111,7 @@ func TestPutGetObject(s *S3Conf) {
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
out, err := s3client.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &name,
|
||||
Key: &obj,
|
||||
})
|
||||
defer cancel()
|
||||
if err != nil {
|
||||
@@ -108,11 +137,101 @@ func TestPutGetObject(s *S3Conf) {
|
||||
return
|
||||
}
|
||||
|
||||
// Expected error: destination bucket doesn't exist
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{Bucket: &dstBucket, Key: &obj, CopySource: ©Source})
|
||||
cancel()
|
||||
if err == nil {
|
||||
failF("%v: expect bucket not found error instead got success response", testname)
|
||||
return
|
||||
}
|
||||
|
||||
err = setup(s, dstBucket)
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.CopyObject(ctx, &s3.CopyObjectInput{Bucket: &dstBucket, Key: &obj, CopySource: ©Source})
|
||||
cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
copyObjOut, err := s3client.GetObject(ctx, &s3.GetObjectInput{
|
||||
Bucket: &dstBucket,
|
||||
Key: &obj,
|
||||
})
|
||||
defer cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
defer copyObjOut.Body.Close()
|
||||
|
||||
if copyObjOut.ContentLength != int64(datalen) {
|
||||
failF("%v: content length got %v expected %v", testname, copyObjOut.ContentLength, datalen)
|
||||
return
|
||||
}
|
||||
|
||||
b, err = io.ReadAll(copyObjOut.Body)
|
||||
if err != nil {
|
||||
failF("%v: read body %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
copysum := sha256.Sum256(b)
|
||||
if csum != copysum {
|
||||
failF("%v: copied object checksum got %x expected %x", testname, copysum, csum)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
|
||||
_, err = s3client.DeleteObjects(ctx, &s3.DeleteObjectsInput{Bucket: &bucket, Delete: &types.Delete{Objects: []types.ObjectIdentifier{{Key: &obj}, {Key: &obj2}}}})
|
||||
cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
objCount := 0
|
||||
|
||||
in := &s3.ListObjectsV2Input{Bucket: &bucket}
|
||||
for {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
|
||||
out, err := s3client.ListObjectsV2(ctx, in)
|
||||
cancel()
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
objCount += len(out.Contents)
|
||||
if out.IsTruncated {
|
||||
in.ContinuationToken = out.ContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if objCount != 2 {
|
||||
failF("%v: expected object count %v instead got %v", testname, 2, objCount)
|
||||
}
|
||||
|
||||
err = teardown(s, bucket)
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = teardown(s, dstBucket)
|
||||
if err != nil {
|
||||
failF("%v: %v", testname, err)
|
||||
return
|
||||
}
|
||||
|
||||
passF(testname)
|
||||
}
|
||||
|
||||
|
||||
+11
-4
@@ -111,21 +111,28 @@ func containsPart(part int32, list []types.Part) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks if the slices contain the same objects, if the objects doesn't
|
||||
// contain map, slice, channel.
|
||||
func areTagsSame(tags1, tags2 []types.Tag) bool {
|
||||
if len(tags1) != len(tags2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, tag := range tags1 {
|
||||
if *tag.Key != *tags2[i].Key || *tag.Value != *tags2[i].Value {
|
||||
for _, tag := range tags1 {
|
||||
if !containsTag(tag, tags2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func containsTag(tag types.Tag, list []types.Tag) bool {
|
||||
for _, item := range list {
|
||||
if *item.Key == *tag.Key && *item.Value == *tag.Value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkGrants(grts1, grts2 []types.Grant) bool {
|
||||
if len(grts1) != len(grts2) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user