1 use std::fs;
2 use std::path::PathBuf;
3 
4 use tests::util::Dir;
5 use WalkDir;
6 
7 #[test]
send_sync_traits()8 fn send_sync_traits() {
9     use {IntoIter, FilterEntry};
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]
empty()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]
empty_follow()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]
empty_file()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]
empty_file_follow()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]
one_dir()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]
one_file()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]
one_dir_one_file()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]
many_files()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]
many_dirs()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]
many_mixed()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]
nested()211 fn nested() {
212     let nested = PathBuf::from(
213         "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     );
215     let dir = Dir::tmp();
216     dir.mkdirp(&nested);
217     dir.touch(nested.join("A"));
218 
219     let wd = WalkDir::new(dir.path());
220     let r = dir.run_recursive(wd);
221     r.assert_no_errors();
222 
223     let expected = vec![
224         dir.path().to_path_buf(),
225         dir.join("a"),
226         dir.join("a/b"),
227         dir.join("a/b/c"),
228         dir.join("a/b/c/d"),
229         dir.join("a/b/c/d/e"),
230         dir.join("a/b/c/d/e/f"),
231         dir.join("a/b/c/d/e/f/g"),
232         dir.join("a/b/c/d/e/f/g/h"),
233         dir.join("a/b/c/d/e/f/g/h/i"),
234         dir.join("a/b/c/d/e/f/g/h/i/j"),
235         dir.join("a/b/c/d/e/f/g/h/i/j/k"),
236         dir.join("a/b/c/d/e/f/g/h/i/j/k/l"),
237         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m"),
238         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n"),
239         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o"),
240         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p"),
241         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q"),
242         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r"),
243         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s"),
244         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t"),
245         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u"),
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"),
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"),
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"),
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"),
250         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"),
251         dir.join(&nested).join("A"),
252     ];
253     assert_eq!(expected, r.sorted_paths());
254 }
255 
256 #[test]
nested_small_max_open()257 fn nested_small_max_open() {
258     let nested = PathBuf::from(
259         "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",
260     );
261     let dir = Dir::tmp();
262     dir.mkdirp(&nested);
263     dir.touch(nested.join("A"));
264 
265     let wd = WalkDir::new(dir.path()).max_open(1);
266     let r = dir.run_recursive(wd);
267     r.assert_no_errors();
268 
269     let expected = vec![
270         dir.path().to_path_buf(),
271         dir.join("a"),
272         dir.join("a/b"),
273         dir.join("a/b/c"),
274         dir.join("a/b/c/d"),
275         dir.join("a/b/c/d/e"),
276         dir.join("a/b/c/d/e/f"),
277         dir.join("a/b/c/d/e/f/g"),
278         dir.join("a/b/c/d/e/f/g/h"),
279         dir.join("a/b/c/d/e/f/g/h/i"),
280         dir.join("a/b/c/d/e/f/g/h/i/j"),
281         dir.join("a/b/c/d/e/f/g/h/i/j/k"),
282         dir.join("a/b/c/d/e/f/g/h/i/j/k/l"),
283         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m"),
284         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n"),
285         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o"),
286         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p"),
287         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q"),
288         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r"),
289         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s"),
290         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t"),
291         dir.join("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u"),
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"),
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"),
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"),
295         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"),
296         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"),
297         dir.join(&nested).join("A"),
298     ];
299     assert_eq!(expected, r.sorted_paths());
300 }
301 
302 #[test]
siblings()303 fn siblings() {
304     let dir = Dir::tmp();
305     dir.mkdirp("foo");
306     dir.mkdirp("bar");
307     dir.touch_all(&["foo/a", "foo/b"]);
308     dir.touch_all(&["bar/a", "bar/b"]);
309 
310     let wd = WalkDir::new(dir.path());
311     let r = dir.run_recursive(wd);
312     r.assert_no_errors();
313 
314     let expected = vec![
315         dir.path().to_path_buf(),
316         dir.join("bar"),
317         dir.join("bar").join("a"),
318         dir.join("bar").join("b"),
319         dir.join("foo"),
320         dir.join("foo").join("a"),
321         dir.join("foo").join("b"),
322     ];
323     assert_eq!(expected, r.sorted_paths());
324 }
325 
326 #[test]
sym_root_file_nofollow()327 fn sym_root_file_nofollow() {
328     let dir = Dir::tmp();
329     dir.touch("a");
330     dir.symlink_file("a", "a-link");
331 
332     let wd = WalkDir::new(dir.join("a-link"));
333     let r = dir.run_recursive(wd);
334     r.assert_no_errors();
335 
336     let ents = r.sorted_ents();
337     assert_eq!(1, ents.len());
338     let link = &ents[0];
339 
340     assert_eq!(dir.join("a-link"), link.path());
341 
342     assert!(link.path_is_symlink());
343 
344     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
345 
346     assert_eq!(0, link.depth());
347 
348     assert!(link.file_type().is_symlink());
349     assert!(!link.file_type().is_file());
350     assert!(!link.file_type().is_dir());
351 
352     assert!(link.metadata().unwrap().file_type().is_symlink());
353     assert!(!link.metadata().unwrap().is_file());
354     assert!(!link.metadata().unwrap().is_dir());
355 }
356 
357 #[test]
sym_root_file_follow()358 fn sym_root_file_follow() {
359     let dir = Dir::tmp();
360     dir.touch("a");
361     dir.symlink_file("a", "a-link");
362 
363     let wd = WalkDir::new(dir.join("a-link")).follow_links(true);
364     let r = dir.run_recursive(wd);
365     r.assert_no_errors();
366 
367     let ents = r.sorted_ents();
368     let link = &ents[0];
369 
370     assert_eq!(dir.join("a-link"), link.path());
371 
372     assert!(link.path_is_symlink());
373 
374     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
375 
376     assert_eq!(0, link.depth());
377 
378     assert!(!link.file_type().is_symlink());
379     assert!(link.file_type().is_file());
380     assert!(!link.file_type().is_dir());
381 
382     assert!(!link.metadata().unwrap().file_type().is_symlink());
383     assert!(link.metadata().unwrap().is_file());
384     assert!(!link.metadata().unwrap().is_dir());
385 }
386 
387 #[test]
sym_root_dir_nofollow()388 fn sym_root_dir_nofollow() {
389     let dir = Dir::tmp();
390     dir.mkdirp("a");
391     dir.symlink_dir("a", "a-link");
392     dir.touch("a/zzz");
393 
394     let wd = WalkDir::new(dir.join("a-link"));
395     let r = dir.run_recursive(wd);
396     r.assert_no_errors();
397 
398     let ents = r.sorted_ents();
399     assert_eq!(2, ents.len());
400     let link = &ents[0];
401 
402     assert_eq!(dir.join("a-link"), link.path());
403 
404     assert!(link.path_is_symlink());
405 
406     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
407 
408     assert_eq!(0, link.depth());
409 
410     assert!(link.file_type().is_symlink());
411     assert!(!link.file_type().is_file());
412     assert!(!link.file_type().is_dir());
413 
414     assert!(link.metadata().unwrap().file_type().is_symlink());
415     assert!(!link.metadata().unwrap().is_file());
416     assert!(!link.metadata().unwrap().is_dir());
417 
418     let link_zzz = &ents[1];
419     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
420     assert!(!link_zzz.path_is_symlink());
421 }
422 
423 #[test]
sym_root_dir_follow()424 fn sym_root_dir_follow() {
425     let dir = Dir::tmp();
426     dir.mkdirp("a");
427     dir.symlink_dir("a", "a-link");
428     dir.touch("a/zzz");
429 
430     let wd = WalkDir::new(dir.join("a-link")).follow_links(true);
431     let r = dir.run_recursive(wd);
432     r.assert_no_errors();
433 
434     let ents = r.sorted_ents();
435     assert_eq!(2, ents.len());
436     let link = &ents[0];
437 
438     assert_eq!(dir.join("a-link"), link.path());
439 
440     assert!(link.path_is_symlink());
441 
442     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
443 
444     assert_eq!(0, link.depth());
445 
446     assert!(!link.file_type().is_symlink());
447     assert!(!link.file_type().is_file());
448     assert!(link.file_type().is_dir());
449 
450     assert!(!link.metadata().unwrap().file_type().is_symlink());
451     assert!(!link.metadata().unwrap().is_file());
452     assert!(link.metadata().unwrap().is_dir());
453 
454     let link_zzz = &ents[1];
455     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
456     assert!(!link_zzz.path_is_symlink());
457 }
458 
459 #[test]
sym_file_nofollow()460 fn sym_file_nofollow() {
461     let dir = Dir::tmp();
462     dir.touch("a");
463     dir.symlink_file("a", "a-link");
464 
465     let wd = WalkDir::new(dir.path());
466     let r = dir.run_recursive(wd);
467     r.assert_no_errors();
468 
469     let ents = r.sorted_ents();
470     assert_eq!(3, ents.len());
471     let (src, link) = (&ents[1], &ents[2]);
472 
473     assert_eq!(dir.join("a"), src.path());
474     assert_eq!(dir.join("a-link"), link.path());
475 
476     assert!(!src.path_is_symlink());
477     assert!(link.path_is_symlink());
478 
479     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
480 
481     assert_eq!(1, src.depth());
482     assert_eq!(1, link.depth());
483 
484     assert!(src.file_type().is_file());
485     assert!(link.file_type().is_symlink());
486     assert!(!link.file_type().is_file());
487     assert!(!link.file_type().is_dir());
488 
489     assert!(src.metadata().unwrap().is_file());
490     assert!(link.metadata().unwrap().file_type().is_symlink());
491     assert!(!link.metadata().unwrap().is_file());
492     assert!(!link.metadata().unwrap().is_dir());
493 }
494 
495 #[test]
sym_file_follow()496 fn sym_file_follow() {
497     let dir = Dir::tmp();
498     dir.touch("a");
499     dir.symlink_file("a", "a-link");
500 
501     let wd = WalkDir::new(dir.path()).follow_links(true);
502     let r = dir.run_recursive(wd);
503     r.assert_no_errors();
504 
505     let ents = r.sorted_ents();
506     assert_eq!(3, ents.len());
507     let (src, link) = (&ents[1], &ents[2]);
508 
509     assert_eq!(dir.join("a"), src.path());
510     assert_eq!(dir.join("a-link"), link.path());
511 
512     assert!(!src.path_is_symlink());
513     assert!(link.path_is_symlink());
514 
515     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
516 
517     assert_eq!(1, src.depth());
518     assert_eq!(1, link.depth());
519 
520     assert!(src.file_type().is_file());
521     assert!(!link.file_type().is_symlink());
522     assert!(link.file_type().is_file());
523     assert!(!link.file_type().is_dir());
524 
525     assert!(src.metadata().unwrap().is_file());
526     assert!(!link.metadata().unwrap().file_type().is_symlink());
527     assert!(link.metadata().unwrap().is_file());
528     assert!(!link.metadata().unwrap().is_dir());
529 }
530 
531 #[test]
sym_dir_nofollow()532 fn sym_dir_nofollow() {
533     let dir = Dir::tmp();
534     dir.mkdirp("a");
535     dir.symlink_dir("a", "a-link");
536     dir.touch("a/zzz");
537 
538     let wd = WalkDir::new(dir.path());
539     let r = dir.run_recursive(wd);
540     r.assert_no_errors();
541 
542     let ents = r.sorted_ents();
543     assert_eq!(4, ents.len());
544     let (src, link) = (&ents[1], &ents[3]);
545 
546     assert_eq!(dir.join("a"), src.path());
547     assert_eq!(dir.join("a-link"), link.path());
548 
549     assert!(!src.path_is_symlink());
550     assert!(link.path_is_symlink());
551 
552     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
553 
554     assert_eq!(1, src.depth());
555     assert_eq!(1, link.depth());
556 
557     assert!(src.file_type().is_dir());
558     assert!(link.file_type().is_symlink());
559     assert!(!link.file_type().is_file());
560     assert!(!link.file_type().is_dir());
561 
562     assert!(src.metadata().unwrap().is_dir());
563     assert!(link.metadata().unwrap().file_type().is_symlink());
564     assert!(!link.metadata().unwrap().is_file());
565     assert!(!link.metadata().unwrap().is_dir());
566 }
567 
568 #[test]
sym_dir_follow()569 fn sym_dir_follow() {
570     let dir = Dir::tmp();
571     dir.mkdirp("a");
572     dir.symlink_dir("a", "a-link");
573     dir.touch("a/zzz");
574 
575     let wd = WalkDir::new(dir.path()).follow_links(true);
576     let r = dir.run_recursive(wd);
577     r.assert_no_errors();
578 
579     let ents = r.sorted_ents();
580     assert_eq!(5, ents.len());
581     let (src, link) = (&ents[1], &ents[3]);
582 
583     assert_eq!(dir.join("a"), src.path());
584     assert_eq!(dir.join("a-link"), link.path());
585 
586     assert!(!src.path_is_symlink());
587     assert!(link.path_is_symlink());
588 
589     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
590 
591     assert_eq!(1, src.depth());
592     assert_eq!(1, link.depth());
593 
594     assert!(src.file_type().is_dir());
595     assert!(!link.file_type().is_symlink());
596     assert!(!link.file_type().is_file());
597     assert!(link.file_type().is_dir());
598 
599     assert!(src.metadata().unwrap().is_dir());
600     assert!(!link.metadata().unwrap().file_type().is_symlink());
601     assert!(!link.metadata().unwrap().is_file());
602     assert!(link.metadata().unwrap().is_dir());
603 
604     let (src_zzz, link_zzz) = (&ents[2], &ents[4]);
605     assert_eq!(dir.join("a").join("zzz"), src_zzz.path());
606     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
607     assert!(!src_zzz.path_is_symlink());
608     assert!(!link_zzz.path_is_symlink());
609 }
610 
611 #[test]
sym_noloop()612 fn sym_noloop() {
613     let dir = Dir::tmp();
614     dir.mkdirp("a/b/c");
615     dir.symlink_dir("a", "a/b/c/a-link");
616 
617     let wd = WalkDir::new(dir.path());
618     let r = dir.run_recursive(wd);
619     // There's no loop if we aren't following symlinks.
620     r.assert_no_errors();
621 
622     assert_eq!(5, r.ents().len());
623 }
624 
625 #[test]
sym_loop_detect()626 fn sym_loop_detect() {
627     let dir = Dir::tmp();
628     dir.mkdirp("a/b/c");
629     dir.symlink_dir("a", "a/b/c/a-link");
630 
631     let wd = WalkDir::new(dir.path()).follow_links(true);
632     let r = dir.run_recursive(wd);
633 
634     let (ents, errs) = (r.sorted_ents(), r.errs());
635     assert_eq!(4, ents.len());
636     assert_eq!(1, errs.len());
637 
638     let err = &errs[0];
639 
640     let expected = dir.join("a/b/c/a-link");
641     assert_eq!(Some(&*expected), err.path());
642 
643     let expected = dir.join("a");
644     assert_eq!(Some(&*expected), err.loop_ancestor());
645 
646     assert_eq!(4, err.depth());
647     assert!(err.io_error().is_none());
648 }
649 
650 #[test]
sym_self_loop_no_error()651 fn sym_self_loop_no_error() {
652     let dir = Dir::tmp();
653     dir.symlink_file("a", "a");
654 
655     let wd = WalkDir::new(dir.path());
656     let r = dir.run_recursive(wd);
657     // No errors occur because even though the symlink points to nowhere, it
658     // is never followed, and thus no error occurs.
659     r.assert_no_errors();
660     assert_eq!(2, r.ents().len());
661 
662     let ent = &r.ents()[1];
663     assert_eq!(dir.join("a"), ent.path());
664     assert!(ent.path_is_symlink());
665 
666     assert!(ent.file_type().is_symlink());
667     assert!(!ent.file_type().is_file());
668     assert!(!ent.file_type().is_dir());
669 
670     assert!(ent.metadata().unwrap().file_type().is_symlink());
671     assert!(!ent.metadata().unwrap().file_type().is_file());
672     assert!(!ent.metadata().unwrap().file_type().is_dir());
673 }
674 
675 #[test]
sym_file_self_loop_io_error()676 fn sym_file_self_loop_io_error() {
677     let dir = Dir::tmp();
678     dir.symlink_file("a", "a");
679 
680     let wd = WalkDir::new(dir.path()).follow_links(true);
681     let r = dir.run_recursive(wd);
682 
683     let (ents, errs) = (r.sorted_ents(), r.errs());
684     assert_eq!(1, ents.len());
685     assert_eq!(1, errs.len());
686 
687     let err = &errs[0];
688 
689     let expected = dir.join("a");
690     assert_eq!(Some(&*expected), err.path());
691     assert_eq!(1, err.depth());
692     assert!(err.loop_ancestor().is_none());
693     assert!(err.io_error().is_some());
694 }
695 
696 #[test]
sym_dir_self_loop_io_error()697 fn sym_dir_self_loop_io_error() {
698     let dir = Dir::tmp();
699     dir.symlink_dir("a", "a");
700 
701     let wd = WalkDir::new(dir.path()).follow_links(true);
702     let r = dir.run_recursive(wd);
703 
704     let (ents, errs) = (r.sorted_ents(), r.errs());
705     assert_eq!(1, ents.len());
706     assert_eq!(1, errs.len());
707 
708     let err = &errs[0];
709 
710     let expected = dir.join("a");
711     assert_eq!(Some(&*expected), err.path());
712     assert_eq!(1, err.depth());
713     assert!(err.loop_ancestor().is_none());
714     assert!(err.io_error().is_some());
715 }
716 
717 #[test]
min_depth_1()718 fn min_depth_1() {
719     let dir = Dir::tmp();
720     dir.mkdirp("a/b");
721 
722     let wd = WalkDir::new(dir.path()).min_depth(1);
723     let r = dir.run_recursive(wd);
724     r.assert_no_errors();
725 
726     let expected = vec![
727         dir.join("a"),
728         dir.join("a").join("b"),
729     ];
730     assert_eq!(expected, r.sorted_paths());
731 }
732 
733 #[test]
min_depth_2()734 fn min_depth_2() {
735     let dir = Dir::tmp();
736     dir.mkdirp("a/b");
737 
738     let wd = WalkDir::new(dir.path()).min_depth(2);
739     let r = dir.run_recursive(wd);
740     r.assert_no_errors();
741 
742     let expected = vec![
743         dir.join("a").join("b"),
744     ];
745     assert_eq!(expected, r.sorted_paths());
746 }
747 
748 #[test]
max_depth_0()749 fn max_depth_0() {
750     let dir = Dir::tmp();
751     dir.mkdirp("a/b");
752 
753     let wd = WalkDir::new(dir.path()).max_depth(0);
754     let r = dir.run_recursive(wd);
755     r.assert_no_errors();
756 
757     let expected = vec![
758         dir.path().to_path_buf(),
759     ];
760     assert_eq!(expected, r.sorted_paths());
761 }
762 
763 #[test]
max_depth_1()764 fn max_depth_1() {
765     let dir = Dir::tmp();
766     dir.mkdirp("a/b");
767 
768     let wd = WalkDir::new(dir.path()).max_depth(1);
769     let r = dir.run_recursive(wd);
770     r.assert_no_errors();
771 
772     let expected = vec![
773         dir.path().to_path_buf(),
774         dir.join("a"),
775     ];
776     assert_eq!(expected, r.sorted_paths());
777 }
778 
779 #[test]
max_depth_2()780 fn max_depth_2() {
781     let dir = Dir::tmp();
782     dir.mkdirp("a/b");
783 
784     let wd = WalkDir::new(dir.path()).max_depth(2);
785     let r = dir.run_recursive(wd);
786     r.assert_no_errors();
787 
788     let expected = vec![
789         dir.path().to_path_buf(),
790         dir.join("a"),
791         dir.join("a").join("b"),
792     ];
793     assert_eq!(expected, r.sorted_paths());
794 }
795 
796 // FIXME: This test seems wrong. It should return nothing!
797 #[test]
min_max_depth_diff_nada()798 fn min_max_depth_diff_nada() {
799     let dir = Dir::tmp();
800     dir.mkdirp("a/b/c");
801 
802     let wd = WalkDir::new(dir.path()).min_depth(3).max_depth(2);
803     let r = dir.run_recursive(wd);
804     r.assert_no_errors();
805 
806     let expected = vec![
807         dir.join("a").join("b").join("c"),
808     ];
809     assert_eq!(expected, r.sorted_paths());
810 }
811 
812 #[test]
min_max_depth_diff_0()813 fn min_max_depth_diff_0() {
814     let dir = Dir::tmp();
815     dir.mkdirp("a/b/c");
816 
817     let wd = WalkDir::new(dir.path()).min_depth(2).max_depth(2);
818     let r = dir.run_recursive(wd);
819     r.assert_no_errors();
820 
821     let expected = vec![
822         dir.join("a").join("b"),
823     ];
824     assert_eq!(expected, r.sorted_paths());
825 }
826 
827 #[test]
min_max_depth_diff_1()828 fn min_max_depth_diff_1() {
829     let dir = Dir::tmp();
830     dir.mkdirp("a/b/c");
831 
832     let wd = WalkDir::new(dir.path()).min_depth(1).max_depth(2);
833     let r = dir.run_recursive(wd);
834     r.assert_no_errors();
835 
836     let expected = vec![
837         dir.join("a"),
838         dir.join("a").join("b"),
839     ];
840     assert_eq!(expected, r.sorted_paths());
841 }
842 
843 #[test]
contents_first()844 fn contents_first() {
845     let dir = Dir::tmp();
846     dir.touch("a");
847 
848     let wd = WalkDir::new(dir.path()).contents_first(true);
849     let r = dir.run_recursive(wd);
850     r.assert_no_errors();
851 
852     let expected = vec![
853         dir.join("a"),
854         dir.path().to_path_buf(),
855     ];
856     assert_eq!(expected, r.paths());
857 }
858 
859 #[test]
skip_current_dir()860 fn skip_current_dir() {
861     let dir = Dir::tmp();
862     dir.mkdirp("foo/bar/baz");
863     dir.mkdirp("quux");
864 
865     let mut paths = vec![];
866     let mut it = WalkDir::new(dir.path()).into_iter();
867     while let Some(result) = it.next() {
868         let ent = result.unwrap();
869         paths.push(ent.path().to_path_buf());
870         if ent.file_name() == "bar" {
871             it.skip_current_dir();
872         }
873     }
874     paths.sort();
875 
876     let expected = vec![
877         dir.path().to_path_buf(),
878         dir.join("foo"),
879         dir.join("foo").join("bar"),
880         dir.join("quux"),
881     ];
882     assert_eq!(expected, paths);
883 }
884 
885 #[test]
filter_entry()886 fn filter_entry() {
887     let dir = Dir::tmp();
888     dir.mkdirp("foo/bar/baz/abc");
889     dir.mkdirp("quux");
890 
891     let wd = WalkDir::new(dir.path())
892         .into_iter()
893         .filter_entry(|ent| ent.file_name() != "baz");
894     let r = dir.run_recursive(wd);
895     r.assert_no_errors();
896 
897     let expected = vec![
898         dir.path().to_path_buf(),
899         dir.join("foo"),
900         dir.join("foo").join("bar"),
901         dir.join("quux"),
902     ];
903     assert_eq!(expected, r.sorted_paths());
904 }
905 
906 #[test]
sort()907 fn sort() {
908     let dir = Dir::tmp();
909     dir.mkdirp("foo/bar/baz/abc");
910     dir.mkdirp("quux");
911 
912     let wd = WalkDir::new(dir.path())
913         .sort_by(|a,b| a.file_name().cmp(b.file_name()).reverse());
914     let r = dir.run_recursive(wd);
915     r.assert_no_errors();
916 
917     let expected = vec![
918         dir.path().to_path_buf(),
919         dir.join("quux"),
920         dir.join("foo"),
921         dir.join("foo").join("bar"),
922         dir.join("foo").join("bar").join("baz"),
923         dir.join("foo").join("bar").join("baz").join("abc"),
924     ];
925     assert_eq!(expected, r.paths());
926 }
927 
928 #[test]
sort_max_open()929 fn sort_max_open() {
930     let dir = Dir::tmp();
931     dir.mkdirp("foo/bar/baz/abc");
932     dir.mkdirp("quux");
933 
934     let wd = WalkDir::new(dir.path())
935         .max_open(1)
936         .sort_by(|a,b| a.file_name().cmp(b.file_name()).reverse());
937     let r = dir.run_recursive(wd);
938     r.assert_no_errors();
939 
940     let expected = vec![
941         dir.path().to_path_buf(),
942         dir.join("quux"),
943         dir.join("foo"),
944         dir.join("foo").join("bar"),
945         dir.join("foo").join("bar").join("baz"),
946         dir.join("foo").join("bar").join("baz").join("abc"),
947     ];
948     assert_eq!(expected, r.paths());
949 }
950 
951 #[cfg(target_os = "linux")]
952 #[test]
same_file_system()953 fn same_file_system() {
954     use std::path::Path;
955 
956     // This test is a little weird since it's not clear whether it's a good
957     // idea to setup a distinct mounted volume in these tests. Instead, we
958     // probe for an existing one.
959     if !Path::new("/sys").is_dir() {
960         return;
961     }
962 
963     let dir = Dir::tmp();
964     dir.touch("a");
965     dir.symlink_dir("/sys", "sys-link");
966 
967     // First, do a sanity check that things work without following symlinks.
968     let wd = WalkDir::new(dir.path());
969     let r = dir.run_recursive(wd);
970     r.assert_no_errors();
971 
972     let expected = vec![
973         dir.path().to_path_buf(),
974         dir.join("a"),
975         dir.join("sys-link"),
976     ];
977     assert_eq!(expected, r.sorted_paths());
978 
979     // ... now follow symlinks and ensure we don't descend into /sys.
980     let wd = WalkDir::new(dir.path())
981         .same_file_system(true)
982         .follow_links(true);
983     let r = dir.run_recursive(wd);
984     r.assert_no_errors();
985 
986     let expected = vec![
987         dir.path().to_path_buf(),
988         dir.join("a"),
989         dir.join("sys-link"),
990     ];
991     assert_eq!(expected, r.sorted_paths());
992 }
993 
994 // Tests that skip_current_dir doesn't destroy internal invariants.
995 //
996 // See: https://github.com/BurntSushi/walkdir/issues/118
997 #[test]
regression_skip_current_dir()998 fn regression_skip_current_dir() {
999     let dir = Dir::tmp();
1000     dir.mkdirp("foo/a/b");
1001     dir.mkdirp("foo/1/2");
1002 
1003     let mut wd = WalkDir::new(dir.path()).max_open(1).into_iter();
1004     wd.next();
1005     wd.next();
1006     wd.next();
1007     wd.next();
1008 
1009     wd.skip_current_dir();
1010     wd.skip_current_dir();
1011     wd.next();
1012 }
1013