1 package sysfs
2
3 import (
4 "errors"
5 "fmt"
6 "io/fs"
7 "os"
8 "path"
9 "runtime"
10 "testing"
11 "time"
12
13 "github.com/tetratelabs/wazero/experimental/sys"
14 "github.com/tetratelabs/wazero/internal/fstest"
15 "github.com/tetratelabs/wazero/internal/platform"
16 "github.com/tetratelabs/wazero/internal/testing/require"
17 )
18
19 func TestDirFS(t *testing.T) {
20 testFS := DirFS(".")
21
22
23 f, errno := testFS.OpenFile("/", sys.O_RDONLY, 0)
24 require.EqualErrno(t, 0, errno)
25 require.EqualErrno(t, 0, f.Close())
26
27 t.Run("host path not found", func(t *testing.T) {
28 testFS := DirFS("a")
29 _, errno = testFS.OpenFile(".", sys.O_RDONLY, 0)
30 require.EqualErrno(t, sys.ENOENT, errno)
31 })
32 t.Run("host path not a directory", func(t *testing.T) {
33 arg0 := os.Args[0]
34
35 testFS := DirFS(arg0)
36 d, errno := testFS.OpenFile(".", sys.O_RDONLY, 0)
37 require.EqualErrno(t, 0, errno)
38 _, errno = d.Readdir(-1)
39 require.EqualErrno(t, sys.EBADF, errno)
40 })
41 }
42
43 func TestDirFS_join(t *testing.T) {
44 testFS := DirFS("/").(*dirFS)
45 require.Equal(t, "/", testFS.join(""))
46 require.Equal(t, "/", testFS.join("."))
47 require.Equal(t, "/", testFS.join("/"))
48 require.Equal(t, "/tmp", testFS.join("tmp"))
49
50 testFS = DirFS(".").(*dirFS)
51 require.Equal(t, ".", testFS.join(""))
52 require.Equal(t, ".", testFS.join("."))
53 require.Equal(t, ".", testFS.join("/"))
54 require.Equal(t, "."+string(os.PathSeparator)+"tmp", testFS.join("tmp"))
55 }
56
57 func TestDirFS_String(t *testing.T) {
58 testFS := DirFS(".")
59
60
61 require.Equal(t, ".", testFS.(fmt.Stringer).String())
62 }
63
64 func TestDirFS_Lstat(t *testing.T) {
65 tmpDir := t.TempDir()
66 require.NoError(t, fstest.WriteTestFiles(tmpDir))
67
68 testFS := DirFS(tmpDir)
69 for _, path := range []string{"animals.txt", "sub", "sub-link"} {
70 require.EqualErrno(t, 0, testFS.Symlink(path, path+"-link"))
71 }
72
73 testLstat(t, testFS)
74 }
75
76 func TestDirFS_MkDir(t *testing.T) {
77 tmpDir := t.TempDir()
78 testFS := DirFS(tmpDir)
79
80 name := "mkdir"
81 realPath := path.Join(tmpDir, name)
82
83 t.Run("doesn't exist", func(t *testing.T) {
84 require.EqualErrno(t, 0, testFS.Mkdir(name, fs.ModeDir))
85
86 stat, err := os.Stat(realPath)
87 require.NoError(t, err)
88
89 require.Equal(t, name, stat.Name())
90 require.True(t, stat.IsDir())
91 })
92
93 t.Run("dir exists", func(t *testing.T) {
94 err := testFS.Mkdir(name, fs.ModeDir)
95 require.EqualErrno(t, sys.EEXIST, err)
96 })
97
98 t.Run("file exists", func(t *testing.T) {
99 require.NoError(t, os.Remove(realPath))
100 require.NoError(t, os.Mkdir(realPath, 0o700))
101
102 err := testFS.Mkdir(name, fs.ModeDir)
103 require.EqualErrno(t, sys.EEXIST, err)
104 })
105 t.Run("try creating on file", func(t *testing.T) {
106 filePath := path.Join("non-existing-dir", "foo.txt")
107 err := testFS.Mkdir(filePath, fs.ModeDir)
108 require.EqualErrno(t, sys.ENOENT, err)
109 })
110
111
112 require.NoError(t, os.Remove(realPath))
113
114
115 if runtime.GOOS != "windows" {
116 t.Run("dir", func(t *testing.T) {
117 require.NoError(t, os.Mkdir(realPath, 0o444))
118 defer os.RemoveAll(realPath)
119 testChmod(t, testFS, name)
120 })
121 }
122
123 t.Run("file", func(t *testing.T) {
124 require.NoError(t, os.WriteFile(realPath, nil, 0o444))
125 defer os.RemoveAll(realPath)
126 testChmod(t, testFS, name)
127 })
128 }
129
130 func testChmod(t *testing.T, testFS sys.FS, path string) {
131
132 requireMode(t, testFS, path, 0o444)
133
134
135 require.EqualErrno(t, 0, testFS.Chmod(path, 0o666))
136 requireMode(t, testFS, path, 0o666)
137
138 if runtime.GOOS != "windows" {
139
140 require.EqualErrno(t, 0, testFS.Chmod(path, 0o500))
141 requireMode(t, testFS, path, 0o500)
142 }
143 }
144
145 func requireMode(t *testing.T, testFS sys.FS, path string, mode fs.FileMode) {
146 st, errno := testFS.Stat(path)
147 require.EqualErrno(t, 0, errno)
148
149 require.Equal(t, mode, st.Mode.Perm())
150 }
151
152 func TestDirFS_Rename(t *testing.T) {
153 t.Run("from doesn't exist", func(t *testing.T) {
154 tmpDir := t.TempDir()
155 testFS := DirFS(tmpDir)
156
157 file1 := "file1"
158 file1Path := path.Join(tmpDir, file1)
159 err := os.WriteFile(file1Path, []byte{1}, 0o600)
160 require.NoError(t, err)
161
162 err = testFS.Rename("file2", file1)
163 require.EqualErrno(t, sys.ENOENT, err)
164 })
165 t.Run("file to non-exist", func(t *testing.T) {
166 tmpDir := t.TempDir()
167 testFS := DirFS(tmpDir)
168
169 file1 := "file1"
170 file1Path := path.Join(tmpDir, file1)
171 file1Contents := []byte{1}
172 errno := os.WriteFile(file1Path, file1Contents, 0o600)
173 require.NoError(t, errno)
174
175 file2 := "file2"
176 file2Path := path.Join(tmpDir, file2)
177 errno = testFS.Rename(file1, file2)
178 require.EqualErrno(t, 0, errno)
179
180
181 _, errno = os.Stat(file1Path)
182 require.EqualErrno(t, sys.ENOENT, sys.UnwrapOSError(errno))
183
184 s, err := os.Stat(file2Path)
185 require.NoError(t, err)
186 require.False(t, s.IsDir())
187 })
188 t.Run("dir to non-exist", func(t *testing.T) {
189 tmpDir := t.TempDir()
190 testFS := DirFS(tmpDir)
191
192 dir1 := "dir1"
193 dir1Path := path.Join(tmpDir, dir1)
194 require.NoError(t, os.Mkdir(dir1Path, 0o700))
195
196 dir2 := "dir2"
197 dir2Path := path.Join(tmpDir, dir2)
198 errrno := testFS.Rename(dir1, dir2)
199 require.EqualErrno(t, 0, errrno)
200
201
202 _, err := os.Stat(dir1Path)
203 require.EqualErrno(t, sys.ENOENT, sys.UnwrapOSError(err))
204
205 s, err := os.Stat(dir2Path)
206 require.NoError(t, err)
207 require.True(t, s.IsDir())
208 })
209 t.Run("dir to file", func(t *testing.T) {
210 tmpDir := t.TempDir()
211 testFS := DirFS(tmpDir)
212
213 dir1 := "dir1"
214 dir1Path := path.Join(tmpDir, dir1)
215 require.NoError(t, os.Mkdir(dir1Path, 0o700))
216
217 dir2 := "dir2"
218 dir2Path := path.Join(tmpDir, dir2)
219
220
221 f, err := os.OpenFile(dir2Path, os.O_RDWR|os.O_CREATE, 0o600)
222 require.NoError(t, err)
223 require.NoError(t, f.Close())
224
225 errno := testFS.Rename(dir1, dir2)
226 require.EqualErrno(t, sys.ENOTDIR, errno)
227 })
228 t.Run("file to dir", func(t *testing.T) {
229 tmpDir := t.TempDir()
230 testFS := DirFS(tmpDir)
231
232 file1 := "file1"
233 file1Path := path.Join(tmpDir, file1)
234 file1Contents := []byte{1}
235 err := os.WriteFile(file1Path, file1Contents, 0o600)
236 require.NoError(t, err)
237
238 dir1 := "dir1"
239 dir1Path := path.Join(tmpDir, dir1)
240 require.NoError(t, os.Mkdir(dir1Path, 0o700))
241
242 errno := testFS.Rename(file1, dir1)
243 require.EqualErrno(t, sys.EISDIR, errno)
244 })
245
246
247 t.Run("dir to empty dir should be fine", func(t *testing.T) {
248 tmpDir := t.TempDir()
249 testFS := DirFS(tmpDir)
250
251 dir1 := "dir1"
252 dir1Path := path.Join(tmpDir, dir1)
253 require.NoError(t, os.Mkdir(dir1Path, 0o700))
254
255
256 file1 := "file1"
257 file1Path := path.Join(dir1Path, file1)
258 file1Contents := []byte{1}
259 err := os.WriteFile(file1Path, file1Contents, 0o600)
260 require.NoError(t, err)
261
262 dir2 := "dir2"
263 dir2Path := path.Join(tmpDir, dir2)
264 require.NoError(t, os.Mkdir(dir2Path, 0o700))
265
266 errno := testFS.Rename(dir1, dir2)
267 require.EqualErrno(t, 0, errno)
268
269
270 _, err = os.Stat(dir1Path)
271 require.EqualErrno(t, sys.ENOENT, sys.UnwrapOSError(err))
272
273
274 s, err := os.Stat(path.Join(dir2Path, file1))
275 require.NoError(t, err)
276 require.False(t, s.IsDir())
277 })
278
279
280 t.Run("dir to non empty dir should be EXIST", func(t *testing.T) {
281 tmpDir := t.TempDir()
282 testFS := DirFS(tmpDir)
283
284 dir1 := "dir1"
285 dir1Path := path.Join(tmpDir, dir1)
286 require.NoError(t, os.Mkdir(dir1Path, 0o700))
287
288
289 file1 := "file1"
290 file1Path := path.Join(dir1Path, file1)
291 file1Contents := []byte{1}
292 err := os.WriteFile(file1Path, file1Contents, 0o600)
293 require.NoError(t, err)
294
295 dir2 := "dir2"
296 dir2Path := path.Join(tmpDir, dir2)
297 require.NoError(t, os.Mkdir(dir2Path, 0o700))
298
299
300 err = os.WriteFile(path.Join(dir2Path, "existing.txt"), []byte("any thing"), 0o600)
301 require.NoError(t, err)
302
303 errno := testFS.Rename(dir1, dir2)
304 require.EqualErrno(t, sys.ENOTEMPTY, errno)
305 })
306
307 t.Run("file to file", func(t *testing.T) {
308 tmpDir := t.TempDir()
309 testFS := DirFS(tmpDir)
310
311 file1 := "file1"
312 file1Path := path.Join(tmpDir, file1)
313 file1Contents := []byte{1}
314 err := os.WriteFile(file1Path, file1Contents, 0o600)
315 require.NoError(t, err)
316
317 file2 := "file2"
318 file2Path := path.Join(tmpDir, file2)
319 file2Contents := []byte{2}
320 err = os.WriteFile(file2Path, file2Contents, 0o600)
321 require.NoError(t, err)
322
323 errno := testFS.Rename(file1, file2)
324 require.EqualErrno(t, 0, errno)
325
326
327 _, err = os.Stat(file1Path)
328 require.EqualErrno(t, sys.ENOENT, sys.UnwrapOSError(err))
329
330
331 b, err := os.ReadFile(file2Path)
332 require.NoError(t, err)
333 require.Equal(t, file1Contents, b)
334 })
335 t.Run("dir to itself", func(t *testing.T) {
336 tmpDir := t.TempDir()
337 testFS := DirFS(tmpDir)
338
339 dir1 := "dir1"
340 dir1Path := path.Join(tmpDir, dir1)
341 require.NoError(t, os.Mkdir(dir1Path, 0o700))
342
343 errno := testFS.Rename(dir1, dir1)
344 require.EqualErrno(t, 0, errno)
345
346 s, err := os.Stat(dir1Path)
347 require.NoError(t, err)
348 require.True(t, s.IsDir())
349 })
350 t.Run("file to itself", func(t *testing.T) {
351 tmpDir := t.TempDir()
352 testFS := DirFS(tmpDir)
353
354 file1 := "file1"
355 file1Path := path.Join(tmpDir, file1)
356 file1Contents := []byte{1}
357 err := os.WriteFile(file1Path, file1Contents, 0o600)
358 require.NoError(t, err)
359
360 errno := testFS.Rename(file1, file1)
361 require.EqualErrno(t, 0, errno)
362
363 b, err := os.ReadFile(file1Path)
364 require.NoError(t, err)
365 require.Equal(t, file1Contents, b)
366 })
367 }
368
369 func TestDirFS_Rmdir(t *testing.T) {
370 t.Run("doesn't exist", func(t *testing.T) {
371 tmpDir := t.TempDir()
372 testFS := DirFS(tmpDir)
373
374 name := "rmdir"
375
376 err := testFS.Rmdir(name)
377 require.EqualErrno(t, sys.ENOENT, err)
378 })
379
380 t.Run("dir not empty", func(t *testing.T) {
381 tmpDir := t.TempDir()
382 testFS := DirFS(tmpDir)
383
384 name := "rmdir"
385 realPath := path.Join(tmpDir, name)
386
387 require.NoError(t, os.Mkdir(realPath, 0o700))
388 fileInDir := path.Join(realPath, "file")
389 require.NoError(t, os.WriteFile(fileInDir, []byte{}, 0o600))
390
391 err := testFS.Rmdir(name)
392 require.EqualErrno(t, sys.ENOTEMPTY, err)
393
394 require.NoError(t, os.Remove(fileInDir))
395 })
396
397 t.Run("dir previously not empty", func(t *testing.T) {
398 tmpDir := t.TempDir()
399 testFS := DirFS(tmpDir)
400
401 name := "rmdir"
402 realPath := path.Join(tmpDir, name)
403 require.NoError(t, os.Mkdir(realPath, 0o700))
404
405
406 fileInDir := path.Join(realPath, "file")
407 require.NoError(t, os.WriteFile(fileInDir, []byte{}, 0o600))
408 require.NoError(t, os.Remove(fileInDir))
409
410
411 errno := testFS.Rmdir(name)
412 require.EqualErrno(t, 0, errno)
413 })
414
415 t.Run("dir empty", func(t *testing.T) {
416 tmpDir := t.TempDir()
417 testFS := DirFS(tmpDir)
418
419 name := "rmdir"
420 realPath := path.Join(tmpDir, name)
421 require.NoError(t, os.Mkdir(realPath, 0o700))
422 require.EqualErrno(t, 0, testFS.Rmdir(name))
423 _, err := os.Stat(realPath)
424 require.Error(t, err)
425 })
426
427 t.Run("dir empty while opening", func(t *testing.T) {
428 tmpDir := t.TempDir()
429 testFS := DirFS(tmpDir)
430
431 name := "rmdir"
432 realPath := path.Join(tmpDir, name)
433 require.NoError(t, os.Mkdir(realPath, 0o700))
434
435 f, errno := testFS.OpenFile(name, sys.O_DIRECTORY, 0o700)
436 require.EqualErrno(t, 0, errno)
437 defer f.Close()
438
439 require.EqualErrno(t, 0, testFS.Rmdir(name))
440 _, err := os.Stat(realPath)
441 require.Error(t, err)
442 })
443
444 t.Run("not directory", func(t *testing.T) {
445 tmpDir := t.TempDir()
446 testFS := DirFS(tmpDir)
447
448 name := "rmdir"
449 realPath := path.Join(tmpDir, name)
450
451 require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
452
453 err := testFS.Rmdir(name)
454 require.EqualErrno(t, sys.ENOTDIR, err)
455
456 require.NoError(t, os.Remove(realPath))
457 })
458 }
459
460 func TestDirFS_Unlink(t *testing.T) {
461 t.Run("doesn't exist", func(t *testing.T) {
462 tmpDir := t.TempDir()
463 testFS := DirFS(tmpDir)
464 name := "unlink"
465
466 err := testFS.Unlink(name)
467 require.EqualErrno(t, sys.ENOENT, err)
468 })
469
470 t.Run("target: dir", func(t *testing.T) {
471 tmpDir := t.TempDir()
472 testFS := DirFS(tmpDir)
473
474 dir := "dir"
475 realPath := path.Join(tmpDir, dir)
476
477 require.NoError(t, os.Mkdir(realPath, 0o700))
478
479 err := testFS.Unlink(dir)
480 require.EqualErrno(t, sys.EISDIR, err)
481
482 require.NoError(t, os.Remove(realPath))
483 })
484
485 t.Run("target: symlink to dir", func(t *testing.T) {
486 tmpDir := t.TempDir()
487 testFS := DirFS(tmpDir)
488
489
490 subDirName := "subdir"
491 subDirRealPath := path.Join(tmpDir, subDirName)
492 require.NoError(t, os.Mkdir(subDirRealPath, 0o700))
493
494
495 const symlinkName = "symlink-to-dir"
496 require.EqualErrno(t, 0, testFS.Symlink("subdir", symlinkName))
497
498
499 errno := testFS.Unlink(symlinkName)
500 require.EqualErrno(t, 0, errno)
501 })
502
503 t.Run("file exists", func(t *testing.T) {
504 tmpDir := t.TempDir()
505 testFS := DirFS(tmpDir)
506
507 name := "unlink"
508 realPath := path.Join(tmpDir, name)
509
510 require.NoError(t, os.WriteFile(realPath, []byte{}, 0o600))
511
512 require.EqualErrno(t, 0, testFS.Unlink(name))
513
514 _, err := os.Stat(realPath)
515 require.Error(t, err)
516 })
517 }
518
519 func TestDirFS_Utimesns(t *testing.T) {
520 tmpDir := t.TempDir()
521 testFS := DirFS(tmpDir)
522
523 file := "file"
524 err := os.WriteFile(path.Join(tmpDir, file), []byte{}, 0o700)
525 require.NoError(t, err)
526
527 dir := "dir"
528 err = os.Mkdir(path.Join(tmpDir, dir), 0o700)
529 require.NoError(t, err)
530
531 t.Run("doesn't exist", func(t *testing.T) {
532 err := testFS.Utimens("nope", 0, 0)
533 require.EqualErrno(t, sys.ENOENT, err)
534 })
535
536
537
538
539
540 tests := []struct {
541 name string
542 atim, mtim int64
543 }{
544 {
545 name: "nil",
546 },
547 {
548 name: "a=omit,m=omit",
549 atim: sys.UTIME_OMIT,
550 mtim: sys.UTIME_OMIT,
551 },
552 {
553 name: "a=set,m=omit",
554 atim: int64(123*time.Second + 4*time.Microsecond),
555 mtim: sys.UTIME_OMIT,
556 },
557 {
558 name: "a=omit,m=set",
559 atim: sys.UTIME_OMIT,
560 mtim: int64(123*time.Second + 4*time.Microsecond),
561 },
562 {
563 name: "a=set,m=set",
564 atim: int64(123*time.Second + 4*time.Microsecond),
565 mtim: int64(223*time.Second + 5*time.Microsecond),
566 },
567 }
568
569 for _, fileType := range []string{"dir", "file", "link"} {
570 for _, tt := range tests {
571 tc := tt
572 fileType := fileType
573 name := fileType + " " + tc.name
574
575 t.Run(name, func(t *testing.T) {
576 tmpDir := t.TempDir()
577 testFS := DirFS(tmpDir)
578
579 file := path.Join(tmpDir, "file")
580 errno := os.WriteFile(file, []byte{}, 0o700)
581 require.NoError(t, errno)
582
583 link := file + "-link"
584 require.NoError(t, os.Symlink(file, link))
585
586 dir := path.Join(tmpDir, "dir")
587 errno = os.Mkdir(dir, 0o700)
588 require.NoError(t, errno)
589
590 var path, statPath string
591 switch fileType {
592 case "dir":
593 path = "dir"
594 statPath = "dir"
595 case "file":
596 path = "file"
597 statPath = "file"
598 case "link":
599 path = "file-link"
600 statPath = "file"
601 default:
602 panic(tc)
603 }
604
605 oldSt, errno := testFS.Lstat(statPath)
606 require.EqualErrno(t, 0, errno)
607
608 errno = testFS.Utimens(path, tc.atim, tc.mtim)
609 require.EqualErrno(t, 0, errno)
610
611 newSt, errno := testFS.Lstat(statPath)
612 require.EqualErrno(t, 0, errno)
613
614 if platform.CompilerSupported() {
615 if tc.atim == sys.UTIME_OMIT {
616 require.Equal(t, oldSt.Atim, newSt.Atim)
617 } else {
618 require.Equal(t, tc.atim, newSt.Atim)
619 }
620 }
621
622
623 if tc.mtim == sys.UTIME_OMIT {
624 require.Equal(t, oldSt.Mtim, newSt.Mtim)
625 } else {
626 require.Equal(t, tc.mtim, newSt.Mtim)
627 }
628 })
629 }
630 }
631 }
632
633 func TestDirFS_OpenFile(t *testing.T) {
634 tmpDir := t.TempDir()
635
636
637 tmpDir = path.Join(tmpDir, t.Name())
638 require.NoError(t, os.Mkdir(tmpDir, 0o700))
639 require.NoError(t, fstest.WriteTestFiles(tmpDir))
640
641 testFS := DirFS(tmpDir)
642
643 testOpen_Read(t, testFS, statSetsIno(), true)
644
645 testOpen_O_RDWR(t, tmpDir, testFS)
646
647 t.Run("path outside root valid", func(t *testing.T) {
648 _, err := testFS.OpenFile("../foo", sys.O_RDONLY, 0)
649
650
651 require.True(t, errors.Is(err, fs.ErrNotExist))
652 })
653 }
654
655 func TestDirFS_Stat(t *testing.T) {
656 tmpDir := t.TempDir()
657 require.NoError(t, fstest.WriteTestFiles(tmpDir))
658
659 testFS := DirFS(tmpDir)
660 testStat(t, testFS)
661
662
663 if runtime.GOOS != "windows" {
664 t.Run("strange name", func(t *testing.T) {
665 name := `e:xperi\ment.txt`
666 require.NoError(t, os.WriteFile(path.Join(tmpDir, name), nil, 0o600))
667
668 _, errno := testFS.Stat(name)
669 require.EqualErrno(t, 0, errno)
670 })
671 }
672 }
673
674 func TestDirFS_Readdir(t *testing.T) {
675 root := t.TempDir()
676 testFS := DirFS(root)
677
678 const readDirTarget = "dir"
679 errno := testFS.Mkdir(readDirTarget, 0o700)
680 require.EqualErrno(t, 0, errno)
681
682
683 dirFile, errno := testFS.OpenFile(readDirTarget, sys.O_RDONLY, 0)
684 require.EqualErrno(t, 0, errno)
685 defer dirFile.Close()
686
687
688 require.NoError(t, os.WriteFile(path.Join(root, readDirTarget, "1"), nil, 0o444))
689 require.NoError(t, os.WriteFile(path.Join(root, readDirTarget, "2"), nil, 0o444))
690
691
692
693
694 t.Run("Sees files written after open", func(t *testing.T) {
695 dirents, errno := dirFile.Readdir(1)
696 require.EqualErrno(t, 0, errno)
697
698 require.Equal(t, 1, len(dirents))
699 n := dirents[0].Name
700 switch n {
701 case "1", "2":
702 default:
703 require.Equal(t, "1", n)
704 }
705 })
706
707
708
709
710
711
712 t.Run("sys.ENOENT or no error, deleted while reading", func(t *testing.T) {
713 require.NoError(t, os.RemoveAll(path.Join(root, readDirTarget)))
714
715 dirents, errno := dirFile.Readdir(-1)
716 if errno != 0 {
717 require.EqualErrno(t, sys.ENOENT, errno)
718 }
719
720 require.Equal(t, 0, len(dirents))
721 })
722 }
723
724 func TestDirFS_Link(t *testing.T) {
725 t.Parallel()
726
727
728 tmpDir := t.TempDir()
729 require.NoError(t, fstest.WriteTestFiles(tmpDir))
730
731 testFS := DirFS(tmpDir)
732
733 require.EqualErrno(t, testFS.Link("cat", ""), sys.ENOENT)
734 require.EqualErrno(t, testFS.Link("sub/test.txt", "sub/test.txt"), sys.EEXIST)
735 require.EqualErrno(t, testFS.Link("sub/test.txt", "."), sys.EEXIST)
736 require.EqualErrno(t, testFS.Link("sub/test.txt", ""), sys.EEXIST)
737 require.EqualErrno(t, testFS.Link("sub/test.txt", "/"), sys.EEXIST)
738 require.EqualErrno(t, 0, testFS.Link("sub/test.txt", "foo"))
739 }
740
741 func TestDirFS_Symlink(t *testing.T) {
742 t.Parallel()
743
744
745 tmpDir := t.TempDir()
746 require.NoError(t, fstest.WriteTestFiles(tmpDir))
747
748 testFS := DirFS(tmpDir)
749
750 require.EqualErrno(t, sys.EEXIST, testFS.Symlink("sub/test.txt", "sub/test.txt"))
751
752 require.EqualErrno(t, 0, testFS.Symlink("non-existing", "aa"))
753 require.EqualErrno(t, 0, testFS.Symlink("sub/", "symlinked-subdir"))
754
755 st, err := os.Lstat(path.Join(tmpDir, "aa"))
756 require.NoError(t, err)
757 require.Equal(t, "aa", st.Name())
758 require.True(t, st.Mode()&fs.ModeSymlink > 0 && !st.IsDir())
759
760 st, err = os.Lstat(path.Join(tmpDir, "symlinked-subdir"))
761 require.NoError(t, err)
762 require.Equal(t, "symlinked-subdir", st.Name())
763 require.True(t, st.Mode()&fs.ModeSymlink > 0)
764 }
765
766 func TestDirFS_Readlink(t *testing.T) {
767 tmpDir := t.TempDir()
768 require.NoError(t, fstest.WriteTestFiles(tmpDir))
769
770 testFS := DirFS(tmpDir)
771 testReadlink(t, testFS, testFS)
772 }
773
View as plain text