@ -27,10 +27,8 @@ import (
"net/http/httptest"
"net/url"
"os"
"reflect"
"strings"
"testing"
"time"
router "github.com/gorilla/mux"
"github.com/minio/minio/pkg/auth"
@ -1051,140 +1049,6 @@ func buildAdminRequest(queryVal url.Values, opHdr, method string,
return req , nil
}
// mkHealUploadQuery - helper to build HealUploadHandler query string.
func mkHealUploadQuery ( bucket , object , uploadID , dryRun string ) url . Values {
queryVal := url . Values { }
queryVal . Set ( string ( mgmtBucket ) , bucket )
queryVal . Set ( string ( mgmtObject ) , object )
queryVal . Set ( string ( mgmtUploadID ) , uploadID )
queryVal . Set ( "heal" , "" )
queryVal . Set ( string ( mgmtDryRun ) , dryRun )
return queryVal
}
// TestHealUploadHandler - test for HealUploadHandler.
func TestHealUploadHandler ( t * testing . T ) {
adminTestBed , err := prepareAdminXLTestBed ( )
if err != nil {
t . Fatal ( "Failed to initialize a single node XL backend for admin handler tests." )
}
defer adminTestBed . TearDown ( )
// Create an object myobject under bucket mybucket.
bucketName := "mybucket"
objName := "myobject"
err = adminTestBed . objLayer . MakeBucketWithLocation ( bucketName , "" )
if err != nil {
t . Fatalf ( "Failed to make bucket %s - %v" , bucketName , err )
}
// Create a new multipart upload.
uploadID , err := adminTestBed . objLayer . NewMultipartUpload ( bucketName , objName , nil )
if err != nil {
t . Fatalf ( "Failed to create a new multipart upload %s/%s - %v" ,
bucketName , objName , err )
}
// Upload a part.
partID := 1
_ , err = adminTestBed . objLayer . PutObjectPart ( bucketName , objName , uploadID ,
partID , mustGetHashReader ( t , bytes . NewReader ( [ ] byte ( "hello" ) ) , int64 ( len ( "hello" ) ) , "" , "" ) )
if err != nil {
t . Fatalf ( "Failed to upload part %d of %s/%s - %v" , partID ,
bucketName , objName , err )
}
testCases := [ ] struct {
bucket string
object string
dryrun string
statusCode int
} {
// 1. Valid test case.
{
bucket : bucketName ,
object : objName ,
statusCode : http . StatusOK ,
} ,
// 2. Invalid bucket name.
{
bucket : ` invalid\\Bucket ` ,
object : "myobject" ,
statusCode : http . StatusBadRequest ,
} ,
// 3. Bucket not found.
{
bucket : "bucketnotfound" ,
object : "myobject" ,
statusCode : http . StatusNotFound ,
} ,
// 4. Invalid object name.
{
bucket : bucketName ,
object : ` invalid\\Object ` ,
statusCode : http . StatusBadRequest ,
} ,
// 5. Object not found.
{
bucket : bucketName ,
object : "objectnotfound" ,
statusCode : http . StatusNotFound ,
} ,
// 6. Valid test case with dry-run.
{
bucket : bucketName ,
object : objName ,
dryrun : "yes" ,
statusCode : http . StatusOK ,
} ,
}
for i , test := range testCases {
// Prepare query params.
queryVal := mkHealUploadQuery ( test . bucket , test . object , uploadID , test . dryrun )
req , err1 := buildAdminRequest ( queryVal , "upload" , http . MethodPost , 0 , nil )
if err1 != nil {
t . Fatalf ( "Test %d - Failed to construct heal object request - %v" , i + 1 , err1 )
}
rec := httptest . NewRecorder ( )
adminTestBed . mux . ServeHTTP ( rec , req )
if test . statusCode != rec . Code {
t . Errorf ( "Test %d - Expected HTTP status code %d but received %d" , i + 1 , test . statusCode , rec . Code )
}
}
sample := testCases [ 0 ]
// Modify authorization header after signing to test signature
// mismatch handling.
queryVal := mkHealUploadQuery ( sample . bucket , sample . object , uploadID , sample . dryrun )
req , err := buildAdminRequest ( queryVal , "upload" , "POST" , 0 , nil )
if err != nil {
t . Fatalf ( "Failed to construct heal object request - %v" , err )
}
// Set x-amz-date to a date different than time of signing.
req . Header . Set ( "x-amz-date" , time . Time { } . Format ( iso8601Format ) )
rec := httptest . NewRecorder ( )
adminTestBed . mux . ServeHTTP ( rec , req )
if rec . Code != http . StatusForbidden {
t . Errorf ( "Expected %d but received %d" , http . StatusBadRequest , rec . Code )
}
// Set objectAPI to nil to test Server not initialized case.
resetGlobalObjectAPI ( )
queryVal = mkHealUploadQuery ( sample . bucket , sample . object , uploadID , sample . dryrun )
req , err = buildAdminRequest ( queryVal , "upload" , "POST" , 0 , nil )
if err != nil {
t . Fatalf ( "Failed to construct heal object request - %v" , err )
}
rec = httptest . NewRecorder ( )
adminTestBed . mux . ServeHTTP ( rec , req )
if rec . Code != http . StatusServiceUnavailable {
t . Errorf ( "Expected %d but received %d" , http . StatusServiceUnavailable , rec . Code )
}
}
// TestHealFormatHandler - test for HealFormatHandler.
func TestHealFormatHandler ( t * testing . T ) {
adminTestBed , err := prepareAdminXLTestBed ( )
@ -1477,172 +1341,6 @@ func TestWriteSetConfigResponse(t *testing.T) {
}
}
// mkListUploadsHealQuery - helper function to construct query values for
// listUploadsHeal.
func mkListUploadsHealQuery ( bucket , prefix , keyMarker , uploadIDMarker , delimiter , maxUploadsStr string ) url . Values {
queryVal := make ( url . Values )
queryVal . Set ( "heal" , "" )
queryVal . Set ( string ( mgmtBucket ) , bucket )
queryVal . Set ( string ( mgmtPrefix ) , prefix )
queryVal . Set ( string ( mgmtKeyMarker ) , keyMarker )
queryVal . Set ( string ( mgmtUploadIDMarker ) , uploadIDMarker )
queryVal . Set ( string ( mgmtDelimiter ) , delimiter )
queryVal . Set ( string ( mgmtMaxUploads ) , maxUploadsStr )
return queryVal
}
func TestListHealUploadsHandler ( t * testing . T ) {
adminTestBed , err := prepareAdminXLTestBed ( )
if err != nil {
t . Fatal ( "Failed to initialize a single node XL backend for admin handler tests." )
}
defer adminTestBed . TearDown ( )
err = adminTestBed . objLayer . MakeBucketWithLocation ( "mybucket" , "" )
if err != nil {
t . Fatalf ( "Failed to make bucket - %v" , err )
}
// Delete bucket after running all test cases.
defer adminTestBed . objLayer . DeleteBucket ( "mybucket" )
testCases := [ ] struct {
bucket string
prefix string
keyMarker string
delimiter string
maxKeys string
statusCode int
expectedResp ListMultipartUploadsResponse
} {
// 1. Valid params.
{
bucket : "mybucket" ,
prefix : "prefix" ,
keyMarker : "prefix11" ,
delimiter : "/" ,
maxKeys : "10" ,
statusCode : http . StatusOK ,
expectedResp : ListMultipartUploadsResponse {
XMLName : xml . Name { Space : "http://s3.amazonaws.com/doc/2006-03-01/" , Local : "ListMultipartUploadsResult" } ,
Bucket : "mybucket" ,
KeyMarker : "prefix11" ,
Delimiter : "/" ,
Prefix : "prefix" ,
MaxUploads : 10 ,
} ,
} ,
// 2. Valid params with empty prefix.
{
bucket : "mybucket" ,
prefix : "" ,
keyMarker : "" ,
delimiter : "/" ,
maxKeys : "10" ,
statusCode : http . StatusOK ,
expectedResp : ListMultipartUploadsResponse {
XMLName : xml . Name { Space : "http://s3.amazonaws.com/doc/2006-03-01/" , Local : "ListMultipartUploadsResult" } ,
Bucket : "mybucket" ,
KeyMarker : "" ,
Delimiter : "/" ,
Prefix : "" ,
MaxUploads : 10 ,
} ,
} ,
// 3. Invalid params with invalid bucket.
{
bucket : ` invalid\\Bucket ` ,
prefix : "prefix" ,
keyMarker : "prefix11" ,
delimiter : "/" ,
maxKeys : "10" ,
statusCode : getAPIError ( ErrInvalidBucketName ) . HTTPStatusCode ,
} ,
// 4. Invalid params with invalid prefix.
{
bucket : "mybucket" ,
prefix : ` invalid\\Prefix ` ,
keyMarker : "prefix11" ,
delimiter : "/" ,
maxKeys : "10" ,
statusCode : getAPIError ( ErrInvalidObjectName ) . HTTPStatusCode ,
} ,
// 5. Invalid params with invalid maxKeys.
{
bucket : "mybucket" ,
prefix : "prefix" ,
keyMarker : "prefix11" ,
delimiter : "/" ,
maxKeys : "-1" ,
statusCode : getAPIError ( ErrInvalidMaxUploads ) . HTTPStatusCode ,
} ,
// 6. Invalid params with unsupported prefix marker combination.
{
bucket : "mybucket" ,
prefix : "prefix" ,
keyMarker : "notmatchingmarker" ,
delimiter : "/" ,
maxKeys : "10" ,
statusCode : getAPIError ( ErrNotImplemented ) . HTTPStatusCode ,
} ,
// 7. Invalid params with unsupported delimiter.
{
bucket : "mybucket" ,
prefix : "prefix" ,
keyMarker : "notmatchingmarker" ,
delimiter : "unsupported" ,
maxKeys : "10" ,
statusCode : getAPIError ( ErrNotImplemented ) . HTTPStatusCode ,
} ,
// 8. Invalid params with invalid max Keys
{
bucket : "mybucket" ,
prefix : "prefix" ,
keyMarker : "prefix11" ,
delimiter : "/" ,
maxKeys : "999999999999999999999999999" ,
statusCode : getAPIError ( ErrInvalidMaxUploads ) . HTTPStatusCode ,
} ,
}
for i , test := range testCases {
queryVal := mkListUploadsHealQuery ( test . bucket , test . prefix , test . keyMarker , "" , test . delimiter , test . maxKeys )
req , err := buildAdminRequest ( queryVal , "list-uploads" , http . MethodGet , 0 , nil )
if err != nil {
t . Fatalf ( "Test %d - Failed to construct list uploads needing heal request - %v" , i + 1 , err )
}
rec := httptest . NewRecorder ( )
adminTestBed . mux . ServeHTTP ( rec , req )
if test . statusCode != rec . Code {
t . Errorf ( "Test %d - Expected HTTP status code %d but received %d" , i + 1 , test . statusCode , rec . Code )
}
// Compare result with the expected one only when we receive 200 OK
if rec . Code == http . StatusOK {
resp := rec . Result ( )
xmlBytes , err := ioutil . ReadAll ( resp . Body )
if err != nil {
t . Errorf ( "Test %d: Failed to read response %v" , i + 1 , err )
}
var actualResult ListMultipartUploadsResponse
err = xml . Unmarshal ( xmlBytes , & actualResult )
if err != nil {
t . Errorf ( "Test %d: Failed to unmarshal xml %v" , i + 1 , err )
}
if ! reflect . DeepEqual ( test . expectedResp , actualResult ) {
t . Fatalf ( "Test %d: Unexpected response `%+v`, expected: `%+v`" , i + 1 , test . expectedResp , actualResult )
}
}
}
}
// Test for newHealResult helper function.
func TestNewHealResult ( t * testing . T ) {
testCases := [ ] struct {