github.com/27149chen/afero@v1.6.2/memmap_test.go (about) 1 package afero 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 "runtime" 9 "testing" 10 "time" 11 ) 12 13 func TestNormalizePath(t *testing.T) { 14 type test struct { 15 input string 16 expected string 17 } 18 19 data := []test{ 20 {".", FilePathSeparator}, 21 {"./", FilePathSeparator}, 22 {"..", FilePathSeparator}, 23 {"../", FilePathSeparator}, 24 {"./..", FilePathSeparator}, 25 {"./../", FilePathSeparator}, 26 } 27 28 for i, d := range data { 29 cpath := normalizePath(d.input) 30 if d.expected != cpath { 31 t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, cpath) 32 } 33 } 34 } 35 36 func TestPathErrors(t *testing.T) { 37 path := filepath.Join(".", "some", "path") 38 path2 := filepath.Join(".", "different", "path") 39 fs := NewMemMapFs() 40 perm := os.FileMode(0755) 41 uid := 1000 42 gid := 1000 43 44 // relevant functions: 45 // func (m *MemMapFs) Chmod(name string, mode os.FileMode) error 46 // func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error 47 // func (m *MemMapFs) Create(name string) (File, error) 48 // func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error 49 // func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error 50 // func (m *MemMapFs) Open(name string) (File, error) 51 // func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) 52 // func (m *MemMapFs) Remove(name string) error 53 // func (m *MemMapFs) Rename(oldname, newname string) error 54 // func (m *MemMapFs) Stat(name string) (os.FileInfo, error) 55 56 err := fs.Chmod(path, perm) 57 checkPathError(t, err, "Chmod") 58 59 err = fs.Chown(path, uid, gid) 60 checkPathError(t, err, "Chown") 61 62 err = fs.Chtimes(path, time.Now(), time.Now()) 63 checkPathError(t, err, "Chtimes") 64 65 // fs.Create doesn't return an error 66 67 err = fs.Mkdir(path2, perm) 68 if err != nil { 69 t.Error(err) 70 } 71 err = fs.Mkdir(path2, perm) 72 checkPathError(t, err, "Mkdir") 73 74 err = fs.MkdirAll(path2, perm) 75 if err != nil { 76 t.Error("MkdirAll:", err) 77 } 78 79 _, err = fs.Open(path) 80 checkPathError(t, err, "Open") 81 82 _, err = fs.OpenFile(path, os.O_RDWR, perm) 83 checkPathError(t, err, "OpenFile") 84 85 err = fs.Remove(path) 86 checkPathError(t, err, "Remove") 87 88 err = fs.RemoveAll(path) 89 if err != nil { 90 t.Error("RemoveAll:", err) 91 } 92 93 err = fs.Rename(path, path2) 94 checkPathError(t, err, "Rename") 95 96 _, err = fs.Stat(path) 97 checkPathError(t, err, "Stat") 98 } 99 100 func checkPathError(t *testing.T, err error, op string) { 101 pathErr, ok := err.(*os.PathError) 102 if !ok { 103 t.Error(op+":", err, "is not a os.PathError") 104 return 105 } 106 _, ok = pathErr.Err.(*os.PathError) 107 if ok { 108 t.Error(op+":", err, "contains another os.PathError") 109 } 110 } 111 112 func TestMemFsRename(t *testing.T) { 113 memFs := &MemMapFs{} 114 115 const ( 116 oldPath = "/old" 117 newPath = "/new" 118 fileName = "afero.txt" 119 subDirName = "subdir" 120 subDirFileName = "subafero.txt" 121 ) 122 err := memFs.Mkdir(oldPath, 0700) 123 if err != nil { 124 t.Fatal(err) 125 } 126 oldFilePath := filepath.Join(oldPath, fileName) 127 _, err = memFs.Create(oldFilePath) 128 if err != nil { 129 t.Fatal(err) 130 } 131 oldSubDirPath := filepath.Join(oldPath, subDirName) 132 err = memFs.Mkdir(oldSubDirPath, 0700) 133 if err != nil { 134 t.Fatal(err) 135 } 136 oldSubDirFilePath := filepath.Join(oldPath, subDirName, subDirFileName) 137 _, err = memFs.Create(oldSubDirFilePath) 138 if err != nil { 139 t.Fatal(err) 140 } 141 142 err = memFs.Rename(oldPath, newPath) 143 if err != nil { 144 t.Fatal(err) 145 } 146 fmt.Println("MemFs contents:") 147 memFs.List() 148 fmt.Println() 149 150 newFilePath := filepath.Join(newPath, fileName) 151 newSubDirFilePath := filepath.Join(newPath, subDirName, subDirFileName) 152 _, err = memFs.Stat(newFilePath) 153 if err != nil { 154 t.Errorf("File should exist in new directory %q but received error: %s", newFilePath, err) 155 } 156 _, err = memFs.Stat(newSubDirFilePath) 157 if err != nil { 158 t.Errorf("File should exist in new sub directory %q but received error: %s", newSubDirFilePath, err) 159 } 160 161 _, err = memFs.Stat(oldFilePath) 162 if err == nil { 163 t.Errorf("File should not exist in old directory %q", oldFilePath) 164 } 165 _, err = memFs.Stat(oldSubDirFilePath) 166 if err == nil { 167 t.Errorf("File should not exist in old sub directory %q", oldSubDirFilePath) 168 } 169 } 170 171 // Ensure os.O_EXCL is correctly handled. 172 func TestOpenFileExcl(t *testing.T) { 173 const fileName = "/myFileTest" 174 const fileMode = os.FileMode(0765) 175 176 fs := NewMemMapFs() 177 178 // First creation should succeed. 179 f, err := fs.OpenFile(fileName, os.O_CREATE|os.O_EXCL, fileMode) 180 if err != nil { 181 t.Errorf("OpenFile Create Excl failed: %s", err) 182 return 183 } 184 f.Close() 185 186 // Second creation should fail. 187 _, err = fs.OpenFile(fileName, os.O_CREATE|os.O_EXCL, fileMode) 188 if err == nil { 189 t.Errorf("OpenFile Create Excl should have failed, but it didn't") 190 } 191 checkPathError(t, err, "Open") 192 } 193 194 // Ensure Permissions are set on OpenFile/Mkdir/MkdirAll 195 func TestPermSet(t *testing.T) { 196 const fileName = "/myFileTest" 197 const dirPath = "/myDirTest" 198 const dirPathAll = "/my/path/to/dir" 199 200 const fileMode = os.FileMode(0765) 201 // directories will also have the directory bit set 202 const dirMode = fileMode | os.ModeDir 203 204 fs := NewMemMapFs() 205 206 // Test Openfile 207 f, err := fs.OpenFile(fileName, os.O_CREATE, fileMode) 208 if err != nil { 209 t.Errorf("OpenFile Create failed: %s", err) 210 return 211 } 212 f.Close() 213 214 s, err := fs.Stat(fileName) 215 if err != nil { 216 t.Errorf("Stat failed: %s", err) 217 return 218 } 219 if s.Mode().String() != fileMode.String() { 220 t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), fileMode.String()) 221 return 222 } 223 224 // Test Mkdir 225 err = fs.Mkdir(dirPath, dirMode) 226 if err != nil { 227 t.Errorf("MkDir Create failed: %s", err) 228 return 229 } 230 s, err = fs.Stat(dirPath) 231 if err != nil { 232 t.Errorf("Stat failed: %s", err) 233 return 234 } 235 // sets File 236 if s.Mode().String() != dirMode.String() { 237 t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String()) 238 return 239 } 240 241 // Test MkdirAll 242 err = fs.MkdirAll(dirPathAll, dirMode) 243 if err != nil { 244 t.Errorf("MkDir Create failed: %s", err) 245 return 246 } 247 s, err = fs.Stat(dirPathAll) 248 if err != nil { 249 t.Errorf("Stat failed: %s", err) 250 return 251 } 252 if s.Mode().String() != dirMode.String() { 253 t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String()) 254 return 255 } 256 } 257 258 // Fails if multiple file objects use the same file.at counter in MemMapFs 259 func TestMultipleOpenFiles(t *testing.T) { 260 defer removeAllTestFiles(t) 261 const fileName = "afero-demo2.txt" 262 263 var data = make([][]byte, len(Fss)) 264 265 for i, fs := range Fss { 266 dir := testDir(fs) 267 path := filepath.Join(dir, fileName) 268 fh1, err := fs.Create(path) 269 if err != nil { 270 t.Error("fs.Create failed: " + err.Error()) 271 } 272 _, err = fh1.Write([]byte("test")) 273 if err != nil { 274 t.Error("fh.Write failed: " + err.Error()) 275 } 276 _, err = fh1.Seek(0, os.SEEK_SET) 277 if err != nil { 278 t.Error(err) 279 } 280 281 fh2, err := fs.OpenFile(path, os.O_RDWR, 0777) 282 if err != nil { 283 t.Error("fs.OpenFile failed: " + err.Error()) 284 } 285 _, err = fh2.Seek(0, os.SEEK_END) 286 if err != nil { 287 t.Error(err) 288 } 289 _, err = fh2.Write([]byte("data")) 290 if err != nil { 291 t.Error(err) 292 } 293 err = fh2.Close() 294 if err != nil { 295 t.Error(err) 296 } 297 298 _, err = fh1.Write([]byte("data")) 299 if err != nil { 300 t.Error(err) 301 } 302 err = fh1.Close() 303 if err != nil { 304 t.Error(err) 305 } 306 // the file now should contain "datadata" 307 data[i], err = ReadFile(fs, path) 308 if err != nil { 309 t.Error(err) 310 } 311 } 312 313 for i, fs := range Fss { 314 if i == 0 { 315 continue 316 } 317 if string(data[0]) != string(data[i]) { 318 t.Errorf("%s and %s don't behave the same\n"+ 319 "%s: \"%s\"\n%s: \"%s\"\n", 320 Fss[0].Name(), fs.Name(), Fss[0].Name(), data[0], fs.Name(), data[i]) 321 } 322 } 323 } 324 325 // Test if file.Write() fails when opened as read only 326 func TestReadOnly(t *testing.T) { 327 defer removeAllTestFiles(t) 328 const fileName = "afero-demo.txt" 329 330 for _, fs := range Fss { 331 dir := testDir(fs) 332 path := filepath.Join(dir, fileName) 333 334 f, err := fs.Create(path) 335 if err != nil { 336 t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) 337 } 338 _, err = f.Write([]byte("test")) 339 if err != nil { 340 t.Error(fs.Name()+":", "Write failed: "+err.Error()) 341 } 342 f.Close() 343 344 f, err = fs.Open(path) 345 if err != nil { 346 t.Error("fs.Open failed: " + err.Error()) 347 } 348 _, err = f.Write([]byte("data")) 349 if err == nil { 350 t.Error(fs.Name()+":", "No write error") 351 } 352 f.Close() 353 354 f, err = fs.OpenFile(path, os.O_RDONLY, 0644) 355 if err != nil { 356 t.Error("fs.Open failed: " + err.Error()) 357 } 358 _, err = f.Write([]byte("data")) 359 if err == nil { 360 t.Error(fs.Name()+":", "No write error") 361 } 362 f.Close() 363 } 364 } 365 366 func TestWriteCloseTime(t *testing.T) { 367 defer removeAllTestFiles(t) 368 const fileName = "afero-demo.txt" 369 370 for _, fs := range Fss { 371 dir := testDir(fs) 372 path := filepath.Join(dir, fileName) 373 374 f, err := fs.Create(path) 375 if err != nil { 376 t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) 377 } 378 f.Close() 379 380 f, err = fs.Create(path) 381 if err != nil { 382 t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) 383 } 384 fi, err := f.Stat() 385 if err != nil { 386 t.Error(fs.Name()+":", "Stat failed: "+err.Error()) 387 } 388 timeBefore := fi.ModTime() 389 390 // sorry for the delay, but we have to make sure time advances, 391 // also on non Un*x systems... 392 switch runtime.GOOS { 393 case "windows": 394 time.Sleep(2 * time.Second) 395 case "darwin": 396 time.Sleep(1 * time.Second) 397 default: // depending on the FS, this may work with < 1 second, on my old ext3 it does not 398 time.Sleep(1 * time.Second) 399 } 400 401 _, err = f.Write([]byte("test")) 402 if err != nil { 403 t.Error(fs.Name()+":", "Write failed: "+err.Error()) 404 } 405 f.Close() 406 fi, err = fs.Stat(path) 407 if err != nil { 408 t.Error(fs.Name()+":", "fs.Stat failed: "+err.Error()) 409 } 410 if fi.ModTime().Equal(timeBefore) { 411 t.Error(fs.Name()+":", "ModTime was not set on Close()") 412 } 413 } 414 } 415 416 // This test should be run with the race detector on: 417 // go test -race -v -timeout 10s -run TestRacingDeleteAndClose 418 func TestRacingDeleteAndClose(t *testing.T) { 419 fs := NewMemMapFs() 420 pathname := "testfile" 421 f, err := fs.Create(pathname) 422 if err != nil { 423 t.Fatal(err) 424 } 425 426 in := make(chan bool) 427 428 go func() { 429 <-in 430 f.Close() 431 }() 432 go func() { 433 <-in 434 fs.Remove(pathname) 435 }() 436 close(in) 437 } 438 439 // This test should be run with the race detector on: 440 // go test -run TestMemFsDataRace -race 441 func TestMemFsDataRace(t *testing.T) { 442 const dir = "test_dir" 443 fs := NewMemMapFs() 444 445 if err := fs.MkdirAll(dir, 0777); err != nil { 446 t.Fatal(err) 447 } 448 449 const n = 1000 450 done := make(chan struct{}) 451 452 go func() { 453 defer close(done) 454 for i := 0; i < n; i++ { 455 fname := filepath.Join(dir, fmt.Sprintf("%d.txt", i)) 456 if err := WriteFile(fs, fname, []byte(""), 0777); err != nil { 457 panic(err) 458 } 459 if err := fs.Remove(fname); err != nil { 460 panic(err) 461 } 462 } 463 }() 464 465 loop: 466 for { 467 select { 468 case <-done: 469 break loop 470 default: 471 _, err := ReadDir(fs, dir) 472 if err != nil { 473 t.Fatal(err) 474 } 475 } 476 } 477 } 478 479 // root is a directory 480 func TestMemFsRootDirMode(t *testing.T) { 481 t.Parallel() 482 483 fs := NewMemMapFs() 484 info, err := fs.Stat("/") 485 if err != nil { 486 t.Fatal(err) 487 } 488 if !info.IsDir() { 489 t.Error("should be a directory") 490 } 491 if !info.Mode().IsDir() { 492 t.Errorf("FileMode is not directory, is %s", info.Mode().String()) 493 } 494 } 495 496 // MkdirAll creates intermediate directories with correct mode 497 func TestMemFsMkdirAllMode(t *testing.T) { 498 t.Parallel() 499 500 fs := NewMemMapFs() 501 err := fs.MkdirAll("/a/b/c", 0755) 502 if err != nil { 503 t.Fatal(err) 504 } 505 info, err := fs.Stat("/a") 506 if err != nil { 507 t.Fatal(err) 508 } 509 if !info.Mode().IsDir() { 510 t.Error("/a: mode is not directory") 511 } 512 if info.Mode() != os.FileMode(os.ModeDir|0755) { 513 t.Errorf("/a: wrong permissions, expected drwxr-xr-x, got %s", info.Mode()) 514 } 515 info, err = fs.Stat("/a/b") 516 if err != nil { 517 t.Fatal(err) 518 } 519 if !info.Mode().IsDir() { 520 t.Error("/a/b: mode is not directory") 521 } 522 if info.Mode() != os.FileMode(os.ModeDir|0755) { 523 t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode()) 524 } 525 info, err = fs.Stat("/a/b/c") 526 if err != nil { 527 t.Fatal(err) 528 } 529 if !info.Mode().IsDir() { 530 t.Error("/a/b/c: mode is not directory") 531 } 532 if info.Mode() != os.FileMode(os.ModeDir|0755) { 533 t.Errorf("/a/b/c: wrong permissions, expected drwxr-xr-x, got %s", info.Mode()) 534 } 535 } 536 537 // MkdirAll does not change permissions of already-existing directories 538 func TestMemFsMkdirAllNoClobber(t *testing.T) { 539 t.Parallel() 540 541 fs := NewMemMapFs() 542 err := fs.MkdirAll("/a/b/c", 0755) 543 if err != nil { 544 t.Fatal(err) 545 } 546 info, err := fs.Stat("/a/b") 547 if err != nil { 548 t.Fatal(err) 549 } 550 if info.Mode() != os.FileMode(os.ModeDir|0755) { 551 t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode()) 552 } 553 err = fs.MkdirAll("/a/b/c/d/e/f", 0710) 554 // '/a/b' is unchanged 555 if err != nil { 556 t.Fatal(err) 557 } 558 info, err = fs.Stat("/a/b") 559 if err != nil { 560 t.Fatal(err) 561 } 562 if info.Mode() != os.FileMode(os.ModeDir|0755) { 563 t.Errorf("/a/b: wrong permissions, expected drwxr-xr-x, got %s", info.Mode()) 564 } 565 // new directories created with proper permissions 566 info, err = fs.Stat("/a/b/c/d") 567 if err != nil { 568 t.Fatal(err) 569 } 570 if info.Mode() != os.FileMode(os.ModeDir|0710) { 571 t.Errorf("/a/b/c/d: wrong permissions, expected drwx--x---, got %s", info.Mode()) 572 } 573 info, err = fs.Stat("/a/b/c/d/e") 574 if err != nil { 575 t.Fatal(err) 576 } 577 if info.Mode() != os.FileMode(os.ModeDir|0710) { 578 t.Errorf("/a/b/c/d/e: wrong permissions, expected drwx--x---, got %s", info.Mode()) 579 } 580 info, err = fs.Stat("/a/b/c/d/e/f") 581 if err != nil { 582 t.Fatal(err) 583 } 584 if info.Mode() != os.FileMode(os.ModeDir|0710) { 585 t.Errorf("/a/b/c/d/e/f: wrong permissions, expected drwx--x---, got %s", info.Mode()) 586 } 587 } 588 589 func TestMemFsDirMode(t *testing.T) { 590 fs := NewMemMapFs() 591 err := fs.Mkdir("/testDir1", 0644) 592 if err != nil { 593 t.Error(err) 594 } 595 err = fs.MkdirAll("/sub/testDir2", 0644) 596 if err != nil { 597 t.Error(err) 598 } 599 info, err := fs.Stat("/testDir1") 600 if err != nil { 601 t.Error(err) 602 } 603 if !info.IsDir() { 604 t.Error("should be a directory") 605 } 606 if !info.Mode().IsDir() { 607 t.Error("FileMode is not directory") 608 } 609 info, err = fs.Stat("/sub/testDir2") 610 if err != nil { 611 t.Error(err) 612 } 613 if !info.IsDir() { 614 t.Error("should be a directory") 615 } 616 if !info.Mode().IsDir() { 617 t.Error("FileMode is not directory") 618 } 619 } 620 621 func TestMemFsUnexpectedEOF(t *testing.T) { 622 t.Parallel() 623 624 fs := NewMemMapFs() 625 626 if err := WriteFile(fs, "file.txt", []byte("abc"), 0777); err != nil { 627 t.Fatal(err) 628 } 629 630 f, err := fs.Open("file.txt") 631 if err != nil { 632 t.Fatal(err) 633 } 634 defer f.Close() 635 636 // Seek beyond the end. 637 _, err = f.Seek(512, 0) 638 if err != nil { 639 t.Fatal(err) 640 } 641 642 buff := make([]byte, 256) 643 _, err = io.ReadAtLeast(f, buff, 256) 644 645 if err != io.ErrUnexpectedEOF { 646 t.Fatal("Expected ErrUnexpectedEOF") 647 } 648 } 649 650 func TestMemFsChmod(t *testing.T) { 651 t.Parallel() 652 653 fs := NewMemMapFs() 654 const file = "hello" 655 if err := fs.Mkdir(file, 0700); err != nil { 656 t.Fatal(err) 657 } 658 659 info, err := fs.Stat(file) 660 if err != nil { 661 t.Fatal(err) 662 } 663 if info.Mode().String() != "drwx------" { 664 t.Fatal("mkdir failed to create a directory: mode =", info.Mode()) 665 } 666 667 err = fs.Chmod(file, 0) 668 if err != nil { 669 t.Error("Failed to run chmod:", err) 670 } 671 672 info, err = fs.Stat(file) 673 if err != nil { 674 t.Fatal(err) 675 } 676 if info.Mode().String() != "d---------" { 677 t.Error("chmod should not change file type. New mode =", info.Mode()) 678 } 679 } 680 681 // can't use Mkdir to get around which permissions we're allowed to set 682 func TestMemFsMkdirModeIllegal(t *testing.T) { 683 t.Parallel() 684 685 fs := NewMemMapFs() 686 err := fs.Mkdir("/a", os.ModeSocket|0755) 687 if err != nil { 688 t.Fatal(err) 689 } 690 info, err := fs.Stat("/a") 691 if err != nil { 692 t.Fatal(err) 693 } 694 if info.Mode() != os.FileMode(os.ModeDir|0755) { 695 t.Fatalf("should not be able to use Mkdir to set illegal mode: %s", info.Mode().String()) 696 } 697 } 698 699 // can't use OpenFile to get around which permissions we're allowed to set 700 func TestMemFsOpenFileModeIllegal(t *testing.T) { 701 t.Parallel() 702 703 fs := NewMemMapFs() 704 file, err := fs.OpenFile("/a", os.O_CREATE, os.ModeSymlink|0644) 705 if err != nil { 706 t.Fatal(err) 707 } 708 defer file.Close() 709 info, err := fs.Stat("/a") 710 if err != nil { 711 t.Fatal(err) 712 } 713 if info.Mode() != os.FileMode(0644) { 714 t.Fatalf("should not be able to use OpenFile to set illegal mode: %s", info.Mode().String()) 715 } 716 } 717 718 // LstatIfPossible should always return false, since MemMapFs does not 719 // support symlinks. 720 func TestMemFsLstatIfPossible(t *testing.T) { 721 t.Parallel() 722 723 fs := NewMemMapFs() 724 725 // We assert that fs implements Lstater 726 fsAsserted, ok := fs.(Lstater) 727 if !ok { 728 t.Fatalf("The filesytem does not implement Lstater") 729 } 730 731 file, err := fs.OpenFile("/a.txt", os.O_CREATE, 0o644) 732 if err != nil { 733 t.Fatalf("Error when opening file: %v", err) 734 } 735 defer file.Close() 736 737 _, lstatCalled, err := fsAsserted.LstatIfPossible("/a.txt") 738 if err != nil { 739 t.Fatalf("Function returned err: %v", err) 740 } 741 if lstatCalled { 742 t.Fatalf("Function indicated lstat was called. This should never be true.") 743 } 744 }