From da3ad55483531444154eb30a804b742934b1d557 Mon Sep 17 00:00:00 2001 From: jonaustin09 Date: Fri, 11 Aug 2023 23:33:50 +0400 Subject: [PATCH] feat: Added integration test cases for HeadBucket, HeadObject, DeleteObject, DeleteObjects, ListObjects --- integration/action-tests.go | 35 ++ integration/tests.go | 690 +++++++++++++++++++++--------------- integration/utils.go | 52 ++- 3 files changed, 494 insertions(+), 283 deletions(-) diff --git a/integration/action-tests.go b/integration/action-tests.go index f6f2ae4..d94178b 100644 --- a/integration/action-tests.go +++ b/integration/action-tests.go @@ -6,6 +6,11 @@ func TestCreateBucket(s *S3Conf) { CreateDeleteBucket_success(s) } +func TestHeadBucket(s *S3Conf) { + HeadBucket_non_existing_bucket(s) + HeadBucket_success(s) +} + func TestDeleteBucket(s *S3Conf) { DeleteBucket_non_existing_bucket(s) DeleteBucket_non_empty_bucket(s) @@ -19,6 +24,11 @@ func TestPutObject(s *S3Conf) { PutObject_success(s) } +func TestHeadObject(s *S3Conf) { + HeadObject_non_existing_object(s) + HeadObject_success(s) +} + func TestGetObject(s *S3Conf) { GetObject_non_existing_key(s) GetObject_invalid_ranges(s) @@ -27,6 +37,26 @@ func TestGetObject(s *S3Conf) { GetObject_by_range_success(s) } +func TestListObjects(s *S3Conf) { + ListObjects_non_existing_bucket(s) + ListObjects_with_prefix(s) + ListObject_truncated(s) + ListObjects_invalid_max_keys(s) + ListObjects_max_keys_0(s) +} + +func TestDeleteObject(s *S3Conf) { + DeleteObject_non_existing_object(s) + DeleteObject_success(s) +} + +func TestDeleteObjects(s *S3Conf) { + DeleteObjects_empty_input(s) + //TODO: Uncomment this after fixing the bug: #195 + // DeleteObjects_non_existing_objects(s) + DeleteObjects_success(s) +} + func TestCopyObject(s *S3Conf) { CopyObject_non_existing_dst_bucket(s) CopyObject_success(s) @@ -49,9 +79,14 @@ func TestDeleteObjectTagging(s *S3Conf) { func TestFullFlow(s *S3Conf) { TestCreateBucket(s) + TestHeadBucket(s) TestDeleteBucket(s) TestPutObject(s) + TestHeadObject(s) TestGetObject(s) + TestListObjects(s) + TestDeleteObject(s) + TestDeleteObjects(s) TestCopyObject(s) TestPutObjectTagging(s) TestDeleteObjectTagging(s) diff --git a/integration/tests.go b/integration/tests.go index f4c0aa6..e7ba7ee 100644 --- a/integration/tests.go +++ b/integration/tests.go @@ -71,6 +71,38 @@ func CreateBucket_existing_bucket(s *S3Conf) { passF(testName) } +func HeadBucket_non_existing_bucket(s *S3Conf) { + testName := "HeadBucket_non_existing_bucket" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + bcktName := getBucketName() + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.HeadBucket(ctx, &s3.HeadBucketInput{ + Bucket: &bcktName, + }) + cancel() + if err := checkSdkApiErr(err, "NotFound"); err != nil { + return err + } + return nil + }) +} + +func HeadBucket_success(s *S3Conf) { + testName := "HeadBucket_success" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.HeadBucket(ctx, &s3.HeadBucketInput{ + Bucket: &bucket, + }) + cancel() + if err != nil { + return err + } + return nil + }) +} + func CreateDeleteBucket_success(s *S3Conf) { testName := "CreateBucket_success" runF(testName) @@ -184,6 +216,57 @@ func PutObject_success(s *S3Conf) { }) } +func HeadObject_non_existing_object(s *S3Conf) { + testName := "HeadObject_non_existing_object" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: &bucket, + Key: getPtr("my-obj"), + }) + cancel() + if err := checkSdkApiErr(err, "NotFound"); err != nil { + return err + } + return nil + }) +} + +func HeadObject_success(s *S3Conf) { + testName := "HeadObject_success" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + obj, dataLen := "my-obj", int64(1234567) + meta := map[string]string{ + "key1": "val1", + "key2": "val2", + } + + _, _, err := putObjectWithData(dataLen, &s3.PutObjectInput{Bucket: &bucket, Key: &obj, Metadata: meta}, s3client) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.HeadObject(ctx, &s3.HeadObjectInput{ + Bucket: &bucket, + Key: &obj, + }) + defer cancel() + if err != nil { + return err + } + + if !areMapsSame(out.Metadata, meta) { + return fmt.Errorf("incorrect object metadata") + } + if out.ContentLength != dataLen { + return fmt.Errorf("expected data length %v, instead got %v", dataLen, out.ContentLength) + } + + return nil + }) +} + func GetObject_non_existing_key(s *S3Conf) { testName := "GetObject_non_existing_key" actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -390,6 +473,331 @@ func GetObject_by_range_success(s *S3Conf) { }) } +func ListObjects_non_existing_bucket(s *S3Conf) { + testName := "ListObjects_non_existing_bucket" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + bckt := getBucketName() + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bckt, + }) + cancel() + if err := checkSdkApiErr(err, "NoSuchBucket"); err != nil { + return err + } + return nil + }) +} + +func ListObjects_with_prefix(s *S3Conf) { + testName := "ListObjects_with_prefix" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + prefix := "obj" + objWithPrefix := []string{prefix + "/foo", prefix + "/bar", prefix + "/baz/bla"} + err := putObjects(s3client, append(objWithPrefix, []string{"xzy/csf", "hell"}...), bucket) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + Prefix: &prefix, + }) + cancel() + if err != nil { + return err + } + + if *out.Prefix != prefix { + return fmt.Errorf("expected prefix %v, instead got %v", prefix, *out.Prefix) + } + if !compareObjects(objWithPrefix, out.Contents) { + return fmt.Errorf("unexpected output for list objects with prefix") + } + + return nil + }) +} + +func ListObject_truncated(s *S3Conf) { + testName := "ListObject_truncated" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + maxKeys := int32(2) + err := putObjects(s3client, []string{"foo", "bar", "baz"}, bucket) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + MaxKeys: maxKeys, + }) + cancel() + if err != nil { + return err + } + + if !out.IsTruncated { + return fmt.Errorf("expected output to be truncated") + } + + if out.MaxKeys != maxKeys { + return fmt.Errorf("expected max-keys to be %v, instead got %v", maxKeys, out.MaxKeys) + } + + if !compareObjects([]string{"bar", "baz"}, out.Contents) { + return fmt.Errorf("unexpected output for list objects with max-keys") + } + + //TODO: Add next marker checker after bug-fixing + + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + out, err = s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + Marker: out.NextMarker, + }) + cancel() + if err != nil { + return err + } + + if out.IsTruncated { + return fmt.Errorf("expected output not to be truncated") + } + + if !compareObjects([]string{"foo"}, out.Contents) { + return fmt.Errorf("unexpected output for list objects with max-keys") + } + return nil + }) +} + +func ListObjects_invalid_max_keys(s *S3Conf) { + testName := "ListObjects_invalid_max_keys" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + MaxKeys: -5, + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrInvalidMaxKeys)); err != nil { + return err + } + + return nil + }) +} + +func ListObjects_max_keys_0(s *S3Conf) { + testName := "ListObjects_max_keys_0" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + objects := []string{"foo", "bar", "baz"} + err := putObjects(s3client, objects, bucket) + if err != nil { + return err + } + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + MaxKeys: 0, + }) + cancel() + if err != nil { + return nil + } + + if !compareObjects(objects, out.Contents) { + return fmt.Errorf("unexpected output for list objects with max-keys 0") + } + + return nil + }) +} + +//TODO: Add a test case for delimiter after buf-fixing, as delimiter doesn't work as intended + +func DeleteObject_non_existing_object(s *S3Conf) { + testName := "DeleteObject_non_existing_object" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err := s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ + Bucket: &bucket, + Key: getPtr("my-obj"), + }) + cancel() + if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrNoSuchKey)); err != nil { + return err + } + return nil + }) +} + +func DeleteObject_success(s *S3Conf) { + testName := "DeleteObject_success" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + obj := "my-obj" + err := putObjects(s3client, []string{obj}, bucket) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + _, err = s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ + Bucket: &bucket, + Key: &obj, + }) + cancel() + if err != nil { + return err + } + + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + _, err = s3client.GetObject(ctx, &s3.GetObjectInput{ + Bucket: &bucket, + Key: &obj, + }) + defer cancel() + if err := checkSdkApiErr(err, "NoSuchKey"); err != nil { + return err + } + return nil + }) +} + +func DeleteObjects_empty_input(s *S3Conf) { + testName := "DeleteObjects_empty_input" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + objects := []string{"foo", "bar", "baz"} + err := putObjects(s3client, objects, bucket) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.DeleteObjects(ctx, &s3.DeleteObjectsInput{ + Bucket: &bucket, + Delete: &types.Delete{ + Objects: []types.ObjectIdentifier{}, + }, + }) + cancel() + if err != nil { + return err + } + + if len(out.Deleted) != 0 { + return fmt.Errorf("expected deleted object count 0, instead got %v", len(out.Deleted)) + } + if len(out.Errors) != 0 { + return fmt.Errorf("expected 0 errors, instead got %v", len(out.Errors)) + } + + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + res, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + }) + cancel() + if err != nil { + return err + } + + if !compareObjects(objects, res.Contents) { + return fmt.Errorf("unexpected output for list objects with prefix") + } + + return nil + }) +} + +//TODO: Uncomment the test after fixing the bug: #195 +// func DeleteObjects_non_existing_objects(s *S3Conf) { +// testName := "DeleteObjects_empty_input" +// actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { +// delObjects := []types.ObjectIdentifier{{Key: getPtr("obj1")}, {Key: getPtr("obj2")}} +// +// ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) +// out, err := s3client.DeleteObjects(ctx, &s3.DeleteObjectsInput{ +// Bucket: &bucket, +// Delete: &types.Delete{ +// Objects: delObjects, +// }, +// }) +// cancel() +// if err != nil { +// return err +// } + +// if len(out.Deleted) != 0 { +// return fmt.Errorf("expected deleted object count 0, instead got %v", len(out.Deleted)) +// } +// if len(out.Errors) != 2 { +// return fmt.Errorf("expected 2 errors, instead got %v", len(out.Errors)) +// } + +// for _, delErr := range out.Errors { +// if *delErr.Code != "NoSuchKey" { +// return fmt.Errorf("expected NoSuchKey error, instead got %v", *delErr.Code) +// } +// } + +// return nil +// }) +// } + +func DeleteObjects_success(s *S3Conf) { + testName := "DeleteObjects_success" + actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + objects, objToDel := []string{"obj1", "obj2", "obj3"}, []string{"foo", "bar", "baz"} + err := putObjects(s3client, append(objToDel, objects...), bucket) + + delObjects := []types.ObjectIdentifier{} + for _, key := range objToDel { + k := key + delObjects = append(delObjects, types.ObjectIdentifier{Key: &k}) + } + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + out, err := s3client.DeleteObjects(ctx, &s3.DeleteObjectsInput{ + Bucket: &bucket, + Delete: &types.Delete{ + Objects: delObjects, + }, + }) + cancel() + if err != nil { + return err + } + + if len(out.Deleted) != 3 { + return fmt.Errorf("expected deleted object count 3, instead got %v", len(out.Deleted)) + } + if len(out.Errors) != 0 { + return fmt.Errorf("expected 2 errors, instead got %v", len(out.Errors)) + } + + if !compareDelObjects(objToDel, out.Deleted) { + return fmt.Errorf("unexpected deleted output") + } + + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + res, err := s3client.ListObjects(ctx, &s3.ListObjectsInput{ + Bucket: &bucket, + }) + cancel() + if err != nil { + return err + } + + if !compareObjects(objects, res.Contents) { + return fmt.Errorf("unexpected output for list objects with prefix") + } + + return nil + }) +} + func CopyObject_non_existing_dst_bucket(s *S3Conf) { testName := "CopyObject_non_existing_dst_bucket" actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { @@ -698,193 +1106,6 @@ func DeleteObjectTagging_success(s *S3Conf) { // passF(testname) // } -// func TestPutDirObject(s *S3Conf) { -// testname := "test put directory object" -// runF(testname) - -// bucket := "testbucket3" - -// err := setup(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// name := "myobjectdir/" -// s3client := s3.NewFromConfig(s.Config()) - -// ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObject(ctx, &s3.PutObjectInput{ -// Bucket: &bucket, -// Key: &name, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{Bucket: &bucket, MaxKeys: -4}) -// cancel() -// if err == nil { -// failF("%v: expected invalid argument error", testname) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// out, err := s3client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{Bucket: &bucket}) -// cancel() -// if err != nil { -// failF("failed to list objects: %v", err) -// return -// } - -// if !contains(name, out.Contents) { -// failF("directory object not found") -// return -// } - -// err = teardown(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } -// passF(testname) -// } - -// func TestListObject(s *S3Conf) { -// testname := "list objects" -// runF(testname) - -// bucket := "testbucket4" - -// err := setup(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// s3client := s3.NewFromConfig(s.Config()) - -// dir1 := "myobjectdir/" -// ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObject(ctx, &s3.PutObjectInput{ -// Bucket: &bucket, -// Key: &dir1, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// obj1 := "myobjectdir/myobject" -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObject(ctx, &s3.PutObjectInput{ -// Bucket: &bucket, -// Key: &obj1, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// obj2 := "myobjectdir1/myobject" -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObject(ctx, &s3.PutObjectInput{ -// Bucket: &bucket, -// Key: &obj2, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// // put: -// // "myobjectdir/" -// // "myobjectdir/myobject" -// // "myobjectdir1/myobject" -// // should return: -// // "myobjectdir/myobject" -// // "myobjectdir1/myobject" - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// out, err := s3client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{Bucket: &bucket}) -// cancel() -// if err != nil { -// failF("failed to list objects: %v", err) -// return -// } - -// if !contains(obj1, out.Contents) { -// failF("object %v not found", obj1) -// return -// } -// if !contains(obj2, out.Contents) { -// failF("object %v not found", obj2) -// return -// } -// if out.KeyCount != 2 { -// failF("%v: expected key count: %v, instead got: %v", testname, 2, out.KeyCount) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ -// Bucket: &bucket, -// Key: &obj1, -// }) -// cancel() -// if err != nil { -// failF("failed to delete %v: %v", obj1, err) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ -// Bucket: &bucket, -// Key: &obj2, -// }) -// cancel() -// if err != nil { -// failF("failed to delete %v: %v", obj2, err) -// return -// } - -// // put: -// // "myobjectdir/" -// // "myobjectdir/myobject" -// // "myobjectdir1/myobject" -// // delete: -// // "myobjectdir/myobject" -// // "myobjectdir1/myobject" -// // should return: -// // "myobjectdir/" - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// out, err = s3client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{Bucket: &bucket}) -// cancel() -// if err != nil { -// failF("failed to list objects: %v", err) -// return -// } - -// if !contains(dir1, out.Contents) { -// failF("dir %v not found", dir1) -// return -// } - -// err = teardown(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } -// passF(testname) -// } - // func TestListAbortMultiPartObject(s *S3Conf) { // testname := "list/abort multipart objects" // runF(testname) @@ -1515,101 +1736,6 @@ func DeleteObjectTagging_success(s *S3Conf) { // passF(testname) // } -// func TestPutGetRemoveTags(s *S3Conf) { -// testname := "test put/get/remove object tags" -// runF(testname) - -// bucket := "testbucket13" - -// err := setup(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// obj := "myobject" -// s3client := s3.NewFromConfig(s.Config()) - -// ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObject(ctx, &s3.PutObjectInput{ -// Bucket: &bucket, -// Key: &obj, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// key1 := "hello1" -// key2 := "hello2" -// val1 := "world1" -// val2 := "world2" - -// tagging := types.Tagging{TagSet: []types.Tag{{Key: &key1, Value: &val1}, {Key: &key2, Value: &val2}}} - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.PutObjectTagging(ctx, &s3.PutObjectTaggingInput{ -// Bucket: &bucket, -// Key: &obj, -// Tagging: &tagging, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// out, err := s3client.GetObjectTagging(ctx, &s3.GetObjectTaggingInput{ -// Key: &obj, -// Bucket: &bucket, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// ok := areTagsSame(tagging.TagSet, out.TagSet) -// if !ok { -// failF("%v: expected %v instead got %v", testname, tagging.TagSet, out.TagSet) -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// _, err = s3client.DeleteObjectTagging(ctx, &s3.DeleteObjectTaggingInput{ -// Key: &obj, -// Bucket: &bucket, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) -// out, err = s3client.GetObjectTagging(ctx, &s3.GetObjectTaggingInput{ -// Key: &obj, -// Bucket: &bucket, -// }) -// cancel() -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } - -// if len(out.TagSet) > 0 { -// failF("%v: expected empty tag set instead got %v", testname, out.TagSet) -// } - -// err = teardown(s, bucket) -// if err != nil { -// failF("%v: %v", testname, err) -// return -// } -// passF(testname) -// } - // func TestAclActions(s *S3Conf) { // testname := "test put/get acl" // runF(testname) diff --git a/integration/utils.go b/integration/utils.go index dff7b6d..d76233b 100644 --- a/integration/utils.go +++ b/integration/utils.go @@ -142,6 +142,17 @@ func checkApiErr(err error, apiErr s3err.APIError) error { } } +func checkSdkApiErr(err error, code string) error { + var ae smithy.APIError + if errors.As(err, &ae) { + if ae.ErrorCode() != code { + return fmt.Errorf("expected %v, instead got %v", ae.ErrorCode(), code) + } + return nil + } + return err +} + func putObjectWithData(lgth int64, input *s3.PutObjectInput, client *s3.Client) (csum [32]byte, data []byte, err error) { data = make([]byte, lgth) rand.Read(data) @@ -172,7 +183,6 @@ func isEqual(a, b []byte) bool { func contains(name string, list []types.Object) bool { for _, item := range list { - fmt.Println(*item.Key) if strings.EqualFold(name, *item.Key) { return true } @@ -264,3 +274,43 @@ func areMapsSame(mp1, mp2 map[string]string) bool { } return true } + +func compareObjects(list1 []string, list2 []types.Object) bool { + if len(list1) != len(list2) { + return false + } + + elementMap := make(map[string]bool) + + for _, elem := range list1 { + elementMap[elem] = true + } + + for _, elem := range list2 { + if _, found := elementMap[*elem.Key]; !found { + return false + } + } + + return true +} + +func compareDelObjects(list1 []string, list2 []types.DeletedObject) bool { + if len(list1) != len(list2) { + return false + } + + elementMap := make(map[string]bool) + + for _, elem := range list1 { + elementMap[elem] = true + } + + for _, elem := range list2 { + if _, found := elementMap[*elem.Key]; !found { + return false + } + } + + return true +}