1
2
3
4
5 package embedtest
6
7 import (
8 "embed"
9 "io"
10 "reflect"
11 "slices"
12 "testing"
13 "testing/fstest"
14 )
15
16
17
18 var global embed.FS
19
20
21 var concurrency string
22
23
24 var glass []byte
25
26 func testFiles(t *testing.T, f embed.FS, name, data string) {
27 t.Helper()
28 d, err := f.ReadFile(name)
29 if err != nil {
30 t.Error(err)
31 return
32 }
33 if string(d) != data {
34 t.Errorf("read %v = %q, want %q", name, d, data)
35 }
36 }
37
38 func testString(t *testing.T, s, name, data string) {
39 t.Helper()
40 if s != data {
41 t.Errorf("%v = %q, want %q", name, s, data)
42 }
43 }
44
45 func testDir(t *testing.T, f embed.FS, name string, expect ...string) {
46 t.Helper()
47 dirs, err := f.ReadDir(name)
48 if err != nil {
49 t.Error(err)
50 return
51 }
52 var names []string
53 for _, d := range dirs {
54 name := d.Name()
55 if d.IsDir() {
56 name += "/"
57 }
58 names = append(names, name)
59 }
60 if !slices.Equal(names, expect) {
61 t.Errorf("readdir %v = %v, want %v", name, names, expect)
62 }
63 }
64
65
66 var _ = '"'
67 var _ = '\''
68 var _ = '🦆'
69
70 func TestGlobal(t *testing.T) {
71 testFiles(t, global, "concurrency.txt", "Concurrency is not parallelism.\n")
72 testFiles(t, global, "testdata/hello.txt", "hello, world\n")
73 testFiles(t, global, "testdata/glass.txt", "I can eat glass and it doesn't hurt me.\n")
74
75 if err := fstest.TestFS(global, "concurrency.txt", "testdata/hello.txt"); err != nil {
76 t.Fatal(err)
77 }
78
79 testString(t, concurrency, "concurrency", "Concurrency is not parallelism.\n")
80 testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
81 }
82
83
84 var testDirAll embed.FS
85
86 func TestDir(t *testing.T) {
87 all := testDirAll
88 testFiles(t, all, "testdata/hello.txt", "hello, world\n")
89 testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n")
90 testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n")
91 testFiles(t, all, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
92
93 testDir(t, all, ".", "testdata/")
94 testDir(t, all, "testdata/i", "i18n.txt", "j/")
95 testDir(t, all, "testdata/i/j", "k/")
96 testDir(t, all, "testdata/i/j/k", "k8s.txt")
97 }
98
99 var (
100
101 testHiddenDir embed.FS
102
103
104 testHiddenStar embed.FS
105 )
106
107 func TestHidden(t *testing.T) {
108 dir := testHiddenDir
109 star := testHiddenStar
110
111 t.Logf("//go:embed testdata")
112
113 testDir(t, dir, "testdata",
114 "-not-hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
115
116 t.Logf("//go:embed testdata/*")
117
118 testDir(t, star, "testdata",
119 "-not-hidden/", ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
120
121 testDir(t, star, "testdata/.hidden",
122 "fortune.txt", "more/")
123 }
124
125 func TestUninitialized(t *testing.T) {
126 var uninitialized embed.FS
127 testDir(t, uninitialized, ".")
128 f, err := uninitialized.Open(".")
129 if err != nil {
130 t.Fatal(err)
131 }
132 defer f.Close()
133 fi, err := f.Stat()
134 if err != nil {
135 t.Fatal(err)
136 }
137 if !fi.IsDir() {
138 t.Errorf("in uninitialized embed.FS, . is not a directory")
139 }
140 }
141
142 var (
143
144 helloT []T
145
146 helloUint8 []uint8
147
148 helloEUint8 []EmbedUint8
149
150 helloBytes EmbedBytes
151
152 helloString EmbedString
153 )
154
155 type T byte
156 type EmbedUint8 uint8
157 type EmbedBytes []byte
158 type EmbedString string
159
160
161 func TestAliases(t *testing.T) {
162 all := testDirAll
163 want, e := all.ReadFile("testdata/hello.txt")
164 if e != nil {
165 t.Fatal("ReadFile:", e)
166 }
167 check := func(g any) {
168 got := reflect.ValueOf(g)
169 for i := 0; i < got.Len(); i++ {
170 if byte(got.Index(i).Uint()) != want[i] {
171 t.Fatalf("got %v want %v", got.Bytes(), want)
172 }
173 }
174 }
175 check(helloT)
176 check(helloUint8)
177 check(helloEUint8)
178 check(helloBytes)
179 check(helloString)
180 }
181
182 func TestOffset(t *testing.T) {
183 file, err := testDirAll.Open("testdata/hello.txt")
184 if err != nil {
185 t.Fatal("Open:", err)
186 }
187
188 want := "hello, world\n"
189
190
191 got := make([]byte, len(want))
192 n, err := file.Read(got)
193 if err != nil {
194 t.Fatal("Read:", err)
195 }
196 if n != len(want) {
197 t.Fatal("Read:", n)
198 }
199 if string(got) != want {
200 t.Fatalf("Read: %q", got)
201 }
202
203
204 var buf [1]byte
205 n, err = file.Read(buf[:])
206 if err != io.EOF {
207 t.Fatal("Read:", err)
208 }
209 if n != 0 {
210 t.Fatal("Read:", n)
211 }
212
213
214 seeker := file.(io.Seeker)
215 off, err := seeker.Seek(0, io.SeekCurrent)
216 if err != nil {
217 t.Fatal("Seek:", err)
218 }
219 if off != int64(len(want)) {
220 t.Fatal("Seek:", off)
221 }
222
223
224 at := file.(io.ReaderAt)
225 got = make([]byte, len(want))
226 n, err = at.ReadAt(got, 0)
227 if err != nil {
228 t.Fatal("ReadAt:", err)
229 }
230 if n != len(want) {
231 t.Fatalf("ReadAt: got %d bytes, want %d bytes", n, len(want))
232 }
233 if string(got) != want {
234 t.Fatalf("ReadAt: got %q, want %q", got, want)
235 }
236
237
238 off = int64(7)
239 want = want[off:]
240 got = make([]byte, len(want))
241 n, err = at.ReadAt(got, off)
242 if err != nil {
243 t.Fatal("ReadAt:", err)
244 }
245 if n != len(want) {
246 t.Fatalf("ReadAt: got %d bytes, want %d bytes", n, len(want))
247 }
248 if string(got) != want {
249 t.Fatalf("ReadAt: got %q, want %q", got, want)
250 }
251 }
252
View as plain text