| package afero | 
 |  | 
 | import ( | 
 | 	"os" | 
 | 	"path/filepath" | 
 | 	"runtime" | 
 | 	"testing" | 
 | 	"time" | 
 | ) | 
 |  | 
 | func TestNormalizePath(t *testing.T) { | 
 | 	type test struct { | 
 | 		input    string | 
 | 		expected string | 
 | 	} | 
 |  | 
 | 	data := []test{ | 
 | 		{".", FilePathSeparator}, | 
 | 		{"./", FilePathSeparator}, | 
 | 		{"..", FilePathSeparator}, | 
 | 		{"../", FilePathSeparator}, | 
 | 		{"./..", FilePathSeparator}, | 
 | 		{"./../", FilePathSeparator}, | 
 | 	} | 
 |  | 
 | 	for i, d := range data { | 
 | 		cpath := normalizePath(d.input) | 
 | 		if d.expected != cpath { | 
 | 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, cpath) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | func TestPathErrors(t *testing.T) { | 
 | 	path := filepath.Join(".", "some", "path") | 
 | 	path2 := filepath.Join(".", "different", "path") | 
 | 	fs := NewMemMapFs() | 
 | 	perm := os.FileMode(0755) | 
 |  | 
 | 	// relevant functions: | 
 | 	// func (m *MemMapFs) Chmod(name string, mode os.FileMode) error | 
 | 	// func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error | 
 | 	// func (m *MemMapFs) Create(name string) (File, error) | 
 | 	// func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error | 
 | 	// func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error | 
 | 	// func (m *MemMapFs) Open(name string) (File, error) | 
 | 	// func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) | 
 | 	// func (m *MemMapFs) Remove(name string) error | 
 | 	// func (m *MemMapFs) Rename(oldname, newname string) error | 
 | 	// func (m *MemMapFs) Stat(name string) (os.FileInfo, error) | 
 |  | 
 | 	err := fs.Chmod(path, perm) | 
 | 	checkPathError(t, err, "Chmod") | 
 |  | 
 | 	err = fs.Chtimes(path, time.Now(), time.Now()) | 
 | 	checkPathError(t, err, "Chtimes") | 
 |  | 
 | 	// fs.Create doesn't return an error | 
 |  | 
 | 	err = fs.Mkdir(path2, perm) | 
 | 	if err != nil { | 
 | 		t.Error(err) | 
 | 	} | 
 | 	err = fs.Mkdir(path2, perm) | 
 | 	checkPathError(t, err, "Mkdir") | 
 |  | 
 | 	err = fs.MkdirAll(path2, perm) | 
 | 	if err != nil { | 
 | 		t.Error("MkdirAll:", err) | 
 | 	} | 
 |  | 
 | 	_, err = fs.Open(path) | 
 | 	checkPathError(t, err, "Open") | 
 |  | 
 | 	_, err = fs.OpenFile(path, os.O_RDWR, perm) | 
 | 	checkPathError(t, err, "OpenFile") | 
 |  | 
 | 	err = fs.Remove(path) | 
 | 	checkPathError(t, err, "Remove") | 
 |  | 
 | 	err = fs.RemoveAll(path) | 
 | 	if err != nil { | 
 | 		t.Error("RemoveAll:", err) | 
 | 	} | 
 |  | 
 | 	err = fs.Rename(path, path2) | 
 | 	checkPathError(t, err, "Rename") | 
 |  | 
 | 	_, err = fs.Stat(path) | 
 | 	checkPathError(t, err, "Stat") | 
 | } | 
 |  | 
 | func checkPathError(t *testing.T, err error, op string) { | 
 | 	pathErr, ok := err.(*os.PathError) | 
 | 	if !ok { | 
 | 		t.Error(op+":", err, "is not a os.PathError") | 
 | 		return | 
 | 	} | 
 | 	_, ok = pathErr.Err.(*os.PathError) | 
 | 	if ok { | 
 | 		t.Error(op+":", err, "contains another os.PathError") | 
 | 	} | 
 | } | 
 |  | 
 | // Fails if multiple file objects use the same file.at counter in MemMapFs | 
 | func TestMultipleOpenFiles(t *testing.T) { | 
 | 	defer removeAllTestFiles(t) | 
 | 	const fileName = "afero-demo2.txt" | 
 |  | 
 | 	var data = make([][]byte, len(Fss)) | 
 |  | 
 | 	for i, fs := range Fss { | 
 | 		dir := testDir(fs) | 
 | 		path := filepath.Join(dir, fileName) | 
 | 		fh1, err := fs.Create(path) | 
 | 		if err != nil { | 
 | 			t.Error("fs.Create failed: " + err.Error()) | 
 | 		} | 
 | 		_, err = fh1.Write([]byte("test")) | 
 | 		if err != nil { | 
 | 			t.Error("fh.Write failed: " + err.Error()) | 
 | 		} | 
 | 		_, err = fh1.Seek(0, os.SEEK_SET) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 |  | 
 | 		fh2, err := fs.OpenFile(path, os.O_RDWR, 0777) | 
 | 		if err != nil { | 
 | 			t.Error("fs.OpenFile failed: " + err.Error()) | 
 | 		} | 
 | 		_, err = fh2.Seek(0, os.SEEK_END) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 | 		_, err = fh2.Write([]byte("data")) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 | 		err = fh2.Close() | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 |  | 
 | 		_, err = fh1.Write([]byte("data")) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 | 		err = fh1.Close() | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 | 		// the file now should contain "datadata" | 
 | 		data[i], err = ReadFile(fs, path) | 
 | 		if err != nil { | 
 | 			t.Error(err) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	for i, fs := range Fss { | 
 | 		if i == 0 { | 
 | 			continue | 
 | 		} | 
 | 		if string(data[0]) != string(data[i]) { | 
 | 			t.Errorf("%s and %s don't behave the same\n"+ | 
 | 				"%s: \"%s\"\n%s: \"%s\"\n", | 
 | 				Fss[0].Name(), fs.Name(), Fss[0].Name(), data[0], fs.Name(), data[i]) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | // Test if file.Write() fails when opened as read only | 
 | func TestReadOnly(t *testing.T) { | 
 | 	defer removeAllTestFiles(t) | 
 | 	const fileName = "afero-demo.txt" | 
 |  | 
 | 	for _, fs := range Fss { | 
 | 		dir := testDir(fs) | 
 | 		path := filepath.Join(dir, fileName) | 
 |  | 
 | 		f, err := fs.Create(path) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) | 
 | 		} | 
 | 		_, err = f.Write([]byte("test")) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "Write failed: "+err.Error()) | 
 | 		} | 
 | 		f.Close() | 
 |  | 
 | 		f, err = fs.Open(path) | 
 | 		if err != nil { | 
 | 			t.Error("fs.Open failed: " + err.Error()) | 
 | 		} | 
 | 		_, err = f.Write([]byte("data")) | 
 | 		if err == nil { | 
 | 			t.Error(fs.Name()+":", "No write error") | 
 | 		} | 
 | 		f.Close() | 
 |  | 
 | 		f, err = fs.OpenFile(path, os.O_RDONLY, 0644) | 
 | 		if err != nil { | 
 | 			t.Error("fs.Open failed: " + err.Error()) | 
 | 		} | 
 | 		_, err = f.Write([]byte("data")) | 
 | 		if err == nil { | 
 | 			t.Error(fs.Name()+":", "No write error") | 
 | 		} | 
 | 		f.Close() | 
 | 	} | 
 | } | 
 |  | 
 | func TestWriteCloseTime(t *testing.T) { | 
 | 	defer removeAllTestFiles(t) | 
 | 	const fileName = "afero-demo.txt" | 
 |  | 
 | 	for _, fs := range Fss { | 
 | 		dir := testDir(fs) | 
 | 		path := filepath.Join(dir, fileName) | 
 |  | 
 | 		f, err := fs.Create(path) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) | 
 | 		} | 
 | 		f.Close() | 
 |  | 
 | 		f, err = fs.Create(path) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "fs.Create failed: "+err.Error()) | 
 | 		} | 
 | 		fi, err := f.Stat() | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "Stat failed: "+err.Error()) | 
 | 		} | 
 | 		timeBefore := fi.ModTime() | 
 |  | 
 | 		// sorry for the delay, but we have to make sure time advances, | 
 | 		// also on non Un*x systems... | 
 | 		switch runtime.GOOS { | 
 | 		case "windows": | 
 | 			time.Sleep(2 * time.Second) | 
 | 		case "darwin": | 
 | 			time.Sleep(1 * time.Second) | 
 | 		default: // depending on the FS, this may work with < 1 second, on my old ext3 it does not | 
 | 			time.Sleep(1 * time.Second) | 
 | 		} | 
 |  | 
 | 		_, err = f.Write([]byte("test")) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "Write failed: "+err.Error()) | 
 | 		} | 
 | 		f.Close() | 
 | 		fi, err = fs.Stat(path) | 
 | 		if err != nil { | 
 | 			t.Error(fs.Name()+":", "fs.Stat failed: "+err.Error()) | 
 | 		} | 
 | 		if fi.ModTime().Equal(timeBefore) { | 
 | 			t.Error(fs.Name()+":", "ModTime was not set on Close()") | 
 | 		} | 
 | 	} | 
 | } |