github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/client-fs_test.go (about) 1 // Copyright (c) 2015-2022 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "bytes" 22 "context" 23 "io" 24 "os" 25 "path/filepath" 26 "runtime" 27 28 checkv1 "gopkg.in/check.v1" 29 ) 30 31 // Test list files in a folder. 32 func (s *TestSuite) TestList(c *checkv1.C) { 33 root, e := os.MkdirTemp(os.TempDir(), "fs-") 34 c.Assert(e, checkv1.IsNil) 35 defer os.RemoveAll(root) 36 37 // Create multiple files. 38 objectPath := filepath.Join(root, "object1") 39 fsClient, err := fsNew(objectPath) 40 c.Assert(err, checkv1.IsNil) 41 42 data := "hello" 43 44 reader := bytes.NewReader([]byte(data)) 45 var n int64 46 n, err = fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 47 metadata: map[string]string{ 48 "Content-Type": "application/octet-stream", 49 }, 50 }, 51 ) 52 c.Assert(err, checkv1.IsNil) 53 c.Assert(n, checkv1.Equals, int64(len(data))) 54 55 objectPath = filepath.Join(root, "object2") 56 fsClient, err = fsNew(objectPath) 57 c.Assert(err, checkv1.IsNil) 58 59 reader = bytes.NewReader([]byte(data)) 60 n, err = fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 61 metadata: map[string]string{ 62 "Content-Type": "application/octet-stream", 63 }, 64 }) 65 c.Assert(err, checkv1.IsNil) 66 c.Assert(n, checkv1.Equals, int64(len(data))) 67 68 fsClient, err = fsNew(root) 69 c.Assert(err, checkv1.IsNil) 70 71 // Verify previously create files and list them. 72 var contents []*ClientContent 73 for content := range fsClient.List(globalContext, ListOptions{ShowDir: DirNone}) { 74 if content.Err != nil { 75 err = content.Err 76 break 77 } 78 contents = append(contents, content) 79 } 80 c.Assert(err, checkv1.IsNil) 81 c.Assert(len(contents), checkv1.Equals, 1) 82 c.Assert(contents[0].Type.IsDir(), checkv1.Equals, true) 83 84 // Create another file. 85 objectPath = filepath.Join(root, "test1/newObject1") 86 fsClient, err = fsNew(objectPath) 87 c.Assert(err, checkv1.IsNil) 88 89 reader = bytes.NewReader([]byte(data)) 90 n, err = fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 91 metadata: map[string]string{ 92 "Content-Type": "application/octet-stream", 93 }, 94 }) 95 c.Assert(err, checkv1.IsNil) 96 c.Assert(n, checkv1.Equals, int64(len(data))) 97 98 fsClient, err = fsNew(root) 99 c.Assert(err, checkv1.IsNil) 100 101 contents = nil 102 // List non recursive to list only top level files. 103 for content := range fsClient.List(globalContext, ListOptions{ShowDir: DirNone}) { 104 if content.Err != nil { 105 err = content.Err 106 break 107 } 108 contents = append(contents, content) 109 } 110 c.Assert(err, checkv1.IsNil) 111 c.Assert(len(contents), checkv1.Equals, 1) 112 c.Assert(contents[0].Type.IsDir(), checkv1.Equals, true) 113 114 fsClient, err = fsNew(root) 115 c.Assert(err, checkv1.IsNil) 116 117 contents = nil 118 // List recursively all files and verify. 119 for content := range fsClient.List(globalContext, ListOptions{Recursive: true, ShowDir: DirNone}) { 120 if content.Err != nil { 121 err = content.Err 122 break 123 } 124 contents = append(contents, content) 125 } 126 127 c.Assert(err, checkv1.IsNil) 128 c.Assert(len(contents), checkv1.Equals, 3) 129 130 var regularFiles int 131 var regularDirs int 132 // Test number of expected files and directories. 133 for _, content := range contents { 134 if content.Type.IsRegular() { 135 regularFiles++ 136 continue 137 } 138 if content.Type.IsDir() { 139 regularDirs++ 140 continue 141 } 142 } 143 c.Assert(regularDirs, checkv1.Equals, 0) 144 c.Assert(regularFiles, checkv1.Equals, 3) 145 146 // Create an ignored file and list to verify if its ignored. 147 objectPath = filepath.Join(root, "test1/.DS_Store") 148 fsClient, err = fsNew(objectPath) 149 c.Assert(err, checkv1.IsNil) 150 151 reader = bytes.NewReader([]byte(data)) 152 n, err = fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 153 metadata: map[string]string{ 154 "Content-Type": "application/octet-stream", 155 }, 156 }) 157 c.Assert(err, checkv1.IsNil) 158 c.Assert(n, checkv1.Equals, int64(len(data))) 159 160 fsClient, err = fsNew(root) 161 c.Assert(err, checkv1.IsNil) 162 163 contents = nil 164 // List recursively all files and verify. 165 for content := range fsClient.List(globalContext, ListOptions{Recursive: true, ShowDir: DirNone}) { 166 if content.Err != nil { 167 err = content.Err 168 break 169 } 170 contents = append(contents, content) 171 } 172 173 c.Assert(err, checkv1.IsNil) 174 switch runtime.GOOS { 175 case "darwin": 176 c.Assert(len(contents), checkv1.Equals, 3) 177 default: 178 c.Assert(len(contents), checkv1.Equals, 4) 179 } 180 181 regularFiles = 0 182 // Test number of expected files. 183 for _, content := range contents { 184 if content.Type.IsRegular() { 185 regularFiles++ 186 continue 187 } 188 } 189 switch runtime.GOOS { 190 case "darwin": 191 c.Assert(regularFiles, checkv1.Equals, 3) 192 default: 193 c.Assert(regularFiles, checkv1.Equals, 4) 194 } 195 } 196 197 // Test put bucket aka 'mkdir()' operation. 198 func (s *TestSuite) TestPutBucket(c *checkv1.C) { 199 root, e := os.MkdirTemp(os.TempDir(), "fs-") 200 c.Assert(e, checkv1.IsNil) 201 defer os.RemoveAll(root) 202 203 bucketPath := filepath.Join(root, "bucket") 204 fsClient, err := fsNew(bucketPath) 205 c.Assert(err, checkv1.IsNil) 206 err = fsClient.MakeBucket(context.Background(), "us-east-1", true, false) 207 c.Assert(err, checkv1.IsNil) 208 } 209 210 // Test stat bucket aka 'stat()' operation. 211 func (s *TestSuite) TestStatBucket(c *checkv1.C) { 212 root, e := os.MkdirTemp(os.TempDir(), "fs-") 213 c.Assert(e, checkv1.IsNil) 214 defer os.RemoveAll(root) 215 216 bucketPath := filepath.Join(root, "bucket") 217 218 fsClient, err := fsNew(bucketPath) 219 c.Assert(err, checkv1.IsNil) 220 err = fsClient.MakeBucket(context.Background(), "us-east-1", true, false) 221 c.Assert(err, checkv1.IsNil) 222 _, err = fsClient.Stat(context.Background(), StatOptions{}) 223 c.Assert(err, checkv1.IsNil) 224 } 225 226 // Test bucket acl fails for directories. 227 func (s *TestSuite) TestBucketACLFails(c *checkv1.C) { 228 root, e := os.MkdirTemp(os.TempDir(), "fs-") 229 c.Assert(e, checkv1.IsNil) 230 defer os.RemoveAll(root) 231 232 bucketPath := filepath.Join(root, "bucket") 233 fsClient, err := fsNew(bucketPath) 234 c.Assert(err, checkv1.IsNil) 235 err = fsClient.MakeBucket(context.Background(), "us-east-1", true, false) 236 c.Assert(err, checkv1.IsNil) 237 238 // On windows setting permissions is not supported. 239 if runtime.GOOS != "windows" { 240 err = fsClient.SetAccess(context.Background(), "readonly", false) 241 c.Assert(err, checkv1.IsNil) 242 243 _, _, err = fsClient.GetAccess(context.Background()) 244 c.Assert(err, checkv1.IsNil) 245 } 246 } 247 248 // Test creating a file. 249 func (s *TestSuite) TestPut(c *checkv1.C) { 250 root, e := os.MkdirTemp(os.TempDir(), "fs-") 251 c.Assert(e, checkv1.IsNil) 252 defer os.RemoveAll(root) 253 254 objectPath := filepath.Join(root, "object") 255 fsClient, err := fsNew(objectPath) 256 c.Assert(err, checkv1.IsNil) 257 258 data := "hello" 259 reader := bytes.NewReader([]byte(data)) 260 var n int64 261 n, err = fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 262 metadata: map[string]string{ 263 "Content-Type": "application/octet-stream", 264 }, 265 }, 266 ) 267 268 c.Assert(err, checkv1.IsNil) 269 c.Assert(n, checkv1.Equals, int64(len(data))) 270 } 271 272 // Test read a file. 273 func (s *TestSuite) TestGet(c *checkv1.C) { 274 root, e := os.MkdirTemp(os.TempDir(), "fs-") 275 c.Assert(e, checkv1.IsNil) 276 defer os.RemoveAll(root) 277 278 objectPath := filepath.Join(root, "object") 279 fsClient, err := fsNew(objectPath) 280 c.Assert(err, checkv1.IsNil) 281 282 data := "hello" 283 var reader io.Reader 284 reader = bytes.NewReader([]byte(data)) 285 n, err := fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 286 metadata: map[string]string{ 287 "Content-Type": "application/octet-stream", 288 }, 289 }) 290 c.Assert(err, checkv1.IsNil) 291 c.Assert(n, checkv1.Equals, int64(len(data))) 292 293 reader, _, err = fsClient.Get(context.Background(), GetOptions{}) 294 c.Assert(err, checkv1.IsNil) 295 var results bytes.Buffer 296 _, e = io.Copy(&results, reader) 297 c.Assert(e, checkv1.IsNil) 298 c.Assert([]byte(data), checkv1.DeepEquals, results.Bytes()) 299 } 300 301 // Test get range in a file. 302 func (s *TestSuite) TestGetRange(c *checkv1.C) { 303 root, e := os.MkdirTemp(os.TempDir(), "fs-") 304 c.Assert(e, checkv1.IsNil) 305 defer os.RemoveAll(root) 306 307 objectPath := filepath.Join(root, "object") 308 fsClient, err := fsNew(objectPath) 309 c.Assert(err, checkv1.IsNil) 310 311 data := "hello world" 312 var reader io.Reader 313 reader = bytes.NewReader([]byte(data)) 314 n, err := fsClient.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 315 metadata: map[string]string{ 316 "Content-Type": "application/octet-stream", 317 }, 318 }) 319 c.Assert(err, checkv1.IsNil) 320 c.Assert(n, checkv1.Equals, int64(len(data))) 321 322 reader, _, err = fsClient.Get(context.Background(), GetOptions{}) 323 c.Assert(err, checkv1.IsNil) 324 var results bytes.Buffer 325 buf := make([]byte, 5) 326 m, e := reader.(io.ReaderAt).ReadAt(buf, 0) 327 c.Assert(e, checkv1.IsNil) 328 c.Assert(m, checkv1.Equals, 5) 329 _, e = results.Write(buf) 330 c.Assert(e, checkv1.IsNil) 331 c.Assert([]byte("hello"), checkv1.DeepEquals, results.Bytes()) 332 } 333 334 // Test stat file. 335 func (s *TestSuite) TestStatObject(c *checkv1.C) { 336 root, e := os.MkdirTemp(os.TempDir(), "fs-") 337 c.Assert(e, checkv1.IsNil) 338 defer os.RemoveAll(root) 339 340 objectPath := filepath.Join(root, "object") 341 fsClient, err := fsNew(objectPath) 342 c.Assert(err, checkv1.IsNil) 343 344 data := "hello" 345 dataLen := len(data) 346 reader := bytes.NewReader([]byte(data)) 347 n, err := fsClient.Put(context.Background(), reader, int64(dataLen), nil, PutOptions{ 348 metadata: map[string]string{ 349 "Content-Type": "application/octet-stream", 350 }, 351 }, 352 ) 353 c.Assert(err, checkv1.IsNil) 354 c.Assert(n, checkv1.Equals, int64(len(data))) 355 356 content, err := fsClient.Stat(context.Background(), StatOptions{}) 357 c.Assert(err, checkv1.IsNil) 358 c.Assert(content.Size, checkv1.Equals, int64(dataLen)) 359 } 360 361 // Test copy. 362 func (s *TestSuite) TestCopy(c *checkv1.C) { 363 root, e := os.MkdirTemp(os.TempDir(), "fs-") 364 c.Assert(e, checkv1.IsNil) 365 defer os.RemoveAll(root) 366 sourcePath := filepath.Join(root, "source") 367 targetPath := filepath.Join(root, "target") 368 fsClientTarget, err := fsNew(targetPath) 369 c.Assert(err, checkv1.IsNil) 370 fsClientSource, err := fsNew(sourcePath) 371 c.Assert(err, checkv1.IsNil) 372 373 data := "hello world" 374 reader := bytes.NewReader([]byte(data)) 375 n, err := fsClientSource.Put(context.Background(), reader, int64(len(data)), nil, PutOptions{ 376 metadata: map[string]string{ 377 "Content-Type": "application/octet-stream", 378 }, 379 }) 380 c.Assert(err, checkv1.IsNil) 381 c.Assert(n, checkv1.Equals, int64(len(data))) 382 err = fsClientTarget.Copy(context.Background(), sourcePath, CopyOptions{size: int64(len(data))}, nil) 383 c.Assert(err, checkv1.IsNil) 384 }