Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: go/src/infra/tools/cipd/files_test.go

Issue 1129043003: cipd: Refactor client to make it more readable. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « go/src/infra/tools/cipd/files.go ('k') | go/src/infra/tools/cipd/local/builder.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package cipd
6
7 import (
8 "io/ioutil"
9 "os"
10 "path/filepath"
11 "testing"
12
13 . "github.com/smartystreets/goconvey/convey"
14 )
15
16 func TestScanFileSystem(t *testing.T) {
17 Convey("Given a temp directory", t, func() {
18 tempDir, err := ioutil.TempDir("", "cipd_test")
19 So(err, ShouldBeNil)
20 Reset(func() { os.RemoveAll(tempDir) })
21
22 Convey("Scan empty dir works", func() {
23 files, err := ScanFileSystem(tempDir, tempDir, nil)
24 So(files, ShouldBeEmpty)
25 So(err, ShouldBeNil)
26 })
27
28 Convey("Discovering single file works", func() {
29 writeFile(tempDir, "single_file", "12345", 0666)
30 files, err := ScanFileSystem(tempDir, tempDir, nil)
31 So(len(files), ShouldEqual, 1)
32 So(err, ShouldBeNil)
33
34 file := files[0]
35 So(file.Name(), ShouldEqual, "single_file")
36 So(file.Size(), ShouldEqual, uint64(5))
37 So(file.Executable(), ShouldBeFalse)
38
39 r, err := file.Open()
40 if r != nil {
41 defer r.Close()
42 }
43 So(err, ShouldBeNil)
44 buf, err := ioutil.ReadAll(r)
45 So(buf, ShouldResemble, []byte("12345"))
46 So(err, ShouldBeNil)
47 })
48
49 Convey("Discovering single executable file works", func() {
50 writeFile(tempDir, "single_file", "12345", 0766)
51 files, err := ScanFileSystem(tempDir, tempDir, nil)
52 So(len(files), ShouldEqual, 1)
53 So(err, ShouldBeNil)
54 file := files[0]
55 So(file.Executable(), ShouldBeTrue)
56 })
57
58 Convey("Relative symlink to outside of package cause error", fun c() {
59 writeSymlink(tempDir, "a/b1/rel_symlink", filepath.FromS lash("../../.."))
60 _, err := ScanFileSystem(tempDir, tempDir, nil)
61 So(err, ShouldNotBeNil)
62 })
63
64 Convey("Enumerating subdirectories", func() {
65 writeFile(tempDir, "a", "", 0666)
66 writeFile(tempDir, "b", "", 0666)
67 writeFile(tempDir, "1/a", "", 0666)
68 writeFile(tempDir, "1/b", "", 0666)
69 writeFile(tempDir, "1/2/a", "", 0666)
70 files, err := ScanFileSystem(tempDir, tempDir, nil)
71 So(err, ShouldBeNil)
72 names := []string{}
73 for _, f := range files {
74 names = append(names, f.Name())
75 }
76 // Order matters. Slashes matters.
77 So(names, ShouldResemble, []string{
78 "1/2/a",
79 "1/a",
80 "1/b",
81 "a",
82 "b",
83 })
84 })
85
86 Convey("Empty subdirectories are skipped", func() {
87 mkDir(tempDir, "a")
88 mkDir(tempDir, "1/2/3")
89 mkDir(tempDir, "1/c")
90 writeFile(tempDir, "1/d/file", "1234", 0666)
91 files, err := ScanFileSystem(tempDir, tempDir, nil)
92 So(len(files), ShouldEqual, 1)
93 So(err, ShouldBeNil)
94 So(files[0].Name(), ShouldEqual, "1/d/file")
95 })
96
97 Convey("Non root start path works", func() {
98 writeFile(tempDir, "a", "", 0666)
99 writeFile(tempDir, "b", "", 0666)
100 writeFile(tempDir, "1/a", "", 0666)
101 writeFile(tempDir, "1/b", "", 0666)
102 writeFile(tempDir, "1/2/a", "", 0666)
103 files, err := ScanFileSystem(filepath.Join(tempDir, "1") , tempDir, nil)
104 So(err, ShouldBeNil)
105 names := []string{}
106 for _, f := range files {
107 names = append(names, f.Name())
108 }
109 // Order matters. Slashes matters.
110 So(names, ShouldResemble, []string{
111 "1/2/a",
112 "1/a",
113 "1/b",
114 })
115 })
116
117 Convey("Start path must be under root", func() {
118 _, err := ScanFileSystem(filepath.Dir(tempDir), tempDir, nil)
119 So(err, ShouldNotBeNil)
120 })
121
122 Convey("Exclude filter works", func() {
123 writeFile(tempDir, "a", "", 0666)
124 writeFile(tempDir, "b", "", 0666)
125 writeFile(tempDir, "1/a", "", 0666)
126 writeFile(tempDir, "1/b", "", 0666)
127 writeFile(tempDir, "1/2/a", "", 0666)
128
129 // Exclude "a" and entire "1/" directory.
130 excluderCalls := []string{}
131 excluder := func(abs string) bool {
132 excluderCalls = append(excluderCalls, abs)
133 if abs == filepath.Join(tempDir, "a") {
134 return true
135 }
136 if abs == filepath.Join(tempDir, "1") {
137 return true
138 }
139 return false
140 }
141
142 files, err := ScanFileSystem(tempDir, tempDir, excluder)
143 So(err, ShouldBeNil)
144 So(len(files), ShouldEqual, 1)
145 So(files[0].Name(), ShouldEqual, "b")
146
147 // "1/*" subdir should have been skipped completely.
148 So(excluderCalls, ShouldResemble, []string{
149 filepath.Join(tempDir, "1"),
150 filepath.Join(tempDir, "a"),
151 filepath.Join(tempDir, "b"),
152 })
153 })
154 })
155 }
156
157 func TestWrapFile(t *testing.T) {
158 Convey("Given a temp directory", t, func() {
159 tempDir, err := ioutil.TempDir("", "cipd_test")
160 So(err, ShouldBeNil)
161 Reset(func() { os.RemoveAll(tempDir) })
162
163 Convey("WrapFile simple file works", func() {
164 writeFile(tempDir, "dir/a/b", "12345", 0666)
165 out, err := WrapFile(filepath.Join(tempDir, "dir", "a", "b"), tempDir, nil)
166 So(err, ShouldBeNil)
167 So(out.Name(), ShouldEqual, "dir/a/b")
168 })
169
170 Convey("WrapFile executable file works", func() {
171 writeFile(tempDir, "single_file", "12345", 0766)
172 out, err := WrapFile(filepath.Join(tempDir, "single_file "), tempDir, nil)
173 So(err, ShouldBeNil)
174 So(out.Executable(), ShouldBeTrue)
175 })
176
177 Convey("WrapFile directory fails", func() {
178 mkDir(tempDir, "dir")
179 _, err := WrapFile(filepath.Join(tempDir, "dir"), tempDi r, nil)
180 So(err, ShouldNotBeNil)
181 })
182
183 Convey("WrapFile outside of root fails", func() {
184 mkDir(tempDir, "a")
185 writeFile(tempDir, "b", "body", 0666)
186 _, err := WrapFile(filepath.Join(tempDir, "b"), filepath .Join(tempDir, "a"), nil)
187 So(err, ShouldNotBeNil)
188 })
189
190 Convey("WrapFile outside of root fails (tricky path)", func() {
191 mkDir(tempDir, "a")
192 // "abc" starts with "a", it tricks naive string.HasPref ix subpath check.
193 writeFile(tempDir, "abc", "body", 0666)
194 _, err := WrapFile(filepath.Join(tempDir, "abc"), filepa th.Join(tempDir, "a"), nil)
195 So(err, ShouldNotBeNil)
196 })
197
198 Convey("WrapFile rel symlink in root", func() {
199 writeSymlink(tempDir, "a/b/c", filepath.FromSlash("../.. /d"))
200 mkDir(tempDir, "d")
201 out, err := WrapFile(filepath.Join(tempDir, "a", "b", "c "), tempDir, nil)
202 So(err, ShouldBeNil)
203 ensureSymlinkTarget(out, "../../d")
204 })
205
206 Convey("WrapFile rel symlink outside root", func() {
207 writeSymlink(tempDir, "a/b/c", filepath.FromSlash("../.. /../d"))
208 _, err := WrapFile(filepath.Join(tempDir, "a", "b", "c") , tempDir, nil)
209 So(err, ShouldNotBeNil)
210 })
211
212 Convey("WrapFile abs symlink in root", func() {
213 writeSymlink(tempDir, "a/b/c", filepath.Join(tempDir, "a ", "d"))
214 out, err := WrapFile(filepath.Join(tempDir, "a", "b", "c "), tempDir, nil)
215 So(err, ShouldBeNil)
216 ensureSymlinkTarget(out, "../d")
217 })
218
219 Convey("WrapFile abs symlink outside root", func() {
220 writeSymlink(tempDir, "a/b/c", filepath.Dir(tempDir))
221 out, err := WrapFile(filepath.Join(tempDir, "a", "b", "c "), tempDir, nil)
222 So(err, ShouldBeNil)
223 ensureSymlinkTarget(out, filepath.ToSlash(filepath.Dir(t empDir)))
224 })
225 })
226 }
227
228 func mkDir(root string, path string) {
229 abs := filepath.Join(root, filepath.FromSlash(path))
230 err := os.MkdirAll(abs, 0777)
231 if err != nil {
232 panic("Failed to create a directory under temp directory")
233 }
234 }
235
236 func writeFile(root string, path string, data string, mode os.FileMode) {
237 abs := filepath.Join(root, filepath.FromSlash(path))
238 os.MkdirAll(filepath.Dir(abs), 0777)
239 err := ioutil.WriteFile(abs, []byte(data), mode)
240 if err != nil {
241 panic("Failed to write a temp file")
242 }
243 }
244
245 func writeSymlink(root string, path string, target string) {
246 abs := filepath.Join(root, filepath.FromSlash(path))
247 os.MkdirAll(filepath.Dir(abs), 0777)
248 err := os.Symlink(target, abs)
249 if err != nil {
250 panic("Failed to create symlink")
251 }
252 }
253
254 func ensureSymlinkTarget(file File, target string) {
255 So(file.Symlink(), ShouldBeTrue)
256 discoveredTarget, err := file.SymlinkTarget()
257 So(err, ShouldBeNil)
258 So(discoveredTarget, ShouldEqual, target)
259 }
260
261 func TestFileSystemDestination(t *testing.T) {
262 Convey("Given a temp directory", t, func() {
263 tempDir, err := ioutil.TempDir("", "cipd_test")
264 destDir := filepath.Join(tempDir, "dest")
265 So(err, ShouldBeNil)
266 dest := NewFileSystemDestination(destDir)
267 Reset(func() { os.RemoveAll(tempDir) })
268
269 writeFileToDest := func(name string, executable bool, data strin g) {
270 writer, err := dest.CreateFile(name, executable)
271 if writer != nil {
272 defer writer.Close()
273 }
274 So(err, ShouldBeNil)
275 _, err = writer.Write([]byte(data))
276 So(err, ShouldBeNil)
277 }
278
279 writeSymlinkToDest := func(name string, target string) {
280 err := dest.CreateSymlink(name, target)
281 So(err, ShouldBeNil)
282 }
283
284 Convey("Empty success write works", func() {
285 So(dest.Begin(), ShouldBeNil)
286 So(dest.End(true), ShouldBeNil)
287
288 // Should create a new directory.
289 stat, err := os.Stat(destDir)
290 So(err, ShouldBeNil)
291 So(stat.IsDir(), ShouldBeTrue)
292
293 // And it should be empty.
294 files, err := ScanFileSystem(destDir, destDir, nil)
295 So(err, ShouldBeNil)
296 So(len(files), ShouldEqual, 0)
297 })
298
299 Convey("Empty failed write works", func() {
300 So(dest.Begin(), ShouldBeNil)
301 So(dest.End(false), ShouldBeNil)
302
303 // Doesn't create a directory.
304 _, err := os.Stat(destDir)
305 So(os.IsNotExist(err), ShouldBeTrue)
306 })
307
308 Convey("Double begin or double end fails", func() {
309 So(dest.Begin(), ShouldBeNil)
310 So(dest.Begin(), ShouldNotBeNil)
311 So(dest.End(true), ShouldBeNil)
312 So(dest.End(true), ShouldNotBeNil)
313 })
314
315 Convey("CreateFile works only when destination is open", func() {
316 wr, err := dest.CreateFile("testing", true)
317 So(wr, ShouldBeNil)
318 So(err, ShouldNotBeNil)
319 })
320
321 Convey("CreateFile rejects invalid relative paths", func() {
322 So(dest.Begin(), ShouldBeNil)
323 defer dest.End(true)
324
325 // Rel path that is still inside the package is ok.
326 wr, err := dest.CreateFile("a/b/c/../../../d", false)
327 So(err, ShouldBeNil)
328 wr.Close()
329
330 // Rel path pointing outside is forbidden.
331 _, err = dest.CreateFile("a/b/c/../../../../d", false)
332 So(err, ShouldNotBeNil)
333 })
334
335 Convey("CreateSymlink rejects invalid relative paths", func() {
336 So(dest.Begin(), ShouldBeNil)
337 defer dest.End(true)
338
339 // Rel symlink to a file inside the destination is OK.
340 So(dest.CreateSymlink("a/b/c", "../.."), ShouldBeNil)
341 // Rel symlink to a file outside -> error.
342 So(dest.CreateSymlink("a/b/c", "../../.."), ShouldNotBeN il)
343 })
344
345 Convey("Committing bunch of files works", func() {
346 So(dest.Begin(), ShouldBeNil)
347 writeFileToDest("a", false, "a data")
348 writeFileToDest("exe", true, "exe data")
349 writeFileToDest("dir/c", false, "dir/c data")
350 writeFileToDest("dir/dir/d", false, "dir/dir/c data")
351 writeSymlinkToDest("abs_symlink", filepath.FromSlash(tem pDir))
352 writeSymlinkToDest("dir/dir/rel_symlink", "../../a")
353 So(dest.End(true), ShouldBeNil)
354
355 // Ensure everything is there.
356 files, err := ScanFileSystem(destDir, destDir, nil)
357 So(err, ShouldBeNil)
358 names := []string{}
359 for _, f := range files {
360 names = append(names, f.Name())
361 }
362 So(names, ShouldResemble, []string{
363 "a",
364 "abs_symlink",
365 "dir/c",
366 "dir/dir/d",
367 "dir/dir/rel_symlink",
368 "exe",
369 })
370
371 // Ensure data is valid (check first file only).
372 r, err := files[0].Open()
373 if r != nil {
374 defer r.Close()
375 }
376 So(err, ShouldBeNil)
377 data, err := ioutil.ReadAll(r)
378 So(err, ShouldBeNil)
379 So(data, ShouldResemble, []byte("a data"))
380
381 // Ensure file mode is valid.
382 So(files[5].Name(), ShouldEqual, "exe")
383 So(files[5].Executable(), ShouldBeTrue)
384
385 // Ensure absolute symlink if valid.
386 So(files[1].Name(), ShouldEqual, "abs_symlink")
387 ensureSymlinkTarget(files[1], filepath.FromSlash(tempDir ))
388
389 // Ensure relative symlink is valid.
390 So(files[4].Name(), ShouldEqual, "dir/dir/rel_symlink")
391 ensureSymlinkTarget(files[4], "../../a")
392
393 // Ensure no temp files left.
394 allFiles, err := ScanFileSystem(tempDir, tempDir, nil)
395 So(len(allFiles), ShouldEqual, len(files))
396 })
397
398 Convey("Rolling back bunch of files works", func() {
399 So(dest.Begin(), ShouldBeNil)
400 writeFileToDest("a", false, "a data")
401 writeFileToDest("dir/c", false, "dir/c data")
402 writeSymlinkToDest("dir/d", "c")
403 So(dest.End(false), ShouldBeNil)
404
405 // No dest directory.
406 _, err := os.Stat(destDir)
407 So(os.IsNotExist(err), ShouldBeTrue)
408
409 // Ensure no temp files left.
410 allFiles, err := ScanFileSystem(tempDir, tempDir, nil)
411 So(len(allFiles), ShouldEqual, 0)
412 })
413
414 Convey("Overwriting a directory works", func() {
415 // Create dest directory manually with some stuff.
416 err := os.Mkdir(destDir, 0777)
417 So(err, ShouldBeNil)
418 err = ioutil.WriteFile(filepath.Join(destDir, "data"), [ ]byte("data"), 0666)
419 So(err, ShouldBeNil)
420
421 // Now deploy something to it.
422 So(dest.Begin(), ShouldBeNil)
423 writeFileToDest("a", false, "a data")
424 writeSymlinkToDest("b", "a")
425 So(dest.End(true), ShouldBeNil)
426
427 // Overwritten.
428 files, err := ScanFileSystem(destDir, destDir, nil)
429 So(err, ShouldBeNil)
430 So(len(files), ShouldEqual, 2)
431 So(files[0].Name(), ShouldEqual, "a")
432 So(files[1].Name(), ShouldEqual, "b")
433 })
434
435 Convey("Not overwriting a directory works", func() {
436 // Create dest directory manually with some stuff.
437 err := os.Mkdir(destDir, 0777)
438 So(err, ShouldBeNil)
439 err = ioutil.WriteFile(filepath.Join(destDir, "data"), [ ]byte("data"), 0666)
440 So(err, ShouldBeNil)
441
442 // Now attempt deploy something to it, but roll back.
443 So(dest.Begin(), ShouldBeNil)
444 writeFileToDest("a", false, "a data")
445 writeSymlinkToDest("b", "a")
446 So(dest.End(false), ShouldBeNil)
447
448 // Kept as is.
449 files, err := ScanFileSystem(destDir, destDir, nil)
450 So(err, ShouldBeNil)
451 So(len(files), ShouldEqual, 1)
452 So(files[0].Name(), ShouldEqual, "data")
453 })
454
455 Convey("Opening file twice fails", func() {
456 So(dest.Begin(), ShouldBeNil)
457 writeFileToDest("a", false, "a data")
458 w, err := dest.CreateFile("a", false)
459 So(w, ShouldBeNil)
460 So(err, ShouldNotBeNil)
461 So(dest.End(true), ShouldBeNil)
462 })
463
464 Convey("End with opened files fail", func() {
465 So(dest.Begin(), ShouldBeNil)
466 w, err := dest.CreateFile("a", false)
467 So(w, ShouldNotBeNil)
468 So(err, ShouldBeNil)
469 So(dest.End(true), ShouldNotBeNil)
470 w.Close()
471 So(dest.End(true), ShouldBeNil)
472 })
473 })
474 }
OLDNEW
« no previous file with comments | « go/src/infra/tools/cipd/files.go ('k') | go/src/infra/tools/cipd/local/builder.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698