1 use std::fs;
2 use std::path::PathBuf;
3 
4 use crate::tests::util::Dir;
5 use crate::WalkDir;
6 
7 #[test]
send_sync_traits()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]
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 =
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]
nested_small_max_open()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]
siblings()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]
sym_root_file_nofollow()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]
sym_root_file_follow()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]
sym_root_dir_nofollow()386 fn sym_root_dir_nofollow() {
387     let dir = Dir::tmp();
388     dir.mkdirp("a");
389     dir.symlink_dir("a", "a-link");
390     dir.touch("a/zzz");
391 
392     let wd = WalkDir::new(dir.join("a-link"));
393     let r = dir.run_recursive(wd);
394     r.assert_no_errors();
395 
396     let ents = r.sorted_ents();
397     assert_eq!(2, ents.len());
398     let link = &ents[0];
399 
400     assert_eq!(dir.join("a-link"), link.path());
401 
402     assert!(link.path_is_symlink());
403 
404     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
405 
406     assert_eq!(0, link.depth());
407 
408     assert!(link.file_type().is_symlink());
409     assert!(!link.file_type().is_file());
410     assert!(!link.file_type().is_dir());
411 
412     assert!(link.metadata().unwrap().file_type().is_symlink());
413     assert!(!link.metadata().unwrap().is_file());
414     assert!(!link.metadata().unwrap().is_dir());
415 
416     let link_zzz = &ents[1];
417     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
418     assert!(!link_zzz.path_is_symlink());
419 }
420 
421 #[test]
sym_root_dir_follow()422 fn sym_root_dir_follow() {
423     let dir = Dir::tmp();
424     dir.mkdirp("a");
425     dir.symlink_dir("a", "a-link");
426     dir.touch("a/zzz");
427 
428     let wd = WalkDir::new(dir.join("a-link")).follow_links(true);
429     let r = dir.run_recursive(wd);
430     r.assert_no_errors();
431 
432     let ents = r.sorted_ents();
433     assert_eq!(2, ents.len());
434     let link = &ents[0];
435 
436     assert_eq!(dir.join("a-link"), link.path());
437 
438     assert!(link.path_is_symlink());
439 
440     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
441 
442     assert_eq!(0, link.depth());
443 
444     assert!(!link.file_type().is_symlink());
445     assert!(!link.file_type().is_file());
446     assert!(link.file_type().is_dir());
447 
448     assert!(!link.metadata().unwrap().file_type().is_symlink());
449     assert!(!link.metadata().unwrap().is_file());
450     assert!(link.metadata().unwrap().is_dir());
451 
452     let link_zzz = &ents[1];
453     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
454     assert!(!link_zzz.path_is_symlink());
455 }
456 
457 #[test]
sym_file_nofollow()458 fn sym_file_nofollow() {
459     let dir = Dir::tmp();
460     dir.touch("a");
461     dir.symlink_file("a", "a-link");
462 
463     let wd = WalkDir::new(dir.path());
464     let r = dir.run_recursive(wd);
465     r.assert_no_errors();
466 
467     let ents = r.sorted_ents();
468     assert_eq!(3, ents.len());
469     let (src, link) = (&ents[1], &ents[2]);
470 
471     assert_eq!(dir.join("a"), src.path());
472     assert_eq!(dir.join("a-link"), link.path());
473 
474     assert!(!src.path_is_symlink());
475     assert!(link.path_is_symlink());
476 
477     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
478 
479     assert_eq!(1, src.depth());
480     assert_eq!(1, link.depth());
481 
482     assert!(src.file_type().is_file());
483     assert!(link.file_type().is_symlink());
484     assert!(!link.file_type().is_file());
485     assert!(!link.file_type().is_dir());
486 
487     assert!(src.metadata().unwrap().is_file());
488     assert!(link.metadata().unwrap().file_type().is_symlink());
489     assert!(!link.metadata().unwrap().is_file());
490     assert!(!link.metadata().unwrap().is_dir());
491 }
492 
493 #[test]
sym_file_follow()494 fn sym_file_follow() {
495     let dir = Dir::tmp();
496     dir.touch("a");
497     dir.symlink_file("a", "a-link");
498 
499     let wd = WalkDir::new(dir.path()).follow_links(true);
500     let r = dir.run_recursive(wd);
501     r.assert_no_errors();
502 
503     let ents = r.sorted_ents();
504     assert_eq!(3, ents.len());
505     let (src, link) = (&ents[1], &ents[2]);
506 
507     assert_eq!(dir.join("a"), src.path());
508     assert_eq!(dir.join("a-link"), link.path());
509 
510     assert!(!src.path_is_symlink());
511     assert!(link.path_is_symlink());
512 
513     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
514 
515     assert_eq!(1, src.depth());
516     assert_eq!(1, link.depth());
517 
518     assert!(src.file_type().is_file());
519     assert!(!link.file_type().is_symlink());
520     assert!(link.file_type().is_file());
521     assert!(!link.file_type().is_dir());
522 
523     assert!(src.metadata().unwrap().is_file());
524     assert!(!link.metadata().unwrap().file_type().is_symlink());
525     assert!(link.metadata().unwrap().is_file());
526     assert!(!link.metadata().unwrap().is_dir());
527 }
528 
529 #[test]
sym_dir_nofollow()530 fn sym_dir_nofollow() {
531     let dir = Dir::tmp();
532     dir.mkdirp("a");
533     dir.symlink_dir("a", "a-link");
534     dir.touch("a/zzz");
535 
536     let wd = WalkDir::new(dir.path());
537     let r = dir.run_recursive(wd);
538     r.assert_no_errors();
539 
540     let ents = r.sorted_ents();
541     assert_eq!(4, ents.len());
542     let (src, link) = (&ents[1], &ents[3]);
543 
544     assert_eq!(dir.join("a"), src.path());
545     assert_eq!(dir.join("a-link"), link.path());
546 
547     assert!(!src.path_is_symlink());
548     assert!(link.path_is_symlink());
549 
550     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
551 
552     assert_eq!(1, src.depth());
553     assert_eq!(1, link.depth());
554 
555     assert!(src.file_type().is_dir());
556     assert!(link.file_type().is_symlink());
557     assert!(!link.file_type().is_file());
558     assert!(!link.file_type().is_dir());
559 
560     assert!(src.metadata().unwrap().is_dir());
561     assert!(link.metadata().unwrap().file_type().is_symlink());
562     assert!(!link.metadata().unwrap().is_file());
563     assert!(!link.metadata().unwrap().is_dir());
564 }
565 
566 #[test]
sym_dir_follow()567 fn sym_dir_follow() {
568     let dir = Dir::tmp();
569     dir.mkdirp("a");
570     dir.symlink_dir("a", "a-link");
571     dir.touch("a/zzz");
572 
573     let wd = WalkDir::new(dir.path()).follow_links(true);
574     let r = dir.run_recursive(wd);
575     r.assert_no_errors();
576 
577     let ents = r.sorted_ents();
578     assert_eq!(5, ents.len());
579     let (src, link) = (&ents[1], &ents[3]);
580 
581     assert_eq!(dir.join("a"), src.path());
582     assert_eq!(dir.join("a-link"), link.path());
583 
584     assert!(!src.path_is_symlink());
585     assert!(link.path_is_symlink());
586 
587     assert_eq!(dir.join("a"), fs::read_link(link.path()).unwrap());
588 
589     assert_eq!(1, src.depth());
590     assert_eq!(1, link.depth());
591 
592     assert!(src.file_type().is_dir());
593     assert!(!link.file_type().is_symlink());
594     assert!(!link.file_type().is_file());
595     assert!(link.file_type().is_dir());
596 
597     assert!(src.metadata().unwrap().is_dir());
598     assert!(!link.metadata().unwrap().file_type().is_symlink());
599     assert!(!link.metadata().unwrap().is_file());
600     assert!(link.metadata().unwrap().is_dir());
601 
602     let (src_zzz, link_zzz) = (&ents[2], &ents[4]);
603     assert_eq!(dir.join("a").join("zzz"), src_zzz.path());
604     assert_eq!(dir.join("a-link").join("zzz"), link_zzz.path());
605     assert!(!src_zzz.path_is_symlink());
606     assert!(!link_zzz.path_is_symlink());
607 }
608 
609 #[test]
sym_noloop()610 fn sym_noloop() {
611     let dir = Dir::tmp();
612     dir.mkdirp("a/b/c");
613     dir.symlink_dir("a", "a/b/c/a-link");
614 
615     let wd = WalkDir::new(dir.path());
616     let r = dir.run_recursive(wd);
617     // There's no loop if we aren't following symlinks.
618     r.assert_no_errors();
619 
620     assert_eq!(5, r.ents().len());
621 }
622 
623 #[test]
sym_loop_detect()624 fn sym_loop_detect() {
625     let dir = Dir::tmp();
626     dir.mkdirp("a/b/c");
627     dir.symlink_dir("a", "a/b/c/a-link");
628 
629     let wd = WalkDir::new(dir.path()).follow_links(true);
630     let r = dir.run_recursive(wd);
631 
632     let (ents, errs) = (r.sorted_ents(), r.errs());
633     assert_eq!(4, ents.len());
634     assert_eq!(1, errs.len());
635 
636     let err = &errs[0];
637 
638     let expected = dir.join("a/b/c/a-link");
639     assert_eq!(Some(&*expected), err.path());
640 
641     let expected = dir.join("a");
642     assert_eq!(Some(&*expected), err.loop_ancestor());
643 
644     assert_eq!(4, err.depth());
645     assert!(err.io_error().is_none());
646 }
647 
648 #[test]
sym_self_loop_no_error()649 fn sym_self_loop_no_error() {
650     let dir = Dir::tmp();
651     dir.symlink_file("a", "a");
652 
653     let wd = WalkDir::new(dir.path());
654     let r = dir.run_recursive(wd);
655     // No errors occur because even though the symlink points to nowhere, it
656     // is never followed, and thus no error occurs.
657     r.assert_no_errors();
658     assert_eq!(2, r.ents().len());
659 
660     let ent = &r.ents()[1];
661     assert_eq!(dir.join("a"), ent.path());
662     assert!(ent.path_is_symlink());
663 
664     assert!(ent.file_type().is_symlink());
665     assert!(!ent.file_type().is_file());
666     assert!(!ent.file_type().is_dir());
667 
668     assert!(ent.metadata().unwrap().file_type().is_symlink());
669     assert!(!ent.metadata().unwrap().file_type().is_file());
670     assert!(!ent.metadata().unwrap().file_type().is_dir());
671 }
672 
673 #[test]
sym_file_self_loop_io_error()674 fn sym_file_self_loop_io_error() {
675     let dir = Dir::tmp();
676     dir.symlink_file("a", "a");
677 
678     let wd = WalkDir::new(dir.path()).follow_links(true);
679     let r = dir.run_recursive(wd);
680 
681     let (ents, errs) = (r.sorted_ents(), r.errs());
682     assert_eq!(1, ents.len());
683     assert_eq!(1, errs.len());
684 
685     let err = &errs[0];
686 
687     let expected = dir.join("a");
688     assert_eq!(Some(&*expected), err.path());
689     assert_eq!(1, err.depth());
690     assert!(err.loop_ancestor().is_none());
691     assert!(err.io_error().is_some());
692 }
693 
694 #[test]
sym_dir_self_loop_io_error()695 fn sym_dir_self_loop_io_error() {
696     let dir = Dir::tmp();
697     dir.symlink_dir("a", "a");
698 
699     let wd = WalkDir::new(dir.path()).follow_links(true);
700     let r = dir.run_recursive(wd);
701 
702     let (ents, errs) = (r.sorted_ents(), r.errs());
703     assert_eq!(1, ents.len());
704     assert_eq!(1, errs.len());
705 
706     let err = &errs[0];
707 
708     let expected = dir.join("a");
709     assert_eq!(Some(&*expected), err.path());
710     assert_eq!(1, err.depth());
711     assert!(err.loop_ancestor().is_none());
712     assert!(err.io_error().is_some());
713 }
714 
715 #[test]
min_depth_1()716 fn min_depth_1() {
717     let dir = Dir::tmp();
718     dir.mkdirp("a/b");
719 
720     let wd = WalkDir::new(dir.path()).min_depth(1);
721     let r = dir.run_recursive(wd);
722     r.assert_no_errors();
723 
724     let expected = vec![dir.join("a"), dir.join("a").join("b")];
725     assert_eq!(expected, r.sorted_paths());
726 }
727 
728 #[test]
min_depth_2()729 fn min_depth_2() {
730     let dir = Dir::tmp();
731     dir.mkdirp("a/b");
732 
733     let wd = WalkDir::new(dir.path()).min_depth(2);
734     let r = dir.run_recursive(wd);
735     r.assert_no_errors();
736 
737     let expected = vec![dir.join("a").join("b")];
738     assert_eq!(expected, r.sorted_paths());
739 }
740 
741 #[test]
max_depth_0()742 fn max_depth_0() {
743     let dir = Dir::tmp();
744     dir.mkdirp("a/b");
745 
746     let wd = WalkDir::new(dir.path()).max_depth(0);
747     let r = dir.run_recursive(wd);
748     r.assert_no_errors();
749 
750     let expected = vec![dir.path().to_path_buf()];
751     assert_eq!(expected, r.sorted_paths());
752 }
753 
754 #[test]
max_depth_1()755 fn max_depth_1() {
756     let dir = Dir::tmp();
757     dir.mkdirp("a/b");
758 
759     let wd = WalkDir::new(dir.path()).max_depth(1);
760     let r = dir.run_recursive(wd);
761     r.assert_no_errors();
762 
763     let expected = vec![dir.path().to_path_buf(), dir.join("a")];
764     assert_eq!(expected, r.sorted_paths());
765 }
766 
767 #[test]
max_depth_2()768 fn max_depth_2() {
769     let dir = Dir::tmp();
770     dir.mkdirp("a/b");
771 
772     let wd = WalkDir::new(dir.path()).max_depth(2);
773     let r = dir.run_recursive(wd);
774     r.assert_no_errors();
775 
776     let expected =
777         vec![dir.path().to_path_buf(), dir.join("a"), dir.join("a").join("b")];
778     assert_eq!(expected, r.sorted_paths());
779 }
780 
781 // FIXME: This test seems wrong. It should return nothing!
782 #[test]
min_max_depth_diff_nada()783 fn min_max_depth_diff_nada() {
784     let dir = Dir::tmp();
785     dir.mkdirp("a/b/c");
786 
787     let wd = WalkDir::new(dir.path()).min_depth(3).max_depth(2);
788     let r = dir.run_recursive(wd);
789     r.assert_no_errors();
790 
791     let expected = vec![dir.join("a").join("b").join("c")];
792     assert_eq!(expected, r.sorted_paths());
793 }
794 
795 #[test]
min_max_depth_diff_0()796 fn min_max_depth_diff_0() {
797     let dir = Dir::tmp();
798     dir.mkdirp("a/b/c");
799 
800     let wd = WalkDir::new(dir.path()).min_depth(2).max_depth(2);
801     let r = dir.run_recursive(wd);
802     r.assert_no_errors();
803 
804     let expected = vec![dir.join("a").join("b")];
805     assert_eq!(expected, r.sorted_paths());
806 }
807 
808 #[test]
min_max_depth_diff_1()809 fn min_max_depth_diff_1() {
810     let dir = Dir::tmp();
811     dir.mkdirp("a/b/c");
812 
813     let wd = WalkDir::new(dir.path()).min_depth(1).max_depth(2);
814     let r = dir.run_recursive(wd);
815     r.assert_no_errors();
816 
817     let expected = vec![dir.join("a"), dir.join("a").join("b")];
818     assert_eq!(expected, r.sorted_paths());
819 }
820 
821 #[test]
contents_first()822 fn contents_first() {
823     let dir = Dir::tmp();
824     dir.touch("a");
825 
826     let wd = WalkDir::new(dir.path()).contents_first(true);
827     let r = dir.run_recursive(wd);
828     r.assert_no_errors();
829 
830     let expected = vec![dir.join("a"), dir.path().to_path_buf()];
831     assert_eq!(expected, r.paths());
832 }
833 
834 #[test]
skip_current_dir()835 fn skip_current_dir() {
836     let dir = Dir::tmp();
837     dir.mkdirp("foo/bar/baz");
838     dir.mkdirp("quux");
839 
840     let mut paths = vec![];
841     let mut it = WalkDir::new(dir.path()).into_iter();
842     while let Some(result) = it.next() {
843         let ent = result.unwrap();
844         paths.push(ent.path().to_path_buf());
845         if ent.file_name() == "bar" {
846             it.skip_current_dir();
847         }
848     }
849     paths.sort();
850 
851     let expected = vec![
852         dir.path().to_path_buf(),
853         dir.join("foo"),
854         dir.join("foo").join("bar"),
855         dir.join("quux"),
856     ];
857     assert_eq!(expected, paths);
858 }
859 
860 #[test]
filter_entry()861 fn filter_entry() {
862     let dir = Dir::tmp();
863     dir.mkdirp("foo/bar/baz/abc");
864     dir.mkdirp("quux");
865 
866     let wd = WalkDir::new(dir.path())
867         .into_iter()
868         .filter_entry(|ent| ent.file_name() != "baz");
869     let r = dir.run_recursive(wd);
870     r.assert_no_errors();
871 
872     let expected = vec![
873         dir.path().to_path_buf(),
874         dir.join("foo"),
875         dir.join("foo").join("bar"),
876         dir.join("quux"),
877     ];
878     assert_eq!(expected, r.sorted_paths());
879 }
880 
881 #[test]
sort()882 fn sort() {
883     let dir = Dir::tmp();
884     dir.mkdirp("foo/bar/baz/abc");
885     dir.mkdirp("quux");
886 
887     let wd = WalkDir::new(dir.path())
888         .sort_by(|a, b| a.file_name().cmp(b.file_name()).reverse());
889     let r = dir.run_recursive(wd);
890     r.assert_no_errors();
891 
892     let expected = vec![
893         dir.path().to_path_buf(),
894         dir.join("quux"),
895         dir.join("foo"),
896         dir.join("foo").join("bar"),
897         dir.join("foo").join("bar").join("baz"),
898         dir.join("foo").join("bar").join("baz").join("abc"),
899     ];
900     assert_eq!(expected, r.paths());
901 }
902 
903 #[test]
sort_max_open()904 fn sort_max_open() {
905     let dir = Dir::tmp();
906     dir.mkdirp("foo/bar/baz/abc");
907     dir.mkdirp("quux");
908 
909     let wd = WalkDir::new(dir.path())
910         .max_open(1)
911         .sort_by(|a, b| a.file_name().cmp(b.file_name()).reverse());
912     let r = dir.run_recursive(wd);
913     r.assert_no_errors();
914 
915     let expected = vec![
916         dir.path().to_path_buf(),
917         dir.join("quux"),
918         dir.join("foo"),
919         dir.join("foo").join("bar"),
920         dir.join("foo").join("bar").join("baz"),
921         dir.join("foo").join("bar").join("baz").join("abc"),
922     ];
923     assert_eq!(expected, r.paths());
924 }
925 
926 #[cfg(target_os = "linux")]
927 #[test]
same_file_system()928 fn same_file_system() {
929     use std::path::Path;
930 
931     // This test is a little weird since it's not clear whether it's a good
932     // idea to setup a distinct mounted volume in these tests. Instead, we
933     // probe for an existing one.
934     if !Path::new("/sys").is_dir() {
935         return;
936     }
937 
938     let dir = Dir::tmp();
939     dir.touch("a");
940     dir.symlink_dir("/sys", "sys-link");
941 
942     // First, do a sanity check that things work without following symlinks.
943     let wd = WalkDir::new(dir.path());
944     let r = dir.run_recursive(wd);
945     r.assert_no_errors();
946 
947     let expected =
948         vec![dir.path().to_path_buf(), dir.join("a"), dir.join("sys-link")];
949     assert_eq!(expected, r.sorted_paths());
950 
951     // ... now follow symlinks and ensure we don't descend into /sys.
952     let wd =
953         WalkDir::new(dir.path()).same_file_system(true).follow_links(true);
954     let r = dir.run_recursive(wd);
955     r.assert_no_errors();
956 
957     let expected =
958         vec![dir.path().to_path_buf(), dir.join("a"), dir.join("sys-link")];
959     assert_eq!(expected, r.sorted_paths());
960 }
961 
962 // Tests that skip_current_dir doesn't destroy internal invariants.
963 //
964 // See: https://github.com/BurntSushi/walkdir/issues/118
965 #[test]
regression_skip_current_dir()966 fn regression_skip_current_dir() {
967     let dir = Dir::tmp();
968     dir.mkdirp("foo/a/b");
969     dir.mkdirp("foo/1/2");
970 
971     let mut wd = WalkDir::new(dir.path()).max_open(1).into_iter();
972     wd.next();
973     wd.next();
974     wd.next();
975     wd.next();
976 
977     wd.skip_current_dir();
978     wd.skip_current_dir();
979     wd.next();
980 }
981