storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/fs-v1_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2016, 2017 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "bytes" 21 "os" 22 "path/filepath" 23 "testing" 24 25 "storj.io/minio/pkg/madmin" 26 ) 27 28 // Tests for if parent directory is object 29 func TestFSParentDirIsObject(t *testing.T) { 30 obj, disk, err := prepareFS() 31 if err != nil { 32 t.Fatal(err) 33 } 34 defer os.RemoveAll(disk) 35 36 bucketName := "testbucket" 37 objectName := "object" 38 39 if err = obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}); err != nil { 40 t.Fatal(err) 41 } 42 objectContent := "12345" 43 objInfo, err := obj.PutObject(GlobalContext, bucketName, objectName, 44 mustGetPutObjReader(t, bytes.NewReader([]byte(objectContent)), int64(len(objectContent)), "", ""), ObjectOptions{}) 45 if err != nil { 46 t.Fatal(err) 47 } 48 if objInfo.Name != objectName { 49 t.Fatalf("Unexpected object name returned got %s, expected %s", objInfo.Name, objectName) 50 } 51 52 fs := obj.(*FSObjects) 53 testCases := []struct { 54 parentIsObject bool 55 objectName string 56 }{ 57 // parentIsObject is true if object is available. 58 { 59 parentIsObject: true, 60 objectName: objectName, 61 }, 62 { 63 parentIsObject: false, 64 objectName: "", 65 }, 66 { 67 parentIsObject: false, 68 objectName: ".", 69 }, 70 // Should not cause infinite loop. 71 { 72 parentIsObject: false, 73 objectName: SlashSeparator, 74 }, 75 { 76 parentIsObject: false, 77 objectName: "\\", 78 }, 79 // Should not cause infinite loop with double forward slash. 80 { 81 parentIsObject: false, 82 objectName: "//", 83 }, 84 } 85 for i, testCase := range testCases { 86 gotValue := fs.parentDirIsObject(GlobalContext, bucketName, testCase.objectName) 87 if testCase.parentIsObject != gotValue { 88 t.Errorf("Test %d: Unexpected value returned got %t, expected %t", i+1, gotValue, testCase.parentIsObject) 89 } 90 } 91 } 92 93 // TestNewFS - tests initialization of all input disks 94 // and constructs a valid `FS` object layer. 95 func TestNewFS(t *testing.T) { 96 // Do not attempt to create this path, the test validates 97 // so that NewFSObjectLayer initializes non existing paths 98 // and successfully returns initialized object layer. 99 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 100 defer os.RemoveAll(disk) 101 102 _, err := NewFSObjectLayer("") 103 if err != errInvalidArgument { 104 t.Errorf("Expecting error invalid argument, got %s", err) 105 } 106 _, err = NewFSObjectLayer(disk) 107 if err != nil { 108 errMsg := "Unable to recognize backend format, Disk is not in FS format." 109 if err.Error() == errMsg { 110 t.Errorf("Expecting %s, got %s", errMsg, err) 111 } 112 } 113 } 114 115 // TestFSShutdown - initialize a new FS object layer then calls 116 // Shutdown to check returned results 117 func TestFSShutdown(t *testing.T) { 118 bucketName := "testbucket" 119 objectName := "object" 120 // Create and return an fsObject with its path in the disk 121 prepareTest := func() (*FSObjects, string) { 122 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 123 obj := initFSObjects(disk, t) 124 fs := obj.(*FSObjects) 125 126 objectContent := "12345" 127 obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}) 128 obj.PutObject(GlobalContext, bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader([]byte(objectContent)), int64(len(objectContent)), "", ""), ObjectOptions{}) 129 return fs, disk 130 } 131 132 // Test Shutdown with regular conditions 133 fs, disk := prepareTest() 134 if err := fs.Shutdown(GlobalContext); err != nil { 135 t.Fatal("Cannot shutdown the FS object: ", err) 136 } 137 os.RemoveAll(disk) 138 139 // Test Shutdown with faulty disk 140 fs, disk = prepareTest() 141 fs.DeleteObject(GlobalContext, bucketName, objectName, ObjectOptions{}) 142 os.RemoveAll(disk) 143 if err := fs.Shutdown(GlobalContext); err != nil { 144 t.Fatal("Got unexpected fs shutdown error: ", err) 145 } 146 } 147 148 // TestFSGetBucketInfo - test GetBucketInfo with healty and faulty disks 149 func TestFSGetBucketInfo(t *testing.T) { 150 // Prepare for testing 151 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 152 defer os.RemoveAll(disk) 153 154 obj := initFSObjects(disk, t) 155 fs := obj.(*FSObjects) 156 bucketName := "bucket" 157 158 err := obj.MakeBucketWithLocation(GlobalContext, "a", BucketOptions{}) 159 if !isSameType(err, BucketNameInvalid{}) { 160 t.Fatal("BucketNameInvalid error not returned") 161 } 162 163 err = obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}) 164 if err != nil { 165 t.Fatal(err) 166 } 167 168 // Test with valid parameters 169 info, err := fs.GetBucketInfo(GlobalContext, bucketName) 170 if err != nil { 171 t.Fatal(err) 172 } 173 if info.Name != bucketName { 174 t.Fatalf("wrong bucket name, expected: %s, found: %s", bucketName, info.Name) 175 } 176 177 // Test with non-existent bucket 178 _, err = fs.GetBucketInfo(GlobalContext, "a") 179 if !isSameType(err, BucketNotFound{}) { 180 t.Fatal("BucketNotFound error not returned") 181 } 182 183 // Check for buckets and should get disk not found. 184 os.RemoveAll(disk) 185 186 if _, err = fs.GetBucketInfo(GlobalContext, bucketName); err != nil { 187 if !isSameType(err, BucketNotFound{}) { 188 t.Fatal("BucketNotFound error not returned") 189 } 190 } 191 } 192 193 func TestFSPutObject(t *testing.T) { 194 // Prepare for tests 195 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 196 defer os.RemoveAll(disk) 197 198 obj := initFSObjects(disk, t) 199 bucketName := "bucket" 200 objectName := "1/2/3/4/object" 201 202 if err := obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}); err != nil { 203 t.Fatal(err) 204 } 205 206 // With a regular object. 207 _, err := obj.PutObject(GlobalContext, bucketName+"non-existent", objectName, mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), int64(len("abcd")), "", ""), ObjectOptions{}) 208 if err == nil { 209 t.Fatal("Unexpected should fail here, bucket doesn't exist") 210 } 211 if _, ok := err.(BucketNotFound); !ok { 212 t.Fatalf("Expected error type BucketNotFound, got %#v", err) 213 } 214 215 // With a directory object. 216 _, err = obj.PutObject(GlobalContext, bucketName+"non-existent", objectName+SlashSeparator, mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), 0, "", ""), ObjectOptions{}) 217 if err == nil { 218 t.Fatal("Unexpected should fail here, bucket doesn't exist") 219 } 220 if _, ok := err.(BucketNotFound); !ok { 221 t.Fatalf("Expected error type BucketNotFound, got %#v", err) 222 } 223 224 _, err = obj.PutObject(GlobalContext, bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), int64(len("abcd")), "", ""), ObjectOptions{}) 225 if err != nil { 226 t.Fatal(err) 227 } 228 _, err = obj.PutObject(GlobalContext, bucketName, objectName+"/1", mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), int64(len("abcd")), "", ""), ObjectOptions{}) 229 if err == nil { 230 t.Fatal("Unexpected should fail here, backend corruption occurred") 231 } 232 if nerr, ok := err.(ParentIsObject); !ok { 233 t.Fatalf("Expected ParentIsObject, got %#v", err) 234 } else { 235 if nerr.Bucket != "bucket" { 236 t.Fatalf("Expected 'bucket', got %s", nerr.Bucket) 237 } 238 if nerr.Object != "1/2/3/4/object/1" { 239 t.Fatalf("Expected '1/2/3/4/object/1', got %s", nerr.Object) 240 } 241 } 242 243 _, err = obj.PutObject(GlobalContext, bucketName, objectName+"/1/", mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), 0, "", ""), ObjectOptions{}) 244 if err == nil { 245 t.Fatal("Unexpected should fail here, backned corruption occurred") 246 } 247 if nerr, ok := err.(ParentIsObject); !ok { 248 t.Fatalf("Expected ParentIsObject, got %#v", err) 249 } else { 250 if nerr.Bucket != "bucket" { 251 t.Fatalf("Expected 'bucket', got %s", nerr.Bucket) 252 } 253 if nerr.Object != "1/2/3/4/object/1/" { 254 t.Fatalf("Expected '1/2/3/4/object/1/', got %s", nerr.Object) 255 } 256 } 257 } 258 259 // TestFSDeleteObject - test fs.DeleteObject() with healthy and corrupted disks 260 func TestFSDeleteObject(t *testing.T) { 261 // Prepare for tests 262 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 263 defer os.RemoveAll(disk) 264 265 obj := initFSObjects(disk, t) 266 fs := obj.(*FSObjects) 267 bucketName := "bucket" 268 objectName := "object" 269 270 obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}) 271 obj.PutObject(GlobalContext, bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), int64(len("abcd")), "", ""), ObjectOptions{}) 272 273 // Test with invalid bucket name 274 if _, err := fs.DeleteObject(GlobalContext, "fo", objectName, ObjectOptions{}); !isSameType(err, BucketNameInvalid{}) { 275 t.Fatal("Unexpected error: ", err) 276 } 277 // Test with bucket does not exist 278 if _, err := fs.DeleteObject(GlobalContext, "foobucket", "fooobject", ObjectOptions{}); !isSameType(err, BucketNotFound{}) { 279 t.Fatal("Unexpected error: ", err) 280 } 281 // Test with invalid object name 282 if _, err := fs.DeleteObject(GlobalContext, bucketName, "\\", ObjectOptions{}); !(isSameType(err, ObjectNotFound{}) || isSameType(err, ObjectNameInvalid{})) { 283 t.Fatal("Unexpected error: ", err) 284 } 285 // Test with object does not exist. 286 if _, err := fs.DeleteObject(GlobalContext, bucketName, "foooobject", ObjectOptions{}); !isSameType(err, ObjectNotFound{}) { 287 t.Fatal("Unexpected error: ", err) 288 } 289 // Test with valid condition 290 if _, err := fs.DeleteObject(GlobalContext, bucketName, objectName, ObjectOptions{}); err != nil { 291 t.Fatal("Unexpected error: ", err) 292 } 293 294 // Delete object should err disk not found. 295 os.RemoveAll(disk) 296 if _, err := fs.DeleteObject(GlobalContext, bucketName, objectName, ObjectOptions{}); err != nil { 297 if !isSameType(err, BucketNotFound{}) { 298 t.Fatal("Unexpected error: ", err) 299 } 300 } 301 302 } 303 304 // TestFSDeleteBucket - tests for fs DeleteBucket 305 func TestFSDeleteBucket(t *testing.T) { 306 // Prepare for testing 307 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 308 defer os.RemoveAll(disk) 309 310 obj := initFSObjects(disk, t) 311 fs := obj.(*FSObjects) 312 bucketName := "bucket" 313 314 err := obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}) 315 if err != nil { 316 t.Fatal("Unexpected error: ", err) 317 } 318 319 // Test with an invalid bucket name 320 if err = fs.DeleteBucket(GlobalContext, "fo", false); !isSameType(err, BucketNotFound{}) { 321 t.Fatal("Unexpected error: ", err) 322 } 323 324 // Test with an inexistant bucket 325 if err = fs.DeleteBucket(GlobalContext, "foobucket", false); !isSameType(err, BucketNotFound{}) { 326 t.Fatal("Unexpected error: ", err) 327 } 328 // Test with a valid case 329 if err = fs.DeleteBucket(GlobalContext, bucketName, false); err != nil { 330 t.Fatal("Unexpected error: ", err) 331 } 332 333 obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}) 334 335 // Delete bucket should get error disk not found. 336 os.RemoveAll(disk) 337 if err = fs.DeleteBucket(GlobalContext, bucketName, false); err != nil { 338 if !isSameType(err, BucketNotFound{}) { 339 t.Fatal("Unexpected error: ", err) 340 } 341 } 342 } 343 344 // TestFSListBuckets - tests for fs ListBuckets 345 func TestFSListBuckets(t *testing.T) { 346 // Prepare for tests 347 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 348 defer os.RemoveAll(disk) 349 350 obj := initFSObjects(disk, t) 351 fs := obj.(*FSObjects) 352 353 bucketName := "bucket" 354 if err := obj.MakeBucketWithLocation(GlobalContext, bucketName, BucketOptions{}); err != nil { 355 t.Fatal("Unexpected error: ", err) 356 } 357 358 // Create a bucket with invalid name 359 if err := os.MkdirAll(pathJoin(fs.fsPath, "vo^"), 0777); err != nil { 360 t.Fatal("Unexpected error: ", err) 361 } 362 f, err := os.Create(pathJoin(fs.fsPath, "test")) 363 if err != nil { 364 t.Fatal("Unexpected error: ", err) 365 } 366 f.Close() 367 368 // Test list buckets to have only one entry. 369 buckets, err := fs.ListBuckets(GlobalContext) 370 if err != nil { 371 t.Fatal("Unexpected error: ", err) 372 } 373 if len(buckets) != 1 { 374 t.Fatal("ListBuckets not working properly", buckets) 375 } 376 377 // Test ListBuckets with disk not found. 378 os.RemoveAll(disk) 379 if _, err := fs.ListBuckets(GlobalContext); err != nil { 380 if err != errDiskNotFound { 381 t.Fatal("Unexpected error: ", err) 382 } 383 } 384 } 385 386 // TestFSHealObject - tests for fs HealObject 387 func TestFSHealObject(t *testing.T) { 388 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 389 defer os.RemoveAll(disk) 390 391 obj := initFSObjects(disk, t) 392 _, err := obj.HealObject(GlobalContext, "bucket", "object", "", madmin.HealOpts{}) 393 if err == nil || !isSameType(err, NotImplemented{}) { 394 t.Fatalf("Heal Object should return NotImplemented error ") 395 } 396 } 397 398 // TestFSHealObjects - tests for fs HealObjects to return not implemented. 399 func TestFSHealObjects(t *testing.T) { 400 disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) 401 defer os.RemoveAll(disk) 402 403 obj := initFSObjects(disk, t) 404 err := obj.HealObjects(GlobalContext, "bucket", "prefix", madmin.HealOpts{}, nil) 405 if err == nil || !isSameType(err, NotImplemented{}) { 406 t.Fatalf("Heal Object should return NotImplemented error ") 407 } 408 }