Source file
src/os/stat_test.go
Documentation: os
1
2
3
4
5 package os_test
6
7 import (
8 "internal/testenv"
9 "io/fs"
10 "os"
11 "path/filepath"
12 "testing"
13 )
14
15
16 func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, fs.FileInfo)) {
17
18 sfi, err := os.Stat(path)
19 if err != nil {
20 t.Error(err)
21 return
22 }
23 statCheck(t, path, sfi)
24
25
26 lsfi, err := os.Lstat(path)
27 if err != nil {
28 t.Error(err)
29 return
30 }
31 lstatCheck(t, path, lsfi)
32
33 if isLink {
34 if os.SameFile(sfi, lsfi) {
35 t.Errorf("stat and lstat of %q should not be the same", path)
36 }
37 } else {
38 if !os.SameFile(sfi, lsfi) {
39 t.Errorf("stat and lstat of %q should be the same", path)
40 }
41 }
42
43
44 f, err := os.Open(path)
45 if err != nil {
46 t.Error(err)
47 return
48 }
49 defer f.Close()
50
51 sfi2, err := f.Stat()
52 if err != nil {
53 t.Error(err)
54 return
55 }
56 statCheck(t, path, sfi2)
57
58 if !os.SameFile(sfi, sfi2) {
59 t.Errorf("stat of open %q file and stat of %q should be the same", path, path)
60 }
61
62 if isLink {
63 if os.SameFile(sfi2, lsfi) {
64 t.Errorf("stat of opened %q file and lstat of %q should not be the same", path, path)
65 }
66 } else {
67 if !os.SameFile(sfi2, lsfi) {
68 t.Errorf("stat of opened %q file and lstat of %q should be the same", path, path)
69 }
70 }
71
72
73 if len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
74
75 return
76 }
77 parentdir := filepath.Dir(path)
78 parent, err := os.Open(parentdir)
79 if err != nil {
80 t.Error(err)
81 return
82 }
83 defer parent.Close()
84
85 fis, err := parent.Readdir(-1)
86 if err != nil {
87 t.Error(err)
88 return
89 }
90 var lsfi2 fs.FileInfo
91 base := filepath.Base(path)
92 for _, fi2 := range fis {
93 if fi2.Name() == base {
94 lsfi2 = fi2
95 break
96 }
97 }
98 if lsfi2 == nil {
99 t.Errorf("failed to find %q in its parent", path)
100 return
101 }
102 lstatCheck(t, path, lsfi2)
103
104 if !os.SameFile(lsfi, lsfi2) {
105 t.Errorf("lstat of %q file in %q directory and %q should be the same", lsfi2.Name(), parentdir, path)
106 }
107 }
108
109
110 func testIsDir(t *testing.T, path string, fi fs.FileInfo) {
111 t.Helper()
112 if !fi.IsDir() {
113 t.Errorf("%q should be a directory", path)
114 }
115 if fi.Mode()&fs.ModeSymlink != 0 {
116 t.Errorf("%q should not be a symlink", path)
117 }
118 }
119
120
121 func testIsSymlink(t *testing.T, path string, fi fs.FileInfo) {
122 t.Helper()
123 if fi.IsDir() {
124 t.Errorf("%q should not be a directory", path)
125 }
126 if fi.Mode()&fs.ModeSymlink == 0 {
127 t.Errorf("%q should be a symlink", path)
128 }
129 }
130
131
132 func testIsFile(t *testing.T, path string, fi fs.FileInfo) {
133 t.Helper()
134 if fi.IsDir() {
135 t.Errorf("%q should not be a directory", path)
136 }
137 if fi.Mode()&fs.ModeSymlink != 0 {
138 t.Errorf("%q should not be a symlink", path)
139 }
140 }
141
142 func testDirStats(t *testing.T, path string) {
143 testStatAndLstat(t, path, false, testIsDir, testIsDir)
144 }
145
146 func testFileStats(t *testing.T, path string) {
147 testStatAndLstat(t, path, false, testIsFile, testIsFile)
148 }
149
150 func testSymlinkStats(t *testing.T, path string, isdir bool) {
151 if isdir {
152 testStatAndLstat(t, path, true, testIsDir, testIsSymlink)
153 } else {
154 testStatAndLstat(t, path, true, testIsFile, testIsSymlink)
155 }
156 }
157
158 func testSymlinkSameFile(t *testing.T, path, link string) {
159 pathfi, err := os.Stat(path)
160 if err != nil {
161 t.Error(err)
162 return
163 }
164
165 linkfi, err := os.Stat(link)
166 if err != nil {
167 t.Error(err)
168 return
169 }
170 if !os.SameFile(pathfi, linkfi) {
171 t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", path, link)
172 }
173
174 linkfi, err = os.Lstat(link)
175 if err != nil {
176 t.Error(err)
177 return
178 }
179 if os.SameFile(pathfi, linkfi) {
180 t.Errorf("os.Stat(%q) and os.Lstat(%q) are the same file", path, link)
181 }
182 }
183
184 func testSymlinkSameFileOpen(t *testing.T, link string) {
185 f, err := os.Open(link)
186 if err != nil {
187 t.Error(err)
188 return
189 }
190 defer f.Close()
191
192 fi, err := f.Stat()
193 if err != nil {
194 t.Error(err)
195 return
196 }
197
198 fi2, err := os.Stat(link)
199 if err != nil {
200 t.Error(err)
201 return
202 }
203
204 if !os.SameFile(fi, fi2) {
205 t.Errorf("os.Open(%q).Stat() and os.Stat(%q) are not the same file", link, link)
206 }
207 }
208
209 func TestDirAndSymlinkStats(t *testing.T) {
210 testenv.MustHaveSymlink(t)
211 t.Parallel()
212
213 tmpdir := t.TempDir()
214 dir := filepath.Join(tmpdir, "dir")
215 if err := os.Mkdir(dir, 0777); err != nil {
216 t.Fatal(err)
217 }
218 testDirStats(t, dir)
219
220 dirlink := filepath.Join(tmpdir, "link")
221 if err := os.Symlink(dir, dirlink); err != nil {
222 t.Fatal(err)
223 }
224 testSymlinkStats(t, dirlink, true)
225 testSymlinkSameFile(t, dir, dirlink)
226 testSymlinkSameFileOpen(t, dirlink)
227
228 linklink := filepath.Join(tmpdir, "linklink")
229 if err := os.Symlink(dirlink, linklink); err != nil {
230 t.Fatal(err)
231 }
232 testSymlinkStats(t, linklink, true)
233 testSymlinkSameFile(t, dir, linklink)
234 testSymlinkSameFileOpen(t, linklink)
235 }
236
237 func TestFileAndSymlinkStats(t *testing.T) {
238 testenv.MustHaveSymlink(t)
239 t.Parallel()
240
241 tmpdir := t.TempDir()
242 file := filepath.Join(tmpdir, "file")
243 if err := os.WriteFile(file, []byte(""), 0644); err != nil {
244 t.Fatal(err)
245 }
246 testFileStats(t, file)
247
248 filelink := filepath.Join(tmpdir, "link")
249 if err := os.Symlink(file, filelink); err != nil {
250 t.Fatal(err)
251 }
252 testSymlinkStats(t, filelink, false)
253 testSymlinkSameFile(t, file, filelink)
254 testSymlinkSameFileOpen(t, filelink)
255
256 linklink := filepath.Join(tmpdir, "linklink")
257 if err := os.Symlink(filelink, linklink); err != nil {
258 t.Fatal(err)
259 }
260 testSymlinkStats(t, linklink, false)
261 testSymlinkSameFile(t, file, linklink)
262 testSymlinkSameFileOpen(t, linklink)
263 }
264
265
266 func TestSymlinkWithTrailingSlash(t *testing.T) {
267 testenv.MustHaveSymlink(t)
268 t.Parallel()
269
270 tmpdir := t.TempDir()
271 dir := filepath.Join(tmpdir, "dir")
272 if err := os.Mkdir(dir, 0777); err != nil {
273 t.Fatal(err)
274 }
275 dirlink := filepath.Join(tmpdir, "link")
276 if err := os.Symlink(dir, dirlink); err != nil {
277 t.Fatal(err)
278 }
279 dirlinkWithSlash := dirlink + string(os.PathSeparator)
280
281 testDirStats(t, dirlinkWithSlash)
282
283 fi1, err := os.Stat(dir)
284 if err != nil {
285 t.Error(err)
286 return
287 }
288 fi2, err := os.Stat(dirlinkWithSlash)
289 if err != nil {
290 t.Error(err)
291 return
292 }
293 if !os.SameFile(fi1, fi2) {
294 t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", dir, dirlinkWithSlash)
295 }
296 }
297
View as plain text