mirror of
https://github.com/minio/minio.git
synced 2025-04-22 03:24:38 -04:00
Add PutObjectHandler unit tests covering failure cases (#3096)
This commit is contained in:
parent
485c0ea8bf
commit
12cd2da265
@ -292,6 +292,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
unexpectedEOF
|
unexpectedEOF
|
||||||
signatureMismatch
|
signatureMismatch
|
||||||
chunkDateMismatch
|
chunkDateMismatch
|
||||||
|
tooBigDecodedLength
|
||||||
)
|
)
|
||||||
|
|
||||||
// byte data for PutObject.
|
// byte data for PutObject.
|
||||||
@ -444,9 +445,27 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
shouldPass: false,
|
shouldPass: false,
|
||||||
fault: chunkDateMismatch,
|
fault: chunkDateMismatch,
|
||||||
},
|
},
|
||||||
|
// Test case - 10
|
||||||
|
// Set x-amz-decoded-content-length to a value too big to hold in int64.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: oneKData,
|
||||||
|
dataLen: 1024,
|
||||||
|
chunkSize: 1024,
|
||||||
|
expectedContent: []byte{},
|
||||||
|
expectedRespStatus: http.StatusInternalServerError,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
shouldPass: false,
|
||||||
|
fault: tooBigDecodedLength,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Iterating over the cases, fetching the object validating the response.
|
// Iterating over the cases, fetching the object validating the response.
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
|
if i != 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
|
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
// construct HTTP request for Put Object end point.
|
// construct HTTP request for Put Object end point.
|
||||||
@ -477,6 +496,9 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
req, err = malformDataSigV4(req, 'z')
|
req, err = malformDataSigV4(req, 'z')
|
||||||
case unexpectedEOF:
|
case unexpectedEOF:
|
||||||
req, err = truncateChunkByHalfSigv4(req)
|
req, err = truncateChunkByHalfSigv4(req)
|
||||||
|
case tooBigDecodedLength:
|
||||||
|
// Set decoded length to a large value out of int64 range to simulate parse failure.
|
||||||
|
req.Header.Set("x-amz-decoded-content-length", "9999999999999999999999")
|
||||||
}
|
}
|
||||||
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
||||||
@ -529,14 +551,29 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
// byte data for PutObject.
|
// byte data for PutObject.
|
||||||
bytesData := generateBytesData(6 * 1024 * 1024)
|
bytesData := generateBytesData(6 * 1024 * 1024)
|
||||||
|
|
||||||
|
copySourceHeader := http.Header{}
|
||||||
|
copySourceHeader.Set("X-Amz-Copy-Source", "somewhere")
|
||||||
|
invalidMD5Header := http.Header{}
|
||||||
|
invalidMD5Header.Set("Content-Md5", "42")
|
||||||
|
|
||||||
|
addCustomHeaders := func(req *http.Request, customHeaders http.Header) {
|
||||||
|
for k, values := range customHeaders {
|
||||||
|
for _, value := range values {
|
||||||
|
req.Header.Set(k, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test cases with inputs and expected result for GetObject.
|
// test cases with inputs and expected result for GetObject.
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
bucketName string
|
bucketName string
|
||||||
objectName string
|
objectName string
|
||||||
|
headers http.Header
|
||||||
data []byte
|
data []byte
|
||||||
dataLen int
|
dataLen int
|
||||||
accessKey string
|
accessKey string
|
||||||
secretKey string
|
secretKey string
|
||||||
|
fault Fault
|
||||||
// expected output.
|
// expected output.
|
||||||
expectedRespStatus int // expected response status body.
|
expectedRespStatus int // expected response status body.
|
||||||
}{
|
}{
|
||||||
@ -564,6 +601,54 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
|
|
||||||
expectedRespStatus: http.StatusForbidden,
|
expectedRespStatus: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
|
// Test case - 3.
|
||||||
|
// Test Case with invalid header key X-Amz-Copy-Source.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
headers: copySourceHeader,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
// Test case - 4.
|
||||||
|
// Test Case with invalid Content-Md5 value
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
headers: invalidMD5Header,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
// Test case - 5.
|
||||||
|
// Test Case with object greater than maximum allowed size.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
fault: TooBigObject,
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
// Test case - 6.
|
||||||
|
// Test Case with missing content length
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
fault: MissingContentLength,
|
||||||
|
expectedRespStatus: http.StatusLengthRequired,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Iterating over the cases, fetching the object validating the response.
|
// Iterating over the cases, fetching the object validating the response.
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
@ -576,6 +661,17 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Test %d: Failed to create HTTP request for Put Object: <ERROR> %v", i+1, err)
|
t.Fatalf("Test %d: Failed to create HTTP request for Put Object: <ERROR> %v", i+1, err)
|
||||||
}
|
}
|
||||||
|
// Add test case specific headers to the request.
|
||||||
|
addCustomHeaders(req, testCase.headers)
|
||||||
|
|
||||||
|
// Inject faults if specified in testCase.fault
|
||||||
|
switch testCase.fault {
|
||||||
|
case MissingContentLength:
|
||||||
|
req.ContentLength = -1
|
||||||
|
req.TransferEncoding = []string{}
|
||||||
|
case TooBigObject:
|
||||||
|
req.ContentLength = maxObjectSize + 1
|
||||||
|
}
|
||||||
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
// Call the ServeHTTP to execute the handler,`func (api objectAPIHandlers) GetObjectHandler` handles the request.
|
||||||
apiRouter.ServeHTTP(rec, req)
|
apiRouter.ServeHTTP(rec, req)
|
||||||
@ -608,6 +704,18 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
|||||||
t.Fatalf("Test %d: %s: Failed to create HTTP request for PutObject: <ERROR> %v", i+1, instanceType, err)
|
t.Fatalf("Test %d: %s: Failed to create HTTP request for PutObject: <ERROR> %v", i+1, instanceType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add test case specific headers to the request.
|
||||||
|
addCustomHeaders(reqV2, testCase.headers)
|
||||||
|
|
||||||
|
// Inject faults if specified in testCase.fault
|
||||||
|
switch testCase.fault {
|
||||||
|
case MissingContentLength:
|
||||||
|
reqV2.ContentLength = -1
|
||||||
|
reqV2.TransferEncoding = []string{}
|
||||||
|
case TooBigObject:
|
||||||
|
reqV2.ContentLength = maxObjectSize + 1
|
||||||
|
}
|
||||||
|
|
||||||
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
|
||||||
// Call the ServeHTTP to execute the handler.
|
// Call the ServeHTTP to execute the handler.
|
||||||
apiRouter.ServeHTTP(recV2, reqV2)
|
apiRouter.ServeHTTP(recV2, reqV2)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user