mirror of
https://github.com/minio/minio.git
synced 2025-05-21 17:43:48 -04:00
tests: add unit test for DeleteMultipleObjectsHandler. (#3267)
Fixes #3058
This commit is contained in:
parent
1b85302161
commit
61d67a061c
@ -19,8 +19,10 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -607,3 +609,165 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap
|
|||||||
// `ExecObjectLayerAPINilTest` manages the operation.
|
// `ExecObjectLayerAPINilTest` manages the operation.
|
||||||
ExecObjectLayerAPINilTest(t, "", "", instanceType, apiRouter, nilReq)
|
ExecObjectLayerAPINilTest(t, "", "", instanceType, apiRouter, nilReq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper for calling DeleteMultipleObjects HTTP handler tests for both XL multiple disks and single node setup.
|
||||||
|
func TestAPIDeleteMultipleObjectsHandler(t *testing.T) {
|
||||||
|
ExecObjectLayerAPITest(t, testAPIDeleteMultipleObjectsHandler, []string{"DeleteMultipleObjects"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler,
|
||||||
|
credentials credential, t *testing.T) {
|
||||||
|
initBucketPolicies(obj)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
// register event notifier.
|
||||||
|
err = initEventNotifier(obj)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Notifier initialization failed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBytes := []byte("hello")
|
||||||
|
sha256sum := ""
|
||||||
|
var objectNames []string
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
objectName := "test-object-" + strconv.Itoa(i)
|
||||||
|
// uploading the object.
|
||||||
|
_, err = obj.PutObject(bucketName, objectName, int64(len(contentBytes)), bytes.NewBuffer(contentBytes),
|
||||||
|
make(map[string]string), sha256sum)
|
||||||
|
// if object upload fails stop the test.
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Put Object %d: Error uploading object: <ERROR> %v", i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// object used for the test.
|
||||||
|
objectNames = append(objectNames, objectName)
|
||||||
|
}
|
||||||
|
|
||||||
|
getObjectIdentifierList := func(objectNames []string) (objectIdentifierList []ObjectIdentifier) {
|
||||||
|
for _, objectName := range objectNames {
|
||||||
|
objectIdentifierList = append(objectIdentifierList, ObjectIdentifier{objectName})
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectIdentifierList
|
||||||
|
}
|
||||||
|
|
||||||
|
requestList := []DeleteObjectsRequest{
|
||||||
|
{Quiet: false, Objects: getObjectIdentifierList(objectNames[:5])},
|
||||||
|
{Quiet: true, Objects: getObjectIdentifierList(objectNames[5:])},
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate multi objects delete response.
|
||||||
|
successRequest0 := encodeResponse(requestList[0])
|
||||||
|
successResponse0 := generateMultiDeleteResponse(requestList[0].Quiet, requestList[0].Objects, nil)
|
||||||
|
encodedSuccessResponse0 := encodeResponse(successResponse0)
|
||||||
|
|
||||||
|
successRequest1 := encodeResponse(requestList[1])
|
||||||
|
successResponse1 := generateMultiDeleteResponse(requestList[1].Quiet, requestList[1].Objects, nil)
|
||||||
|
encodedSuccessResponse1 := encodeResponse(successResponse1)
|
||||||
|
|
||||||
|
// generate multi objects delete response for errors.
|
||||||
|
// errorRequest := encodeResponse(requestList[1])
|
||||||
|
errorResponse := generateMultiDeleteResponse(requestList[1].Quiet, requestList[1].Objects, nil)
|
||||||
|
encodedErrorResponse := encodeResponse(errorResponse)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
bucket string
|
||||||
|
objects []byte
|
||||||
|
accessKey string
|
||||||
|
secretKey string
|
||||||
|
expectedContent []byte
|
||||||
|
expectedRespStatus int
|
||||||
|
}{
|
||||||
|
// Test case - 1.
|
||||||
|
// Delete objects with invalid access key.
|
||||||
|
{
|
||||||
|
bucket: bucketName,
|
||||||
|
objects: successRequest0,
|
||||||
|
accessKey: "Invalid-AccessID",
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedContent: nil,
|
||||||
|
expectedRespStatus: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
// Test case - 2.
|
||||||
|
// Delete valid objects with quiet flag off.
|
||||||
|
{
|
||||||
|
bucket: bucketName,
|
||||||
|
objects: successRequest0,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedContent: encodedSuccessResponse0,
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
},
|
||||||
|
// Test case - 3.
|
||||||
|
// Delete valid objects with quiet flag on.
|
||||||
|
{
|
||||||
|
bucket: bucketName,
|
||||||
|
objects: successRequest1,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedContent: encodedSuccessResponse1,
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
},
|
||||||
|
// Test case - 4.
|
||||||
|
// Delete previously deleted objects.
|
||||||
|
{
|
||||||
|
bucket: bucketName,
|
||||||
|
objects: successRequest1,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedContent: encodedErrorResponse,
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
var req *http.Request
|
||||||
|
var actualContent []byte
|
||||||
|
|
||||||
|
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
||||||
|
req, err = newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", bucketName),
|
||||||
|
int64(len(testCase.objects)), bytes.NewReader(testCase.objects), testCase.accessKey, testCase.secretKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create HTTP request for DeleteMultipleObjects: <ERROR> %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
|
// Call the ServeHTTP to executes the registered handler.
|
||||||
|
apiRouter.ServeHTTP(rec, req)
|
||||||
|
// Assert the response code with the expected status.
|
||||||
|
if rec.Code != testCase.expectedRespStatus {
|
||||||
|
t.Errorf("Case %d: Minio %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, rec.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the response body.
|
||||||
|
actualContent, err = ioutil.ReadAll(rec.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Test %d : Minio %s: Failed parsing response body: <ERROR> %v", i+1, instanceType, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify whether the bucket obtained object is same as the one created.
|
||||||
|
if testCase.expectedContent != nil && !bytes.Equal(testCase.expectedContent, actualContent) {
|
||||||
|
t.Errorf("Test %d : Minio %s: Object content differs from expected value.", i+1, instanceType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently anonymous user cannot delete multiple objects in Minio server, hence no test case is required.
|
||||||
|
|
||||||
|
// HTTP request to test the case of `objectLayer` being set to `nil`.
|
||||||
|
// There is no need to use an existing bucket or valid input for creating the request,
|
||||||
|
// since the `objectLayer==nil` check is performed before any other checks inside the handlers.
|
||||||
|
// The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called.
|
||||||
|
// Indicating that all parts are uploaded and initiating completeMultipartUpload.
|
||||||
|
nilBucket := "dummy-bucket"
|
||||||
|
nilObject := ""
|
||||||
|
|
||||||
|
nilReq, err := newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", nilBucket), 0, nil, "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Minio %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType)
|
||||||
|
}
|
||||||
|
// execute the object layer set to `nil` test.
|
||||||
|
// `ExecObjectLayerAPINilTest` manages the operation.
|
||||||
|
ExecObjectLayerAPINilTest(t, nilBucket, nilObject, instanceType, apiRouter, nilReq)
|
||||||
|
}
|
||||||
|
@ -1416,6 +1416,13 @@ func getDeleteBucketURL(endPoint, bucketName string) string {
|
|||||||
return makeTestTargetURL(endPoint, bucketName, "", url.Values{})
|
return makeTestTargetURL(endPoint, bucketName, "", url.Values{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return URL for deleting the bucket.
|
||||||
|
func getDeleteMultipleObjectsURL(endPoint, bucketName string) string {
|
||||||
|
queryValue := url.Values{}
|
||||||
|
queryValue.Set("delete", "")
|
||||||
|
return makeTestTargetURL(endPoint, bucketName, "", queryValue)
|
||||||
|
}
|
||||||
|
|
||||||
// return URL For fetching location of the bucket.
|
// return URL For fetching location of the bucket.
|
||||||
func getBucketLocationURL(endPoint, bucketName string) string {
|
func getBucketLocationURL(endPoint, bucketName string) string {
|
||||||
queryValue := url.Values{}
|
queryValue := url.Values{}
|
||||||
@ -1970,6 +1977,9 @@ func registerBucketLevelFunc(bucket *router.Router, api objectAPIHandlers, apiFu
|
|||||||
case "HeadBucket":
|
case "HeadBucket":
|
||||||
// Register HeadBucket handler.
|
// Register HeadBucket handler.
|
||||||
bucket.Methods("HEAD").HandlerFunc(api.HeadBucketHandler)
|
bucket.Methods("HEAD").HandlerFunc(api.HeadBucketHandler)
|
||||||
|
case "DeleteMultipleObjects":
|
||||||
|
// Register DeleteMultipleObjects handler.
|
||||||
|
bucket.Methods("POST").HandlerFunc(api.DeleteMultipleObjectsHandler).Queries("delete", "")
|
||||||
case "NewMultipart":
|
case "NewMultipart":
|
||||||
// Register New Multipart upload handler.
|
// Register New Multipart upload handler.
|
||||||
bucket.Methods("POST").Path("/{object:.+}").HandlerFunc(api.NewMultipartUploadHandler).Queries("uploads", "")
|
bucket.Methods("POST").Path("/{object:.+}").HandlerFunc(api.NewMultipartUploadHandler).Queries("uploads", "")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user