2016-09-09 19:18:38 +02:00
/ *
* Minio Cloud Storage , ( C ) 2016 Minio , Inc .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
package cmd
import (
"bytes"
"encoding/xml"
"net/http"
"net/http/httptest"
"testing"
)
// Wrapper for calling GetBucketPolicy HTTP handler tests for both XL multiple disks and single node setup.
func TestGetBucketLocationHandler ( t * testing . T ) {
2016-10-09 18:21:37 +02:00
ExecObjectLayerAPITest ( t , testGetBucketLocationHandler , [ ] string { "GetBucketLocation" } )
2016-09-09 19:18:38 +02:00
}
2016-10-09 18:21:37 +02:00
func testGetBucketLocationHandler ( obj ObjectLayer , instanceType , bucketName string , apiRouter http . Handler ,
credentials credential , t * testing . T ) {
2016-09-26 23:28:35 +02:00
initBucketPolicies ( obj )
2016-09-09 19:18:38 +02:00
// test cases with sample input and expected output.
testCases := [ ] struct {
bucketName string
accessKey string
secretKey string
// expected Response.
expectedRespStatus int
locationResponse [ ] byte
errorResponse APIErrorResponse
shouldPass bool
} {
2016-10-13 18:25:56 +02:00
// Test case - 1.
2016-09-09 19:18:38 +02:00
// Tests for authenticated request and proper response.
{
2016-10-13 18:25:56 +02:00
bucketName : bucketName ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusOK ,
locationResponse : [ ] byte ( ` < ? xml version = "1.0" encoding = "UTF-8" ? >
2016-09-09 19:18:38 +02:00
< LocationConstraint xmlns = "http://s3.amazonaws.com/doc/2006-03-01/" > < / LocationConstraint > ` ) ,
2016-10-13 18:25:56 +02:00
errorResponse : APIErrorResponse { } ,
shouldPass : true ,
2016-09-09 19:18:38 +02:00
} ,
2016-10-13 18:25:56 +02:00
// Test case - 2.
// Tests for signature mismatch error.
2016-09-09 19:18:38 +02:00
{
2016-10-13 18:25:56 +02:00
bucketName : bucketName ,
accessKey : "abcd" ,
secretKey : "abcd" ,
expectedRespStatus : http . StatusForbidden ,
locationResponse : [ ] byte ( "" ) ,
errorResponse : APIErrorResponse {
2016-09-09 19:18:38 +02:00
Resource : "/" + bucketName + "/" ,
2016-10-13 18:25:56 +02:00
Code : "InvalidAccessKeyID" ,
Message : "The access key ID you provided does not exist in our records." ,
2016-09-09 19:18:38 +02:00
} ,
2016-10-13 18:25:56 +02:00
shouldPass : false ,
2016-09-09 19:18:38 +02:00
} ,
}
for i , testCase := range testCases {
2016-10-13 18:25:56 +02:00
if i != 1 {
continue
}
2016-10-11 09:00:02 +02:00
// initialize httptest Recorder, this records any mutations to response writer inside the handler.
2016-09-09 19:18:38 +02:00
rec := httptest . NewRecorder ( )
2016-09-14 04:00:01 +02:00
// construct HTTP request for Get bucket location.
2016-09-30 23:32:13 +02:00
req , err := newTestSignedRequestV4 ( "GET" , getBucketLocationURL ( "" , testCase . bucketName ) , 0 , nil , testCase . accessKey , testCase . secretKey )
2016-09-09 19:18:38 +02:00
if err != nil {
2016-09-14 04:00:01 +02:00
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for GetBucketLocationHandler: <ERROR> %v" , i + 1 , instanceType , err )
2016-09-09 19:18:38 +02:00
}
2016-10-13 18:25:56 +02:00
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
2016-09-09 19:18:38 +02:00
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( rec , req )
if rec . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , rec . Code )
}
if ! bytes . Equal ( testCase . locationResponse , rec . Body . Bytes ( ) ) && testCase . shouldPass {
t . Errorf ( "Test %d: %s: Expected the response to be `%s`, but instead found `%s`" , i + 1 , instanceType , string ( testCase . locationResponse ) , string ( rec . Body . Bytes ( ) ) )
}
errorResponse := APIErrorResponse { }
err = xml . Unmarshal ( rec . Body . Bytes ( ) , & errorResponse )
if err != nil && ! testCase . shouldPass {
t . Fatalf ( "Test %d: %s: Unable to marshal response body %s" , i + 1 , instanceType , string ( rec . Body . Bytes ( ) ) )
}
if errorResponse . Resource != testCase . errorResponse . Resource {
t . Errorf ( "Test %d: %s: Expected the error resource to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Resource , errorResponse . Resource )
}
if errorResponse . Message != testCase . errorResponse . Message {
t . Errorf ( "Test %d: %s: Expected the error message to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Message , errorResponse . Message )
}
if errorResponse . Code != testCase . errorResponse . Code {
t . Errorf ( "Test %d: %s: Expected the error code to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Code , errorResponse . Code )
}
2016-10-13 18:25:56 +02:00
// Verify response of the V2 signed HTTP request.
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
recV2 := httptest . NewRecorder ( )
// construct HTTP request for PUT bucket policy endpoint.
reqV2 , err := newTestSignedRequestV2 ( "GET" , getBucketLocationURL ( "" , testCase . bucketName ) , 0 , nil , testCase . accessKey , testCase . secretKey )
if err != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: <ERROR> %v" , i + 1 , instanceType , err )
}
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( recV2 , reqV2 )
if recV2 . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , recV2 . Code )
}
errorResponse = APIErrorResponse { }
err = xml . Unmarshal ( recV2 . Body . Bytes ( ) , & errorResponse )
if err != nil && ! testCase . shouldPass {
t . Fatalf ( "Test %d: %s: Unable to marshal response body %s" , i + 1 , instanceType , string ( recV2 . Body . Bytes ( ) ) )
}
if errorResponse . Resource != testCase . errorResponse . Resource {
t . Errorf ( "Test %d: %s: Expected the error resource to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Resource , errorResponse . Resource )
}
if errorResponse . Message != testCase . errorResponse . Message {
t . Errorf ( "Test %d: %s: Expected the error message to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Message , errorResponse . Message )
}
if errorResponse . Code != testCase . errorResponse . Code {
t . Errorf ( "Test %d: %s: Expected the error code to be `%s`, but instead found `%s`" , i + 1 , instanceType , testCase . errorResponse . Code , errorResponse . Code )
}
2016-09-09 19:18:38 +02:00
}
2016-10-09 18:21:37 +02:00
// Test for Anonymous/unsigned http request.
// ListBucketsHandler doesn't support bucket policies, setting the policies shouldn't make any difference.
anonReq , err := newTestRequest ( "GET" , getBucketLocationURL ( "" , bucketName ) , 0 , nil )
if err != nil {
t . Fatalf ( "Minio %s: Failed to create an anonymous request." , instanceType )
}
// ExecObjectLayerAPIAnonTest - Calls the HTTP API handler using the anonymous request, validates the ErrAccessDeniedResponse,
// sets the bucket policy using the policy statement generated from `getReadOnlyBucketStatement` so that the
// unsigned request goes through and its validated again.
ExecObjectLayerAPIAnonTest ( t , "TestGetBucketLocationHandler" , bucketName , "" , instanceType , apiRouter , anonReq , getReadOnlyBucketStatement )
2016-10-11 09:00:02 +02:00
// HTTP request for testing when `objectLayer` is set to `nil`.
// There is no need to use an existing bucket and 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.
nilBucket := "dummy-bucket"
nilReq , err := newTestRequest ( "GET" , getBucketLocationURL ( "" , 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 )
}
// Executes the object layer set to `nil` test.
// `ExecObjectLayerAPINilTest` manages the operation.
ExecObjectLayerAPINilTest ( t , nilBucket , "" , instanceType , apiRouter , nilReq )
2016-09-09 19:18:38 +02:00
}
// Wrapper for calling HeadBucket HTTP handler tests for both XL multiple disks and single node setup.
func TestHeadBucketHandler ( t * testing . T ) {
2016-10-09 18:21:37 +02:00
ExecObjectLayerAPITest ( t , testHeadBucketHandler , [ ] string { "HeadBucket" } )
2016-09-09 19:18:38 +02:00
}
2016-10-09 18:21:37 +02:00
func testHeadBucketHandler ( obj ObjectLayer , instanceType , bucketName string , apiRouter http . Handler ,
credentials credential , t * testing . T ) {
2016-09-26 23:28:35 +02:00
initBucketPolicies ( obj )
2016-09-09 19:18:38 +02:00
// test cases with sample input and expected output.
testCases := [ ] struct {
bucketName string
accessKey string
secretKey string
// expected Response.
expectedRespStatus int
} {
2016-10-13 18:25:56 +02:00
// Test case - 1.
2016-09-09 19:18:38 +02:00
// Bucket exists.
{
bucketName : bucketName ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusOK ,
} ,
2016-10-13 18:25:56 +02:00
// Test case - 2.
2016-09-09 19:18:38 +02:00
// Non-existent bucket name.
{
bucketName : "2333" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusNotFound ,
} ,
2016-10-13 18:25:56 +02:00
// Test case - 3.
// Testing for signature mismatch error.
// setting invalid acess and secret key.
2016-09-09 19:18:38 +02:00
{
bucketName : bucketName ,
2016-10-13 18:25:56 +02:00
accessKey : "abcd" ,
secretKey : "abcd" ,
2016-09-09 19:18:38 +02:00
expectedRespStatus : http . StatusForbidden ,
} ,
}
for i , testCase := range testCases {
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
rec := httptest . NewRecorder ( )
2016-09-14 04:00:01 +02:00
// construct HTTP request for HEAD bucket.
2016-09-30 23:32:13 +02:00
req , err := newTestSignedRequestV4 ( "HEAD" , getHEADBucketURL ( "" , testCase . bucketName ) , 0 , nil , testCase . accessKey , testCase . secretKey )
2016-09-09 19:18:38 +02:00
if err != nil {
2016-09-14 04:00:01 +02:00
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for HeadBucketHandler: <ERROR> %v" , i + 1 , instanceType , err )
2016-09-09 19:18:38 +02:00
}
2016-10-13 18:25:56 +02:00
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
2016-09-09 19:18:38 +02:00
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( rec , req )
if rec . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , rec . Code )
}
2016-10-13 18:25:56 +02:00
// Verify response the V2 signed HTTP request.
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
recV2 := httptest . NewRecorder ( )
// construct HTTP request for PUT bucket policy endpoint.
reqV2 , err := newTestSignedRequestV2 ( "HEAD" , getHEADBucketURL ( "" , testCase . bucketName ) , 0 , nil , testCase . accessKey , testCase . secretKey )
if err != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: <ERROR> %v" , i + 1 , instanceType , err )
}
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( recV2 , reqV2 )
if recV2 . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , recV2 . Code )
}
2016-09-09 19:18:38 +02:00
}
2016-10-09 18:21:37 +02:00
// Test for Anonymous/unsigned http request.
anonReq , err := newTestRequest ( "HEAD" , getHEADBucketURL ( "" , bucketName ) , 0 , nil )
if err != nil {
t . Fatalf ( "Minio %s: Failed to create an anonymous request for bucket \"%s\": <ERROR> %v" ,
instanceType , bucketName , err )
}
// ExecObjectLayerAPIAnonTest - Calls the HTTP API handler using the anonymous request, validates the ErrAccessDeniedResponse,
// sets the bucket policy using the policy statement generated from `getReadOnlyBucketStatement` so that the
// unsigned request goes through and its validated again.
ExecObjectLayerAPIAnonTest ( t , "TestHeadBucketHandler" , bucketName , "" , instanceType , apiRouter , anonReq , getReadOnlyBucketStatement )
2016-10-11 09:00:02 +02:00
// HTTP request for testing when `objectLayer` is set to `nil`.
// There is no need to use an existing bucket and 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.
nilBucket := "dummy-bucket"
nilReq , err := newTestRequest ( "HEAD" , getHEADBucketURL ( "" , 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 , "" , instanceType , apiRouter , nilReq )
2016-09-09 19:18:38 +02:00
}
2016-09-14 04:00:01 +02:00
// Wrapper for calling TestListMultipartUploadsHandler tests for both XL multiple disks and single node setup.
func TestListMultipartUploadsHandler ( t * testing . T ) {
2016-10-09 18:21:37 +02:00
ExecObjectLayerAPITest ( t , testListMultipartUploadsHandler , [ ] string { "ListMultipartUploads" } )
2016-09-14 04:00:01 +02:00
}
// testListMultipartUploadsHandler - Tests validate listing of multipart uploads.
2016-10-09 18:21:37 +02:00
func testListMultipartUploadsHandler ( obj ObjectLayer , instanceType , bucketName string , apiRouter http . Handler ,
credentials credential , t * testing . T ) {
2016-09-26 23:28:35 +02:00
initBucketPolicies ( obj )
2016-09-14 04:00:01 +02:00
// Collection of non-exhaustive ListMultipartUploads test cases, valid errors
// and success responses.
testCases := [ ] struct {
// Inputs to ListMultipartUploads.
bucket string
prefix string
keyMarker string
uploadIDMarker string
delimiter string
maxUploads string
2016-10-13 18:25:56 +02:00
accessKey string
secretKey string
2016-09-14 04:00:01 +02:00
expectedRespStatus int
shouldPass bool
} {
2016-10-13 18:25:56 +02:00
// Test case - 1.
// Setting invalid bucket name.
{
bucket : ".test" ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "0" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusBadRequest ,
shouldPass : false ,
} ,
// Test case - 2.
// Setting a non-existent bucket.
{
bucket : "volatile-bucket-1" ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "0" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusNotFound ,
shouldPass : false ,
} ,
// Test case -3.
// Setting invalid delimiter, expecting the HTTP response status to be http.StatusNotImplemented.
{
bucket : bucketName ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "-" ,
maxUploads : "0" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusNotImplemented ,
shouldPass : false ,
} ,
// Test case - 4.
// Setting Invalid prefix and marker combination.
{
bucket : bucketName ,
prefix : "asia" ,
keyMarker : "europe-object" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "0" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusNotImplemented ,
shouldPass : false ,
} ,
// Test case - 5.
// Invalid upload id and marker combination.
{
bucket : bucketName ,
prefix : "asia" ,
keyMarker : "asia/europe/" ,
uploadIDMarker : "abc" ,
delimiter : "" ,
maxUploads : "0" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusNotImplemented ,
shouldPass : false ,
} ,
// Test case - 6.
// Setting a negative value to max-uploads paramater, should result in http.StatusBadRequest.
{
bucket : bucketName ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "-1" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusBadRequest ,
shouldPass : false ,
} ,
// Test case - 7.
// Case with right set of parameters,
// should result in success 200OK.
{
bucket : bucketName ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "/" ,
maxUploads : "100" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusOK ,
shouldPass : true ,
} ,
// Test case - 8.
// Good case without delimiter.
{
bucket : bucketName ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "100" ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusOK ,
shouldPass : true ,
} ,
// Test case - 9.
// Setting Invalid AccessKey and SecretKey to induce and verify Signature Mismatch error.
{
bucket : bucketName ,
prefix : "" ,
keyMarker : "" ,
uploadIDMarker : "" ,
delimiter : "" ,
maxUploads : "100" ,
accessKey : "abcd" ,
secretKey : "abcd" ,
expectedRespStatus : http . StatusForbidden ,
shouldPass : true ,
} ,
2016-09-14 04:00:01 +02:00
}
for i , testCase := range testCases {
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
rec := httptest . NewRecorder ( )
// construct HTTP request for List multipart uploads endpoint.
u := getListMultipartUploadsURLWithParams ( "" , testCase . bucket , testCase . prefix , testCase . keyMarker , testCase . uploadIDMarker , testCase . delimiter , testCase . maxUploads )
2016-10-13 18:25:56 +02:00
req , gerr := newTestSignedRequestV4 ( "GET" , u , 0 , nil , testCase . accessKey , testCase . secretKey )
2016-09-14 04:00:01 +02:00
if gerr != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for ListMultipartUploadsHandler: <ERROR> %v" , i + 1 , instanceType , gerr )
}
2016-10-13 18:25:56 +02:00
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
2016-09-14 04:00:01 +02:00
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( rec , req )
if rec . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , rec . Code )
}
2016-10-13 18:25:56 +02:00
// Verify response the V2 signed HTTP request.
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
recV2 := httptest . NewRecorder ( )
// construct HTTP request for PUT bucket policy endpoint.
// verify response for V2 signed HTTP request.
reqV2 , err := newTestSignedRequestV2 ( "GET" , u , 0 , nil , testCase . accessKey , testCase . secretKey )
if err != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: <ERROR> %v" , i + 1 , instanceType , err )
}
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( recV2 , reqV2 )
if recV2 . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , recV2 . Code )
}
2016-09-14 04:00:01 +02:00
}
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
rec := httptest . NewRecorder ( )
// construct HTTP request for List multipart uploads endpoint.
u := getListMultipartUploadsURLWithParams ( "" , bucketName , "" , "" , "" , "" , "" )
2016-09-30 23:32:13 +02:00
req , err := newTestSignedRequestV4 ( "GET" , u , 0 , nil , "" , "" ) // Generate an anonymous request.
2016-09-14 04:00:01 +02:00
if err != nil {
t . Fatalf ( "Test %s: Failed to create HTTP request for ListMultipartUploadsHandler: <ERROR> %v" , instanceType , err )
}
2016-10-13 18:25:56 +02:00
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
2016-09-14 04:00:01 +02:00
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( rec , req )
if rec . Code != http . StatusForbidden {
t . Errorf ( "Test %s: Expected the response status to be `http.StatusForbidden`, but instead found `%d`" , instanceType , rec . Code )
}
2016-10-09 18:21:37 +02:00
url := getListMultipartUploadsURLWithParams ( "" , testCases [ 6 ] . bucket , testCases [ 6 ] . prefix , testCases [ 6 ] . keyMarker ,
testCases [ 6 ] . uploadIDMarker , testCases [ 6 ] . delimiter , testCases [ 6 ] . maxUploads )
// Test for Anonymous/unsigned http request.
anonReq , err := newTestRequest ( "GET" , url , 0 , nil )
if err != nil {
t . Fatalf ( "Minio %s: Failed to create an anonymous request for bucket \"%s\": <ERROR> %v" ,
instanceType , bucketName , err )
}
// ExecObjectLayerAPIAnonTest - Calls the HTTP API handler using the anonymous request, validates the ErrAccessDeniedResponse,
// sets the bucket policy using the policy statement generated from `getWriteOnlyBucketStatement` so that the
// unsigned request goes through and its validated again.
ExecObjectLayerAPIAnonTest ( t , "TestListMultipartUploadsHandler" , bucketName , "" , instanceType , apiRouter , anonReq , getWriteOnlyBucketStatement )
2016-10-11 09:00:02 +02:00
// HTTP request for testing when `objectLayer` is set to `nil`.
// There is no need to use an existing bucket and 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.
nilBucket := "dummy-bucket"
url = getListMultipartUploadsURLWithParams ( "" , nilBucket , "dummy-prefix" , testCases [ 6 ] . keyMarker ,
testCases [ 6 ] . uploadIDMarker , testCases [ 6 ] . delimiter , testCases [ 6 ] . maxUploads )
nilReq , err := newTestRequest ( "GET" , url , 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 , "" , instanceType , apiRouter , nilReq )
2016-09-14 04:00:01 +02:00
}
2016-09-15 08:53:42 +02:00
// Wrapper for calling TestListBucketsHandler tests for both XL multiple disks and single node setup.
func TestListBucketsHandler ( t * testing . T ) {
2016-10-09 18:21:37 +02:00
ExecObjectLayerAPITest ( t , testListBucketsHandler , [ ] string { "ListBuckets" } )
2016-09-15 08:53:42 +02:00
}
// testListBucketsHandler - Tests validate listing of buckets.
2016-10-09 18:21:37 +02:00
func testListBucketsHandler ( obj ObjectLayer , instanceType , bucketName string , apiRouter http . Handler ,
credentials credential , t * testing . T ) {
2016-09-15 08:53:42 +02:00
testCases := [ ] struct {
bucketName string
accessKey string
secretKey string
expectedRespStatus int
} {
2016-10-13 18:25:56 +02:00
// Test case - 1.
2016-09-15 08:53:42 +02:00
// Validate a good case request succeeds.
{
bucketName : bucketName ,
accessKey : credentials . AccessKeyID ,
secretKey : credentials . SecretAccessKey ,
expectedRespStatus : http . StatusOK ,
} ,
2016-10-13 18:25:56 +02:00
// Test case - 2.
// Test case with invalid accessKey to produce and validate Signature MisMatch error.
2016-09-15 08:53:42 +02:00
{
bucketName : bucketName ,
2016-10-13 18:25:56 +02:00
accessKey : "abcd" ,
secretKey : "abcd" ,
2016-09-15 08:53:42 +02:00
expectedRespStatus : http . StatusForbidden ,
} ,
}
for i , testCase := range testCases {
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
rec := httptest . NewRecorder ( )
2016-09-30 23:32:13 +02:00
req , lerr := newTestSignedRequestV4 ( "GET" , getListBucketURL ( "" ) , 0 , nil , testCase . accessKey , testCase . secretKey )
2016-09-15 08:53:42 +02:00
if lerr != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for ListBucketsHandler: <ERROR> %v" , i + 1 , instanceType , lerr )
}
2016-10-13 18:25:56 +02:00
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
2016-09-15 08:53:42 +02:00
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( rec , req )
if rec . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , rec . Code )
}
2016-10-13 18:25:56 +02:00
// Verify response of the V2 signed HTTP request.
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
recV2 := httptest . NewRecorder ( )
// construct HTTP request for PUT bucket policy endpoint.
// verify response for V2 signed HTTP request.
reqV2 , err := newTestSignedRequestV2 ( "GET" , getListBucketURL ( "" ) , 0 , nil , testCase . accessKey , testCase . secretKey )
if err != nil {
t . Fatalf ( "Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: <ERROR> %v" , i + 1 , instanceType , err )
}
// Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler.
// Call the ServeHTTP to execute the handler.
apiRouter . ServeHTTP ( recV2 , reqV2 )
if recV2 . Code != testCase . expectedRespStatus {
t . Errorf ( "Test %d: %s: Expected the response status to be `%d`, but instead found `%d`" , i + 1 , instanceType , testCase . expectedRespStatus , recV2 . Code )
}
2016-09-15 08:53:42 +02:00
}
2016-10-09 18:21:37 +02:00
// Test for Anonymous/unsigned http request.
// ListBucketsHandler doesn't support bucket policies, setting the policies shouldn't make a difference.
anonReq , err := newTestRequest ( "GET" , getListBucketURL ( "" ) , 0 , nil )
if err != nil {
t . Fatalf ( "Minio %s: Failed to create an anonymous request." , instanceType )
}
// ExecObjectLayerAPIAnonTest - Calls the HTTP API handler using the anonymous request, validates the ErrAccessDeniedResponse,
// sets the bucket policy using the policy statement generated from `getWriteOnlyObjectStatement` so that the
// unsigned request goes through and its validated again.
ExecObjectLayerAPIAnonTest ( t , "ListBucketsHandler" , "" , "" , instanceType , apiRouter , anonReq , getWriteOnlyObjectStatement )
2016-10-11 09:00:02 +02:00
// HTTP request for testing when `objectLayer` is set to `nil`.
// There is no need to use an existing bucket and 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.
nilReq , err := newTestRequest ( "GET" , getListBucketURL ( "" ) , 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 , "" , "" , instanceType , apiRouter , nilReq )
2016-09-15 08:53:42 +02:00
}