1 | use std::fs; |
2 | use std::path::PathBuf; |
3 | |
4 | use crate::tests::util::Dir; |
5 | use crate::WalkDir; |
6 | |
7 | #[test] |
8 | fn send_sync_traits() { |
9 | use crate::{FilterEntry, IntoIter}; |
10 | |
11 | fn assert_send<T: Send>() {} |
12 | fn assert_sync<T: Sync>() {} |
13 | |
14 | assert_send::<WalkDir>(); |
15 | assert_sync::<WalkDir>(); |
16 | assert_send::<IntoIter>(); |
17 | assert_sync::<IntoIter>(); |
18 | assert_send::<FilterEntry<IntoIter, u8>>(); |
19 | assert_sync::<FilterEntry<IntoIter, u8>>(); |
20 | } |
21 | |
22 | #[test] |
23 | fn empty() { |
24 | let dir = Dir::tmp(); |
25 | let wd = WalkDir::new(dir.path()); |
26 | let r = dir.run_recursive(wd); |
27 | r.assert_no_errors(); |
28 | |
29 | assert_eq!(1, r.ents().len()); |
30 | let ent = &r.ents()[0]; |
31 | assert!(ent.file_type().is_dir()); |
32 | assert!(!ent.path_is_symlink()); |
33 | assert_eq!(0, ent.depth()); |
34 | assert_eq!(dir.path(), ent.path()); |
35 | assert_eq!(dir.path().file_name().unwrap(), ent.file_name()); |
36 | } |
37 | |
38 | #[test] |
39 | fn empty_follow() { |
40 | let dir = Dir::tmp(); |
41 | let wd = WalkDir::new(dir.path()).follow_links(true); |
42 | let r = dir.run_recursive(wd); |
43 | r.assert_no_errors(); |
44 | |
45 | assert_eq!(1, r.ents().len()); |
46 | let ent = &r.ents()[0]; |
47 | assert!(ent.file_type().is_dir()); |
48 | assert!(!ent.path_is_symlink()); |
49 | assert_eq!(0, ent.depth()); |
50 | assert_eq!(dir.path(), ent.path()); |
51 | assert_eq!(dir.path().file_name().unwrap(), ent.file_name()); |
52 | } |
53 | |
54 | #[test] |
55 | fn empty_file() { |
56 | let dir = Dir::tmp(); |
57 | dir.touch("a" ); |
58 | |
59 | let wd = WalkDir::new(dir.path().join("a" )); |
60 | let r = dir.run_recursive(wd); |
61 | r.assert_no_errors(); |
62 | |
63 | assert_eq!(1, r.ents().len()); |
64 | let ent = &r.ents()[0]; |
65 | assert!(ent.file_type().is_file()); |
66 | assert!(!ent.path_is_symlink()); |
67 | assert_eq!(0, ent.depth()); |
68 | assert_eq!(dir.join("a" ), ent.path()); |
69 | assert_eq!("a" , ent.file_name()); |
70 | } |
71 | |
72 | #[test] |
73 | fn empty_file_follow() { |
74 | let dir = Dir::tmp(); |
75 | dir.touch("a" ); |
76 | |
77 | let wd = WalkDir::new(dir.path().join("a" )).follow_links(true); |
78 | let r = dir.run_recursive(wd); |
79 | r.assert_no_errors(); |
80 | |
81 | assert_eq!(1, r.ents().len()); |
82 | let ent = &r.ents()[0]; |
83 | assert!(ent.file_type().is_file()); |
84 | assert!(!ent.path_is_symlink()); |
85 | assert_eq!(0, ent.depth()); |
86 | assert_eq!(dir.join("a" ), ent.path()); |
87 | assert_eq!("a" , ent.file_name()); |
88 | } |
89 | |
90 | #[test] |
91 | fn one_dir() { |
92 | let dir = Dir::tmp(); |
93 | dir.mkdirp("a" ); |
94 | |
95 | let wd = WalkDir::new(dir.path()); |
96 | let r = dir.run_recursive(wd); |
97 | r.assert_no_errors(); |
98 | |
99 | let ents = r.ents(); |
100 | assert_eq!(2, ents.len()); |
101 | let ent = &ents[1]; |
102 | assert_eq!(dir.join("a" ), ent.path()); |
103 | assert_eq!(1, ent.depth()); |
104 | assert_eq!("a" , ent.file_name()); |
105 | assert!(ent.file_type().is_dir()); |
106 | } |
107 | |
108 | #[test] |
109 | fn one_file() { |
110 | let dir = Dir::tmp(); |
111 | dir.touch("a" ); |
112 | |
113 | let wd = WalkDir::new(dir.path()); |
114 | let r = dir.run_recursive(wd); |
115 | r.assert_no_errors(); |
116 | |
117 | let ents = r.ents(); |
118 | assert_eq!(2, ents.len()); |
119 | let ent = &ents[1]; |
120 | assert_eq!(dir.join("a" ), ent.path()); |
121 | assert_eq!(1, ent.depth()); |
122 | assert_eq!("a" , ent.file_name()); |
123 | assert!(ent.file_type().is_file()); |
124 | } |
125 | |
126 | #[test] |
127 | fn one_dir_one_file() { |
128 | let dir = Dir::tmp(); |
129 | dir.mkdirp("foo" ); |
130 | dir.touch("foo/a" ); |
131 | |
132 | let wd = WalkDir::new(dir.path()); |
133 | let r = dir.run_recursive(wd); |
134 | r.assert_no_errors(); |
135 | |
136 | let expected = vec![ |
137 | dir.path().to_path_buf(), |
138 | dir.join("foo" ), |
139 | dir.join("foo" ).join("a" ), |
140 | ]; |
141 | assert_eq!(expected, r.sorted_paths()); |
142 | } |
143 | |
144 | #[test] |
145 | fn many_files() { |
146 | let dir = Dir::tmp(); |
147 | dir.mkdirp("foo" ); |
148 | dir.touch_all(&["foo/a" , "foo/b" , "foo/c" ]); |
149 | |
150 | let wd = WalkDir::new(dir.path()); |
151 | let r = dir.run_recursive(wd); |
152 | r.assert_no_errors(); |
153 | |
154 | let expected = vec![ |
155 | dir.path().to_path_buf(), |
156 | dir.join("foo" ), |
157 | dir.join("foo" ).join("a" ), |
158 | dir.join("foo" ).join("b" ), |
159 | dir.join("foo" ).join("c" ), |
160 | ]; |
161 | assert_eq!(expected, r.sorted_paths()); |
162 | } |
163 | |
164 | #[test] |
165 | fn many_dirs() { |
166 | let dir = Dir::tmp(); |
167 | dir.mkdirp("foo/a" ); |
168 | dir.mkdirp("foo/b" ); |
169 | dir.mkdirp("foo/c" ); |
170 | |
171 | let wd = WalkDir::new(dir.path()); |
172 | let r = dir.run_recursive(wd); |
173 | r.assert_no_errors(); |
174 | |
175 | let expected = vec![ |
176 | dir.path().to_path_buf(), |
177 | dir.join("foo" ), |
178 | dir.join("foo" ).join("a" ), |
179 | dir.join("foo" ).join("b" ), |
180 | dir.join("foo" ).join("c" ), |
181 | ]; |
182 | assert_eq!(expected, r.sorted_paths()); |
183 | } |
184 | |
185 | #[test] |
186 | fn many_mixed() { |
187 | let dir = Dir::tmp(); |
188 | dir.mkdirp("foo/a" ); |
189 | dir.mkdirp("foo/c" ); |
190 | dir.mkdirp("foo/e" ); |
191 | dir.touch_all(&["foo/b" , "foo/d" , "foo/f" ]); |
192 | |
193 | let wd = WalkDir::new(dir.path()); |
194 | let r = dir.run_recursive(wd); |
195 | r.assert_no_errors(); |
196 | |
197 | let expected = vec![ |
198 | dir.path().to_path_buf(), |
199 | dir.join("foo" ), |
200 | dir.join("foo" ).join("a" ), |
201 | dir.join("foo" ).join("b" ), |
202 | dir.join("foo" ).join("c" ), |
203 | dir.join("foo" ).join("d" ), |
204 | dir.join("foo" ).join("e" ), |
205 | dir.join("foo" ).join("f" ), |
206 | ]; |
207 | assert_eq!(expected, r.sorted_paths()); |
208 | } |
209 | |
210 | #[test] |
211 | fn nested() { |
212 | let nested = |
213 | PathBuf::from("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" ); |
214 | let dir = Dir::tmp(); |
215 | dir.mkdirp(&nested); |
216 | dir.touch(nested.join("A" )); |
217 | |
218 | let wd = WalkDir::new(dir.path()); |
219 | let r = dir.run_recursive(wd); |
220 | r.assert_no_errors(); |
221 | |
222 | let expected = vec![ |
223 | dir.path().to_path_buf(), |
224 | dir.join("a" ), |
225 | dir.join("a/b" ), |
226 | dir.join("a/b/c" ), |
227 | dir.join("a/b/c/d" ), |
228 | dir.join("a/b/c/d/e" ), |
229 | dir.join("a/b/c/d/e/f" ), |
230 | dir.join("a/b/c/d/e/f/g" ), |
231 | dir.join("a/b/c/d/e/f/g/h" ), |
232 | dir.join("a/b/c/d/e/f/g/h/i" ), |
233 | dir.join("a/b/c/d/e/f/g/h/i/j" ), |
234 | dir.join("a/b/c/d/e/f/g/h/i/j/k" ), |
235 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l" ), |
236 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m" ), |
237 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n" ), |
238 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o" ), |
239 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p" ), |
240 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q" ), |
241 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r" ), |
242 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s" ), |
243 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t" ), |
244 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u" ), |
245 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v" ), |
246 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w" ), |
247 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x" ), |
248 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y" ), |
249 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" ), |
250 | dir.join(&nested).join("A" ), |
251 | ]; |
252 | assert_eq!(expected, r.sorted_paths()); |
253 | } |
254 | |
255 | #[test] |
256 | fn nested_small_max_open() { |
257 | let nested = |
258 | PathBuf::from("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" ); |
259 | let dir = Dir::tmp(); |
260 | dir.mkdirp(&nested); |
261 | dir.touch(nested.join("A" )); |
262 | |
263 | let wd = WalkDir::new(dir.path()).max_open(1); |
264 | let r = dir.run_recursive(wd); |
265 | r.assert_no_errors(); |
266 | |
267 | let expected = vec![ |
268 | dir.path().to_path_buf(), |
269 | dir.join("a" ), |
270 | dir.join("a/b" ), |
271 | dir.join("a/b/c" ), |
272 | dir.join("a/b/c/d" ), |
273 | dir.join("a/b/c/d/e" ), |
274 | dir.join("a/b/c/d/e/f" ), |
275 | dir.join("a/b/c/d/e/f/g" ), |
276 | dir.join("a/b/c/d/e/f/g/h" ), |
277 | dir.join("a/b/c/d/e/f/g/h/i" ), |
278 | dir.join("a/b/c/d/e/f/g/h/i/j" ), |
279 | dir.join("a/b/c/d/e/f/g/h/i/j/k" ), |
280 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l" ), |
281 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m" ), |
282 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n" ), |
283 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o" ), |
284 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p" ), |
285 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q" ), |
286 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r" ), |
287 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s" ), |
288 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t" ), |
289 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u" ), |
290 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v" ), |
291 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w" ), |
292 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x" ), |
293 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y" ), |
294 | dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z" ), |
295 | dir.join(&nested).join("A" ), |
296 | ]; |
297 | assert_eq!(expected, r.sorted_paths()); |
298 | } |
299 | |
300 | #[test] |
301 | fn siblings() { |
302 | let dir = Dir::tmp(); |
303 | dir.mkdirp("foo" ); |
304 | dir.mkdirp("bar" ); |
305 | dir.touch_all(&["foo/a" , "foo/b" ]); |
306 | dir.touch_all(&["bar/a" , "bar/b" ]); |
307 | |
308 | let wd = WalkDir::new(dir.path()); |
309 | let r = dir.run_recursive(wd); |
310 | r.assert_no_errors(); |
311 | |
312 | let expected = vec![ |
313 | dir.path().to_path_buf(), |
314 | dir.join("bar" ), |
315 | dir.join("bar" ).join("a" ), |
316 | dir.join("bar" ).join("b" ), |
317 | dir.join("foo" ), |
318 | dir.join("foo" ).join("a" ), |
319 | dir.join("foo" ).join("b" ), |
320 | ]; |
321 | assert_eq!(expected, r.sorted_paths()); |
322 | } |
323 | |
324 | #[test] |
325 | fn sym_root_file_nofollow() { |
326 | let dir = Dir::tmp(); |
327 | dir.touch("a" ); |
328 | dir.symlink_file("a" , "a-link" ); |
329 | |
330 | let wd = WalkDir::new(dir.join("a-link" )); |
331 | let r = dir.run_recursive(wd); |
332 | r.assert_no_errors(); |
333 | |
334 | let ents = r.sorted_ents(); |
335 | assert_eq!(1, ents.len()); |
336 | let link = &ents[0]; |
337 | |
338 | assert_eq!(dir.join("a-link" ), link.path()); |
339 | |
340 | assert!(link.path_is_symlink()); |
341 | |
342 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
343 | |
344 | assert_eq!(0, link.depth()); |
345 | |
346 | assert!(link.file_type().is_symlink()); |
347 | assert!(!link.file_type().is_file()); |
348 | assert!(!link.file_type().is_dir()); |
349 | |
350 | assert!(link.metadata().unwrap().file_type().is_symlink()); |
351 | assert!(!link.metadata().unwrap().is_file()); |
352 | assert!(!link.metadata().unwrap().is_dir()); |
353 | } |
354 | |
355 | #[test] |
356 | fn sym_root_file_follow() { |
357 | let dir = Dir::tmp(); |
358 | dir.touch("a" ); |
359 | dir.symlink_file("a" , "a-link" ); |
360 | |
361 | let wd = WalkDir::new(dir.join("a-link" )).follow_links(true); |
362 | let r = dir.run_recursive(wd); |
363 | r.assert_no_errors(); |
364 | |
365 | let ents = r.sorted_ents(); |
366 | let link = &ents[0]; |
367 | |
368 | assert_eq!(dir.join("a-link" ), link.path()); |
369 | |
370 | assert!(link.path_is_symlink()); |
371 | |
372 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
373 | |
374 | assert_eq!(0, link.depth()); |
375 | |
376 | assert!(!link.file_type().is_symlink()); |
377 | assert!(link.file_type().is_file()); |
378 | assert!(!link.file_type().is_dir()); |
379 | |
380 | assert!(!link.metadata().unwrap().file_type().is_symlink()); |
381 | assert!(link.metadata().unwrap().is_file()); |
382 | assert!(!link.metadata().unwrap().is_dir()); |
383 | } |
384 | |
385 | #[test] |
386 | fn broken_sym_root_dir_nofollow_and_root_nofollow() { |
387 | let dir = Dir::tmp(); |
388 | dir.symlink_dir("broken" , "a-link" ); |
389 | |
390 | let wd = WalkDir::new(dir.join("a-link" )) |
391 | .follow_links(false) |
392 | .follow_root_links(false); |
393 | let r = dir.run_recursive(wd); |
394 | let ents = r.sorted_ents(); |
395 | assert_eq!(ents.len(), 1); |
396 | let link = &ents[0]; |
397 | assert_eq!(dir.join("a-link" ), link.path()); |
398 | assert!(link.path_is_symlink()); |
399 | } |
400 | |
401 | #[test] |
402 | fn broken_sym_root_dir_follow_and_root_nofollow() { |
403 | let dir = Dir::tmp(); |
404 | dir.symlink_dir("broken" , "a-link" ); |
405 | |
406 | let wd = WalkDir::new(dir.join("a-link" )) |
407 | .follow_links(true) |
408 | .follow_root_links(false); |
409 | let r = dir.run_recursive(wd); |
410 | assert!(r.sorted_ents().is_empty()); |
411 | assert_eq!( |
412 | r.errs().len(), |
413 | 1, |
414 | "broken symlink cannot be traversed - they are followed if symlinks are followed" |
415 | ); |
416 | } |
417 | |
418 | #[test] |
419 | fn broken_sym_root_dir_root_is_always_followed() { |
420 | let dir = Dir::tmp(); |
421 | dir.symlink_dir("broken" , "a-link" ); |
422 | |
423 | for follow_symlinks in &[true, false] { |
424 | let wd = |
425 | WalkDir::new(dir.join("a-link" )).follow_links(*follow_symlinks); |
426 | let r = dir.run_recursive(wd); |
427 | assert!(r.sorted_ents().is_empty()); |
428 | assert_eq!( |
429 | r.errs().len(), |
430 | 1, |
431 | "broken symlink in roots cannot be traversed, they are always followed" |
432 | ); |
433 | } |
434 | } |
435 | |
436 | #[test] |
437 | fn sym_root_dir_nofollow_root_nofollow() { |
438 | let dir = Dir::tmp(); |
439 | dir.mkdirp("a" ); |
440 | dir.symlink_dir("a" , "a-link" ); |
441 | dir.touch("a/zzz" ); |
442 | |
443 | let wd = WalkDir::new(dir.join("a-link" )).follow_root_links(false); |
444 | let r = dir.run_recursive(wd); |
445 | r.assert_no_errors(); |
446 | |
447 | let ents = r.sorted_ents(); |
448 | assert_eq!(1, ents.len()); |
449 | let link = &ents[0]; |
450 | assert_eq!(dir.join("a-link" ), link.path()); |
451 | assert_eq!(0, link.depth()); |
452 | } |
453 | |
454 | #[test] |
455 | fn sym_root_dir_nofollow_root_follow() { |
456 | let dir = Dir::tmp(); |
457 | dir.mkdirp("a" ); |
458 | dir.symlink_dir("a" , "a-link" ); |
459 | dir.touch("a/zzz" ); |
460 | |
461 | let wd = WalkDir::new(dir.join("a-link" )); |
462 | let r = dir.run_recursive(wd); |
463 | r.assert_no_errors(); |
464 | |
465 | let ents = r.sorted_ents(); |
466 | assert_eq!(2, ents.len()); |
467 | let link = &ents[0]; |
468 | |
469 | assert_eq!(dir.join("a-link" ), link.path()); |
470 | |
471 | assert!(link.path_is_symlink()); |
472 | |
473 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
474 | |
475 | assert_eq!(0, link.depth()); |
476 | |
477 | assert!(link.file_type().is_symlink()); |
478 | assert!(!link.file_type().is_file()); |
479 | assert!(!link.file_type().is_dir()); |
480 | |
481 | assert!(link.metadata().unwrap().file_type().is_symlink()); |
482 | assert!(!link.metadata().unwrap().is_file()); |
483 | assert!(!link.metadata().unwrap().is_dir()); |
484 | |
485 | let link_zzz = &ents[1]; |
486 | assert_eq!(dir.join("a-link" ).join("zzz" ), link_zzz.path()); |
487 | assert!(!link_zzz.path_is_symlink()); |
488 | } |
489 | |
490 | #[test] |
491 | fn sym_root_dir_follow() { |
492 | let dir = Dir::tmp(); |
493 | dir.mkdirp("a" ); |
494 | dir.symlink_dir("a" , "a-link" ); |
495 | dir.touch("a/zzz" ); |
496 | |
497 | let wd = WalkDir::new(dir.join("a-link" )).follow_links(true); |
498 | let r = dir.run_recursive(wd); |
499 | r.assert_no_errors(); |
500 | |
501 | let ents = r.sorted_ents(); |
502 | assert_eq!(2, ents.len()); |
503 | let link = &ents[0]; |
504 | |
505 | assert_eq!(dir.join("a-link" ), link.path()); |
506 | |
507 | assert!(link.path_is_symlink()); |
508 | |
509 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
510 | |
511 | assert_eq!(0, link.depth()); |
512 | |
513 | assert!(!link.file_type().is_symlink()); |
514 | assert!(!link.file_type().is_file()); |
515 | assert!(link.file_type().is_dir()); |
516 | |
517 | assert!(!link.metadata().unwrap().file_type().is_symlink()); |
518 | assert!(!link.metadata().unwrap().is_file()); |
519 | assert!(link.metadata().unwrap().is_dir()); |
520 | |
521 | let link_zzz = &ents[1]; |
522 | assert_eq!(dir.join("a-link" ).join("zzz" ), link_zzz.path()); |
523 | assert!(!link_zzz.path_is_symlink()); |
524 | } |
525 | |
526 | #[test] |
527 | fn sym_file_nofollow() { |
528 | let dir = Dir::tmp(); |
529 | dir.touch("a" ); |
530 | dir.symlink_file("a" , "a-link" ); |
531 | |
532 | let wd = WalkDir::new(dir.path()); |
533 | let r = dir.run_recursive(wd); |
534 | r.assert_no_errors(); |
535 | |
536 | let ents = r.sorted_ents(); |
537 | assert_eq!(3, ents.len()); |
538 | let (src, link) = (&ents[1], &ents[2]); |
539 | |
540 | assert_eq!(dir.join("a" ), src.path()); |
541 | assert_eq!(dir.join("a-link" ), link.path()); |
542 | |
543 | assert!(!src.path_is_symlink()); |
544 | assert!(link.path_is_symlink()); |
545 | |
546 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
547 | |
548 | assert_eq!(1, src.depth()); |
549 | assert_eq!(1, link.depth()); |
550 | |
551 | assert!(src.file_type().is_file()); |
552 | assert!(link.file_type().is_symlink()); |
553 | assert!(!link.file_type().is_file()); |
554 | assert!(!link.file_type().is_dir()); |
555 | |
556 | assert!(src.metadata().unwrap().is_file()); |
557 | assert!(link.metadata().unwrap().file_type().is_symlink()); |
558 | assert!(!link.metadata().unwrap().is_file()); |
559 | assert!(!link.metadata().unwrap().is_dir()); |
560 | } |
561 | |
562 | #[test] |
563 | fn sym_file_follow() { |
564 | let dir = Dir::tmp(); |
565 | dir.touch("a" ); |
566 | dir.symlink_file("a" , "a-link" ); |
567 | |
568 | let wd = WalkDir::new(dir.path()).follow_links(true); |
569 | let r = dir.run_recursive(wd); |
570 | r.assert_no_errors(); |
571 | |
572 | let ents = r.sorted_ents(); |
573 | assert_eq!(3, ents.len()); |
574 | let (src, link) = (&ents[1], &ents[2]); |
575 | |
576 | assert_eq!(dir.join("a" ), src.path()); |
577 | assert_eq!(dir.join("a-link" ), link.path()); |
578 | |
579 | assert!(!src.path_is_symlink()); |
580 | assert!(link.path_is_symlink()); |
581 | |
582 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
583 | |
584 | assert_eq!(1, src.depth()); |
585 | assert_eq!(1, link.depth()); |
586 | |
587 | assert!(src.file_type().is_file()); |
588 | assert!(!link.file_type().is_symlink()); |
589 | assert!(link.file_type().is_file()); |
590 | assert!(!link.file_type().is_dir()); |
591 | |
592 | assert!(src.metadata().unwrap().is_file()); |
593 | assert!(!link.metadata().unwrap().file_type().is_symlink()); |
594 | assert!(link.metadata().unwrap().is_file()); |
595 | assert!(!link.metadata().unwrap().is_dir()); |
596 | } |
597 | |
598 | #[test] |
599 | fn sym_dir_nofollow() { |
600 | let dir = Dir::tmp(); |
601 | dir.mkdirp("a" ); |
602 | dir.symlink_dir("a" , "a-link" ); |
603 | dir.touch("a/zzz" ); |
604 | |
605 | let wd = WalkDir::new(dir.path()); |
606 | let r = dir.run_recursive(wd); |
607 | r.assert_no_errors(); |
608 | |
609 | let ents = r.sorted_ents(); |
610 | assert_eq!(4, ents.len()); |
611 | let (src, link) = (&ents[1], &ents[3]); |
612 | |
613 | assert_eq!(dir.join("a" ), src.path()); |
614 | assert_eq!(dir.join("a-link" ), link.path()); |
615 | |
616 | assert!(!src.path_is_symlink()); |
617 | assert!(link.path_is_symlink()); |
618 | |
619 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
620 | |
621 | assert_eq!(1, src.depth()); |
622 | assert_eq!(1, link.depth()); |
623 | |
624 | assert!(src.file_type().is_dir()); |
625 | assert!(link.file_type().is_symlink()); |
626 | assert!(!link.file_type().is_file()); |
627 | assert!(!link.file_type().is_dir()); |
628 | |
629 | assert!(src.metadata().unwrap().is_dir()); |
630 | assert!(link.metadata().unwrap().file_type().is_symlink()); |
631 | assert!(!link.metadata().unwrap().is_file()); |
632 | assert!(!link.metadata().unwrap().is_dir()); |
633 | } |
634 | |
635 | #[test] |
636 | fn sym_dir_follow() { |
637 | let dir = Dir::tmp(); |
638 | dir.mkdirp("a" ); |
639 | dir.symlink_dir("a" , "a-link" ); |
640 | dir.touch("a/zzz" ); |
641 | |
642 | let wd = WalkDir::new(dir.path()).follow_links(true); |
643 | let r = dir.run_recursive(wd); |
644 | r.assert_no_errors(); |
645 | |
646 | let ents = r.sorted_ents(); |
647 | assert_eq!(5, ents.len()); |
648 | let (src, link) = (&ents[1], &ents[3]); |
649 | |
650 | assert_eq!(dir.join("a" ), src.path()); |
651 | assert_eq!(dir.join("a-link" ), link.path()); |
652 | |
653 | assert!(!src.path_is_symlink()); |
654 | assert!(link.path_is_symlink()); |
655 | |
656 | assert_eq!(dir.join("a" ), fs::read_link(link.path()).unwrap()); |
657 | |
658 | assert_eq!(1, src.depth()); |
659 | assert_eq!(1, link.depth()); |
660 | |
661 | assert!(src.file_type().is_dir()); |
662 | assert!(!link.file_type().is_symlink()); |
663 | assert!(!link.file_type().is_file()); |
664 | assert!(link.file_type().is_dir()); |
665 | |
666 | assert!(src.metadata().unwrap().is_dir()); |
667 | assert!(!link.metadata().unwrap().file_type().is_symlink()); |
668 | assert!(!link.metadata().unwrap().is_file()); |
669 | assert!(link.metadata().unwrap().is_dir()); |
670 | |
671 | let (src_zzz, link_zzz) = (&ents[2], &ents[4]); |
672 | assert_eq!(dir.join("a" ).join("zzz" ), src_zzz.path()); |
673 | assert_eq!(dir.join("a-link" ).join("zzz" ), link_zzz.path()); |
674 | assert!(!src_zzz.path_is_symlink()); |
675 | assert!(!link_zzz.path_is_symlink()); |
676 | } |
677 | |
678 | #[test] |
679 | fn sym_noloop() { |
680 | let dir = Dir::tmp(); |
681 | dir.mkdirp("a/b/c" ); |
682 | dir.symlink_dir("a" , "a/b/c/a-link" ); |
683 | |
684 | let wd = WalkDir::new(dir.path()); |
685 | let r = dir.run_recursive(wd); |
686 | // There's no loop if we aren't following symlinks. |
687 | r.assert_no_errors(); |
688 | |
689 | assert_eq!(5, r.ents().len()); |
690 | } |
691 | |
692 | #[test] |
693 | fn sym_loop_detect() { |
694 | let dir = Dir::tmp(); |
695 | dir.mkdirp("a/b/c" ); |
696 | dir.symlink_dir("a" , "a/b/c/a-link" ); |
697 | |
698 | let wd = WalkDir::new(dir.path()).follow_links(true); |
699 | let r = dir.run_recursive(wd); |
700 | |
701 | let (ents, errs) = (r.sorted_ents(), r.errs()); |
702 | assert_eq!(4, ents.len()); |
703 | assert_eq!(1, errs.len()); |
704 | |
705 | let err = &errs[0]; |
706 | |
707 | let expected = dir.join("a/b/c/a-link" ); |
708 | assert_eq!(Some(&*expected), err.path()); |
709 | |
710 | let expected = dir.join("a" ); |
711 | assert_eq!(Some(&*expected), err.loop_ancestor()); |
712 | |
713 | assert_eq!(4, err.depth()); |
714 | assert!(err.io_error().is_none()); |
715 | } |
716 | |
717 | #[test] |
718 | fn sym_self_loop_no_error() { |
719 | let dir = Dir::tmp(); |
720 | dir.symlink_file("a" , "a" ); |
721 | |
722 | let wd = WalkDir::new(dir.path()); |
723 | let r = dir.run_recursive(wd); |
724 | // No errors occur because even though the symlink points to nowhere, it |
725 | // is never followed, and thus no error occurs. |
726 | r.assert_no_errors(); |
727 | assert_eq!(2, r.ents().len()); |
728 | |
729 | let ent = &r.ents()[1]; |
730 | assert_eq!(dir.join("a" ), ent.path()); |
731 | assert!(ent.path_is_symlink()); |
732 | |
733 | assert!(ent.file_type().is_symlink()); |
734 | assert!(!ent.file_type().is_file()); |
735 | assert!(!ent.file_type().is_dir()); |
736 | |
737 | assert!(ent.metadata().unwrap().file_type().is_symlink()); |
738 | assert!(!ent.metadata().unwrap().file_type().is_file()); |
739 | assert!(!ent.metadata().unwrap().file_type().is_dir()); |
740 | } |
741 | |
742 | #[test] |
743 | fn sym_file_self_loop_io_error() { |
744 | let dir = Dir::tmp(); |
745 | dir.symlink_file("a" , "a" ); |
746 | |
747 | let wd = WalkDir::new(dir.path()).follow_links(true); |
748 | let r = dir.run_recursive(wd); |
749 | |
750 | let (ents, errs) = (r.sorted_ents(), r.errs()); |
751 | assert_eq!(1, ents.len()); |
752 | assert_eq!(1, errs.len()); |
753 | |
754 | let err = &errs[0]; |
755 | |
756 | let expected = dir.join("a" ); |
757 | assert_eq!(Some(&*expected), err.path()); |
758 | assert_eq!(1, err.depth()); |
759 | assert!(err.loop_ancestor().is_none()); |
760 | assert!(err.io_error().is_some()); |
761 | } |
762 | |
763 | #[test] |
764 | fn sym_dir_self_loop_io_error() { |
765 | let dir = Dir::tmp(); |
766 | dir.symlink_dir("a" , "a" ); |
767 | |
768 | let wd = WalkDir::new(dir.path()).follow_links(true); |
769 | let r = dir.run_recursive(wd); |
770 | |
771 | let (ents, errs) = (r.sorted_ents(), r.errs()); |
772 | assert_eq!(1, ents.len()); |
773 | assert_eq!(1, errs.len()); |
774 | |
775 | let err = &errs[0]; |
776 | |
777 | let expected = dir.join("a" ); |
778 | assert_eq!(Some(&*expected), err.path()); |
779 | assert_eq!(1, err.depth()); |
780 | assert!(err.loop_ancestor().is_none()); |
781 | assert!(err.io_error().is_some()); |
782 | } |
783 | |
784 | #[test] |
785 | fn min_depth_1() { |
786 | let dir = Dir::tmp(); |
787 | dir.mkdirp("a/b" ); |
788 | |
789 | let wd = WalkDir::new(dir.path()).min_depth(1); |
790 | let r = dir.run_recursive(wd); |
791 | r.assert_no_errors(); |
792 | |
793 | let expected = vec![dir.join("a" ), dir.join("a" ).join("b" )]; |
794 | assert_eq!(expected, r.sorted_paths()); |
795 | } |
796 | |
797 | #[test] |
798 | fn min_depth_2() { |
799 | let dir = Dir::tmp(); |
800 | dir.mkdirp("a/b" ); |
801 | |
802 | let wd = WalkDir::new(dir.path()).min_depth(2); |
803 | let r = dir.run_recursive(wd); |
804 | r.assert_no_errors(); |
805 | |
806 | let expected = vec![dir.join("a" ).join("b" )]; |
807 | assert_eq!(expected, r.sorted_paths()); |
808 | } |
809 | |
810 | #[test] |
811 | fn max_depth_0() { |
812 | let dir = Dir::tmp(); |
813 | dir.mkdirp("a/b" ); |
814 | |
815 | let wd = WalkDir::new(dir.path()).max_depth(0); |
816 | let r = dir.run_recursive(wd); |
817 | r.assert_no_errors(); |
818 | |
819 | let expected = vec![dir.path().to_path_buf()]; |
820 | assert_eq!(expected, r.sorted_paths()); |
821 | } |
822 | |
823 | #[test] |
824 | fn max_depth_1() { |
825 | let dir = Dir::tmp(); |
826 | dir.mkdirp("a/b" ); |
827 | |
828 | let wd = WalkDir::new(dir.path()).max_depth(1); |
829 | let r = dir.run_recursive(wd); |
830 | r.assert_no_errors(); |
831 | |
832 | let expected = vec![dir.path().to_path_buf(), dir.join("a" )]; |
833 | assert_eq!(expected, r.sorted_paths()); |
834 | } |
835 | |
836 | #[test] |
837 | fn max_depth_2() { |
838 | let dir = Dir::tmp(); |
839 | dir.mkdirp("a/b" ); |
840 | |
841 | let wd = WalkDir::new(dir.path()).max_depth(2); |
842 | let r = dir.run_recursive(wd); |
843 | r.assert_no_errors(); |
844 | |
845 | let expected = |
846 | vec![dir.path().to_path_buf(), dir.join("a" ), dir.join("a" ).join("b" )]; |
847 | assert_eq!(expected, r.sorted_paths()); |
848 | } |
849 | |
850 | // FIXME: This test seems wrong. It should return nothing! |
851 | #[test] |
852 | fn min_max_depth_diff_nada() { |
853 | let dir = Dir::tmp(); |
854 | dir.mkdirp("a/b/c" ); |
855 | |
856 | let wd = WalkDir::new(dir.path()).min_depth(3).max_depth(2); |
857 | let r = dir.run_recursive(wd); |
858 | r.assert_no_errors(); |
859 | |
860 | let expected = vec![dir.join("a" ).join("b" ).join("c" )]; |
861 | assert_eq!(expected, r.sorted_paths()); |
862 | } |
863 | |
864 | #[test] |
865 | fn min_max_depth_diff_0() { |
866 | let dir = Dir::tmp(); |
867 | dir.mkdirp("a/b/c" ); |
868 | |
869 | let wd = WalkDir::new(dir.path()).min_depth(2).max_depth(2); |
870 | let r = dir.run_recursive(wd); |
871 | r.assert_no_errors(); |
872 | |
873 | let expected = vec![dir.join("a" ).join("b" )]; |
874 | assert_eq!(expected, r.sorted_paths()); |
875 | } |
876 | |
877 | #[test] |
878 | fn min_max_depth_diff_1() { |
879 | let dir = Dir::tmp(); |
880 | dir.mkdirp("a/b/c" ); |
881 | |
882 | let wd = WalkDir::new(dir.path()).min_depth(1).max_depth(2); |
883 | let r = dir.run_recursive(wd); |
884 | r.assert_no_errors(); |
885 | |
886 | let expected = vec![dir.join("a" ), dir.join("a" ).join("b" )]; |
887 | assert_eq!(expected, r.sorted_paths()); |
888 | } |
889 | |
890 | #[test] |
891 | fn contents_first() { |
892 | let dir = Dir::tmp(); |
893 | dir.touch("a" ); |
894 | |
895 | let wd = WalkDir::new(dir.path()).contents_first(true); |
896 | let r = dir.run_recursive(wd); |
897 | r.assert_no_errors(); |
898 | |
899 | let expected = vec![dir.join("a" ), dir.path().to_path_buf()]; |
900 | assert_eq!(expected, r.paths()); |
901 | } |
902 | |
903 | #[test] |
904 | fn skip_current_dir() { |
905 | let dir = Dir::tmp(); |
906 | dir.mkdirp("foo/bar/baz" ); |
907 | dir.mkdirp("quux" ); |
908 | |
909 | let mut paths = vec![]; |
910 | let mut it = WalkDir::new(dir.path()).into_iter(); |
911 | while let Some(result) = it.next() { |
912 | let ent = result.unwrap(); |
913 | paths.push(ent.path().to_path_buf()); |
914 | if ent.file_name() == "bar" { |
915 | it.skip_current_dir(); |
916 | } |
917 | } |
918 | paths.sort(); |
919 | |
920 | let expected = vec![ |
921 | dir.path().to_path_buf(), |
922 | dir.join("foo" ), |
923 | dir.join("foo" ).join("bar" ), |
924 | dir.join("quux" ), |
925 | ]; |
926 | assert_eq!(expected, paths); |
927 | } |
928 | |
929 | #[test] |
930 | fn filter_entry() { |
931 | let dir = Dir::tmp(); |
932 | dir.mkdirp("foo/bar/baz/abc" ); |
933 | dir.mkdirp("quux" ); |
934 | |
935 | let wd = WalkDir::new(dir.path()) |
936 | .into_iter() |
937 | .filter_entry(|ent| ent.file_name() != "baz" ); |
938 | let r = dir.run_recursive(wd); |
939 | r.assert_no_errors(); |
940 | |
941 | let expected = vec![ |
942 | dir.path().to_path_buf(), |
943 | dir.join("foo" ), |
944 | dir.join("foo" ).join("bar" ), |
945 | dir.join("quux" ), |
946 | ]; |
947 | assert_eq!(expected, r.sorted_paths()); |
948 | } |
949 | |
950 | #[test] |
951 | fn sort_by() { |
952 | let dir = Dir::tmp(); |
953 | dir.mkdirp("foo/bar/baz/abc" ); |
954 | dir.mkdirp("quux" ); |
955 | |
956 | let wd = WalkDir::new(dir.path()) |
957 | .sort_by(|a, b| a.file_name().cmp(b.file_name()).reverse()); |
958 | let r = dir.run_recursive(wd); |
959 | r.assert_no_errors(); |
960 | |
961 | let expected = vec![ |
962 | dir.path().to_path_buf(), |
963 | dir.join("quux" ), |
964 | dir.join("foo" ), |
965 | dir.join("foo" ).join("bar" ), |
966 | dir.join("foo" ).join("bar" ).join("baz" ), |
967 | dir.join("foo" ).join("bar" ).join("baz" ).join("abc" ), |
968 | ]; |
969 | assert_eq!(expected, r.paths()); |
970 | } |
971 | |
972 | #[test] |
973 | fn sort_by_key() { |
974 | let dir = Dir::tmp(); |
975 | dir.mkdirp("foo/bar/baz/abc" ); |
976 | dir.mkdirp("quux" ); |
977 | |
978 | let wd = |
979 | WalkDir::new(dir.path()).sort_by_key(|a| a.file_name().to_owned()); |
980 | let r = dir.run_recursive(wd); |
981 | r.assert_no_errors(); |
982 | |
983 | let expected = vec![ |
984 | dir.path().to_path_buf(), |
985 | dir.join("foo" ), |
986 | dir.join("foo" ).join("bar" ), |
987 | dir.join("foo" ).join("bar" ).join("baz" ), |
988 | dir.join("foo" ).join("bar" ).join("baz" ).join("abc" ), |
989 | dir.join("quux" ), |
990 | ]; |
991 | assert_eq!(expected, r.paths()); |
992 | } |
993 | |
994 | #[test] |
995 | fn sort_by_file_name() { |
996 | let dir = Dir::tmp(); |
997 | dir.mkdirp("foo/bar/baz/abc" ); |
998 | dir.mkdirp("quux" ); |
999 | |
1000 | let wd = WalkDir::new(dir.path()).sort_by_file_name(); |
1001 | let r = dir.run_recursive(wd); |
1002 | r.assert_no_errors(); |
1003 | |
1004 | let expected = vec![ |
1005 | dir.path().to_path_buf(), |
1006 | dir.join("foo" ), |
1007 | dir.join("foo" ).join("bar" ), |
1008 | dir.join("foo" ).join("bar" ).join("baz" ), |
1009 | dir.join("foo" ).join("bar" ).join("baz" ).join("abc" ), |
1010 | dir.join("quux" ), |
1011 | ]; |
1012 | assert_eq!(expected, r.paths()); |
1013 | } |
1014 | |
1015 | #[test] |
1016 | fn sort_max_open() { |
1017 | let dir = Dir::tmp(); |
1018 | dir.mkdirp("foo/bar/baz/abc" ); |
1019 | dir.mkdirp("quux" ); |
1020 | |
1021 | let wd = WalkDir::new(dir.path()) |
1022 | .max_open(1) |
1023 | .sort_by(|a, b| a.file_name().cmp(b.file_name()).reverse()); |
1024 | let r = dir.run_recursive(wd); |
1025 | r.assert_no_errors(); |
1026 | |
1027 | let expected = vec![ |
1028 | dir.path().to_path_buf(), |
1029 | dir.join("quux" ), |
1030 | dir.join("foo" ), |
1031 | dir.join("foo" ).join("bar" ), |
1032 | dir.join("foo" ).join("bar" ).join("baz" ), |
1033 | dir.join("foo" ).join("bar" ).join("baz" ).join("abc" ), |
1034 | ]; |
1035 | assert_eq!(expected, r.paths()); |
1036 | } |
1037 | |
1038 | #[cfg (target_os = "linux" )] |
1039 | #[test] |
1040 | fn same_file_system() { |
1041 | use std::path::Path; |
1042 | |
1043 | // This test is a little weird since it's not clear whether it's a good |
1044 | // idea to setup a distinct mounted volume in these tests. Instead, we |
1045 | // probe for an existing one. |
1046 | if !Path::new("/sys" ).is_dir() { |
1047 | return; |
1048 | } |
1049 | |
1050 | let dir = Dir::tmp(); |
1051 | dir.touch("a" ); |
1052 | dir.symlink_dir("/sys" , "sys-link" ); |
1053 | |
1054 | // First, do a sanity check that things work without following symlinks. |
1055 | let wd = WalkDir::new(dir.path()); |
1056 | let r = dir.run_recursive(wd); |
1057 | r.assert_no_errors(); |
1058 | |
1059 | let expected = |
1060 | vec![dir.path().to_path_buf(), dir.join("a" ), dir.join("sys-link" )]; |
1061 | assert_eq!(expected, r.sorted_paths()); |
1062 | |
1063 | // ... now follow symlinks and ensure we don't descend into /sys. |
1064 | let wd = |
1065 | WalkDir::new(dir.path()).same_file_system(true).follow_links(true); |
1066 | let r = dir.run_recursive(wd); |
1067 | r.assert_no_errors(); |
1068 | |
1069 | let expected = |
1070 | vec![dir.path().to_path_buf(), dir.join("a" ), dir.join("sys-link" )]; |
1071 | assert_eq!(expected, r.sorted_paths()); |
1072 | } |
1073 | |
1074 | // Tests that skip_current_dir doesn't destroy internal invariants. |
1075 | // |
1076 | // See: https://github.com/BurntSushi/walkdir/issues/118 |
1077 | #[test] |
1078 | fn regression_skip_current_dir() { |
1079 | let dir = Dir::tmp(); |
1080 | dir.mkdirp("foo/a/b" ); |
1081 | dir.mkdirp("foo/1/2" ); |
1082 | |
1083 | let mut wd = WalkDir::new(dir.path()).max_open(1).into_iter(); |
1084 | wd.next(); |
1085 | wd.next(); |
1086 | wd.next(); |
1087 | wd.next(); |
1088 | |
1089 | wd.skip_current_dir(); |
1090 | wd.skip_current_dir(); |
1091 | wd.next(); |
1092 | } |
1093 | |