github.com/bpfs/defs@v0.0.15/afero/afero_test.go (about) 1 // Copyright © 2014 Steve Francia <spf@spf13.com>. 2 // Copyright 2009 The Go Authors. All rights reserved. 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 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package afero 16 17 import ( 18 "bytes" 19 "fmt" 20 "io" 21 iofs "io/fs" 22 "os" 23 "path/filepath" 24 "runtime" 25 "strings" 26 "syscall" 27 "testing" 28 ) 29 30 var ( 31 testName = "test.txt" 32 Fss = []Fs{&MemMapFs{}, &OsFs{}} 33 ) 34 35 var testRegistry map[Fs][]string = make(map[Fs][]string) 36 37 func testDir(fs Fs) string { 38 name, err := TempDir(fs, "", "afero") 39 if err != nil { 40 panic(fmt.Sprint("unable to work with test dir", err)) 41 } 42 testRegistry[fs] = append(testRegistry[fs], name) 43 44 return name 45 } 46 47 func tmpFile(fs Fs) File { 48 x, err := TempFile(fs, "", "afero") 49 if err != nil { 50 panic(fmt.Sprint("unable to work with temp file", err)) 51 } 52 53 testRegistry[fs] = append(testRegistry[fs], x.Name()) 54 55 return x 56 } 57 58 // Read with length 0 should not return EOF. 59 func TestRead0(t *testing.T) { 60 for _, fs := range Fss { 61 f := tmpFile(fs) 62 defer f.Close() 63 f.WriteString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") 64 65 var b []byte 66 // b := make([]byte, 0) 67 n, err := f.Read(b) 68 if n != 0 || err != nil { 69 t.Errorf("%v: Read(0) = %d, %v, want 0, nil", fs.Name(), n, err) 70 } 71 f.Seek(0, 0) 72 b = make([]byte, 100) 73 n, err = f.Read(b) 74 if n <= 0 || err != nil { 75 t.Errorf("%v: Read(100) = %d, %v, want >0, nil", fs.Name(), n, err) 76 } 77 } 78 } 79 80 func TestOpenFile(t *testing.T) { 81 defer removeAllTestFiles(t) 82 for _, fs := range Fss { 83 tmp := testDir(fs) 84 path := filepath.Join(tmp, testName) 85 86 f, err := fs.OpenFile(path, os.O_RDWR|os.O_CREATE, 0o600) 87 if err != nil { 88 t.Error(fs.Name(), "OpenFile (O_CREATE) failed:", err) 89 continue 90 } 91 io.WriteString(f, "initial") 92 f.Close() 93 94 f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0o600) 95 if err != nil { 96 t.Error(fs.Name(), "OpenFile (O_APPEND) failed:", err) 97 continue 98 } 99 io.WriteString(f, "|append") 100 f.Close() 101 102 f, _ = fs.OpenFile(path, os.O_RDONLY, 0o600) 103 contents, _ := io.ReadAll(f) 104 expectedContents := "initial|append" 105 if string(contents) != expectedContents { 106 t.Errorf("%v: appending, expected '%v', got: '%v'", fs.Name(), expectedContents, string(contents)) 107 } 108 f.Close() 109 110 f, err = fs.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o600) 111 if err != nil { 112 t.Error(fs.Name(), "OpenFile (O_TRUNC) failed:", err) 113 continue 114 } 115 contents, _ = io.ReadAll(f) 116 if string(contents) != "" { 117 t.Errorf("%v: expected truncated file, got: '%v'", fs.Name(), string(contents)) 118 } 119 f.Close() 120 } 121 } 122 123 func TestCreate(t *testing.T) { 124 defer removeAllTestFiles(t) 125 for _, fs := range Fss { 126 tmp := testDir(fs) 127 path := filepath.Join(tmp, testName) 128 129 f, err := fs.Create(path) 130 if err != nil { 131 t.Error(fs.Name(), "Create failed:", err) 132 f.Close() 133 continue 134 } 135 io.WriteString(f, "initial") 136 f.Close() 137 138 f, err = fs.Create(path) 139 if err != nil { 140 t.Error(fs.Name(), "Create failed:", err) 141 f.Close() 142 continue 143 } 144 secondContent := "second create" 145 io.WriteString(f, secondContent) 146 f.Close() 147 148 f, err = fs.Open(path) 149 if err != nil { 150 t.Error(fs.Name(), "Open failed:", err) 151 f.Close() 152 continue 153 } 154 buf, err := ReadAll(f) 155 if err != nil { 156 t.Error(fs.Name(), "ReadAll failed:", err) 157 f.Close() 158 continue 159 } 160 if string(buf) != secondContent { 161 t.Error(fs.Name(), "Content should be", "\""+secondContent+"\" but is \""+string(buf)+"\"") 162 f.Close() 163 continue 164 } 165 f.Close() 166 } 167 } 168 169 func TestMemFileRead(t *testing.T) { 170 f := tmpFile(new(MemMapFs)) 171 // f := MemFileCreate("testfile") 172 f.WriteString("abcd") 173 f.Seek(0, 0) 174 b := make([]byte, 8) 175 n, err := f.Read(b) 176 if n != 4 { 177 t.Errorf("didn't read all bytes: %v %v %v", n, err, b) 178 } 179 if err != nil { 180 t.Errorf("err is not nil: %v %v %v", n, err, b) 181 } 182 n, err = f.Read(b) 183 if n != 0 { 184 t.Errorf("read more bytes: %v %v %v", n, err, b) 185 } 186 if err != io.EOF { 187 t.Errorf("error is not EOF: %v %v %v", n, err, b) 188 } 189 } 190 191 func TestRename(t *testing.T) { 192 defer removeAllTestFiles(t) 193 for _, fs := range Fss { 194 tDir := testDir(fs) 195 from := filepath.Join(tDir, "/renamefrom") 196 to := filepath.Join(tDir, "/renameto") 197 exists := filepath.Join(tDir, "/renameexists") 198 file, err := fs.Create(from) 199 if err != nil { 200 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err) 201 } 202 if err = file.Close(); err != nil { 203 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err) 204 } 205 file, err = fs.Create(exists) 206 if err != nil { 207 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err) 208 } 209 if err = file.Close(); err != nil { 210 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err) 211 } 212 err = fs.Rename(from, to) 213 if err != nil { 214 t.Fatalf("%s: rename %q, %q failed: %v", fs.Name(), to, from, err) 215 } 216 file, err = fs.Create(from) 217 if err != nil { 218 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err) 219 } 220 if err = file.Close(); err != nil { 221 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err) 222 } 223 err = fs.Rename(from, exists) 224 if err != nil { 225 t.Errorf("%s: rename %q, %q failed: %v", fs.Name(), exists, from, err) 226 } 227 names, err := readDirNames(fs, tDir) 228 if err != nil { 229 t.Errorf("%s: readDirNames error: %v", fs.Name(), err) 230 } 231 found := false 232 for _, e := range names { 233 if e == "renamefrom" { 234 t.Error("File is still called renamefrom") 235 } 236 if e == "renameto" { 237 found = true 238 } 239 } 240 if !found { 241 t.Error("File was not renamed to renameto") 242 } 243 244 _, err = fs.Stat(to) 245 if err != nil { 246 t.Errorf("%s: stat %q failed: %v", fs.Name(), to, err) 247 } 248 } 249 } 250 251 func TestRemove(t *testing.T) { 252 for _, fs := range Fss { 253 254 x, err := TempFile(fs, "", "afero") 255 if err != nil { 256 t.Error(fmt.Sprint("unable to work with temp file", err)) 257 } 258 259 path := x.Name() 260 x.Close() 261 262 tDir := filepath.Dir(path) 263 264 err = fs.Remove(path) 265 if err != nil { 266 t.Errorf("%v: Remove() failed: %v", fs.Name(), err) 267 continue 268 } 269 270 _, err = fs.Stat(path) 271 if !os.IsNotExist(err) { 272 t.Errorf("%v: Remove() didn't remove file", fs.Name()) 273 continue 274 } 275 276 // Deleting non-existent file should raise error 277 err = fs.Remove(path) 278 if !os.IsNotExist(err) { 279 t.Errorf("%v: Remove() didn't raise error for non-existent file", fs.Name()) 280 } 281 282 f, err := fs.Open(tDir) 283 if err != nil { 284 t.Error("TestDir should still exist:", err) 285 } 286 287 names, err := f.Readdirnames(-1) 288 if err != nil { 289 t.Error("Readdirnames failed:", err) 290 } 291 292 for _, e := range names { 293 if e == testName { 294 t.Error("File was not removed from parent directory") 295 } 296 } 297 } 298 } 299 300 func TestTruncate(t *testing.T) { 301 defer removeAllTestFiles(t) 302 for _, fs := range Fss { 303 f := tmpFile(fs) 304 defer f.Close() 305 306 checkSize(t, f, 0) 307 f.Write([]byte("hello, world\n")) 308 checkSize(t, f, 13) 309 f.Truncate(10) 310 checkSize(t, f, 10) 311 f.Truncate(1024) 312 checkSize(t, f, 1024) 313 f.Truncate(0) 314 checkSize(t, f, 0) 315 _, err := f.Write([]byte("surprise!")) 316 if err == nil { 317 checkSize(t, f, 13+9) // wrote at offset past where hello, world was. 318 } 319 } 320 } 321 322 func TestSeek(t *testing.T) { 323 defer removeAllTestFiles(t) 324 for _, fs := range Fss { 325 f := tmpFile(fs) 326 defer f.Close() 327 328 const data = "hello, world\n" 329 io.WriteString(f, data) 330 331 type test struct { 332 in int64 333 whence int 334 out int64 335 } 336 tests := []test{ 337 {0, 1, int64(len(data))}, 338 {0, 0, 0}, 339 {5, 0, 5}, 340 {0, 2, int64(len(data))}, 341 {0, 0, 0}, 342 {-1, 2, int64(len(data)) - 1}, 343 {1 << 33, 0, 1 << 33}, 344 {1 << 33, 2, 1<<33 + int64(len(data))}, 345 } 346 for i, tt := range tests { 347 off, err := f.Seek(tt.in, tt.whence) 348 if off != tt.out || err != nil { 349 if e, ok := err.(*os.PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 { 350 // Reiserfs rejects the big seeks. 351 // http://code.google.com/p/go/issues/detail?id=91 352 break 353 } 354 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out) 355 } 356 } 357 } 358 } 359 360 func TestReadAt(t *testing.T) { 361 defer removeAllTestFiles(t) 362 for _, fs := range Fss { 363 f := tmpFile(fs) 364 defer f.Close() 365 366 const data = "hello, world\n" 367 io.WriteString(f, data) 368 369 b := make([]byte, 5) 370 n, err := f.ReadAt(b, 7) 371 if err != nil || n != len(b) { 372 t.Fatalf("ReadAt 7: %d, %v", n, err) 373 } 374 if string(b) != "world" { 375 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world") 376 } 377 } 378 } 379 380 func TestWriteAt(t *testing.T) { 381 defer removeAllTestFiles(t) 382 for _, fs := range Fss { 383 f := tmpFile(fs) 384 defer f.Close() 385 386 const data = "hello, world\n" 387 io.WriteString(f, data) 388 389 n, err := f.WriteAt([]byte("WORLD"), 7) 390 if err != nil || n != 5 { 391 t.Fatalf("WriteAt 7: %d, %v", n, err) 392 } 393 394 f2, err := fs.Open(f.Name()) 395 if err != nil { 396 t.Fatalf("%v: ReadFile %s: %v", fs.Name(), f.Name(), err) 397 } 398 defer f2.Close() 399 buf := new(bytes.Buffer) 400 buf.ReadFrom(f2) 401 b := buf.Bytes() 402 if string(b) != "hello, WORLD\n" { 403 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n") 404 } 405 406 } 407 } 408 409 func setupTestDir(t *testing.T, fs Fs) string { 410 path := testDir(fs) 411 return setupTestFiles(t, fs, path) 412 } 413 414 func setupTestDirRoot(t *testing.T, fs Fs) string { 415 path := testDir(fs) 416 setupTestFiles(t, fs, path) 417 return path 418 } 419 420 func setupTestDirReusePath(t *testing.T, fs Fs, path string) string { 421 testRegistry[fs] = append(testRegistry[fs], path) 422 return setupTestFiles(t, fs, path) 423 } 424 425 func setupTestFiles(t *testing.T, fs Fs, path string) string { 426 testSubDir := filepath.Join(path, "more", "subdirectories", "for", "testing", "we") 427 err := fs.MkdirAll(testSubDir, 0o700) 428 if err != nil && !os.IsExist(err) { 429 t.Fatal(err) 430 } 431 432 f, err := fs.Create(filepath.Join(testSubDir, "testfile1")) 433 if err != nil { 434 t.Fatal(err) 435 } 436 f.WriteString("Testfile 1 content") 437 f.Close() 438 439 f, err = fs.Create(filepath.Join(testSubDir, "testfile2")) 440 if err != nil { 441 t.Fatal(err) 442 } 443 f.WriteString("Testfile 2 content") 444 f.Close() 445 446 f, err = fs.Create(filepath.Join(testSubDir, "testfile3")) 447 if err != nil { 448 t.Fatal(err) 449 } 450 f.WriteString("Testfile 3 content") 451 f.Close() 452 453 f, err = fs.Create(filepath.Join(testSubDir, "testfile4")) 454 if err != nil { 455 t.Fatal(err) 456 } 457 f.WriteString("Testfile 4 content") 458 f.Close() 459 return testSubDir 460 } 461 462 func TestReaddirnames(t *testing.T) { 463 defer removeAllTestFiles(t) 464 for _, fs := range Fss { 465 testSubDir := setupTestDir(t, fs) 466 tDir := filepath.Dir(testSubDir) 467 468 root, err := fs.Open(tDir) 469 if err != nil { 470 t.Fatal(fs.Name(), tDir, err) 471 } 472 defer root.Close() 473 474 namesRoot, err := root.Readdirnames(-1) 475 if err != nil { 476 t.Fatal(fs.Name(), namesRoot, err) 477 } 478 479 sub, err := fs.Open(testSubDir) 480 if err != nil { 481 t.Fatal(err) 482 } 483 defer sub.Close() 484 485 namesSub, err := sub.Readdirnames(-1) 486 if err != nil { 487 t.Fatal(fs.Name(), namesSub, err) 488 } 489 490 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub) 491 } 492 } 493 494 func TestReaddirSimple(t *testing.T) { 495 defer removeAllTestFiles(t) 496 for _, fs := range Fss { 497 testSubDir := setupTestDir(t, fs) 498 tDir := filepath.Dir(testSubDir) 499 500 root, err := fs.Open(tDir) 501 if err != nil { 502 t.Fatal(err) 503 } 504 defer root.Close() 505 506 rootInfo, err := root.Readdir(1) 507 if err != nil { 508 t.Log(myFileInfo(rootInfo)) 509 t.Error(err) 510 } 511 512 rootInfo, err = root.Readdir(5) 513 if err != io.EOF { 514 t.Log(myFileInfo(rootInfo)) 515 t.Error(err) 516 } 517 518 sub, err := fs.Open(testSubDir) 519 if err != nil { 520 t.Fatal(err) 521 } 522 defer sub.Close() 523 524 subInfo, err := sub.Readdir(5) 525 if err != nil { 526 t.Log(myFileInfo(subInfo)) 527 t.Error(err) 528 } 529 } 530 } 531 532 func TestReaddir(t *testing.T) { 533 defer removeAllTestFiles(t) 534 const nums = 6 535 for num := 0; num < nums; num++ { 536 outputs := make([]string, len(Fss)) 537 infos := make([]string, len(Fss)) 538 for i, fs := range Fss { 539 testSubDir := setupTestDir(t, fs) 540 root, err := fs.Open(testSubDir) 541 if err != nil { 542 t.Fatal(err) 543 } 544 545 infosn := make([]string, nums) 546 547 for j := 0; j < nums; j++ { 548 info, err := root.Readdir(num) 549 outputs[i] += fmt.Sprintf("%v Error: %v\n", myFileInfo(info), err) 550 s := fmt.Sprintln(len(info), err) 551 infosn[j] = s 552 infos[i] += s 553 } 554 root.Close() 555 556 // Also check fs.ReadDirFile interface if implemented 557 if _, ok := root.(iofs.ReadDirFile); ok { 558 root, err = fs.Open(testSubDir) 559 if err != nil { 560 t.Fatal(err) 561 } 562 defer root.Close() 563 564 for j := 0; j < nums; j++ { 565 dirEntries, err := root.(iofs.ReadDirFile).ReadDir(num) 566 s := fmt.Sprintln(len(dirEntries), err) 567 if s != infosn[j] { 568 t.Fatalf("%s: %s != %s", fs.Name(), s, infosn[j]) 569 } 570 } 571 } 572 } 573 574 fail := false 575 for i, o := range infos { 576 if i == 0 { 577 continue 578 } 579 if o != infos[i-1] { 580 fail = true 581 break 582 } 583 } 584 if fail { 585 t.Log("Readdir outputs not equal for Readdir(", num, ")") 586 for i, o := range outputs { 587 t.Log(Fss[i].Name()) 588 t.Log(o) 589 } 590 t.Fail() 591 } 592 } 593 } 594 595 func TestReaddirRegularFile(t *testing.T) { 596 defer removeAllTestFiles(t) 597 for _, fs := range Fss { 598 f := tmpFile(fs) 599 defer f.Close() 600 601 _, err := f.Readdirnames(-1) 602 if err == nil { 603 t.Fatal("Expected error") 604 } 605 606 _, err = f.Readdir(-1) 607 if err == nil { 608 t.Fatal("Expected error") 609 } 610 } 611 } 612 613 type myFileInfo []os.FileInfo 614 615 func (m myFileInfo) String() string { 616 out := "Fileinfos:\n" 617 for _, e := range m { 618 out += " " + e.Name() + "\n" 619 } 620 return out 621 } 622 623 func TestReaddirAll(t *testing.T) { 624 defer removeAllTestFiles(t) 625 for _, fs := range Fss { 626 testSubDir := setupTestDir(t, fs) 627 tDir := filepath.Dir(testSubDir) 628 629 root, err := fs.Open(tDir) 630 if err != nil { 631 t.Fatal(err) 632 } 633 defer root.Close() 634 635 rootInfo, err := root.Readdir(-1) 636 if err != nil { 637 t.Fatal(err) 638 } 639 namesRoot := []string{} 640 for _, e := range rootInfo { 641 namesRoot = append(namesRoot, e.Name()) 642 } 643 644 sub, err := fs.Open(testSubDir) 645 if err != nil { 646 t.Fatal(err) 647 } 648 defer sub.Close() 649 650 subInfo, err := sub.Readdir(-1) 651 if err != nil { 652 t.Fatal(err) 653 } 654 namesSub := []string{} 655 for _, e := range subInfo { 656 namesSub = append(namesSub, e.Name()) 657 } 658 659 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub) 660 } 661 } 662 663 func findNames(fs Fs, t *testing.T, tDir, testSubDir string, root, sub []string) { 664 var foundRoot bool 665 for _, e := range root { 666 f, err := fs.Open(filepath.Join(tDir, e)) 667 if err != nil { 668 t.Error("Open", filepath.Join(tDir, e), ":", err) 669 } 670 defer f.Close() 671 672 if equal(e, "we") { 673 foundRoot = true 674 } 675 } 676 if !foundRoot { 677 t.Logf("Names root: %v", root) 678 t.Logf("Names sub: %v", sub) 679 t.Error("Didn't find subdirectory we") 680 } 681 682 var found1, found2 bool 683 for _, e := range sub { 684 f, err := fs.Open(filepath.Join(testSubDir, e)) 685 if err != nil { 686 t.Error("Open", filepath.Join(testSubDir, e), ":", err) 687 } 688 defer f.Close() 689 690 if equal(e, "testfile1") { 691 found1 = true 692 } 693 if equal(e, "testfile2") { 694 found2 = true 695 } 696 } 697 698 if !found1 { 699 t.Logf("Names root: %v", root) 700 t.Logf("Names sub: %v", sub) 701 t.Error("Didn't find testfile1") 702 } 703 if !found2 { 704 t.Logf("Names root: %v", root) 705 t.Logf("Names sub: %v", sub) 706 t.Error("Didn't find testfile2") 707 } 708 } 709 710 func removeAllTestFiles(t *testing.T) { 711 for fs, list := range testRegistry { 712 for _, path := range list { 713 if err := fs.RemoveAll(path); err != nil { 714 t.Error(fs.Name(), err) 715 } 716 } 717 } 718 testRegistry = make(map[Fs][]string) 719 } 720 721 func equal(name1, name2 string) (r bool) { 722 switch runtime.GOOS { 723 case "windows": 724 r = strings.EqualFold(name1, name2) 725 default: 726 r = name1 == name2 727 } 728 return 729 } 730 731 func checkSize(t *testing.T, f File, size int64) { 732 dir, err := f.Stat() 733 if err != nil { 734 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err) 735 } 736 if dir.Size() != size { 737 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size) 738 } 739 }