1 package afero
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8 )
9
10 func TestSymlinkIfPossible(t *testing.T) {
11 wd, _ := os.Getwd()
12 defer func() {
13 os.Chdir(wd)
14 }()
15
16 osFs := &OsFs{}
17
18 workDir, err := TempDir(osFs, "", "afero-symlink")
19 if err != nil {
20 t.Fatal(err)
21 }
22
23 defer func() {
24 osFs.RemoveAll(workDir)
25 }()
26
27 memWorkDir := "/sym"
28
29 memFs := NewMemMapFs()
30 overlayFs1 := &CopyOnWriteFs{base: osFs, layer: memFs}
31 overlayFs2 := &CopyOnWriteFs{base: memFs, layer: osFs}
32 overlayFsMemOnly := &CopyOnWriteFs{base: memFs, layer: NewMemMapFs()}
33 basePathFs := &BasePathFs{source: osFs, path: workDir}
34 basePathFsMem := &BasePathFs{source: memFs, path: memWorkDir}
35 roFs := &ReadOnlyFs{source: osFs}
36 roFsMem := &ReadOnlyFs{source: memFs}
37
38 pathFileMem := filepath.Join(memWorkDir, "aferom.txt")
39 osPath := filepath.Join(workDir, "afero.txt")
40
41 WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0o777)
42 WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0o777)
43
44 testLink := func(l Linker, source, destination string, output *string) {
45 if fs, ok := l.(Fs); ok {
46 dir := filepath.Dir(destination)
47 if dir != "" {
48 fs.MkdirAll(dir, 0o777)
49 }
50 }
51
52 err := l.SymlinkIfPossible(source, destination)
53 if (err == nil) && (output != nil) {
54 t.Fatalf("Error creating symlink, succeeded when expecting error %v", *output)
55 } else if (err != nil) && (output == nil) {
56 t.Fatalf("Error creating symlink, expected success, got %v", err)
57 } else if err != nil && err.Error() != *output && !strings.HasSuffix(err.Error(), *output) {
58 t.Fatalf("Error creating symlink, expected error '%v', instead got output '%v'", *output, err)
59 } else {
60
61 if output == nil {
62 if lst, ok := l.(Lstater); ok {
63 _, ok, err := lst.LstatIfPossible(destination)
64 if !ok {
65 if err != nil {
66 t.Fatalf("Error calling lstat on file after successful link, got: %v", err)
67 } else {
68 t.Fatalf("Error calling lstat on file after successful link, result didn't use lstat (not link)")
69 }
70 return
71 }
72 }
73 }
74 }
75 }
76
77 notSupported := ErrNoSymlink.Error()
78
79 testLink(osFs, osPath, filepath.Join(workDir, "os/link.txt"), nil)
80 testLink(overlayFs1, osPath, filepath.Join(workDir, "overlay/link1.txt"), ¬Supported)
81 testLink(overlayFs2, pathFileMem, filepath.Join(workDir, "overlay2/link2.txt"), nil)
82 testLink(overlayFsMemOnly, pathFileMem, filepath.Join(memWorkDir, "overlay3/link.txt"), ¬Supported)
83 testLink(basePathFs, "afero.txt", "basepath/link.txt", nil)
84 testLink(basePathFsMem, pathFileMem, "link/file.txt", ¬Supported)
85 testLink(roFs, osPath, filepath.Join(workDir, "ro/link.txt"), ¬Supported)
86 testLink(roFsMem, pathFileMem, filepath.Join(memWorkDir, "ro/link.txt"), ¬Supported)
87 }
88
89 func TestReadlinkIfPossible(t *testing.T) {
90 wd, _ := os.Getwd()
91 defer func() {
92 os.Chdir(wd)
93 }()
94
95 osFs := &OsFs{}
96
97 workDir, err := TempDir(osFs, "", "afero-readlink")
98 if err != nil {
99 t.Fatal(err)
100 }
101
102 defer func() {
103 osFs.RemoveAll(workDir)
104 }()
105
106 memWorkDir := "/read"
107
108 memFs := NewMemMapFs()
109 overlayFs1 := &CopyOnWriteFs{base: osFs, layer: memFs}
110 overlayFs2 := &CopyOnWriteFs{base: memFs, layer: osFs}
111 overlayFsMemOnly := &CopyOnWriteFs{base: memFs, layer: NewMemMapFs()}
112 basePathFs := &BasePathFs{source: osFs, path: workDir}
113 basePathFsMem := &BasePathFs{source: memFs, path: memWorkDir}
114 roFs := &ReadOnlyFs{source: osFs}
115 roFsMem := &ReadOnlyFs{source: memFs}
116
117 pathFileMem := filepath.Join(memWorkDir, "aferom.txt")
118 osPath := filepath.Join(workDir, "afero.txt")
119
120 WriteFile(osFs, osPath, []byte("Hi, Afero!"), 0o777)
121 WriteFile(memFs, filepath.Join(pathFileMem), []byte("Hi, Afero!"), 0o777)
122
123 createLink := func(l Linker, source, destination string) error {
124 if fs, ok := l.(Fs); ok {
125 dir := filepath.Dir(destination)
126 if dir != "" {
127 fs.MkdirAll(dir, 0o777)
128 }
129 }
130
131 return l.SymlinkIfPossible(source, destination)
132 }
133
134 testRead := func(r LinkReader, name string, output *string) {
135 _, err := r.ReadlinkIfPossible(name)
136 if (err != nil) && (output == nil) {
137 t.Fatalf("Error reading link, expected success, got error: %v", err)
138 } else if (err == nil) && (output != nil) {
139 t.Fatalf("Error reading link, succeeded when expecting error: %v", *output)
140 } else if err != nil && err.Error() != *output && !strings.HasSuffix(err.Error(), *output) {
141 t.Fatalf("Error reading link, expected error '%v', instead received '%v'", *output, err)
142 }
143 }
144
145 notSupported := ErrNoReadlink.Error()
146
147 err = createLink(osFs, osPath, filepath.Join(workDir, "os/link.txt"))
148 if err != nil {
149 t.Fatal("Error creating test link: ", err)
150 }
151
152 testRead(osFs, filepath.Join(workDir, "os/link.txt"), nil)
153 testRead(overlayFs1, filepath.Join(workDir, "os/link.txt"), nil)
154 testRead(overlayFs2, filepath.Join(workDir, "os/link.txt"), nil)
155 testRead(overlayFsMemOnly, pathFileMem, ¬Supported)
156 testRead(basePathFs, "os/link.txt", nil)
157 testRead(basePathFsMem, pathFileMem, ¬Supported)
158 testRead(roFs, filepath.Join(workDir, "os/link.txt"), nil)
159 testRead(roFsMem, pathFileMem, ¬Supported)
160 }
161
View as plain text