mirror of
https://github.com/minio/minio.git
synced 2024-12-23 21:55:53 -05:00
tests: Implemented more tests for fs-v1*.go (#2686)
This commit is contained in:
parent
7d37dea449
commit
b89a1cd482
@ -17,7 +17,9 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -64,3 +66,93 @@ func TestHasExtendedHeader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestReadFsMetadata - readFSMetadata testing with a healthy and faulty disk
|
||||
func TestReadFSMetadata(t *testing.T) {
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
if _, err = obj.PutObject(bucketName, objectName, int64(len("abcd")), bytes.NewReader([]byte("abcd")),
|
||||
map[string]string{"X-Amz-Meta-AppId": "a"}); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
|
||||
// Construct the full path of fs.json
|
||||
fsPath := "buckets/" + bucketName + "/" + objectName + "/fs.json"
|
||||
|
||||
// Regular fs metadata reading, no errors expected
|
||||
if _, err = readFSMetadata(fs.storage, ".minio.sys", fsPath); err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
// Corrupted fs.json
|
||||
if err = fs.storage.AppendFile(".minio.sys", fsPath, []byte{'a'}); err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
if _, err = readFSMetadata(fs.storage, ".minio.sys", fsPath); err == nil {
|
||||
t.Fatal("Should fail", err)
|
||||
}
|
||||
|
||||
// Test with corrupted disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
naughty := newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
fs.storage = naughty
|
||||
if _, err = readFSMetadata(fs.storage, ".minio.sys", fsPath); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Should fail", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestWriteFsMetadata - tests of writeFSMetadata with healthy and faulty disks
|
||||
func TestWriteFSMetadata(t *testing.T) {
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
if _, err = obj.PutObject(bucketName, objectName, int64(len("abcd")), bytes.NewReader([]byte("abcd")),
|
||||
map[string]string{"X-Amz-Meta-AppId": "a"}); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
|
||||
// Construct the complete path of fs.json
|
||||
fsPath := "buckets/" + bucketName + "/" + objectName + "/fs.json"
|
||||
|
||||
// Fs metadata reading, no errors expected (healthy disk)
|
||||
fsMeta, err := readFSMetadata(fs.storage, ".minio.sys", fsPath)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
// Reading metadata with a corrupted disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 2; i++ {
|
||||
naughty := newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk, i + 1: errFaultyDisk}, nil)
|
||||
fs.storage = naughty
|
||||
if err = writeFSMetadata(fs.storage, ".minio.sys", fsPath, fsMeta); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected error", i, err)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
165
cmd/fs-v1-multipart-common_test.go
Normal file
165
cmd/fs-v1-multipart-common_test.go
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestFSIsBucketExist - complete test of isBucketExist
|
||||
func TestFSIsBucketExist(t *testing.T) {
|
||||
// Prepare for testing
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
|
||||
if err := obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Cannot create bucket, err: ", err)
|
||||
}
|
||||
|
||||
// Test with a valid bucket
|
||||
if found := fs.isBucketExist(bucketName); !found {
|
||||
t.Fatal("isBucketExist should true")
|
||||
}
|
||||
|
||||
// Test with a inexistant bucket
|
||||
if found := fs.isBucketExist("foo"); found {
|
||||
t.Fatal("isBucketExist should false")
|
||||
}
|
||||
|
||||
// Using a faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
naughty := newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
fs.storage = naughty
|
||||
if found := fs.isBucketExist(bucketName); found {
|
||||
t.Fatal("isBucketExist should return false because it is wired to a corrupted disk")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSIsUploadExists - complete test with valid and invalid cases
|
||||
func TestFSIsUploadExists(t *testing.T) {
|
||||
// Prepare for testing
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
uploadID, err := obj.NewMultipartUpload(bucketName, objectName, nil)
|
||||
|
||||
// Test with valid upload id
|
||||
if exists := fs.isUploadIDExists(bucketName, objectName, uploadID); !exists {
|
||||
t.Fatal("Wrong result, expected: ", exists)
|
||||
}
|
||||
|
||||
// Test with inexistant bucket/object names
|
||||
if exists := fs.isUploadIDExists("bucketfoo", "objectfoo", uploadID); exists {
|
||||
t.Fatal("Wrong result, expected: ", !exists)
|
||||
}
|
||||
|
||||
// Test with inexistant upload ID
|
||||
if exists := fs.isUploadIDExists(bucketName, objectName, uploadID+"-ff"); exists {
|
||||
t.Fatal("Wrong result, expected: ", !exists)
|
||||
}
|
||||
|
||||
// isUploadIdExists with a faulty disk should return false
|
||||
fsStorage := fs.storage.(*posix)
|
||||
naughty := newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
fs.storage = naughty
|
||||
if exists := fs.isUploadIDExists(bucketName, objectName, uploadID); exists {
|
||||
t.Fatal("Wrong result, expected: ", !exists)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSWriteUploadJSON - tests for writeUploadJSON for FS
|
||||
func TestFSWriteUploadJSON(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
uploadID, err := obj.NewMultipartUpload(bucketName, objectName, nil)
|
||||
|
||||
if err := fs.writeUploadJSON(bucketName, objectName, uploadID, time.Now()); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
|
||||
// isUploadIdExists with a faulty disk should return false
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 3; i++ {
|
||||
naughty := newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
fs.storage = naughty
|
||||
if err := fs.writeUploadJSON(bucketName, objectName, uploadID, time.Now()); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSUpdateUploadsJSON - tests for updateUploadsJSON for FS
|
||||
func TestFSUpdateUploadsJSON(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
|
||||
if err := fs.updateUploadsJSON(bucketName, objectName, uploadsV1{}); err != nil {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
|
||||
// isUploadIdExists with a faulty disk should return false
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 2; i++ {
|
||||
naughty := newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
fs.storage = naughty
|
||||
if err := fs.updateUploadsJSON(bucketName, objectName, uploadsV1{}); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected err: ", err)
|
||||
}
|
||||
}
|
||||
}
|
226
cmd/fs-v1-multipart_test.go
Normal file
226
cmd/fs-v1-multipart_test.go
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNewMultipartUploadFaultyDisk - test NewMultipartUpload with faulty disks
|
||||
func TestNewMultipartUploadFaultyDisk(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
if err := obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Cannot create bucket, err: ", err)
|
||||
}
|
||||
|
||||
// Test with faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 5; i++ {
|
||||
// Faulty disk generates errFaultyDisk at 'i' storage api call number
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if _, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"}); errorCause(err) != errFaultyDisk {
|
||||
switch i {
|
||||
case 1:
|
||||
if !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
default:
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestPutObjectPartFaultyDisk - test PutObjectPart with faulty disks
|
||||
func TestPutObjectPartFaultyDisk(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
data := []byte("12345")
|
||||
dataLen := int64(len(data))
|
||||
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Cannot create bucket, err: ", err)
|
||||
}
|
||||
|
||||
uploadID, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"})
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
md5Writer := md5.New()
|
||||
md5Writer.Write(data)
|
||||
md5Hex := hex.EncodeToString(md5Writer.Sum(nil))
|
||||
|
||||
// Test with faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 7; i++ {
|
||||
// Faulty disk generates errFaultyDisk at 'i' storage api call number
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if _, err := fs.PutObjectPart(bucketName, objectName, uploadID, 1, dataLen, bytes.NewReader(data), md5Hex); errorCause(err) != errFaultyDisk {
|
||||
switch i {
|
||||
case 1:
|
||||
if !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
case 2, 4:
|
||||
if !isSameType(errorCause(err), InvalidUploadID{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
default:
|
||||
t.Fatal("Unexpected error ", i, err, reflect.TypeOf(errorCause(err)), reflect.TypeOf(errFaultyDisk))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCompleteMultipartUploadFaultyDisk - test CompleteMultipartUpload with faulty disks
|
||||
func TestCompleteMultipartUploadFaultyDisk(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
data := []byte("12345")
|
||||
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Cannot create bucket, err: ", err)
|
||||
}
|
||||
|
||||
uploadID, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"})
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
md5Writer := md5.New()
|
||||
md5Writer.Write(data)
|
||||
md5Hex := hex.EncodeToString(md5Writer.Sum(nil))
|
||||
|
||||
if _, err := fs.PutObjectPart(bucketName, objectName, uploadID, 1, 5, bytes.NewReader(data), md5Hex); err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
parts := []completePart{{PartNumber: 1, ETag: md5Hex}}
|
||||
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 3; i++ {
|
||||
// Faulty disk generates errFaultyDisk at 'i' storage api call number
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if _, err := fs.CompleteMultipartUpload(bucketName, objectName, uploadID, parts); errorCause(err) != errFaultyDisk {
|
||||
switch i {
|
||||
case 1:
|
||||
if !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
case 2:
|
||||
if !isSameType(errorCause(err), InvalidUploadID{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
default:
|
||||
t.Fatal("Unexpected error ", i, err, reflect.TypeOf(errorCause(err)), reflect.TypeOf(errFaultyDisk))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestListMultipartUploadsFaultyDisk - test ListMultipartUploads with faulty disks
|
||||
func TestListMultipartUploadsFaultyDisk(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
data := []byte("12345")
|
||||
|
||||
if err = obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Cannot create bucket, err: ", err)
|
||||
}
|
||||
|
||||
uploadID, err := fs.NewMultipartUpload(bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"})
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
md5Writer := md5.New()
|
||||
md5Writer.Write(data)
|
||||
md5Hex := hex.EncodeToString(md5Writer.Sum(nil))
|
||||
|
||||
if _, err := fs.PutObjectPart(bucketName, objectName, uploadID, 1, 5, bytes.NewReader(data), md5Hex); err != nil {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 4; i++ {
|
||||
// Faulty disk generates errFaultyDisk at 'i' storage api call number
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if _, err := fs.ListMultipartUploads(bucketName, objectName, "", "", "", 1000); errorCause(err) != errFaultyDisk {
|
||||
switch i {
|
||||
case 1:
|
||||
if !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
case 2:
|
||||
if !isSameType(errorCause(err), InvalidUploadID{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
case 3:
|
||||
if errorCause(err) != errFileNotFound {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
}
|
||||
default:
|
||||
t.Fatal("Unexpected error ", i, err, reflect.TypeOf(errorCause(err)), reflect.TypeOf(errFaultyDisk))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
cmd/fs-v1.go
16
cmd/fs-v1.go
@ -505,20 +505,6 @@ func (fs fsObjects) DeleteObject(bucket, object string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Checks whether bucket exists.
|
||||
func isBucketExist(storage StorageAPI, bucketName string) bool {
|
||||
// Check whether bucket exists.
|
||||
_, err := storage.StatVol(bucketName)
|
||||
if err != nil {
|
||||
if err == errVolumeNotFound {
|
||||
return false
|
||||
}
|
||||
errorIf(err, "Stat failed on bucket "+bucketName+".")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ListObjects - list all objects at prefix upto maxKeys., optionally delimited by '/'. Maintains the list pool
|
||||
// state for future re-entrant list requests.
|
||||
func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, error) {
|
||||
@ -551,7 +537,7 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey
|
||||
return ListObjectsInfo{}, traceError(BucketNameInvalid{Bucket: bucket})
|
||||
}
|
||||
// Verify if bucket exists.
|
||||
if !isBucketExist(fs.storage, bucket) {
|
||||
if !fs.isBucketExist(bucket) {
|
||||
return ListObjectsInfo{}, traceError(BucketNotFound{Bucket: bucket})
|
||||
}
|
||||
if !IsValidObjectPrefix(prefix) {
|
||||
|
@ -68,8 +68,9 @@ func TestNewFS(t *testing.T) {
|
||||
// TestFSShutdown - initialize a new FS object layer then calls Shutdown
|
||||
// to check returned results
|
||||
func TestFSShutdown(t *testing.T) {
|
||||
// Create an FS object and shutdown it. No errors expected
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
@ -85,18 +86,249 @@ func TestFSShutdown(t *testing.T) {
|
||||
obj.MakeBucket(bucketName)
|
||||
obj.PutObject(bucketName, objectName, int64(len(objectContent)), bytes.NewReader([]byte(objectContent)), nil)
|
||||
|
||||
// Test Shutdown with regular conditions
|
||||
if err := fs.Shutdown(); err != nil {
|
||||
t.Fatal("Cannot shutdown the FS object: ", err)
|
||||
}
|
||||
|
||||
// Create an FS and program errors with disks when shutdown is called
|
||||
// Test Shutdown with faulty disks
|
||||
for i := 1; i <= 5; i++ {
|
||||
naughty := newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
fs.storage = naughty
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if err := fs.Shutdown(); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal(i, ", Got unexpected fs shutdown error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
removeAll(disk)
|
||||
}
|
||||
|
||||
// TestFSLoadFormatFS - test loadFormatFS with healty and faulty disks
|
||||
func TestFSLoadFormatFS(t *testing.T) {
|
||||
// Prepare for testing
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, err := newFSObjects(disk)
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
// Regular format loading
|
||||
_, err = loadFormatFS(fs.storage)
|
||||
if err != nil {
|
||||
t.Fatal("Should not fail here", err)
|
||||
}
|
||||
// Loading corrupted format file
|
||||
fs.storage.AppendFile(minioMetaBucket, fsFormatJSONFile, []byte{'b'})
|
||||
_, err = loadFormatFS(fs.storage)
|
||||
if err == nil {
|
||||
t.Fatal("Should return an error here")
|
||||
}
|
||||
// Loading format file from faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
fs.storage = newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
_, err = loadFormatFS(fs.storage)
|
||||
if err != errFaultyDisk {
|
||||
t.Fatal("Should return faulty disk error")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSGetBucketInfo - test GetBucketInfo with healty and faulty disks
|
||||
func TestFSGetBucketInfo(t *testing.T) {
|
||||
// Prepare for testing
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, err := newFSObjects(disk)
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
|
||||
// Test with valid parameters
|
||||
info, err := fs.GetBucketInfo(bucketName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Name != bucketName {
|
||||
t.Fatalf("wrong bucket name, expected: %s, found: %s", bucketName, info.Name)
|
||||
}
|
||||
|
||||
// Test with inexistant bucket
|
||||
_, err = fs.GetBucketInfo("a")
|
||||
if !isSameType(errorCause(err), BucketNameInvalid{}) {
|
||||
t.Fatal("BucketNameInvalid error not returned")
|
||||
}
|
||||
|
||||
// Loading format file from faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
fs.storage = newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
_, err = fs.GetBucketInfo(bucketName)
|
||||
if errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("errFaultyDisk error not returned")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestFSDeleteObject - test fs.DeleteObject() with healthy and corrupted disks
|
||||
func TestFSDeleteObject(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, _ := newFSObjects(disk)
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
objectName := "object"
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
obj.PutObject(bucketName, objectName, int64(len("abcd")), bytes.NewReader([]byte("abcd")), nil)
|
||||
|
||||
// Test with invalid bucket name
|
||||
if err := fs.DeleteObject("fo", objectName); !isSameType(errorCause(err), BucketNameInvalid{}) {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
// Test with invalid object name
|
||||
if err := fs.DeleteObject(bucketName, "^"); !isSameType(errorCause(err), ObjectNameInvalid{}) {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
// Test with inexist bucket/object
|
||||
if err := fs.DeleteObject("foobucket", "fooobject"); !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
// Test with valid condition
|
||||
if err := fs.DeleteObject(bucketName, objectName); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
// Loading format file from faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
fs.storage = newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
if err := fs.DeleteObject(bucketName, objectName); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestFSDeleteBucket - tests for fs DeleteBucket
|
||||
func TestFSDeleteBucket(t *testing.T) {
|
||||
// Prepare for testing
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, _ := newFSObjects(disk)
|
||||
fs := obj.(fsObjects)
|
||||
bucketName := "bucket"
|
||||
|
||||
err := obj.MakeBucket(bucketName)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
// Test with an invalid bucket name
|
||||
if err := fs.DeleteBucket("fo"); !isSameType(errorCause(err), BucketNameInvalid{}) {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
// Test with an inexistant bucket
|
||||
if err := fs.DeleteBucket("foobucket"); !isSameType(errorCause(err), BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
// Test with a valid case
|
||||
if err := fs.DeleteBucket(bucketName); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
obj.MakeBucket(bucketName)
|
||||
|
||||
// Loading format file from faulty disk
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 2; i++ {
|
||||
fs.storage = newNaughtyDisk(fsStorage, map[int]error{i: errFaultyDisk}, nil)
|
||||
if err := fs.DeleteBucket(bucketName); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestFSListBuckets - tests for fs ListBuckets
|
||||
func TestFSListBuckets(t *testing.T) {
|
||||
// Prepare for tests
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, _ := newFSObjects(disk)
|
||||
fs := obj.(fsObjects)
|
||||
|
||||
bucketName := "bucket"
|
||||
|
||||
if err := obj.MakeBucket(bucketName); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
// Create a bucket with invalid name
|
||||
if err := fs.storage.MakeVol("vo^"); err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
// Test
|
||||
buckets, err := fs.ListBuckets()
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
if len(buckets) != 1 {
|
||||
t.Fatal("ListBuckets not working properly")
|
||||
}
|
||||
|
||||
// Test ListBuckets with faulty disks
|
||||
fsStorage := fs.storage.(*posix)
|
||||
for i := 1; i <= 2; i++ {
|
||||
fs.storage = newNaughtyDisk(fsStorage, nil, errFaultyDisk)
|
||||
if _, err := fs.ListBuckets(); errorCause(err) != errFaultyDisk {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestFSHealObject - tests for fs HealObject
|
||||
func TestFSHealObject(t *testing.T) {
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
err = obj.HealObject("bucket", "object")
|
||||
if err == nil || !isSameType(errorCause(err), NotImplemented{}) {
|
||||
t.Fatalf("Heal Object should return NotImplemented error ")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSListObjectHeal - tests for fs ListObjectHeals
|
||||
func TestFSListObjectsHeal(t *testing.T) {
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
_, err = obj.ListObjectsHeal("bucket", "prefix", "marker", "delimiter", 1000)
|
||||
if err == nil || !isSameType(errorCause(err), NotImplemented{}) {
|
||||
t.Fatalf("Heal Object should return NotImplemented error ")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFSHealDiskMetadata - tests for fs HealDiskMetadata
|
||||
func TestFSHealDiskMetadata(t *testing.T) {
|
||||
disk := filepath.Join(os.TempDir(), "minio-"+nextSuffix())
|
||||
defer removeAll(disk)
|
||||
|
||||
obj, err := newFSObjects(disk)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot create a new FS object: ", err)
|
||||
}
|
||||
err = obj.HealDiskMetadata()
|
||||
if err == nil || !isSameType(errorCause(err), NotImplemented{}) {
|
||||
t.Fatalf("Heal Object should return NotImplemented error ")
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
package cmd
|
||||
|
||||
import "github.com/minio/minio/pkg/disk"
|
||||
import (
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// naughtyDisk wraps a POSIX disk and returns programmed errors
|
||||
// specified by the developer. The purpose is to simulate errors
|
||||
@ -31,6 +34,8 @@ type naughtyDisk struct {
|
||||
defaultErr error
|
||||
// The current API call number
|
||||
callNR int
|
||||
// Data protection
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func newNaughtyDisk(d *posix, errs map[int]error, defaultErr error) *naughtyDisk {
|
||||
@ -38,6 +43,8 @@ func newNaughtyDisk(d *posix, errs map[int]error, defaultErr error) *naughtyDisk
|
||||
}
|
||||
|
||||
func (d *naughtyDisk) calcError() (err error) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.callNR++
|
||||
if err, ok := d.errors[d.callNR]; ok {
|
||||
return err
|
||||
|
@ -437,7 +437,7 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
{"test-bucket-list-object", "asia", "europe-object", "", 0, ListObjectsInfo{}, fmt.Errorf("Invalid combination of marker '%s' and prefix '%s'", "europe-object", "asia"), false},
|
||||
// Setting a non-existing directory to be prefix (12-13).
|
||||
{"empty-bucket", "europe/france/", "", "", 1, ListObjectsInfo{}, nil, true},
|
||||
{"empty-bucket", "europe/tunisia/", "", "", 1, ListObjectsInfo{}, nil, true},
|
||||
{"empty-bucket", "africa/tunisia/", "", "", 1, ListObjectsInfo{}, nil, true},
|
||||
// Testing on empty bucket, that is, bucket without any objects in it (14).
|
||||
{"empty-bucket", "", "", "", 0, ListObjectsInfo{}, nil, true},
|
||||
// Setting maxKeys to negative value (15-16).
|
||||
@ -512,6 +512,9 @@ func testListObjects(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
{"test-bucket-list-object", "", "Asia/India/Karnataka/Bangalore/Koramangala/pics", "/", 10, resultCases[29], nil, true},
|
||||
// Test with prefix and delimiter set to '/'. (60)
|
||||
{"test-bucket-list-object", "/", "", "/", 10, resultCases[30], nil, true},
|
||||
|
||||
// Test with invalid prefix (61)
|
||||
{"test-bucket-list-object", "^", "", "/", 10, resultCases[30], ObjectNameInvalid{Bucket: "test-bucket-list-object", Object: "^"}, false},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -36,9 +36,14 @@ func testObjectNewMultipartUpload(obj ObjectLayer, instanceType string, t TestEr
|
||||
bucket := "minio-bucket"
|
||||
object := "minio-object"
|
||||
|
||||
_, err := obj.NewMultipartUpload("--", object, nil)
|
||||
if err == nil {
|
||||
t.Fatalf("%s: Expected to fail since bucket name is invalid.", instanceType)
|
||||
}
|
||||
|
||||
errMsg := "Bucket not found: minio-bucket"
|
||||
// opearation expected to fail since the bucket on which NewMultipartUpload is being initiated doesn't exist.
|
||||
_, err := obj.NewMultipartUpload(bucket, object, nil)
|
||||
_, err = obj.NewMultipartUpload(bucket, object, nil)
|
||||
if err == nil {
|
||||
t.Fatalf("%s: Expected to fail since the NewMultipartUpload is intialized on a non-existent bucket.", instanceType)
|
||||
}
|
||||
@ -53,6 +58,11 @@ func testObjectNewMultipartUpload(obj ObjectLayer, instanceType string, t TestEr
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
|
||||
_, err = obj.NewMultipartUpload(bucket, "^", nil)
|
||||
if err == nil {
|
||||
t.Fatalf("%s: Expected to fail since object name is invalid.", instanceType)
|
||||
}
|
||||
|
||||
uploadID, err := obj.NewMultipartUpload(bucket, object, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
@ -69,6 +79,53 @@ func testObjectNewMultipartUpload(obj ObjectLayer, instanceType string, t TestEr
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling AbortMultipartUpload tests for both XL multiple disks and single node setup.
|
||||
func TestObjectAbortMultipartUpload(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testObjectAbortMultipartUpload)
|
||||
}
|
||||
|
||||
// Tests validate creation of abort multipart upload instance.
|
||||
func testObjectAbortMultipartUpload(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
|
||||
bucket := "minio-bucket"
|
||||
object := "minio-object"
|
||||
|
||||
// Create bucket before intiating NewMultipartUpload.
|
||||
err := obj.MakeBucket(bucket)
|
||||
if err != nil {
|
||||
// failed to create newbucket, abort.
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
|
||||
uploadID, err := obj.NewMultipartUpload(bucket, object, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%s : %s", instanceType, err.Error())
|
||||
}
|
||||
|
||||
abortTestCases := []struct {
|
||||
bucketName string
|
||||
objName string
|
||||
uploadID string
|
||||
expectedErrType error
|
||||
}{
|
||||
{"--", object, uploadID, BucketNameInvalid{}},
|
||||
{bucket, "^", uploadID, ObjectNameInvalid{}},
|
||||
{"foo", object, uploadID, BucketNotFound{}},
|
||||
{bucket, object, "foo-foo", InvalidUploadID{}},
|
||||
{bucket, object, uploadID, nil},
|
||||
}
|
||||
// Iterating over creatPartCases to generate multipart chunks.
|
||||
for i, testCase := range abortTestCases {
|
||||
err = obj.AbortMultipartUpload(testCase.bucketName, testCase.objName, testCase.uploadID)
|
||||
if testCase.expectedErrType == nil && err != nil {
|
||||
t.Errorf("Test %d, unexpected err is received: %v, expected:%v\n", i+1, err, testCase.expectedErrType)
|
||||
}
|
||||
if testCase.expectedErrType != nil && !isSameType(errorCause(err), testCase.expectedErrType) {
|
||||
t.Errorf("Test %d, unexpected err is received: %v, expected:%v\n", i+1, err, testCase.expectedErrType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling isUploadIDExists tests for both XL multiple disks and single node setup.
|
||||
func TestObjectAPIIsUploadIDExists(t *testing.T) {
|
||||
ExecObjectLayerTest(t, testObjectAPIIsUploadIDExists)
|
||||
@ -1716,7 +1773,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
}
|
||||
// Initiate Multipart Upload on the above created bucket.
|
||||
uploadID, err = obj.NewMultipartUpload(bucketNames[0], objectNames[0], nil)
|
||||
uploadID, err = obj.NewMultipartUpload(bucketNames[0], objectNames[0], map[string]string{"X-Amz-Meta-Id": "id"})
|
||||
if err != nil {
|
||||
// Failed to create NewMultipartUpload, abort.
|
||||
t.Fatalf("%s : %s", instanceType, err)
|
||||
@ -1849,6 +1906,7 @@ func testObjectCompleteMultipartUpload(obj ObjectLayer, instanceType string, t T
|
||||
// the case above successfully completes CompleteMultipartUpload, the remaining Parts will be flushed.
|
||||
// Expecting to fail with Invalid UploadID.
|
||||
{bucketNames[0], objectNames[0], uploadIDs[0], inputParts[4].parts, "", InvalidUploadID{UploadID: uploadIDs[0]}, false},
|
||||
// Expecting to fail due to bad
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -148,6 +148,10 @@ func testObjectAPIPutObject(obj ObjectLayer, instanceType string, t TestErrHandl
|
||||
{bucket, object, data, nil, int64(len(data) - 1), md5Hex(data[:len(data)-1]), nil},
|
||||
{bucket, object, nilBytes, nil, int64(len(nilBytes) + 1), md5Hex(nilBytes), IncompleteBody{}},
|
||||
{bucket, object, fiveMBBytes, nil, int64(0), md5Hex(fiveMBBytes), nil},
|
||||
|
||||
// Test case 29
|
||||
// valid data with X-Amz-Meta- meta
|
||||
{bucket, object, data, map[string]string{"X-Amz-Meta-AppID": "a42"}, int64(len(data)), md5Hex(data), nil},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
@ -127,6 +128,11 @@ func nextSuffix() string {
|
||||
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
||||
}
|
||||
|
||||
// isSameType - compares two object types via reflect.TypeOf
|
||||
func isSameType(obj1, obj2 interface{}) bool {
|
||||
return reflect.TypeOf(obj1) == reflect.TypeOf(obj2)
|
||||
}
|
||||
|
||||
// TestServer encapsulates an instantiation of a Minio instance with a temporary backend.
|
||||
// Example usage:
|
||||
// s := StartTestServer(t,"XL")
|
||||
|
Loading…
Reference in New Issue
Block a user