1
16
17 package files
18
19 import (
20 "fmt"
21 "os"
22 "path/filepath"
23 "testing"
24
25 utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
26 utilfs "k8s.io/kubernetes/pkg/util/filesystem"
27 )
28
29 const (
30 prefix = "test-util-files"
31 )
32
33 type file struct {
34 name string
35
36
37
38 mode os.FileMode
39 data string
40 }
41
42 func (f *file) write(fs utilfs.Filesystem, dir string) error {
43 path := filepath.Join(dir, f.name)
44 if f.mode.IsDir() {
45 if err := fs.MkdirAll(path, defaultPerm); err != nil {
46 return err
47 }
48 } else if f.mode.IsRegular() {
49
50 parents := filepath.Dir(path)
51 if err := fs.MkdirAll(parents, defaultPerm); err != nil {
52 return err
53 }
54
55 handle, err := fs.Create(path)
56 if err != nil {
57 return err
58 }
59 _, err = handle.Write([]byte(f.data))
60
61 if cerr := handle.Close(); cerr != nil {
62 return fmt.Errorf("error closing file: %v", cerr)
63 }
64 if err != nil {
65 return err
66 }
67 } else {
68 return fmt.Errorf("mode not implemented for testing %s", f.mode.String())
69 }
70 return nil
71 }
72
73 func (f *file) expect(fs utilfs.Filesystem, dir string) error {
74 path := filepath.Join(dir, f.name)
75 if f.mode.IsDir() {
76 info, err := fs.Stat(path)
77 if err != nil {
78 return err
79 }
80 if !info.IsDir() {
81 return fmt.Errorf("expected directory, got mode %s", info.Mode().String())
82 }
83 } else if f.mode.IsRegular() {
84 info, err := fs.Stat(path)
85 if err != nil {
86 return err
87 }
88 if !info.Mode().IsRegular() {
89 return fmt.Errorf("expected regular file, got mode %s", info.Mode().String())
90 }
91 data, err := fs.ReadFile(path)
92 if err != nil {
93 return err
94 }
95 if f.data != string(data) {
96 return fmt.Errorf("expected file data %q, got %q", f.data, string(data))
97 }
98 } else {
99 return fmt.Errorf("mode not implemented for testing %s", f.mode.String())
100 }
101 return nil
102 }
103
104
105
106
107 type test struct {
108 desc string
109 writes []file
110 expects []file
111 fn func(fs utilfs.Filesystem, dir string, c *test) []error
112 err string
113 }
114
115 func (c *test) write(t *testing.T, fs utilfs.Filesystem, dir string) {
116 for _, f := range c.writes {
117 if err := f.write(fs, dir); err != nil {
118 t.Fatalf("error pre-writing file: %v", err)
119 }
120 }
121 }
122
123
124
125 func (c *test) expect(t *testing.T, fs utilfs.Filesystem, dir string) []error {
126 errs := []error{}
127 for _, f := range c.expects {
128 if err := f.expect(fs, dir); err != nil {
129 msg := fmt.Errorf("expect %#v, got error: %v", f, err)
130 errs = append(errs, msg)
131 if t != nil {
132 t.Errorf("%s", msg)
133 }
134 }
135 }
136 return errs
137 }
138
139
140
141
142 func (c *test) run(t *testing.T, fs utilfs.Filesystem) {
143
144 dir, err := fs.TempDir("", prefix)
145 if err != nil {
146 t.Fatalf("error creating temporary directory for test: %v", err)
147 }
148 defer os.RemoveAll(dir)
149 c.write(t, fs, dir)
150
151 if c.fn != nil {
152 errs := c.fn(fs, dir, c)
153 if len(errs) > 0 {
154 for _, err := range errs {
155 utiltest.ExpectError(t, err, c.err)
156 }
157
158
159 return
160 }
161 c.expect(t, fs, dir)
162 return
163 }
164
165
166 errs := c.expect(nil, fs, dir)
167 for _, err := range errs {
168 utiltest.ExpectError(t, err, c.err)
169 }
170 }
171
172
173 func TestHelpers(t *testing.T) {
174
175 cases := []test{
176 {
177 desc: "regular file",
178 writes: []file{{name: "foo", data: "bar"}},
179 expects: []file{{name: "foo", data: "bar"}},
180 },
181 {
182 desc: "directory",
183 writes: []file{{name: "foo", mode: os.ModeDir}},
184 expects: []file{{name: "foo", mode: os.ModeDir}},
185 },
186 {
187 desc: "deep regular file",
188 writes: []file{{name: "foo/bar", data: "baz"}},
189 expects: []file{{name: "foo/bar", data: "baz"}},
190 },
191 {
192 desc: "deep directory",
193 writes: []file{{name: "foo/bar", mode: os.ModeDir}},
194 expects: []file{{name: "foo/bar", mode: os.ModeDir}},
195 },
196 {
197 desc: "missing file",
198 expects: []file{{name: "foo", data: "bar"}},
199 err: missingFileError,
200 },
201 {
202 desc: "missing directory",
203 expects: []file{{name: "foo/bar", mode: os.ModeDir}},
204 err: missingFolderError,
205 },
206 }
207 for _, c := range cases {
208 t.Run(c.desc, func(t *testing.T) {
209 c.run(t, &utilfs.DefaultFs{})
210 })
211 }
212 }
213
214 func TestFileExists(t *testing.T) {
215 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
216 ok, err := FileExists(fs, filepath.Join(dir, "foo"))
217 if err != nil {
218 return []error{err}
219 }
220 if !ok {
221 return []error{fmt.Errorf("does not exist (test)")}
222 }
223 return nil
224 }
225 cases := []test{
226 {
227 fn: fn,
228 desc: "file exists",
229 writes: []file{{name: "foo"}},
230 },
231 {
232 fn: fn,
233 desc: "file does not exist",
234 err: "does not exist (test)",
235 },
236 {
237 fn: fn,
238 desc: "object has non-file mode",
239 writes: []file{{name: "foo", mode: os.ModeDir}},
240 err: "expected regular file",
241 },
242 }
243 for _, c := range cases {
244 t.Run(c.desc, func(t *testing.T) {
245 c.run(t, &utilfs.DefaultFs{})
246 })
247 }
248 }
249
250 func TestEnsureFile(t *testing.T) {
251 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
252 var errs []error
253 for _, f := range c.expects {
254 if err := EnsureFile(fs, filepath.Join(dir, f.name)); err != nil {
255 errs = append(errs, err)
256 }
257 }
258 return errs
259 }
260 cases := []test{
261 {
262 fn: fn,
263 desc: "file exists",
264 writes: []file{{name: "foo"}},
265 expects: []file{{name: "foo"}},
266 },
267 {
268 fn: fn,
269 desc: "file does not exist",
270 expects: []file{{name: "bar"}},
271 },
272 {
273 fn: fn,
274 desc: "neither parent nor file exists",
275 expects: []file{{name: "baz/quux"}},
276 },
277 }
278 for _, c := range cases {
279 t.Run(c.desc, func(t *testing.T) {
280 c.run(t, &utilfs.DefaultFs{})
281 })
282 }
283 }
284
285
286 func TestReplaceFile(t *testing.T) {
287 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
288 var errs []error
289 for _, f := range c.expects {
290 if err := ReplaceFile(fs, filepath.Join(dir, f.name), []byte(f.data)); err != nil {
291 errs = append(errs, err)
292 }
293 }
294 return errs
295 }
296 cases := []test{
297 {
298 fn: fn,
299 desc: "file exists",
300 writes: []file{{name: "foo"}},
301 expects: []file{{name: "foo", data: "bar"}},
302 },
303 {
304 fn: fn,
305 desc: "file does not exist",
306 expects: []file{{name: "foo", data: "bar"}},
307 },
308 {
309 fn: func(fs utilfs.Filesystem, dir string, c *test) []error {
310 if err := ReplaceFile(fs, filepath.Join(dir, "foo/bar"), []byte("")); err != nil {
311 return []error{err}
312 }
313 return nil
314 },
315 desc: "neither parent nor file exists",
316 err: missingFolderError,
317 },
318 }
319 for _, c := range cases {
320 t.Run(c.desc, func(t *testing.T) {
321 c.run(t, &utilfs.DefaultFs{})
322 })
323 }
324 }
325
326 func TestDirExists(t *testing.T) {
327 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
328 ok, err := DirExists(fs, filepath.Join(dir, "foo"))
329 if err != nil {
330 return []error{err}
331 }
332 if !ok {
333 return []error{fmt.Errorf("does not exist (test)")}
334 }
335 return nil
336 }
337 cases := []test{
338 {
339 fn: fn,
340 desc: "dir exists",
341 writes: []file{{name: "foo", mode: os.ModeDir}},
342 },
343 {
344 fn: fn,
345 desc: "dir does not exist",
346 err: "does not exist (test)",
347 },
348 {
349 fn: fn,
350 desc: "object has non-dir mode",
351 writes: []file{{name: "foo"}},
352 err: "expected dir",
353 },
354 }
355 for _, c := range cases {
356 t.Run(c.desc, func(t *testing.T) {
357 c.run(t, &utilfs.DefaultFs{})
358 })
359 }
360 }
361
362 func TestEnsureDir(t *testing.T) {
363 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
364 var errs []error
365 for _, f := range c.expects {
366 if err := EnsureDir(fs, filepath.Join(dir, f.name)); err != nil {
367 errs = append(errs, err)
368 }
369 }
370 return errs
371 }
372 cases := []test{
373 {
374 fn: fn,
375 desc: "dir exists",
376 writes: []file{{name: "foo", mode: os.ModeDir}},
377 expects: []file{{name: "foo", mode: os.ModeDir}},
378 },
379 {
380 fn: fn,
381 desc: "dir does not exist",
382 expects: []file{{name: "bar", mode: os.ModeDir}},
383 },
384 {
385 fn: fn,
386 desc: "neither parent nor dir exists",
387 expects: []file{{name: "baz/quux", mode: os.ModeDir}},
388 },
389 }
390 for _, c := range cases {
391 t.Run(c.desc, func(t *testing.T) {
392 c.run(t, &utilfs.DefaultFs{})
393 })
394 }
395 }
396
397 func TestWriteTempDir(t *testing.T) {
398
399 c := test{
400 desc: "invalid file key",
401 err: "invalid file key",
402 fn: func(fs utilfs.Filesystem, dir string, c *test) []error {
403 if _, err := WriteTempDir(fs, filepath.Join(dir, "tmpdir"), map[string]string{"foo/bar": ""}); err != nil {
404 return []error{err}
405 }
406 return nil
407 },
408 }
409 c.run(t, &utilfs.DefaultFs{})
410 }
411
412 func TestReplaceDir(t *testing.T) {
413 fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
414 errs := []error{}
415
416
417
418 dirs := map[string]map[string]string{}
419
420
421 for _, f := range c.expects {
422 if f.mode.IsDir() {
423 path := filepath.Join(dir, f.name)
424 if _, ok := dirs[path]; !ok {
425 dirs[path] = map[string]string{}
426 }
427 } else if f.mode.IsRegular() {
428 path := filepath.Join(dir, filepath.Dir(f.name))
429 if _, ok := dirs[path]; !ok {
430
431 errs = append(errs, fmt.Errorf("no prior parent directory in c.expects for file %s", f.name))
432 continue
433 }
434 dirs[path][filepath.Base(f.name)] = f.data
435 }
436 }
437
438
439 if len(errs) > 0 {
440 return errs
441 }
442
443
444 for path, files := range dirs {
445 if err := ReplaceDir(fs, path, files); err != nil {
446 errs = append(errs, err)
447 }
448 }
449 return errs
450 }
451 cases := []test{
452 {
453 fn: fn,
454 desc: "fn catches invalid test case",
455 expects: []file{{name: "foo/bar"}},
456 err: "no prior parent directory",
457 },
458 {
459 fn: fn,
460 desc: "empty dir",
461 expects: []file{{name: "foo", mode: os.ModeDir}},
462 },
463 {
464 fn: fn,
465 desc: "dir with files",
466 expects: []file{
467 {name: "foo", mode: os.ModeDir},
468 {name: "foo/bar", data: "baz"},
469 {name: "foo/baz", data: "bar"},
470 },
471 },
472 }
473 for _, c := range cases {
474 t.Run(c.desc, func(t *testing.T) {
475 c.run(t, &utilfs.DefaultFs{})
476 })
477 }
478 }
479
View as plain text