mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
parent
df2ef64d20
commit
7d37dea449
@ -171,9 +171,15 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
objectName string
|
objectName string
|
||||||
data []byte
|
data []byte
|
||||||
dataLen int
|
dataLen int
|
||||||
|
chunkSize int64
|
||||||
// expected output.
|
// expected output.
|
||||||
expectedContent []byte // expected response body.
|
expectedContent []byte // expected response body.
|
||||||
expectedRespStatus int // expected response status body.
|
expectedRespStatus int // expected response status body.
|
||||||
|
// Access keys
|
||||||
|
accessKey string
|
||||||
|
secretKey string
|
||||||
|
shouldPass bool
|
||||||
|
removeAuthHeader bool
|
||||||
}{
|
}{
|
||||||
// Test case - 1.
|
// Test case - 1.
|
||||||
// Fetching the entire object and validating its contents.
|
// Fetching the entire object and validating its contents.
|
||||||
@ -182,8 +188,69 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
objectName: objectName,
|
objectName: objectName,
|
||||||
data: bytesData,
|
data: bytesData,
|
||||||
dataLen: len(bytesData),
|
dataLen: len(bytesData),
|
||||||
|
chunkSize: 64 * 1024, // 64k
|
||||||
expectedContent: []byte{},
|
expectedContent: []byte{},
|
||||||
expectedRespStatus: http.StatusOK,
|
expectedRespStatus: http.StatusOK,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
shouldPass: true,
|
||||||
|
},
|
||||||
|
// Test case - 2
|
||||||
|
// Small chunk size.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
chunkSize: 1 * 1024, // 1k
|
||||||
|
expectedContent: []byte{},
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
shouldPass: true,
|
||||||
|
},
|
||||||
|
// Test case - 3
|
||||||
|
// Invalid access key id.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
chunkSize: 64 * 1024, // 64k
|
||||||
|
expectedContent: []byte{},
|
||||||
|
expectedRespStatus: http.StatusForbidden,
|
||||||
|
accessKey: "",
|
||||||
|
secretKey: "",
|
||||||
|
shouldPass: false,
|
||||||
|
},
|
||||||
|
// Test case - 4
|
||||||
|
// Wrong auth header returns as bad request.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
chunkSize: 64 * 1024, // 64k
|
||||||
|
expectedContent: []byte{},
|
||||||
|
expectedRespStatus: http.StatusBadRequest,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
shouldPass: false,
|
||||||
|
removeAuthHeader: true,
|
||||||
|
},
|
||||||
|
// Test case - 5
|
||||||
|
// Large chunk size.. also passes.
|
||||||
|
{
|
||||||
|
bucketName: bucketName,
|
||||||
|
objectName: objectName,
|
||||||
|
data: bytesData,
|
||||||
|
dataLen: len(bytesData),
|
||||||
|
chunkSize: 100 * 1024, // 100k
|
||||||
|
expectedContent: []byte{},
|
||||||
|
expectedRespStatus: http.StatusOK,
|
||||||
|
accessKey: credentials.AccessKeyID,
|
||||||
|
secretKey: credentials.SecretAccessKey,
|
||||||
|
shouldPass: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Iterating over the cases, fetching the object validating the response.
|
// Iterating over the cases, fetching the object validating the response.
|
||||||
@ -193,37 +260,43 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
|
|||||||
// construct HTTP request for Put Object end point.
|
// construct HTTP request for Put Object end point.
|
||||||
req, err := newTestStreamingSignedRequest("PUT",
|
req, err := newTestStreamingSignedRequest("PUT",
|
||||||
getPutObjectURL("", testCase.bucketName, testCase.objectName),
|
getPutObjectURL("", testCase.bucketName, testCase.objectName),
|
||||||
int64(testCase.dataLen), 64*1024, bytes.NewReader(testCase.data),
|
int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data),
|
||||||
credentials.AccessKeyID, credentials.SecretAccessKey)
|
testCase.accessKey, testCase.secretKey)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
// Removes auth header if test case requires it.
|
||||||
|
if testCase.removeAuthHeader {
|
||||||
|
req.Header.Del("Authorization")
|
||||||
|
}
|
||||||
// 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)
|
||||||
// Assert the response code with the expected status.
|
// Assert the response code with the expected status.
|
||||||
if rec.Code != testCase.expectedRespStatus {
|
if rec.Code != testCase.expectedRespStatus {
|
||||||
t.Fatalf("Case %d: Expected the response status to be `%d`, but instead found `%d`", i+1, testCase.expectedRespStatus, rec.Code)
|
t.Errorf("Test %d: Expected the response status to be `%d`, but instead found `%d`", i+1, testCase.expectedRespStatus, rec.Code)
|
||||||
}
|
}
|
||||||
// read the response body.
|
// read the response body.
|
||||||
actualContent, err := ioutil.ReadAll(rec.Body)
|
actualContent, err := ioutil.ReadAll(rec.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Test %d: %s: Failed parsing response body: <ERROR> %v", i+1, instanceType, err)
|
t.Fatalf("Test %d: %s: Failed parsing response body: <ERROR> %v", i+1, instanceType, err)
|
||||||
}
|
}
|
||||||
// Verify whether the bucket obtained object is same as the one inserted.
|
if testCase.shouldPass {
|
||||||
if !bytes.Equal(testCase.expectedContent, actualContent) {
|
// Verify whether the bucket obtained object is same as the one inserted.
|
||||||
t.Errorf("Test %d: %s: Object content differs from expected value.: %s", i+1, instanceType, string(actualContent))
|
if !bytes.Equal(testCase.expectedContent, actualContent) {
|
||||||
}
|
t.Errorf("Test %d: %s: Object content differs from expected value.: %s", i+1, instanceType, string(actualContent))
|
||||||
|
}
|
||||||
|
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
err = obj.GetObject(testCase.bucketName, testCase.objectName, 0, int64(bytesDataLen), buffer)
|
err = obj.GetObject(testCase.bucketName, testCase.objectName, 0, int64(bytesDataLen), buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Test %d: %s: Failed to fetch the copied object: <ERROR> %s", i+1, instanceType, err)
|
t.Fatalf("Test %d: %s: Failed to fetch the copied object: <ERROR> %s", i+1, instanceType, err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(bytesData, buffer.Bytes()) {
|
||||||
|
t.Errorf("Test %d: %s: Data Mismatch: Data fetched back from the uploaded object doesn't match the original one.", i+1, instanceType)
|
||||||
|
}
|
||||||
|
buffer.Reset()
|
||||||
}
|
}
|
||||||
if !bytes.Equal(bytesData, buffer.Bytes()) {
|
|
||||||
t.Errorf("Test %d: %s: Data Mismatch: Data fetched back from the uploaded object doesn't match the original one.", i+1, instanceType)
|
|
||||||
}
|
|
||||||
buffer.Reset()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,7 +632,7 @@ func (s *TestSuiteCommon) TestObjectGet(c *C) {
|
|||||||
c.Assert(response.StatusCode, Equals, http.StatusOK)
|
c.Assert(response.StatusCode, Equals, http.StatusOK)
|
||||||
// concurrently reading the object, safety check for races.
|
// concurrently reading the object, safety check for races.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for i := 0; i < ConcurrencyLevel; i++ {
|
for i := 0; i < testConcurrencyLevel; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@ -821,7 +821,7 @@ func (s *TestSuiteCommon) TestPutBucket(c *C) {
|
|||||||
// The purpose this block is not to check for correctness of functionality
|
// The purpose this block is not to check for correctness of functionality
|
||||||
// Run the test with -race flag to utilize this
|
// Run the test with -race flag to utilize this
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for i := 0; i < ConcurrencyLevel; i++ {
|
for i := 0; i < testConcurrencyLevel; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
@ -26,9 +26,9 @@ import (
|
|||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Concurreny level.
|
// concurreny level for certain parallel tests.
|
||||||
const (
|
const (
|
||||||
ConcurrencyLevel = 10
|
testConcurrencyLevel = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -396,13 +396,12 @@ func newTestStreamingRequest(method, urlStr string, dataLength, chunkSize int64,
|
|||||||
|
|
||||||
req.Header.Set("x-amz-content-sha256", "STREAMING-AWS4-HMAC-SHA256-PAYLOAD")
|
req.Header.Set("x-amz-content-sha256", "STREAMING-AWS4-HMAC-SHA256-PAYLOAD")
|
||||||
req.Header.Set("content-encoding", "aws-chunked")
|
req.Header.Set("content-encoding", "aws-chunked")
|
||||||
req.Header.Set("x-amz-storage-class", "REDUCED_REDUNDANCY")
|
|
||||||
|
|
||||||
req.Header.Set("x-amz-decoded-content-length", strconv.FormatInt(dataLength, 10))
|
req.Header.Set("x-amz-decoded-content-length", strconv.FormatInt(dataLength, 10))
|
||||||
req.Header.Set("content-length", strconv.FormatInt(contentLength, 10))
|
req.Header.Set("content-length", strconv.FormatInt(contentLength, 10))
|
||||||
|
|
||||||
// Seek back to beginning.
|
// Seek back to beginning.
|
||||||
body.Seek(0, 0)
|
body.Seek(0, 0)
|
||||||
|
|
||||||
// Add body
|
// Add body
|
||||||
req.Body = ioutil.NopCloser(body)
|
req.Body = ioutil.NopCloser(body)
|
||||||
req.ContentLength = contentLength
|
req.ContentLength = contentLength
|
||||||
@ -422,6 +421,8 @@ func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regionStr := serverConfig.GetRegion()
|
||||||
|
|
||||||
var stream []byte
|
var stream []byte
|
||||||
var buffer []byte
|
var buffer []byte
|
||||||
body.Seek(0, 0)
|
body.Seek(0, 0)
|
||||||
@ -436,7 +437,7 @@ func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSi
|
|||||||
// Get scope.
|
// Get scope.
|
||||||
scope := strings.Join([]string{
|
scope := strings.Join([]string{
|
||||||
currTime.Format(yyyymmdd),
|
currTime.Format(yyyymmdd),
|
||||||
"us-east-1",
|
regionStr,
|
||||||
"s3",
|
"s3",
|
||||||
"aws4_request",
|
"aws4_request",
|
||||||
}, "/")
|
}, "/")
|
||||||
@ -449,7 +450,7 @@ func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSi
|
|||||||
stringToSign = stringToSign + hex.EncodeToString(sum256(buffer[:n]))
|
stringToSign = stringToSign + hex.EncodeToString(sum256(buffer[:n]))
|
||||||
|
|
||||||
date := sumHMAC([]byte("AWS4"+secretKey), []byte(currTime.Format(yyyymmdd)))
|
date := sumHMAC([]byte("AWS4"+secretKey), []byte(currTime.Format(yyyymmdd)))
|
||||||
region := sumHMAC(date, []byte("us-east-1"))
|
region := sumHMAC(date, []byte(regionStr))
|
||||||
service := sumHMAC(region, []byte("s3"))
|
service := sumHMAC(region, []byte("s3"))
|
||||||
signingKey := sumHMAC(service, []byte("aws4_request"))
|
signingKey := sumHMAC(service, []byte("aws4_request"))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user