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