|  | package afero | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "io/ioutil" | 
|  | "os" | 
|  | "testing" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | var tempDirs []string | 
|  |  | 
|  | func NewTempOsBaseFs(t *testing.T) Fs { | 
|  | name, err := TempDir(NewOsFs(), "", "") | 
|  | if err != nil { | 
|  | t.Error("error creating tempDir", err) | 
|  | } | 
|  |  | 
|  | tempDirs = append(tempDirs, name) | 
|  |  | 
|  | return NewBasePathFs(NewOsFs(), name) | 
|  | } | 
|  |  | 
|  | func CleanupTempDirs(t *testing.T) { | 
|  | osfs := NewOsFs() | 
|  | type ev struct{ | 
|  | path string | 
|  | e error | 
|  | } | 
|  |  | 
|  | errs := []ev{} | 
|  |  | 
|  | for _, x := range tempDirs { | 
|  | err := osfs.RemoveAll(x) | 
|  | if err != nil { | 
|  | errs = append(errs, ev{path:x,e: err}) | 
|  | } | 
|  | } | 
|  |  | 
|  | for _, e := range errs { | 
|  | fmt.Println("error removing tempDir", e.path, e.e) | 
|  | } | 
|  |  | 
|  | if len(errs) > 0 { | 
|  | t.Error("error cleaning up tempDirs") | 
|  | } | 
|  | tempDirs = []string{} | 
|  | } | 
|  |  | 
|  | func TestUnionCreateExisting(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  |  | 
|  | ufs := NewCopyOnWriteFs(roBase, &MemMapFs{}) | 
|  |  | 
|  | base.MkdirAll("/home/test", 0777) | 
|  | fh, _ := base.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, err := ufs.OpenFile("/home/test/file.txt", os.O_RDWR, 0666) | 
|  | if err != nil { | 
|  | t.Errorf("Failed to open file r/w: %s", err) | 
|  | } | 
|  |  | 
|  | _, err = fh.Write([]byte("####")) | 
|  | if err != nil { | 
|  | t.Errorf("Failed to write file: %s", err) | 
|  | } | 
|  | fh.Seek(0, 0) | 
|  | data, err := ioutil.ReadAll(fh) | 
|  | if err != nil { | 
|  | t.Errorf("Failed to read file: %s", err) | 
|  | } | 
|  | if string(data) != "#### is a test" { | 
|  | t.Errorf("Got wrong data") | 
|  | } | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = base.Open("/home/test/file.txt") | 
|  | data, err = ioutil.ReadAll(fh) | 
|  | if string(data) != "This is a test" { | 
|  | t.Errorf("Got wrong data in base file") | 
|  | } | 
|  | fh.Close() | 
|  |  | 
|  | fh, err = ufs.Create("/home/test/file.txt") | 
|  | switch err { | 
|  | case nil: | 
|  | if fi, _ := fh.Stat(); fi.Size() != 0 { | 
|  | t.Errorf("Create did not truncate file") | 
|  | } | 
|  | fh.Close() | 
|  | default: | 
|  | t.Errorf("Create failed on existing file") | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | func TestUnionMergeReaddir(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: &MemMapFs{}} | 
|  |  | 
|  | base.MkdirAll("/home/test", 0777) | 
|  | fh, _ := base.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Create("/home/test/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Open("/home/test") | 
|  | files, err := fh.Readdirnames(-1) | 
|  | if err != nil { | 
|  | t.Errorf("Readdirnames failed") | 
|  | } | 
|  | if len(files) != 2 { | 
|  | t.Errorf("Got wrong number of files: %v", files) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestExistingDirectoryCollisionReaddir(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  | overlay := &MemMapFs{} | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: overlay} | 
|  |  | 
|  | base.MkdirAll("/home/test", 0777) | 
|  | fh, _ := base.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | overlay.MkdirAll("home/test", 0777) | 
|  | fh, _ = overlay.Create("/home/test/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Create("/home/test/file3.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Open("/home/test") | 
|  | files, err := fh.Readdirnames(-1) | 
|  | if err != nil { | 
|  | t.Errorf("Readdirnames failed") | 
|  | } | 
|  | if len(files) != 3 { | 
|  | t.Errorf("Got wrong number of files in union: %v", files) | 
|  | } | 
|  |  | 
|  | fh, _ = overlay.Open("/home/test") | 
|  | files, err = fh.Readdirnames(-1) | 
|  | if err != nil { | 
|  | t.Errorf("Readdirnames failed") | 
|  | } | 
|  | if len(files) != 2 { | 
|  | t.Errorf("Got wrong number of files in overlay: %v", files) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestNestedDirBaseReaddir(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  | overlay := &MemMapFs{} | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: overlay} | 
|  |  | 
|  | base.MkdirAll("/home/test/foo/bar", 0777) | 
|  | fh, _ := base.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = base.Create("/home/test/foo/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  | fh, _ = base.Create("/home/test/foo/bar/file3.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | overlay.MkdirAll("/", 0777) | 
|  |  | 
|  | // Opening something only in the base | 
|  | fh, _ = ufs.Open("/home/test/foo") | 
|  | list, err := fh.Readdir(-1) | 
|  | if err != nil { | 
|  | t.Errorf("Readdir failed", err) | 
|  | } | 
|  | if len(list) != 2 { | 
|  | for _, x := range list { | 
|  | fmt.Println(x.Name()) | 
|  | } | 
|  | t.Errorf("Got wrong number of files in union: %v", len(list)) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestNestedDirOverlayReaddir(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  | overlay := &MemMapFs{} | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: overlay} | 
|  |  | 
|  | base.MkdirAll("/", 0777) | 
|  | overlay.MkdirAll("/home/test/foo/bar", 0777) | 
|  | fh, _ := overlay.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  | fh, _ = overlay.Create("/home/test/foo/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  | fh, _ = overlay.Create("/home/test/foo/bar/file3.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | // Opening nested dir only in the overlay | 
|  | fh, _ = ufs.Open("/home/test/foo") | 
|  | list, err := fh.Readdir(-1) | 
|  | if err != nil { | 
|  | t.Errorf("Readdir failed", err) | 
|  | } | 
|  | if len(list) != 2 { | 
|  | for _, x := range list { | 
|  | fmt.Println(x.Name()) | 
|  | } | 
|  | t.Errorf("Got wrong number of files in union: %v", len(list)) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestNestedDirOverlayOsFsReaddir(t *testing.T) { | 
|  | defer CleanupTempDirs(t) | 
|  | base := NewTempOsBaseFs(t) | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  | overlay := NewTempOsBaseFs(t) | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: overlay} | 
|  |  | 
|  | base.MkdirAll("/", 0777) | 
|  | overlay.MkdirAll("/home/test/foo/bar", 0777) | 
|  | fh, _ := overlay.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  | fh, _ = overlay.Create("/home/test/foo/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  | fh, _ = overlay.Create("/home/test/foo/bar/file3.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | // Opening nested dir only in the overlay | 
|  | fh, _ = ufs.Open("/home/test/foo") | 
|  | list, err := fh.Readdir(-1) | 
|  | fh.Close() | 
|  | if err != nil { | 
|  | t.Errorf("Readdir failed", err) | 
|  | } | 
|  | if len(list) != 2 { | 
|  | for _, x := range list { | 
|  | fmt.Println(x.Name()) | 
|  | } | 
|  | t.Errorf("Got wrong number of files in union: %v", len(list)) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestCopyOnWriteFsWithOsFs(t *testing.T) { | 
|  | defer CleanupTempDirs(t) | 
|  | base := NewTempOsBaseFs(t) | 
|  | roBase := &ReadOnlyFs{source: base} | 
|  | overlay := NewTempOsBaseFs(t) | 
|  |  | 
|  | ufs := &CopyOnWriteFs{base: roBase, layer: overlay} | 
|  |  | 
|  | base.MkdirAll("/home/test", 0777) | 
|  | fh, _ := base.Create("/home/test/file.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | overlay.MkdirAll("home/test", 0777) | 
|  | fh, _ = overlay.Create("/home/test/file2.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Create("/home/test/file3.txt") | 
|  | fh.WriteString("This is a test") | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = ufs.Open("/home/test") | 
|  | files, err := fh.Readdirnames(-1) | 
|  | fh.Close() | 
|  | if err != nil { | 
|  | t.Errorf("Readdirnames failed") | 
|  | } | 
|  | if len(files) != 3 { | 
|  | t.Errorf("Got wrong number of files in union: %v", files) | 
|  | } | 
|  |  | 
|  | fh, _ = overlay.Open("/home/test") | 
|  | files, err = fh.Readdirnames(-1) | 
|  | fh.Close() | 
|  | if err != nil { | 
|  | t.Errorf("Readdirnames failed") | 
|  | } | 
|  | if len(files) != 2 { | 
|  | t.Errorf("Got wrong number of files in overlay: %v", files) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestUnionCacheWrite(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | layer := &MemMapFs{} | 
|  |  | 
|  | ufs := NewCacheOnReadFs(base, layer, 0) | 
|  |  | 
|  | base.Mkdir("/data", 0777) | 
|  |  | 
|  | fh, err := ufs.Create("/data/file.txt") | 
|  | if err != nil { | 
|  | t.Errorf("Failed to create file") | 
|  | } | 
|  | _, err = fh.Write([]byte("This is a test")) | 
|  | if err != nil { | 
|  | t.Errorf("Failed to write file") | 
|  | } | 
|  |  | 
|  | fh.Seek(0, os.SEEK_SET) | 
|  | buf := make([]byte, 4) | 
|  | _, err = fh.Read(buf) | 
|  | fh.Write([]byte(" IS A")) | 
|  | fh.Close() | 
|  |  | 
|  | baseData, _ := ReadFile(base, "/data/file.txt") | 
|  | layerData, _ := ReadFile(layer, "/data/file.txt") | 
|  | if string(baseData) != string(layerData) { | 
|  | t.Errorf("Different data: %s <=> %s", baseData, layerData) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestUnionCacheExpire(t *testing.T) { | 
|  | base := &MemMapFs{} | 
|  | layer := &MemMapFs{} | 
|  | ufs := &CacheOnReadFs{base: base, layer: layer, cacheTime: 1 * time.Second} | 
|  |  | 
|  | base.Mkdir("/data", 0777) | 
|  |  | 
|  | fh, err := ufs.Create("/data/file.txt") | 
|  | if err != nil { | 
|  | t.Errorf("Failed to create file") | 
|  | } | 
|  | _, err = fh.Write([]byte("This is a test")) | 
|  | if err != nil { | 
|  | t.Errorf("Failed to write file") | 
|  | } | 
|  | fh.Close() | 
|  |  | 
|  | fh, _ = base.Create("/data/file.txt") | 
|  | // sleep some time, so we really get a different time.Now() on write... | 
|  | time.Sleep(2 * time.Second) | 
|  | fh.WriteString("Another test") | 
|  | fh.Close() | 
|  |  | 
|  | data, _ := ReadFile(ufs, "/data/file.txt") | 
|  | if string(data) != "Another test" { | 
|  | t.Errorf("cache time failed: <%s>", data) | 
|  | } | 
|  | } |