github.com/urjitbhatia/afero@v1.1.0/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 type myFileInfo []os.FileInfo 574 575 func (m myFileInfo) String() string { 576 out := "Fileinfos:\n" 577 for _, e := range m { 578 out += " " + e.Name() + "\n" 579 } 580 return out 581 } 582 583 func TestReaddirAll(t *testing.T) { 584 defer removeAllTestFiles(t) 585 for _, fs := range Fss { 586 testSubDir := setupTestDir(t, fs) 587 tDir := filepath.Dir(testSubDir) 588 589 root, err := fs.Open(tDir) 590 if err != nil { 591 t.Fatal(err) 592 } 593 defer root.Close() 594 595 rootInfo, err := root.Readdir(-1) 596 if err != nil { 597 t.Fatal(err) 598 } 599 var namesRoot = []string{} 600 for _, e := range rootInfo { 601 namesRoot = append(namesRoot, e.Name()) 602 } 603 604 sub, err := fs.Open(testSubDir) 605 if err != nil { 606 t.Fatal(err) 607 } 608 defer sub.Close() 609 610 subInfo, err := sub.Readdir(-1) 611 if err != nil { 612 t.Fatal(err) 613 } 614 var namesSub = []string{} 615 for _, e := range subInfo { 616 namesSub = append(namesSub, e.Name()) 617 } 618 619 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub) 620 } 621 } 622 623 func findNames(fs Fs, t *testing.T, tDir, testSubDir string, root, sub []string) { 624 var foundRoot bool 625 for _, e := range root { 626 f, err := fs.Open(filepath.Join(tDir, e)) 627 if err != nil { 628 t.Error("Open", filepath.Join(tDir, e), ":", err) 629 } 630 defer f.Close() 631 632 if equal(e, "we") { 633 foundRoot = true 634 } 635 } 636 if !foundRoot { 637 t.Logf("Names root: %v", root) 638 t.Logf("Names sub: %v", sub) 639 t.Error("Didn't find subdirectory we") 640 } 641 642 var found1, found2 bool 643 for _, e := range sub { 644 f, err := fs.Open(filepath.Join(testSubDir, e)) 645 if err != nil { 646 t.Error("Open", filepath.Join(testSubDir, e), ":", err) 647 } 648 defer f.Close() 649 650 if equal(e, "testfile1") { 651 found1 = true 652 } 653 if equal(e, "testfile2") { 654 found2 = true 655 } 656 } 657 658 if !found1 { 659 t.Logf("Names root: %v", root) 660 t.Logf("Names sub: %v", sub) 661 t.Error("Didn't find testfile1") 662 } 663 if !found2 { 664 t.Logf("Names root: %v", root) 665 t.Logf("Names sub: %v", sub) 666 t.Error("Didn't find testfile2") 667 } 668 } 669 670 func removeAllTestFiles(t *testing.T) { 671 for fs, list := range testRegistry { 672 for _, path := range list { 673 if err := fs.RemoveAll(path); err != nil { 674 t.Error(fs.Name(), err) 675 } 676 } 677 } 678 testRegistry = make(map[Fs][]string) 679 } 680 681 func equal(name1, name2 string) (r bool) { 682 switch runtime.GOOS { 683 case "windows": 684 r = strings.ToLower(name1) == strings.ToLower(name2) 685 default: 686 r = name1 == name2 687 } 688 return 689 } 690 691 func checkSize(t *testing.T, f File, size int64) { 692 dir, err := f.Stat() 693 if err != nil { 694 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err) 695 } 696 if dir.Size() != size { 697 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size) 698 } 699 }