1
2
3
4
5 package fstest
6
7 import (
8 "errors"
9 "fmt"
10 "io"
11 "io/fs"
12 "strings"
13 "testing"
14 )
15
16 func TestMapFS(t *testing.T) {
17 m := MapFS{
18 "hello": {Data: []byte("hello, world\n")},
19 "fortune/k/ken.txt": {Data: []byte("If a program is too slow, it must have a loop.\n")},
20 }
21 if err := TestFS(m, "hello", "fortune", "fortune/k", "fortune/k/ken.txt"); err != nil {
22 t.Fatal(err)
23 }
24 }
25
26 func TestMapFSChmodDot(t *testing.T) {
27 m := MapFS{
28 "a/b.txt": &MapFile{Mode: 0666},
29 ".": &MapFile{Mode: 0777 | fs.ModeDir},
30 }
31 buf := new(strings.Builder)
32 fs.WalkDir(m, ".", func(path string, d fs.DirEntry, err error) error {
33 fi, err := d.Info()
34 if err != nil {
35 return err
36 }
37 fmt.Fprintf(buf, "%s: %v\n", path, fi.Mode())
38 return nil
39 })
40 want := `
41 .: drwxrwxrwx
42 a: dr-xr-xr-x
43 a/b.txt: -rw-rw-rw-
44 `[1:]
45 got := buf.String()
46 if want != got {
47 t.Errorf("MapFS modes want:\n%s\ngot:\n%s\n", want, got)
48 }
49 }
50
51 func TestMapFSFileInfoName(t *testing.T) {
52 m := MapFS{
53 "path/to/b.txt": &MapFile{},
54 }
55 info, _ := m.Stat("path/to/b.txt")
56 want := "b.txt"
57 got := info.Name()
58 if want != got {
59 t.Errorf("MapFS FileInfo.Name want:\n%s\ngot:\n%s\n", want, got)
60 }
61 }
62
63 func TestMapFSSymlink(t *testing.T) {
64 const fileContent = "If a program is too slow, it must have a loop.\n"
65 m := MapFS{
66 "fortune/k/ken.txt": {Data: []byte(fileContent)},
67 "dirlink": {Data: []byte("fortune/k"), Mode: fs.ModeSymlink},
68 "linklink": {Data: []byte("dirlink"), Mode: fs.ModeSymlink},
69 "ken.txt": {Data: []byte("dirlink/ken.txt"), Mode: fs.ModeSymlink},
70 }
71 if err := TestFS(m, "fortune/k/ken.txt", "dirlink", "ken.txt", "linklink"); err != nil {
72 t.Error(err)
73 }
74
75 gotData, err := fs.ReadFile(m, "ken.txt")
76 if string(gotData) != fileContent || err != nil {
77 t.Errorf("fs.ReadFile(m, \"ken.txt\") = %q, %v; want %q, <nil>", gotData, err, fileContent)
78 }
79 gotLink, err := fs.ReadLink(m, "dirlink")
80 if want := "fortune/k"; gotLink != want || err != nil {
81 t.Errorf("fs.ReadLink(m, \"dirlink\") = %q, %v; want %q, <nil>", gotLink, err, fileContent)
82 }
83 gotInfo, err := fs.Lstat(m, "dirlink")
84 if err != nil {
85 t.Errorf("fs.Lstat(m, \"dirlink\") = _, %v; want _, <nil>", err)
86 } else {
87 if got, want := gotInfo.Name(), "dirlink"; got != want {
88 t.Errorf("fs.Lstat(m, \"dirlink\").Name() = %q; want %q", got, want)
89 }
90 if got, want := gotInfo.Mode(), fs.ModeSymlink; got != want {
91 t.Errorf("fs.Lstat(m, \"dirlink\").Mode() = %v; want %v", got, want)
92 }
93 }
94 gotInfo, err = fs.Stat(m, "dirlink")
95 if err != nil {
96 t.Errorf("fs.Stat(m, \"dirlink\") = _, %v; want _, <nil>", err)
97 } else {
98 if got, want := gotInfo.Name(), "dirlink"; got != want {
99 t.Errorf("fs.Stat(m, \"dirlink\").Name() = %q; want %q", got, want)
100 }
101 if got, want := gotInfo.Mode(), fs.ModeDir|0555; got != want {
102 t.Errorf("fs.Stat(m, \"dirlink\").Mode() = %v; want %v", got, want)
103 }
104 }
105 gotInfo, err = fs.Lstat(m, "linklink")
106 if err != nil {
107 t.Errorf("fs.Lstat(m, \"linklink\") = _, %v; want _, <nil>", err)
108 } else {
109 if got, want := gotInfo.Name(), "linklink"; got != want {
110 t.Errorf("fs.Lstat(m, \"linklink\").Name() = %q; want %q", got, want)
111 }
112 if got, want := gotInfo.Mode(), fs.ModeSymlink; got != want {
113 t.Errorf("fs.Lstat(m, \"linklink\").Mode() = %v; want %v", got, want)
114 }
115 }
116 gotInfo, err = fs.Stat(m, "linklink")
117 if err != nil {
118 t.Errorf("fs.Stat(m, \"linklink\") = _, %v; want _, <nil>", err)
119 } else {
120 if got, want := gotInfo.Name(), "linklink"; got != want {
121 t.Errorf("fs.Stat(m, \"linklink\").Name() = %q; want %q", got, want)
122 }
123 if got, want := gotInfo.Mode(), fs.ModeDir|0555; got != want {
124 t.Errorf("fs.Stat(m, \"linklink\").Mode() = %v; want %v", got, want)
125 }
126 }
127 }
128
129 func TestMapFSReadAt(t *testing.T) {
130 const fileContent = "hello, world\n"
131 m := MapFS{
132 "hello": {Data: []byte(fileContent)},
133 }
134 f, err := m.Open("hello")
135 if err != nil {
136 t.Error(err)
137 }
138 r, ok := f.(io.ReaderAt)
139 if !ok {
140 t.Errorf("Open file does not implement io.ReaderAt")
141 }
142 buf := make([]byte, 1)
143
144 n, err := r.ReadAt(buf, 0)
145 if n != 1 || err != nil {
146 t.Errorf("ReadAt(buf, 0) = %d, %v; want 1, <nil>", n, err)
147 }
148
149 n, err = r.ReadAt(buf, int64(len(fileContent)))
150 if n != 0 || err != io.EOF {
151 t.Errorf("ReadAt(buf, len(fileContent)) = %d, %v; want 0, io.EOF", n, err)
152 }
153
154 n, err = r.ReadAt(buf, int64(len(fileContent)+1))
155 if n != 0 || err != io.EOF {
156 t.Errorf("ReadAt(buf, len(fileContent)+1) = %d, %v; want 0, io.EOF", n, err)
157 }
158 }
159
160 func TestMapFSSeek(t *testing.T) {
161 m := MapFS{
162 "hello": {Data: []byte("hello, world\n")},
163 }
164 f, err := m.Open("hello")
165 if err != nil {
166 t.Error(err)
167 }
168 defer f.Close()
169 s := f.(io.Seeker)
170 _, err = s.Seek(0, io.SeekEnd+5)
171 if err == nil {
172 t.Errorf("Seek: expected error for invalid whence")
173 }
174 if !errors.Is(err, fs.ErrInvalid) {
175 t.Errorf("Seek: expected fs.ErrInvalid, got %v", err)
176 }
177 }
178
View as plain text