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