2016-09-16 16:06:49 -04:00
/ *
2019-04-09 14:39:42 -04:00
* MinIO Cloud Storage , ( C ) 2016 , 2017 MinIO , Inc .
2016-09-16 16:06:49 -04:00
*
* 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"
2018-03-15 16:27:16 -04:00
"context"
2017-08-12 22:25:43 -04:00
"os"
2016-09-16 16:06:49 -04:00
"path/filepath"
2020-03-18 19:19:29 -04:00
"sync"
2016-09-16 16:06:49 -04:00
"testing"
2017-08-10 17:11:57 -04:00
"time"
2016-09-16 16:06:49 -04:00
)
2017-11-30 21:11:42 -05:00
// Tests cleanup multipart uploads for filesystem backend.
2017-08-10 17:11:57 -04:00
func TestFSCleanupMultipartUploadsInRoutine ( t * testing . T ) {
// Prepare for tests
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
2017-08-12 22:25:43 -04:00
defer os . RemoveAll ( disk )
2017-08-10 17:11:57 -04:00
obj := initFSObjects ( disk , t )
2018-02-20 15:21:12 -05:00
fs := obj . ( * FSObjects )
2017-08-10 17:11:57 -04:00
bucketName := "bucket"
objectName := "object"
2020-03-18 19:19:29 -04:00
// Create a context we can cancel.
2020-04-09 12:30:02 -04:00
ctx , cancel := context . WithCancel ( GlobalContext )
2020-05-08 16:44:44 -04:00
obj . MakeBucketWithLocation ( ctx , bucketName , "" , false )
2020-03-18 19:19:29 -04:00
uploadID , err := obj . NewMultipartUpload ( ctx , bucketName , objectName , ObjectOptions { } )
2017-08-10 17:11:57 -04:00
if err != nil {
t . Fatal ( "Unexpected err: " , err )
}
2020-03-18 19:19:29 -04:00
var cleanupWg sync . WaitGroup
cleanupWg . Add ( 1 )
go func ( ) {
defer cleanupWg . Done ( )
2020-04-16 13:56:18 -04:00
fs . cleanupStaleMultipartUploads ( ctx , time . Millisecond , 0 )
2020-03-18 19:19:29 -04:00
} ( )
2017-08-10 17:11:57 -04:00
2020-03-18 19:19:29 -04:00
// Wait for 100ms such that - we have given enough time for
// cleanup routine to kick in. Flaky on slow systems...
time . Sleep ( 100 * time . Millisecond )
cancel ( )
cleanupWg . Wait ( )
2017-08-10 17:11:57 -04:00
// Check if upload id was already purged.
2020-04-09 12:30:02 -04:00
if err = obj . AbortMultipartUpload ( GlobalContext , bucketName , objectName , uploadID ) ; err != nil {
2017-08-10 17:11:57 -04:00
if _ , ok := err . ( InvalidUploadID ) ; ! ok {
t . Fatal ( "Unexpected err: " , err )
}
2020-03-18 19:19:29 -04:00
} else {
t . Error ( "Item was not cleaned up." )
2017-08-10 17:11:57 -04:00
}
}
2016-09-16 16:06:49 -04:00
// TestNewMultipartUploadFaultyDisk - test NewMultipartUpload with faulty disks
func TestNewMultipartUploadFaultyDisk ( t * testing . T ) {
// Prepare for tests
2016-12-16 01:25:05 -05:00
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
2017-08-12 22:25:43 -04:00
defer os . RemoveAll ( disk )
2016-10-05 15:48:07 -04:00
obj := initFSObjects ( disk , t )
2016-09-16 16:06:49 -04:00
2018-02-20 15:21:12 -05:00
fs := obj . ( * FSObjects )
2016-09-16 16:06:49 -04:00
bucketName := "bucket"
objectName := "object"
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2016-09-16 16:06:49 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2017-01-16 20:05:00 -05:00
// Test with disk removed.
2018-05-23 06:11:29 -04:00
os . RemoveAll ( disk )
2020-04-09 12:30:02 -04:00
if _ , err := fs . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } ) ; err != nil {
2018-04-10 12:36:37 -04:00
if ! isSameType ( err , BucketNotFound { } ) {
2017-01-16 20:05:00 -05:00
t . Fatal ( "Unexpected error " , err )
2016-09-16 16:06:49 -04:00
}
}
}
// TestPutObjectPartFaultyDisk - test PutObjectPart with faulty disks
func TestPutObjectPartFaultyDisk ( t * testing . T ) {
// Prepare for tests
2016-12-16 01:25:05 -05:00
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
2017-08-12 22:25:43 -04:00
defer os . RemoveAll ( disk )
2016-10-05 15:48:07 -04:00
obj := initFSObjects ( disk , t )
2018-08-15 00:41:47 -04:00
2016-09-16 16:06:49 -04:00
bucketName := "bucket"
objectName := "object"
data := [ ] byte ( "12345" )
dataLen := int64 ( len ( data ) )
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2016-09-16 16:06:49 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2020-04-09 12:30:02 -04:00
uploadID , err := obj . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } )
2016-09-16 16:06:49 -04:00
if err != nil {
t . Fatal ( "Unexpected error " , err )
}
2016-11-21 16:51:05 -05:00
md5Hex := getMD5Hash ( data )
2016-10-02 18:51:49 -04:00
sha256sum := ""
2016-09-16 16:06:49 -04:00
2019-09-22 13:45:33 -04:00
newDisk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
defer os . RemoveAll ( newDisk )
obj = initFSObjects ( newDisk , t )
2020-04-09 12:30:02 -04:00
if _ , err = obj . PutObjectPart ( GlobalContext , bucketName , objectName , uploadID , 1 , mustGetPutObjReader ( t , bytes . NewReader ( data ) , dataLen , md5Hex , sha256sum ) , ObjectOptions { } ) ; err != nil {
2019-09-22 13:45:33 -04:00
if ! isSameType ( err , BucketNotFound { } ) {
t . Fatal ( "Unexpected error " , err )
}
2016-09-16 16:06:49 -04:00
}
}
// TestCompleteMultipartUploadFaultyDisk - test CompleteMultipartUpload with faulty disks
func TestCompleteMultipartUploadFaultyDisk ( t * testing . T ) {
// Prepare for tests
2016-12-16 01:25:05 -05:00
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
2017-08-12 22:25:43 -04:00
defer os . RemoveAll ( disk )
2016-10-05 15:48:07 -04:00
obj := initFSObjects ( disk , t )
2016-09-16 16:06:49 -04:00
bucketName := "bucket"
objectName := "object"
data := [ ] byte ( "12345" )
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2016-09-16 16:06:49 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2020-04-09 12:30:02 -04:00
uploadID , err := obj . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } )
2016-09-16 16:06:49 -04:00
if err != nil {
t . Fatal ( "Unexpected error " , err )
}
2016-11-21 16:51:05 -05:00
md5Hex := getMD5Hash ( data )
2016-09-16 16:06:49 -04:00
2017-11-14 03:25:10 -05:00
parts := [ ] CompletePart { { PartNumber : 1 , ETag : md5Hex } }
2019-09-22 13:45:33 -04:00
newDisk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
defer os . RemoveAll ( newDisk )
obj = initFSObjects ( newDisk , t )
2020-04-09 12:30:02 -04:00
if _ , err := obj . CompleteMultipartUpload ( GlobalContext , bucketName , objectName , uploadID , parts , ObjectOptions { } ) ; err != nil {
2018-04-10 12:36:37 -04:00
if ! isSameType ( err , BucketNotFound { } ) {
2017-01-16 20:05:00 -05:00
t . Fatal ( "Unexpected error " , err )
2016-09-16 16:06:49 -04:00
}
}
}
2018-01-31 16:17:24 -05:00
// TestCompleteMultipartUpload - test CompleteMultipartUpload
2017-10-18 17:26:20 -04:00
func TestCompleteMultipartUpload ( t * testing . T ) {
// Prepare for tests
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
defer os . RemoveAll ( disk )
obj := initFSObjects ( disk , t )
bucketName := "bucket"
objectName := "object"
data := [ ] byte ( "12345" )
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2020-04-09 12:30:02 -04:00
uploadID , err := obj . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } )
2017-10-18 17:26:20 -04:00
if err != nil {
t . Fatal ( "Unexpected error " , err )
}
md5Hex := getMD5Hash ( data )
2020-04-09 12:30:02 -04:00
if _ , err := obj . PutObjectPart ( GlobalContext , bucketName , objectName , uploadID , 1 , mustGetPutObjReader ( t , bytes . NewReader ( data ) , 5 , md5Hex , "" ) , ObjectOptions { } ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Unexpected error " , err )
}
2017-11-14 03:25:10 -05:00
parts := [ ] CompletePart { { PartNumber : 1 , ETag : md5Hex } }
2020-04-09 12:30:02 -04:00
if _ , err := obj . CompleteMultipartUpload ( GlobalContext , bucketName , objectName , uploadID , parts , ObjectOptions { } ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Unexpected error " , err )
}
}
2018-01-31 16:17:24 -05:00
// TestCompleteMultipartUpload - test CompleteMultipartUpload
2017-10-18 17:26:20 -04:00
func TestAbortMultipartUpload ( t * testing . T ) {
// Prepare for tests
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
defer os . RemoveAll ( disk )
obj := initFSObjects ( disk , t )
bucketName := "bucket"
objectName := "object"
data := [ ] byte ( "12345" )
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2020-04-09 12:30:02 -04:00
uploadID , err := obj . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } )
2017-10-18 17:26:20 -04:00
if err != nil {
t . Fatal ( "Unexpected error " , err )
}
md5Hex := getMD5Hash ( data )
2020-04-09 12:30:02 -04:00
if _ , err := obj . PutObjectPart ( GlobalContext , bucketName , objectName , uploadID , 1 , mustGetPutObjReader ( t , bytes . NewReader ( data ) , 5 , md5Hex , "" ) , ObjectOptions { } ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Unexpected error " , err )
}
2018-01-31 16:17:24 -05:00
time . Sleep ( time . Second ) // Without Sleep on windows, the fs.AbortMultipartUpload() fails with "The process cannot access the file because it is being used by another process."
2020-04-09 12:30:02 -04:00
if err := obj . AbortMultipartUpload ( GlobalContext , bucketName , objectName , uploadID ) ; err != nil {
2017-10-18 17:26:20 -04:00
t . Fatal ( "Unexpected error " , err )
}
}
2016-09-16 16:06:49 -04:00
// TestListMultipartUploadsFaultyDisk - test ListMultipartUploads with faulty disks
func TestListMultipartUploadsFaultyDisk ( t * testing . T ) {
// Prepare for tests
2016-12-16 01:25:05 -05:00
disk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
2017-08-12 22:25:43 -04:00
defer os . RemoveAll ( disk )
2017-01-16 20:05:00 -05:00
2016-10-05 15:48:07 -04:00
obj := initFSObjects ( disk , t )
2017-01-16 20:05:00 -05:00
2016-09-16 16:06:49 -04:00
bucketName := "bucket"
objectName := "object"
2020-05-08 16:44:44 -04:00
if err := obj . MakeBucketWithLocation ( GlobalContext , bucketName , "" , false ) ; err != nil {
2016-09-16 16:06:49 -04:00
t . Fatal ( "Cannot create bucket, err: " , err )
}
2020-04-09 12:30:02 -04:00
_ , err := obj . NewMultipartUpload ( GlobalContext , bucketName , objectName , ObjectOptions { UserDefined : map [ string ] string { "X-Amz-Meta-xid" : "3f" } } )
2016-09-16 16:06:49 -04:00
if err != nil {
t . Fatal ( "Unexpected error " , err )
}
2019-09-22 13:45:33 -04:00
newDisk := filepath . Join ( globalTestTmpDir , "minio-" + nextSuffix ( ) )
defer os . RemoveAll ( newDisk )
obj = initFSObjects ( newDisk , t )
2020-04-09 12:30:02 -04:00
if _ , err := obj . ListMultipartUploads ( GlobalContext , bucketName , objectName , "" , "" , "" , 1000 ) ; err != nil {
2018-04-10 12:36:37 -04:00
if ! isSameType ( err , BucketNotFound { } ) {
2017-01-16 20:05:00 -05:00
t . Fatal ( "Unexpected error " , err )
2016-09-16 16:06:49 -04:00
}
}
}