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