From 0662c90b5c4cf927ed58f09d43654381709309e7 Mon Sep 17 00:00:00 2001 From: jiuker <2818723467@qq.com> Date: Mon, 10 Jun 2024 23:50:49 +0800 Subject: [PATCH] fix: copyObject restore with a specific version, update test cases (#19895) --- cmd/bucket-handlers_test.go | 12 ++-- cmd/bucket-lifecycle-handlers_test.go | 4 +- cmd/bucket-policy-handlers_test.go | 8 +-- cmd/object-handlers.go | 2 +- cmd/object-handlers_test.go | 92 ++++++++++++++++++++------- cmd/object_api_suite_test.go | 60 ++++++++++++----- cmd/test-utils_test.go | 47 +++++++++----- 7 files changed, 157 insertions(+), 68 deletions(-) diff --git a/cmd/bucket-handlers_test.go b/cmd/bucket-handlers_test.go index 7a0bbaf34..48718dfb9 100644 --- a/cmd/bucket-handlers_test.go +++ b/cmd/bucket-handlers_test.go @@ -32,7 +32,7 @@ import ( // Wrapper for calling RemoveBucket HTTP handler tests for both Erasure multiple disks and single node setup. func TestRemoveBucketHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testRemoveBucketHandler, []string{"RemoveBucket"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testRemoveBucketHandler, endpoints: []string{"RemoveBucket"}}) } func testRemoveBucketHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -78,7 +78,7 @@ func testRemoveBucketHandler(obj ObjectLayer, instanceType, bucketName string, a // Wrapper for calling GetBucketPolicy HTTP handler tests for both Erasure multiple disks and single node setup. func TestGetBucketLocationHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testGetBucketLocationHandler, []string{"GetBucketLocation"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testGetBucketLocationHandler, endpoints: []string{"GetBucketLocation"}}) } func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -220,7 +220,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri // Wrapper for calling HeadBucket HTTP handler tests for both Erasure multiple disks and single node setup. func TestHeadBucketHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testHeadBucketHandler, []string{"HeadBucket"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testHeadBucketHandler, endpoints: []string{"HeadBucket"}}) } func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -322,7 +322,7 @@ func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, api // Wrapper for calling TestListMultipartUploadsHandler tests for both Erasure multiple disks and single node setup. func TestListMultipartUploadsHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testListMultipartUploadsHandler, []string{"ListMultipartUploads"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testListMultipartUploadsHandler, endpoints: []string{"ListMultipartUploads"}}) } // testListMultipartUploadsHandler - Tests validate listing of multipart uploads. @@ -558,7 +558,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s // Wrapper for calling TestListBucketsHandler tests for both Erasure multiple disks and single node setup. func TestListBucketsHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testListBucketsHandler, []string{"ListBuckets"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testListBucketsHandler, endpoints: []string{"ListBuckets"}}) } // testListBucketsHandler - Tests validate listing of buckets. @@ -649,7 +649,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap // Wrapper for calling DeleteMultipleObjects HTTP handler tests for both Erasure multiple disks and single node setup. func TestAPIDeleteMultipleObjectsHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testAPIDeleteMultipleObjectsHandler, []string{"DeleteMultipleObjects", "PutBucketPolicy"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIDeleteMultipleObjectsHandler, endpoints: []string{"DeleteMultipleObjects", "PutBucketPolicy"}}) } func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, diff --git a/cmd/bucket-lifecycle-handlers_test.go b/cmd/bucket-lifecycle-handlers_test.go index f101f2ef6..7dc2cf020 100644 --- a/cmd/bucket-lifecycle-handlers_test.go +++ b/cmd/bucket-lifecycle-handlers_test.go @@ -29,7 +29,7 @@ import ( // Test S3 Bucket lifecycle APIs with wrong credentials func TestBucketLifecycleWrongCredentials(t *testing.T) { - ExecObjectLayerAPITest(t, testBucketLifecycleHandlersWrongCredentials, []string{"GetBucketLifecycle", "PutBucketLifecycle", "DeleteBucketLifecycle"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testBucketLifecycleHandlersWrongCredentials, endpoints: []string{"GetBucketLifecycle", "PutBucketLifecycle", "DeleteBucketLifecycle"}}) } // Test for authentication @@ -145,7 +145,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, // Test S3 Bucket lifecycle APIs func TestBucketLifecycle(t *testing.T) { - ExecObjectLayerAPITest(t, testBucketLifecycleHandlers, []string{"GetBucketLifecycle", "PutBucketLifecycle", "DeleteBucketLifecycle"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testBucketLifecycleHandlers, endpoints: []string{"GetBucketLifecycle", "PutBucketLifecycle", "DeleteBucketLifecycle"}}) } // Simple tests of bucket lifecycle: PUT, GET, DELETE. diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go index 751820c8d..402d36efe 100644 --- a/cmd/bucket-policy-handlers_test.go +++ b/cmd/bucket-policy-handlers_test.go @@ -107,7 +107,7 @@ func getAnonWriteOnlyObjectPolicy(bucketName, prefix string) *policy.BucketPolic // Wrapper for calling Create Bucket and ensure we get one and only one success. func TestCreateBucket(t *testing.T) { - ExecObjectLayerAPITest(t, testCreateBucket, []string{"MakeBucket"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testCreateBucket, endpoints: []string{"MakeBucket"}}) } // testCreateBucket - Test for calling Create Bucket and ensure we get one and only one success. @@ -154,7 +154,7 @@ func testCreateBucket(obj ObjectLayer, instanceType, bucketName string, apiRoute // Wrapper for calling Put Bucket Policy HTTP handler tests for both Erasure multiple disks and single node setup. func TestPutBucketPolicyHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testPutBucketPolicyHandler, []string{"PutBucketPolicy"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testPutBucketPolicyHandler, endpoints: []string{"PutBucketPolicy"}}) } // testPutBucketPolicyHandler - Test for Bucket policy end point. @@ -373,7 +373,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // Wrapper for calling Get Bucket Policy HTTP handler tests for both Erasure multiple disks and single node setup. func TestGetBucketPolicyHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testGetBucketPolicyHandler, []string{"PutBucketPolicy", "GetBucketPolicy"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testGetBucketPolicyHandler, endpoints: []string{"PutBucketPolicy", "GetBucketPolicy"}}) } // testGetBucketPolicyHandler - Test for end point which fetches the access policy json of the given bucket. @@ -577,7 +577,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // Wrapper for calling Delete Bucket Policy HTTP handler tests for both Erasure multiple disks and single node setup. func TestDeleteBucketPolicyHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testDeleteBucketPolicyHandler, []string{"PutBucketPolicy", "DeleteBucketPolicy"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testDeleteBucketPolicyHandler, endpoints: []string{"PutBucketPolicy", "DeleteBucketPolicy"}}) } // testDeleteBucketPolicyHandler - Test for Delete bucket policy end point. diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 56d6a692c..99415107b 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1580,7 +1580,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // Pass the decompressed stream to such calls. isDstCompressed := isCompressible(r.Header, dstObject) && length > minCompressibleSize && - !isRemoteCopyRequired(ctx, srcBucket, dstBucket, objectAPI) && !cpSrcDstSame && !objectEncryption + !isRemoteCopyRequired(ctx, srcBucket, dstBucket, objectAPI) && !objectEncryption if isDstCompressed { compressMetadata = make(map[string]string, 2) // Preserving the compression metadata. diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index cafc361ab..679dc55ec 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -61,7 +61,7 @@ const ( // Wrapper for calling HeadObject API handler tests for both Erasure multiple disks and FS single drive setup. func TestAPIHeadObjectHandler(t *testing.T) { - ExecObjectLayerAPITest(t, testAPIHeadObjectHandler, []string{"HeadObject"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIHeadObjectHandler, endpoints: []string{"HeadObject"}}) } func testAPIHeadObjectHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -207,7 +207,7 @@ func TestAPIHeadObjectHandlerWithEncryption(t *testing.T) { defer func() { globalPolicySys = nil }() defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPIHeadObjectHandlerWithEncryption, []string{"NewMultipart", "PutObjectPart", "CompleteMultipart", "GetObject", "PutObject", "HeadObject"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIHeadObjectHandlerWithEncryption, endpoints: []string{"NewMultipart", "PutObjectPart", "CompleteMultipart", "GetObject", "PutObject", "HeadObject"}}) } func testAPIHeadObjectHandlerWithEncryption(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -707,7 +707,13 @@ func testAPIGetObjectWithMPHandler(obj ObjectLayer, instanceType, bucketName str {"enc-mp-2", []int64{5487701, 5487799, 3}, mapCopy(metaWithSSEC)}, {"enc-mp-3", []int64{10499807, 10499963, 7}, mapCopy(metaWithSSEC)}, } - + // SSEC can't be used with compression + globalCompressConfigMu.Lock() + globalCompressEnabled := globalCompressConfig.Enabled + globalCompressConfigMu.Unlock() + if globalCompressEnabled { + objectInputs = objectInputs[0:8] + } // iterate through the above set of inputs and upload the object. for _, input := range objectInputs { uploadTestObject(t, apiRouter, credentials, bucketName, input.objectName, input.partLengths, input.metaData, false) @@ -898,6 +904,14 @@ func testAPIGetObjectWithPartNumberHandler(obj ObjectLayer, instanceType, bucket {"enc-mp-3", []int64{10499807, 10499963, 7}, mapCopy(metaWithSSEC)}, } + // SSEC can't be used with compression + globalCompressConfigMu.Lock() + globalCompressEnabled := globalCompressConfig.Enabled + globalCompressConfigMu.Unlock() + if globalCompressEnabled { + objectInputs = objectInputs[0:9] + } + // iterate through the above set of inputs and upload the object. for _, input := range objectInputs { uploadTestObject(t, apiRouter, credentials, bucketName, input.objectName, input.partLengths, input.metaData, false) @@ -2119,7 +2133,7 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri // Wrapper for calling Copy Object API handler tests for both Erasure multiple disks and single node setup. func TestAPICopyObjectHandler(t *testing.T) { defer DetectTestLeak(t)() - ExecExtendedObjectLayerAPITest(t, testAPICopyObjectHandler, []string{"CopyObject"}) + ExecExtendedObjectLayerAPITest(t, testAPICopyObjectHandler, []string{"CopyObject", "PutObject"}) } func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -2150,7 +2164,10 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, new(bytes.Buffer), new(bytes.Buffer), } - + bucketInfo, err := obj.GetBucketInfo(context.Background(), bucketName, BucketOptions{}) + if err != nil { + t.Fatalf("Test -1: %s: Failed to get bucket info: %s", instanceType, err) + } // set of inputs for uploading the objects before tests for downloading is done. putObjectInputs := []struct { bucketName string @@ -2167,21 +2184,29 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, // used for anonymous HTTP request test. {bucketName, anonObject, int64(len(bytesData[0].byteData)), bytesData[0].byteData, bytesData[0].md5sum, make(map[string]string)}, } - // iterate through the above set of inputs and upload the object. for i, input := range putObjectInputs { - // uploading the object. - var objInfo ObjectInfo - objInfo, err = obj.PutObject(context.Background(), input.bucketName, input.objectName, mustGetPutObjReader(t, bytes.NewReader(input.textData), input.contentLength, input.md5sum, ""), ObjectOptions{UserDefined: input.metaData}) - // if object upload fails stop the test. + rec := httptest.NewRecorder() + req, err := newTestSignedRequestV4(http.MethodPut, getPutObjectURL("", input.bucketName, input.objectName), + input.contentLength, bytes.NewReader(input.textData), credentials.AccessKey, credentials.SecretKey, nil) if err != nil { - t.Fatalf("Put Object case %d: Error uploading object: %v", i+1, err) + t.Fatalf("Test %d: Failed to create HTTP request for Put Object: %v", i, err) } - if objInfo.ETag != input.md5sum { - t.Fatalf("Put Object case %d: Checksum mismatched: got %s, expected %s", i+1, input.md5sum, objInfo.ETag) + apiRouter.ServeHTTP(rec, req) + if rec.Code != http.StatusOK { + b, err := io.ReadAll(rec.Body) + if err != nil { + t.Fatal(err) + } + var apiErr APIErrorResponse + err = xml.Unmarshal(b, &apiErr) + if err != nil { + t.Fatal(err) + } + gotErr := apiErr.Code + t.Errorf("test %d: want api got %q", i, gotErr) } } - // test cases with inputs and expected result for Copy Object. testCases := []struct { bucketName string @@ -2434,6 +2459,22 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, } for i, testCase := range testCases { + if bucketInfo.Versioning { + if strings.Contains(testCase.copySourceHeader, "versionId=null") { + testCase.expectedRespStatus = http.StatusNotFound + } + } + values := url.Values{} + if testCase.expectedRespStatus == http.StatusOK { + r, err := obj.GetObjectNInfo(context.Background(), testCase.bucketName, objectName, nil, nil, opts) + if err != nil { + t.Fatalf("Test %d: %s reading completed file failed: %v", i, instanceType, err) + } + r.Close() + if r.ObjInfo.VersionID != "" { + values.Set(xhttp.VersionID, r.ObjInfo.VersionID) + } + } var req *http.Request var reqV2 *http.Request // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. @@ -2446,7 +2487,11 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, } // "X-Amz-Copy-Source" header contains the information about the source bucket and the object to copied. if testCase.copySourceHeader != "" { - req.Header.Set("X-Amz-Copy-Source", testCase.copySourceHeader) + if values.Encode() != "" && !strings.Contains(testCase.copySourceHeader, "?") { + req.Header.Set("X-Amz-Copy-Source", testCase.copySourceHeader+"?"+values.Encode()) + } else { + req.Header.Set("X-Amz-Copy-Source", testCase.copySourceHeader) + } } if testCase.copyModifiedHeader != "" { req.Header.Set("X-Amz-Copy-Source-If-Modified-Since", testCase.copyModifiedHeader) @@ -2552,10 +2597,10 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, if testCase.copySourceSame { // encryption will rotate creds, so fail only for non-encryption scenario. if GlobalKMS == nil { - t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i, instanceType, testCase.expectedRespStatus, rec.Code) + t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i, instanceType, testCase.expectedRespStatus, recV2.Code) } } else { - t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, rec.Code) + t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, recV2.Code) } } } @@ -2588,7 +2633,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, // The UploadID from the response body is parsed and its existence is asserted with an attempt to ListParts using it. func TestAPINewMultipartHandler(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPINewMultipartHandler, []string{"NewMultipart"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPINewMultipartHandler, endpoints: []string{"NewMultipart"}}) } func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -2727,7 +2772,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string // The UploadID from the response body is parsed and its existence is asserted with an attempt to ListParts using it. func TestAPINewMultipartHandlerParallel(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPINewMultipartHandlerParallel, []string{"NewMultipart"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPINewMultipartHandlerParallel, endpoints: []string{"NewMultipart"}}) } func testAPINewMultipartHandlerParallel(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -2790,7 +2835,7 @@ func testAPINewMultipartHandlerParallel(obj ObjectLayer, instanceType, bucketNam // The UploadID from the response body is parsed and its existence is asserted with an attempt to ListParts using it. func TestAPICompleteMultipartHandler(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPICompleteMultipartHandler, []string{"CompleteMultipart"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPICompleteMultipartHandler, endpoints: []string{"CompleteMultipart"}}) } func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -3159,7 +3204,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s // The UploadID from the response body is parsed and its existence is asserted with an attempt to ListParts using it. func TestAPIAbortMultipartHandler(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPIAbortMultipartHandler, []string{"AbortMultipart"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIAbortMultipartHandler, endpoints: []string{"AbortMultipart"}}) } func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -3319,7 +3364,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri // Wrapper for calling Delete Object API handler tests for both Erasure multiple disks and FS single drive setup. func TestAPIDeleteObjectHandler(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPIDeleteObjectHandler, []string{"DeleteObject"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIDeleteObjectHandler, endpoints: []string{"DeleteObject"}}) } func testAPIDeleteObjectHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, @@ -3881,8 +3926,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin // when signature type of the HTTP request is `Presigned`. func TestAPIListObjectPartsHandlerPreSign(t *testing.T) { defer DetectTestLeak(t)() - ExecObjectLayerAPITest(t, testAPIListObjectPartsHandlerPreSign, - []string{"PutObjectPart", "NewMultipart", "ListObjectParts"}) + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: testAPIListObjectPartsHandlerPreSign, endpoints: []string{"PutObjectPart", "NewMultipart", "ListObjectParts"}}) } func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, diff --git a/cmd/object_api_suite_test.go b/cmd/object_api_suite_test.go index aa1f4f161..3df725188 100644 --- a/cmd/object_api_suite_test.go +++ b/cmd/object_api_suite_test.go @@ -511,12 +511,12 @@ func testBucketRecreateFails(obj ObjectLayer, instanceType string, t TestErrHand } } -func enableCompression(t *testing.T, encrypt bool) { +func enableCompression(t *testing.T, encrypt bool, mimeTypes []string, extensions []string) { // Enable compression and exec... globalCompressConfigMu.Lock() globalCompressConfig.Enabled = true - globalCompressConfig.MimeTypes = nil - globalCompressConfig.Extensions = nil + globalCompressConfig.MimeTypes = mimeTypes + globalCompressConfig.Extensions = extensions globalCompressConfig.AllowEncrypted = encrypt globalCompressConfigMu.Unlock() if encrypt { @@ -553,11 +553,14 @@ func resetCompressEncryption() { GlobalKMS = nil } -func execExtended(t *testing.T, fn func(t *testing.T)) { +func execExtended(t *testing.T, fn func(t *testing.T, init func(), bucketOptions MakeBucketOptions)) { // Exec with default settings... resetCompressEncryption() t.Run("default", func(t *testing.T) { - fn(t) + fn(t, nil, MakeBucketOptions{}) + }) + t.Run("defaultVerioned", func(t *testing.T) { + fn(t, nil, MakeBucketOptions{VersioningEnabled: true}) }) if testing.Short() { @@ -565,28 +568,55 @@ func execExtended(t *testing.T, fn func(t *testing.T)) { } t.Run("compressed", func(t *testing.T) { - resetCompressEncryption() - enableCompression(t, false) - fn(t) + fn(t, func() { + resetCompressEncryption() + enableCompression(t, false, []string{"*"}, []string{"*"}) + }, MakeBucketOptions{}) + }) + t.Run("compressedVerioned", func(t *testing.T) { + fn(t, func() { + resetCompressEncryption() + enableCompression(t, false, []string{"*"}, []string{"*"}) + }, MakeBucketOptions{ + VersioningEnabled: true, + }) }) t.Run("encrypted", func(t *testing.T) { - resetCompressEncryption() - enableEncryption(t) - fn(t) + fn(t, func() { + resetCompressEncryption() + enableEncryption(t) + }, MakeBucketOptions{}) + }) + t.Run("encryptedVerioned", func(t *testing.T) { + fn(t, func() { + resetCompressEncryption() + enableEncryption(t) + }, MakeBucketOptions{ + VersioningEnabled: true, + }) }) t.Run("compressed+encrypted", func(t *testing.T) { - resetCompressEncryption() - enableCompression(t, true) - fn(t) + fn(t, func() { + resetCompressEncryption() + enableCompression(t, true, []string{"*"}, []string{"*"}) + }, MakeBucketOptions{}) + }) + t.Run("compressed+encryptedVerioned", func(t *testing.T) { + fn(t, func() { + resetCompressEncryption() + enableCompression(t, true, []string{"*"}, []string{"*"}) + }, MakeBucketOptions{ + VersioningEnabled: true, + }) }) } // ExecExtendedObjectLayerTest will execute the tests with combinations of encrypted & compressed. // This can be used to test functionality when reading and writing data. func ExecExtendedObjectLayerTest(t *testing.T, objTest objTestType) { - execExtended(t, func(t *testing.T) { + execExtended(t, func(t *testing.T, init func(), bucketOptions MakeBucketOptions) { ExecObjectLayerTest(t, objTest) }) } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 6d62b9c05..ab4295db0 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -1540,7 +1540,7 @@ func removeRoots(roots []string) { // initializes the specified API endpoints for the tests. // initializes the root and returns its path. // return credentials. -func initAPIHandlerTest(ctx context.Context, obj ObjectLayer, endpoints []string) (string, http.Handler, error) { +func initAPIHandlerTest(ctx context.Context, obj ObjectLayer, endpoints []string, makeBucketOptions MakeBucketOptions) (string, http.Handler, error) { initAllSubsystems(ctx) initConfigSubsystem(ctx, obj) @@ -1549,9 +1549,8 @@ func initAPIHandlerTest(ctx context.Context, obj ObjectLayer, endpoints []string // get random bucket name. bucketName := getRandomBucketName() - // Create bucket. - err := obj.MakeBucket(context.Background(), bucketName, MakeBucketOptions{}) + err := obj.MakeBucket(context.Background(), bucketName, makeBucketOptions) if err != nil { // failed to create newbucket, return err. return "", nil, err @@ -1741,9 +1740,17 @@ func ExecObjectLayerAPINilTest(t TestErrHandler, bucketName, objectName, instanc } } +type ExecObjectLayerAPITestArgs struct { + t *testing.T + objAPITest objAPITestType + endpoints []string + init func() + makeBucketOptions MakeBucketOptions +} + // ExecObjectLayerAPITest - executes object layer API tests. // Creates single node and Erasure ObjectLayer instance, registers the specified API end points and runs test for both the layers. -func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints []string) { +func ExecObjectLayerAPITest(args ExecObjectLayerAPITestArgs) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -1753,24 +1760,28 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ objLayer, fsDir, err := prepareFS(ctx) if err != nil { - t.Fatalf("Initialization of object layer failed for single node setup: %s", err) + args.t.Fatalf("Initialization of object layer failed for single node setup: %s", err) } - bucketFS, fsAPIRouter, err := initAPIHandlerTest(ctx, objLayer, endpoints) + bucketFS, fsAPIRouter, err := initAPIHandlerTest(ctx, objLayer, args.endpoints, args.makeBucketOptions) if err != nil { - t.Fatalf("Initialization of API handler tests failed: %s", err) + args.t.Fatalf("Initialization of API handler tests failed: %s", err) + } + + if args.init != nil { + args.init() } // initialize the server and obtain the credentials and root. // credentials are necessary to sign the HTTP request. if err = newTestConfig(globalMinioDefaultRegion, objLayer); err != nil { - t.Fatalf("Unable to initialize server config. %s", err) + args.t.Fatalf("Unable to initialize server config. %s", err) } credentials := globalActiveCred // Executing the object layer tests for single node setup. - objAPITest(objLayer, ErasureSDStr, bucketFS, fsAPIRouter, credentials, t) + args.objAPITest(objLayer, ErasureSDStr, bucketFS, fsAPIRouter, credentials, args.t) // reset globals. // this is to make sure that the tests are not affected by modified value. @@ -1778,23 +1789,27 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ objLayer, erasureDisks, err := prepareErasure16(ctx) if err != nil { - t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err) + args.t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err) } defer objLayer.Shutdown(ctx) - bucketErasure, erAPIRouter, err := initAPIHandlerTest(ctx, objLayer, endpoints) + bucketErasure, erAPIRouter, err := initAPIHandlerTest(ctx, objLayer, args.endpoints, args.makeBucketOptions) if err != nil { - t.Fatalf("Initialization of API handler tests failed: %s", err) + args.t.Fatalf("Initialization of API handler tests failed: %s", err) + } + + if args.init != nil { + args.init() } // initialize the server and obtain the credentials and root. // credentials are necessary to sign the HTTP request. if err = newTestConfig(globalMinioDefaultRegion, objLayer); err != nil { - t.Fatalf("Unable to initialize server config. %s", err) + args.t.Fatalf("Unable to initialize server config. %s", err) } // Executing the object layer tests for Erasure. - objAPITest(objLayer, ErasureTestStr, bucketErasure, erAPIRouter, credentials, t) + args.objAPITest(objLayer, ErasureTestStr, bucketErasure, erAPIRouter, credentials, args.t) // clean up the temporary test backend. removeRoots(append(erasureDisks, fsDir)) @@ -1803,8 +1818,8 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ // ExecExtendedObjectLayerTest will execute the tests with combinations of encrypted & compressed. // This can be used to test functionality when reading and writing data. func ExecExtendedObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints []string) { - execExtended(t, func(t *testing.T) { - ExecObjectLayerAPITest(t, objAPITest, endpoints) + execExtended(t, func(t *testing.T, init func(), makeBucketOptions MakeBucketOptions) { + ExecObjectLayerAPITest(ExecObjectLayerAPITestArgs{t: t, objAPITest: objAPITest, endpoints: endpoints, init: init, makeBucketOptions: makeBucketOptions}) }) }