1use std::fs;
2use std::path::PathBuf;
3
4use crate::tests::util::Dir;
5use crate::WalkDir;
6
7#[test]
8fn 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]
23fn 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]
39fn 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]
55fn 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]
73fn 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]
91fn 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]
109fn 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]
127fn 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]
145fn 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]
165fn 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]
186fn 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]
211fn 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]
256fn 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]
301fn 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]
325fn 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]
356fn 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]
386fn 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]
402fn 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]
419fn 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]
437fn 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]
455fn 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]
491fn 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]
527fn 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]
563fn 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]
599fn 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]
636fn 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]
679fn 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]
693fn 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]
718fn 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]
743fn 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]
764fn 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]
785fn 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]
798fn 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]
811fn 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]
824fn 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]
837fn 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]
852fn 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]
865fn 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]
878fn 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]
891fn 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]
904fn 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]
930fn 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]
951fn 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]
973fn 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]
995fn 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]
1016fn 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]
1040fn 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]
1078fn 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