diff --git a/api/handler/attributes_test.go b/api/handler/attributes_test.go new file mode 100644 index 0000000..c80e641 --- /dev/null +++ b/api/handler/attributes_test.go @@ -0,0 +1,44 @@ +package handler + +import ( + "strings" + "testing" + + "github.com/nspcc-dev/neofs-s3-gw/api" + "github.com/stretchr/testify/require" +) + +func TestGetObjectPartsAttributes(t *testing.T) { + hc := prepareHandlerContext(t) + + bktName := "bucket-get-attributes" + objName, objMultipartName := "object", "object-multipart" + partSize := 8 + + createTestBucket(hc, bktName) + + putObject(t, hc, bktName, objName) + result := getObjectAttributes(hc, bktName, objName, objectParts) + require.Nil(t, result.ObjectParts) + + multipartUpload := createMultipartUpload(hc, bktName, objMultipartName, map[string]string{}) + etag, _ := uploadPart(hc, bktName, objMultipartName, multipartUpload.UploadID, 1, partSize) + completeMultipartUpload(hc, bktName, objMultipartName, multipartUpload.UploadID, []string{etag}) + + result = getObjectAttributes(hc, bktName, objMultipartName, objectParts) + require.NotNil(t, result.ObjectParts) + require.Len(t, result.ObjectParts.Parts, 1) + require.Equal(t, etag, result.ObjectParts.Parts[0].ChecksumSHA256) + require.Equal(t, partSize, result.ObjectParts.Parts[0].Size) + require.Equal(t, 1, result.ObjectParts.PartsCount) +} + +func getObjectAttributes(hc *handlerContext, bktName, objName string, attrs ...string) *GetObjectAttributesResponse { + w, r := prepareTestRequest(hc, bktName, objName, nil) + r.Header.Set(api.AmzObjectAttributes, strings.Join(attrs, ",")) + hc.Handler().GetObjectAttributesHandler(w, r) + result := &GetObjectAttributesResponse{} + parseTestResponse(hc.t, w, result) + + return result +} diff --git a/api/handler/atttributes_test.go b/api/handler/atttributes_test.go deleted file mode 100644 index 0678053..0000000 --- a/api/handler/atttributes_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package handler - -import ( - "bytes" - "net/http" - "net/url" - "testing" - - "github.com/nspcc-dev/neofs-s3-gw/api" - "github.com/nspcc-dev/neofs-s3-gw/api/layer" - "github.com/stretchr/testify/require" -) - -func TestGetObjectPartsAttributes(t *testing.T) { - hc := prepareHandlerContext(t) - - bktName := "bucket-get-attributes" - objName, objMultipartName := "object", "object-multipart" - - createTestBucket(hc, bktName) - - body := bytes.NewReader([]byte("content")) - w, r := prepareTestPayloadRequest(hc, bktName, objName, body) - hc.Handler().PutObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, nil) - r.Header.Set(api.AmzObjectAttributes, objectParts) - hc.Handler().GetObjectAttributesHandler(w, r) - result := &GetObjectAttributesResponse{} - parseTestResponse(t, w, result) - require.Nil(t, result.ObjectParts) - - w, r = prepareTestRequest(hc, bktName, objMultipartName, nil) - hc.Handler().CreateMultipartUploadHandler(w, r) - multipartUpload := &InitiateMultipartUploadResponse{} - parseTestResponse(t, w, multipartUpload) - - body2 := bytes.NewReader([]byte("content2")) - w, r = prepareTestPayloadRequest(hc, bktName, objMultipartName, body2) - query := make(url.Values) - query.Add(uploadIDHeaderName, multipartUpload.UploadID) - query.Add(partNumberHeaderName, "1") - r.URL.RawQuery = query.Encode() - hc.Handler().UploadPartHandler(w, r) - assertStatus(t, w, http.StatusOK) - etag := w.Result().Header.Get(api.ETag) - - completeUpload := &CompleteMultipartUpload{ - Parts: []*layer.CompletedPart{{ - ETag: etag, - PartNumber: 1, - }}, - } - w, r = prepareTestRequest(hc, bktName, objMultipartName, completeUpload) - query = make(url.Values) - query.Add(uploadIDHeaderName, multipartUpload.UploadID) - r.URL.RawQuery = query.Encode() - hc.Handler().CompleteMultipartUploadHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objMultipartName, nil) - r.Header.Set(api.AmzObjectAttributes, objectParts) - hc.Handler().GetObjectAttributesHandler(w, r) - result = &GetObjectAttributesResponse{} - parseTestResponse(t, w, result) - require.NotNil(t, result.ObjectParts) - require.Len(t, result.ObjectParts.Parts, 1) - require.Equal(t, etag, result.ObjectParts.Parts[0].ChecksumSHA256) - require.Equal(t, 8, result.ObjectParts.Parts[0].Size) - require.Equal(t, 1, result.ObjectParts.PartsCount) -} diff --git a/api/handler/encryption_test.go b/api/handler/encryption_test.go index 1932c23..cc73dea 100644 --- a/api/handler/encryption_test.go +++ b/api/handler/encryption_test.go @@ -99,7 +99,7 @@ func TestS3EncryptionSSECMultipartUpload(t *testing.T) { api.ContentType: "text/plain", } - data := multipartUploadEncrypted(t, tc, bktName, objName, headers, objLen, partSize) + data := multipartUploadEncrypted(tc, bktName, objName, headers, objLen, partSize) require.Equal(t, objLen, len(data)) resData, resHeader := getEncryptedObject(t, tc, bktName, objName) @@ -143,8 +143,8 @@ func checkContentUsingRangeEnc(t *testing.T, tc *handlerContext, bktName, objNam } } -func multipartUploadEncrypted(t *testing.T, tc *handlerContext, bktName, objName string, headers map[string]string, objLen, partsSize int) (objData []byte) { - multipartInfo := createMultipartUpload(t, tc, bktName, objName, headers) +func multipartUploadEncrypted(hc *handlerContext, bktName, objName string, headers map[string]string, objLen, partsSize int) (objData []byte) { + multipartInfo := createMultipartUploadEncrypted(hc, bktName, objName, headers) var sum, currentPart int var etags []string @@ -158,26 +158,37 @@ func multipartUploadEncrypted(t *testing.T, tc *handlerContext, bktName, objName adjustedSize = objLen - sum } - etag, data := uploadPart(t, tc, bktName, objName, multipartInfo.UploadID, currentPart, adjustedSize) + etag, data := uploadPartEncrypted(hc, bktName, objName, multipartInfo.UploadID, currentPart, adjustedSize) etags = append(etags, etag) objData = append(objData, data...) } - completeMultipartUpload(t, tc, bktName, objName, multipartInfo.UploadID, etags) + completeMultipartUpload(hc, bktName, objName, multipartInfo.UploadID, etags) return } -func createMultipartUpload(t *testing.T, tc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse { - w, r := prepareTestRequest(tc, bktName, objName, nil) - setEncryptHeaders(r) +func createMultipartUploadEncrypted(hc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse { + return createMultipartUploadBase(hc, bktName, objName, true, headers) +} + +func createMultipartUpload(hc *handlerContext, bktName, objName string, headers map[string]string) *InitiateMultipartUploadResponse { + return createMultipartUploadBase(hc, bktName, objName, false, headers) +} + +func createMultipartUploadBase(hc *handlerContext, bktName, objName string, encrypted bool, headers map[string]string) *InitiateMultipartUploadResponse { + w, r := prepareTestRequest(hc, bktName, objName, nil) + if encrypted { + setEncryptHeaders(r) + } setHeaders(r, headers) - tc.Handler().CreateMultipartUploadHandler(w, r) + hc.Handler().CreateMultipartUploadHandler(w, r) multipartInitInfo := &InitiateMultipartUploadResponse{} - readResponse(t, w, http.StatusOK, multipartInitInfo) + readResponse(hc.t, w, http.StatusOK, multipartInitInfo) return multipartInitInfo } -func completeMultipartUpload(t *testing.T, tc *handlerContext, bktName, objName, uploadID string, partsETags []string) { + +func completeMultipartUpload(hc *handlerContext, bktName, objName, uploadID string, partsETags []string) { query := make(url.Values) query.Set(uploadIDQuery, uploadID) complete := &CompleteMultipartUpload{ @@ -190,24 +201,34 @@ func completeMultipartUpload(t *testing.T, tc *handlerContext, bktName, objName, }) } - w, r := prepareTestFullRequest(tc, bktName, objName, query, complete) - tc.Handler().CompleteMultipartUploadHandler(w, r) - assertStatus(t, w, http.StatusOK) + w, r := prepareTestFullRequest(hc, bktName, objName, query, complete) + hc.Handler().CompleteMultipartUploadHandler(w, r) + assertStatus(hc.t, w, http.StatusOK) } -func uploadPart(t *testing.T, tc *handlerContext, bktName, objName, uploadID string, num, size int) (string, []byte) { +func uploadPartEncrypted(hc *handlerContext, bktName, objName, uploadID string, num, size int) (string, []byte) { + return uploadPartBase(hc, bktName, objName, true, uploadID, num, size) +} + +func uploadPart(hc *handlerContext, bktName, objName, uploadID string, num, size int) (string, []byte) { + return uploadPartBase(hc, bktName, objName, false, uploadID, num, size) +} + +func uploadPartBase(hc *handlerContext, bktName, objName string, encrypted bool, uploadID string, num, size int) (string, []byte) { partBody := make([]byte, size) _, err := rand.Read(partBody) - require.NoError(t, err) + require.NoError(hc.t, err) query := make(url.Values) query.Set(uploadIDQuery, uploadID) query.Set(partNumberQuery, strconv.Itoa(num)) - w, r := prepareTestRequestWithQuery(tc, bktName, objName, query, partBody) - setEncryptHeaders(r) - tc.Handler().UploadPartHandler(w, r) - assertStatus(t, w, http.StatusOK) + w, r := prepareTestRequestWithQuery(hc, bktName, objName, query, partBody) + if encrypted { + setEncryptHeaders(r) + } + hc.Handler().UploadPartHandler(w, r) + assertStatus(hc.t, w, http.StatusOK) return w.Header().Get(api.ETag), partBody } @@ -215,57 +236,21 @@ func uploadPart(t *testing.T, tc *handlerContext, bktName, objName, uploadID str func TestMultipartEncrypted(t *testing.T) { partSize := 5*1048576 + 1<<16 - 5 // 5MB (min part size) + 64kb (cipher block size) - 5 (to check corner range) - tc := prepareHandlerContext(t) + hc := prepareHandlerContext(t) bktName, objName := "bucket-for-sse-c-multipart", "object-to-encrypt-multipart" - createTestBucket(tc, bktName) + createTestBucket(hc, bktName) - w, r := prepareTestRequest(tc, bktName, objName, nil) - setEncryptHeaders(r) - tc.Handler().CreateMultipartUploadHandler(w, r) - multipartInitInfo := &InitiateMultipartUploadResponse{} - readResponse(t, w, http.StatusOK, multipartInitInfo) + multipartInitInfo := createMultipartUploadEncrypted(hc, bktName, objName, map[string]string{}) + part1ETag, part1 := uploadPartEncrypted(hc, bktName, objName, multipartInitInfo.UploadID, 1, partSize) + part2ETag, part2 := uploadPartEncrypted(hc, bktName, objName, multipartInitInfo.UploadID, 2, 5) + completeMultipartUpload(hc, bktName, objName, multipartInitInfo.UploadID, []string{part1ETag, part2ETag}) - part1 := make([]byte, partSize) - for i := range part1 { - part1[i] = 'a' - } - query := make(url.Values) - query.Set(uploadIDQuery, multipartInitInfo.UploadID) - query.Set(partNumberQuery, "1") - w, r = prepareTestRequestWithQuery(tc, bktName, objName, query, part1) - setEncryptHeaders(r) - tc.Handler().UploadPartHandler(w, r) - assertStatus(t, w, http.StatusOK) - part1ETag := w.Header().Get(api.ETag) - - part2 := []byte("part2") - query = make(url.Values) - query.Set(uploadIDQuery, multipartInitInfo.UploadID) - query.Set(partNumberQuery, "2") - w, r = prepareTestRequestWithQuery(tc, bktName, objName, query, part2) - setEncryptHeaders(r) - tc.Handler().UploadPartHandler(w, r) - assertStatus(t, w, http.StatusOK) - part2ETag := w.Header().Get(api.ETag) - - query = make(url.Values) - query.Set(uploadIDQuery, multipartInitInfo.UploadID) - complete := &CompleteMultipartUpload{ - Parts: []*layer.CompletedPart{ - {ETag: part1ETag, PartNumber: 1}, - {ETag: part2ETag, PartNumber: 2}, - }, - } - w, r = prepareTestFullRequest(tc, bktName, objName, query, complete) - tc.Handler().CompleteMultipartUploadHandler(w, r) - assertStatus(t, w, http.StatusOK) - - res, _ := getEncryptedObject(t, tc, bktName, objName) + res, _ := getEncryptedObject(t, hc, bktName, objName) require.Equal(t, len(part1)+len(part2), len(res)) require.Equal(t, append(part1, part2...), res) - part2Range := getEncryptedObjectRange(t, tc, bktName, objName, len(part1), len(part1)+len(part2)-1) + part2Range := getEncryptedObjectRange(t, hc, bktName, objName, len(part1), len(part1)+len(part2)-1) require.Equal(t, part2[0:], part2Range) } diff --git a/api/handler/get_test.go b/api/handler/get_test.go index f439b24..30e065f 100644 --- a/api/handler/get_test.go +++ b/api/handler/get_test.go @@ -155,7 +155,7 @@ func TestGetRange(t *testing.T) { createTestBucket(tc, bktName) content := "123456789abcdef" - putObjectContent(t, tc, bktName, objName, content) + putObjectContent(tc, bktName, objName, content) full := getObjectRange(t, tc, bktName, objName, 0, len(content)-1) require.Equal(t, content, string(full)) @@ -170,11 +170,11 @@ func TestGetRange(t *testing.T) { require.Equal(t, "bcdef", string(end)) } -func putObjectContent(t *testing.T, tc *handlerContext, bktName, objName, content string) { +func putObjectContent(hc *handlerContext, bktName, objName, content string) { body := bytes.NewReader([]byte(content)) - w, r := prepareTestPayloadRequest(tc, bktName, objName, body) - tc.Handler().PutObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + w, r := prepareTestPayloadRequest(hc, bktName, objName, body) + hc.Handler().PutObjectHandler(w, r) + assertStatus(hc.t, w, http.StatusOK) } func getObjectRange(t *testing.T, tc *handlerContext, bktName, objName string, start, end int) []byte { diff --git a/api/handler/locking_test.go b/api/handler/locking_test.go index 3737cff..b2ce0f9 100644 --- a/api/handler/locking_test.go +++ b/api/handler/locking_test.go @@ -423,35 +423,31 @@ func TestObjectLegalHold(t *testing.T) { objName := "obj-for-legal-hold" createTestObject(hc, bktInfo, objName) + getObjectLegalHold(hc, bktName, objName, legalHoldOff) + + putObjectLegalHold(hc, bktName, objName, legalHoldOn) + getObjectLegalHold(hc, bktName, objName, legalHoldOn) + + // to make sure put hold is an idempotent operation + putObjectLegalHold(hc, bktName, objName, legalHoldOn) + + putObjectLegalHold(hc, bktName, objName, legalHoldOff) + getObjectLegalHold(hc, bktName, objName, legalHoldOff) + + // to make sure put hold is an idempotent operation + putObjectLegalHold(hc, bktName, objName, legalHoldOff) +} + +func getObjectLegalHold(hc *handlerContext, bktName, objName, status string) { w, r := prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectLegalHoldHandler(w, r) - assertLegalHold(t, w, legalHoldOff) + assertLegalHold(hc.t, w, status) +} - w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOn}) +func putObjectLegalHold(hc *handlerContext, bktName, objName, status string) { + w, r := prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: status}) hc.Handler().PutObjectLegalHoldHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, nil) - hc.Handler().GetObjectLegalHoldHandler(w, r) - assertLegalHold(t, w, legalHoldOn) - - // to make sure put hold is an idempotent operation - w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOn}) - hc.Handler().PutObjectLegalHoldHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOff}) - hc.Handler().PutObjectLegalHoldHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, nil) - hc.Handler().GetObjectLegalHoldHandler(w, r) - assertLegalHold(t, w, legalHoldOff) - - // to make sure put hold is an idempotent operation - w, r = prepareTestRequest(hc, bktName, objName, &data.LegalHold{Status: legalHoldOff}) - hc.Handler().PutObjectLegalHoldHandler(w, r) - assertStatus(t, w, http.StatusOK) + assertStatus(hc.t, w, http.StatusOK) } func assertLegalHold(t *testing.T, w *httptest.ResponseRecorder, status string) { @@ -471,38 +467,43 @@ func TestObjectRetention(t *testing.T) { objName := "obj-for-retention" createTestObject(hc, bktInfo, objName) - w, r := prepareTestRequest(hc, bktName, objName, nil) - hc.Handler().GetObjectRetentionHandler(w, r) - assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey)) + getObjectRetention(hc, bktName, objName, nil, apiErrors.ErrNoSuchKey) retention := &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().Add(time.Minute).UTC().Format(time.RFC3339)} - w, r = prepareTestRequest(hc, bktName, objName, retention) - hc.Handler().PutObjectRetentionHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, nil) - hc.Handler().GetObjectRetentionHandler(w, r) - assertRetention(t, w, retention) + putObjectRetention(hc, bktName, objName, retention, false, 0) + getObjectRetention(hc, bktName, objName, retention, 0) retention = &data.Retention{Mode: governanceMode, RetainUntilDate: time.Now().UTC().Add(time.Minute).Format(time.RFC3339)} - w, r = prepareTestRequest(hc, bktName, objName, retention) - hc.Handler().PutObjectRetentionHandler(w, r) - assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrInternalError)) + putObjectRetention(hc, bktName, objName, retention, false, apiErrors.ErrInternalError) retention = &data.Retention{Mode: complianceMode, RetainUntilDate: time.Now().Add(time.Minute).UTC().Format(time.RFC3339)} - w, r = prepareTestRequest(hc, bktName, objName, retention) - r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) - hc.Handler().PutObjectRetentionHandler(w, r) - assertStatus(t, w, http.StatusOK) + putObjectRetention(hc, bktName, objName, retention, true, 0) + getObjectRetention(hc, bktName, objName, retention, 0) - w, r = prepareTestRequest(hc, bktName, objName, nil) + putObjectRetention(hc, bktName, objName, retention, true, apiErrors.ErrInternalError) +} + +func getObjectRetention(hc *handlerContext, bktName, objName string, retention *data.Retention, errCode apiErrors.ErrorCode) { + w, r := prepareTestRequest(hc, bktName, objName, nil) hc.Handler().GetObjectRetentionHandler(w, r) - assertRetention(t, w, retention) + if errCode == 0 { + assertRetention(hc.t, w, retention) + } else { + assertS3Error(hc.t, w, apiErrors.GetAPIError(errCode)) + } +} - w, r = prepareTestRequest(hc, bktName, objName, retention) - r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) +func putObjectRetention(hc *handlerContext, bktName, objName string, retention *data.Retention, byPass bool, errCode apiErrors.ErrorCode) { + w, r := prepareTestRequest(hc, bktName, objName, retention) + if byPass { + r.Header.Set(api.AmzBypassGovernanceRetention, strconv.FormatBool(true)) + } hc.Handler().PutObjectRetentionHandler(w, r) - assertS3Error(t, w, apiErrors.GetAPIError(apiErrors.ErrInternalError)) + if errCode == 0 { + assertStatus(hc.t, w, http.StatusOK) + } else { + assertS3Error(hc.t, w, apiErrors.GetAPIError(errCode)) + } } func assertRetention(t *testing.T, w *httptest.ResponseRecorder, retention *data.Retention) { @@ -530,25 +531,13 @@ func TestPutObjectWithLock(t *testing.T) { createTestBucketWithLock(hc, bktName, lockConfig) objDefault := "obj-default-retention" + putObject(t, hc, bktName, objDefault) - w, r := prepareTestRequest(hc, bktName, objDefault, nil) - hc.Handler().PutObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objDefault, nil) - hc.Handler().GetObjectRetentionHandler(w, r) - expectedRetention := &data.Retention{ - Mode: governanceMode, - RetainUntilDate: time.Now().Add(24 * time.Hour).Format(time.RFC3339), - } - assertRetentionApproximate(t, w, expectedRetention, 1) - - w, r = prepareTestRequest(hc, bktName, objDefault, nil) - hc.Handler().GetObjectLegalHoldHandler(w, r) - assertLegalHold(t, w, legalHoldOff) + getObjectRetentionApproximate(hc, bktName, objDefault, governanceMode, time.Now().Add(24*time.Hour)) + getObjectLegalHold(hc, bktName, objDefault, legalHoldOff) objOverride := "obj-override-retention" - w, r = prepareTestRequest(hc, bktName, objOverride, nil) + w, r := prepareTestRequest(hc, bktName, objOverride, nil) r.Header.Set(api.AmzObjectLockMode, complianceMode) r.Header.Set(api.AmzObjectLockLegalHold, legalHoldOn) r.Header.Set(api.AmzBypassGovernanceRetention, "true") @@ -556,17 +545,18 @@ func TestPutObjectWithLock(t *testing.T) { hc.Handler().PutObjectHandler(w, r) assertStatus(t, w, http.StatusOK) - w, r = prepareTestRequest(hc, bktName, objOverride, nil) - hc.Handler().GetObjectRetentionHandler(w, r) - expectedRetention = &data.Retention{ - Mode: complianceMode, - RetainUntilDate: time.Now().Add(2 * 24 * time.Hour).Format(time.RFC3339), - } - assertRetentionApproximate(t, w, expectedRetention, 1) + getObjectRetentionApproximate(hc, bktName, objOverride, complianceMode, time.Now().Add(2*24*time.Hour)) + getObjectLegalHold(hc, bktName, objOverride, legalHoldOn) +} - w, r = prepareTestRequest(hc, bktName, objOverride, nil) - hc.Handler().GetObjectLegalHoldHandler(w, r) - assertLegalHold(t, w, legalHoldOn) +func getObjectRetentionApproximate(hc *handlerContext, bktName, objName, mode string, untilDate time.Time) { + w, r := prepareTestRequest(hc, bktName, objName, nil) + hc.Handler().GetObjectRetentionHandler(w, r) + expectedRetention := &data.Retention{ + Mode: mode, + RetainUntilDate: untilDate.Format(time.RFC3339), + } + assertRetentionApproximate(hc.t, w, expectedRetention, 1) } func TestPutLockErrors(t *testing.T) { diff --git a/api/handler/object_list_test.go b/api/handler/object_list_test.go index 1762f30..e4b0c89 100644 --- a/api/handler/object_list_test.go +++ b/api/handler/object_list_test.go @@ -1,7 +1,6 @@ package handler import ( - "bytes" "net/http" "net/url" "strconv" @@ -44,31 +43,14 @@ func TestParseContinuationToken(t *testing.T) { func TestListObjectNullVersions(t *testing.T) { hc := prepareHandlerContext(t) - bktName := "bucket-versioning-enabled" + bktName, objName := "bucket-versioning-enabled", "object" createTestBucket(hc, bktName) - objName := "object" + putObjectContent(hc, bktName, objName, "content") + putBucketVersioning(t, hc, bktName, true) + putObjectContent(hc, bktName, objName, "content2") - body := bytes.NewReader([]byte("content")) - w, r := prepareTestPayloadRequest(hc, bktName, objName, body) - hc.Handler().PutObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) - - versioning := &VersioningConfiguration{Status: "Enabled"} - w, r = prepareTestRequest(hc, bktName, objName, versioning) - hc.Handler().PutBucketVersioningHandler(w, r) - assertStatus(t, w, http.StatusOK) - - body2 := bytes.NewReader([]byte("content2")) - w, r = prepareTestPayloadRequest(hc, bktName, objName, body2) - hc.Handler().PutObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) - - w, r = prepareTestRequest(hc, bktName, objName, nil) - hc.Handler().ListBucketObjectVersionsHandler(w, r) - - result := &ListObjectsVersionsResponse{} - parseTestResponse(t, w, result) + result := listVersions(t, hc, bktName) require.Len(t, result.Version, 2) require.Equal(t, data.UnversionedObjectVersionID, result.Version[1].VersionID)