1 // Copyright © 2014 Steve Francia <spf@spf13.com>.
2 // Copyright 2009 The Go Authors. All rights reserved.
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
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.
30 var testName = "test.txt"
31 var Fss = []Fs{&MemMapFs{}, &OsFs{}}
33 var testRegistry map[Fs][]string = make(map[Fs][]string)
35 func testDir(fs Fs) string {
36 name, err := TempDir(fs, "", "afero")
38 panic(fmt.Sprint("unable to work with test dir", err))
40 testRegistry[fs] = append(testRegistry[fs], name)
45 func tmpFile(fs Fs) File {
46 x, err := TempFile(fs, "", "afero")
49 panic(fmt.Sprint("unable to work with temp file", err))
52 testRegistry[fs] = append(testRegistry[fs], x.Name())
57 //Read with length 0 should not return EOF.
58 func TestRead0(t *testing.T) {
59 for _, fs := range Fss {
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.")
65 // b := make([]byte, 0)
67 if n != 0 || err != nil {
68 t.Errorf("%v: Read(0) = %d, %v, want 0, nil", fs.Name(), n, err)
73 if n <= 0 || err != nil {
74 t.Errorf("%v: Read(100) = %d, %v, want >0, nil", fs.Name(), n, err)
79 func TestOpenFile(t *testing.T) {
80 defer removeAllTestFiles(t)
81 for _, fs := range Fss {
83 path := filepath.Join(tmp, testName)
85 f, err := fs.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600)
87 t.Error(fs.Name(), "OpenFile (O_CREATE) failed:", err)
90 io.WriteString(f, "initial")
93 f, err = fs.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0600)
95 t.Error(fs.Name(), "OpenFile (O_APPEND) failed:", err)
98 io.WriteString(f, "|append")
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))
109 f, err = fs.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0600)
111 t.Error(fs.Name(), "OpenFile (O_TRUNC) failed:", err)
114 contents, _ = ioutil.ReadAll(f)
115 if string(contents) != "" {
116 t.Errorf("%v: expected truncated file, got: '%v'", fs.Name(), string(contents))
122 func TestCreate(t *testing.T) {
123 defer removeAllTestFiles(t)
124 for _, fs := range Fss {
126 path := filepath.Join(tmp, testName)
128 f, err := fs.Create(path)
130 t.Error(fs.Name(), "Create failed:", err)
134 io.WriteString(f, "initial")
137 f, err = fs.Create(path)
139 t.Error(fs.Name(), "Create failed:", err)
143 secondContent := "second create"
144 io.WriteString(f, secondContent)
147 f, err = fs.Open(path)
149 t.Error(fs.Name(), "Open failed:", err)
153 buf, err := ReadAll(f)
155 t.Error(fs.Name(), "ReadAll failed:", err)
159 if string(buf) != secondContent {
160 t.Error(fs.Name(), "Content should be", "\""+secondContent+"\" but is \""+string(buf)+"\"")
168 func TestMemFileRead(t *testing.T) {
169 f := tmpFile(new(MemMapFs))
170 // f := MemFileCreate("testfile")
171 f.WriteString("abcd")
176 t.Errorf("didn't read all bytes: %v %v %v", n, err, b)
179 t.Errorf("err is not nil: %v %v %v", n, err, b)
183 t.Errorf("read more bytes: %v %v %v", n, err, b)
186 t.Errorf("error is not EOF: %v %v %v", n, err, b)
190 func TestRename(t *testing.T) {
191 defer removeAllTestFiles(t)
192 for _, fs := range Fss {
194 from := filepath.Join(tDir, "/renamefrom")
195 to := filepath.Join(tDir, "/renameto")
196 exists := filepath.Join(tDir, "/renameexists")
197 file, err := fs.Create(from)
199 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
201 if err = file.Close(); err != nil {
202 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
204 file, err = fs.Create(exists)
206 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
208 if err = file.Close(); err != nil {
209 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
211 err = fs.Rename(from, to)
213 t.Fatalf("%s: rename %q, %q failed: %v", fs.Name(), to, from, err)
215 file, err = fs.Create(from)
217 t.Fatalf("%s: open %q failed: %v", fs.Name(), to, err)
219 if err = file.Close(); err != nil {
220 t.Errorf("%s: close %q failed: %v", fs.Name(), to, err)
222 err = fs.Rename(from, exists)
224 t.Errorf("%s: rename %q, %q failed: %v", fs.Name(), exists, from, err)
226 names, err := readDirNames(fs, tDir)
228 t.Errorf("%s: readDirNames error: %v", fs.Name(), err)
231 for _, e := range names {
232 if e == "renamefrom" {
233 t.Error("File is still called renamefrom")
240 t.Error("File was not renamed to renameto")
245 t.Errorf("%s: stat %q failed: %v", fs.Name(), to, err)
250 func TestRemove(t *testing.T) {
251 for _, fs := range Fss {
253 x, err := TempFile(fs, "", "afero")
255 t.Error(fmt.Sprint("unable to work with temp file", err))
261 tDir := filepath.Dir(path)
263 err = fs.Remove(path)
265 t.Errorf("%v: Remove() failed: %v", fs.Name(), err)
269 _, err = fs.Stat(path)
270 if !os.IsNotExist(err) {
271 t.Errorf("%v: Remove() didn't remove file", fs.Name())
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())
281 f, err := fs.Open(tDir)
283 t.Error("TestDir should still exist:", err)
286 names, err := f.Readdirnames(-1)
288 t.Error("Readdirnames failed:", err)
291 for _, e := range names {
293 t.Error("File was not removed from parent directory")
299 func TestTruncate(t *testing.T) {
300 defer removeAllTestFiles(t)
301 for _, fs := range Fss {
306 f.Write([]byte("hello, world\n"))
311 checkSize(t, f, 1024)
314 _, err := f.Write([]byte("surprise!"))
316 checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
321 func TestSeek(t *testing.T) {
322 defer removeAllTestFiles(t)
323 for _, fs := range Fss {
327 const data = "hello, world\n"
328 io.WriteString(f, data)
336 {0, 1, int64(len(data))},
339 {0, 2, int64(len(data))},
341 {-1, 2, int64(len(data)) - 1},
342 {1 << 33, 0, 1 << 33},
343 {1 << 33, 2, 1<<33 + int64(len(data))},
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
353 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
359 func TestReadAt(t *testing.T) {
360 defer removeAllTestFiles(t)
361 for _, fs := range Fss {
365 const data = "hello, world\n"
366 io.WriteString(f, data)
369 n, err := f.ReadAt(b, 7)
370 if err != nil || n != len(b) {
371 t.Fatalf("ReadAt 7: %d, %v", n, err)
373 if string(b) != "world" {
374 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
379 func TestWriteAt(t *testing.T) {
380 defer removeAllTestFiles(t)
381 for _, fs := range Fss {
385 const data = "hello, world\n"
386 io.WriteString(f, data)
388 n, err := f.WriteAt([]byte("WORLD"), 7)
389 if err != nil || n != 5 {
390 t.Fatalf("WriteAt 7: %d, %v", n, err)
393 f2, err := fs.Open(f.Name())
395 t.Fatalf("%v: ReadFile %s: %v", fs.Name(), f.Name(), err)
398 buf := new(bytes.Buffer)
401 if string(b) != "hello, WORLD\n" {
402 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
408 func setupTestDir(t *testing.T, fs Fs) string {
410 return setupTestFiles(t, fs, path)
413 func setupTestDirRoot(t *testing.T, fs Fs) string {
415 setupTestFiles(t, fs, path)
419 func setupTestDirReusePath(t *testing.T, fs Fs, path string) string {
420 testRegistry[fs] = append(testRegistry[fs], path)
421 return setupTestFiles(t, fs, path)
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) {
431 f, err := fs.Create(filepath.Join(testSubDir, "testfile1"))
435 f.WriteString("Testfile 1 content")
438 f, err = fs.Create(filepath.Join(testSubDir, "testfile2"))
442 f.WriteString("Testfile 2 content")
445 f, err = fs.Create(filepath.Join(testSubDir, "testfile3"))
449 f.WriteString("Testfile 3 content")
452 f, err = fs.Create(filepath.Join(testSubDir, "testfile4"))
456 f.WriteString("Testfile 4 content")
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)
467 root, err := fs.Open(tDir)
469 t.Fatal(fs.Name(), tDir, err)
473 namesRoot, err := root.Readdirnames(-1)
475 t.Fatal(fs.Name(), namesRoot, err)
478 sub, err := fs.Open(testSubDir)
484 namesSub, err := sub.Readdirnames(-1)
486 t.Fatal(fs.Name(), namesSub, err)
489 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub)
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)
499 root, err := fs.Open(tDir)
505 rootInfo, err := root.Readdir(1)
507 t.Log(myFileInfo(rootInfo))
511 rootInfo, err = root.Readdir(5)
513 t.Log(myFileInfo(rootInfo))
517 sub, err := fs.Open(testSubDir)
523 subInfo, err := sub.Readdir(5)
525 t.Log(myFileInfo(subInfo))
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)
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)
553 for i, o := range infos {
563 t.Log("Readdir outputs not equal for Readdir(", num, ")")
564 for i, o := range outputs {
573 type myFileInfo []os.FileInfo
575 func (m myFileInfo) String() string {
576 out := "Fileinfos:\n"
577 for _, e := range m {
578 out += " " + e.Name() + "\n"
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)
589 root, err := fs.Open(tDir)
595 rootInfo, err := root.Readdir(-1)
599 var namesRoot = []string{}
600 for _, e := range rootInfo {
601 namesRoot = append(namesRoot, e.Name())
604 sub, err := fs.Open(testSubDir)
610 subInfo, err := sub.Readdir(-1)
614 var namesSub = []string{}
615 for _, e := range subInfo {
616 namesSub = append(namesSub, e.Name())
619 findNames(fs, t, tDir, testSubDir, namesRoot, namesSub)
623 func findNames(fs Fs, t *testing.T, tDir, testSubDir string, root, sub []string) {
625 for _, e := range root {
626 f, err := fs.Open(filepath.Join(tDir, e))
628 t.Error("Open", filepath.Join(tDir, e), ":", err)
637 t.Logf("Names root: %v", root)
638 t.Logf("Names sub: %v", sub)
639 t.Error("Didn't find subdirectory we")
642 var found1, found2 bool
643 for _, e := range sub {
644 f, err := fs.Open(filepath.Join(testSubDir, e))
646 t.Error("Open", filepath.Join(testSubDir, e), ":", err)
650 if equal(e, "testfile1") {
653 if equal(e, "testfile2") {
659 t.Logf("Names root: %v", root)
660 t.Logf("Names sub: %v", sub)
661 t.Error("Didn't find testfile1")
664 t.Logf("Names root: %v", root)
665 t.Logf("Names sub: %v", sub)
666 t.Error("Didn't find testfile2")
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)
678 testRegistry = make(map[Fs][]string)
681 func equal(name1, name2 string) (r bool) {
682 switch runtime.GOOS {
684 r = strings.ToLower(name1) == strings.ToLower(name2)
691 func checkSize(t *testing.T, f File, size int64) {
694 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
696 if dir.Size() != size {
697 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)