Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/walkdir.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/old.rs')
-rw-r--r--src/tests/old.rs786
1 files changed, 786 insertions, 0 deletions
diff --git a/src/tests/old.rs b/src/tests/old.rs
new file mode 100644
index 0000000..72649ff
--- /dev/null
+++ b/src/tests/old.rs
@@ -0,0 +1,786 @@
+#![cfg_attr(windows, allow(dead_code, unused_imports))]
+
+use std::cmp;
+use std::env;
+use std::fs::{self, File};
+use std::io;
+use std::path::{Path, PathBuf};
+use std::collections::HashMap;
+
+use {DirEntry, WalkDir, IntoIter, Error, ErrorInner};
+
+#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+enum Tree {
+ Dir(PathBuf, Vec<Tree>),
+ File(PathBuf),
+ Symlink {
+ src: PathBuf,
+ dst: PathBuf,
+ dir: bool,
+ }
+}
+
+impl Tree {
+ fn from_walk_with<P, F>(
+ p: P,
+ f: F,
+ ) -> io::Result<Tree>
+ where P: AsRef<Path>, F: FnOnce(WalkDir) -> WalkDir {
+ let mut stack = vec![Tree::Dir(p.as_ref().to_path_buf(), vec![])];
+ let it: WalkEventIter = f(WalkDir::new(p)).into();
+ for ev in it {
+ match try!(ev) {
+ WalkEvent::Exit => {
+ let tree = stack.pop().unwrap();
+ if stack.is_empty() {
+ return Ok(tree);
+ }
+ stack.last_mut().unwrap().children_mut().push(tree);
+ }
+ WalkEvent::Dir(dent) => {
+ stack.push(Tree::Dir(pb(dent.file_name()), vec![]));
+ }
+ WalkEvent::File(dent) => {
+ let node = if dent.file_type().is_symlink() {
+ let src = try!(dent.path().read_link());
+ let dst = pb(dent.file_name());
+ let dir = dent.path().is_dir();
+ Tree::Symlink { src: src, dst: dst, dir: dir }
+ } else {
+ Tree::File(pb(dent.file_name()))
+ };
+ stack.last_mut().unwrap().children_mut().push(node);
+ }
+ }
+ }
+ assert_eq!(stack.len(), 1);
+ Ok(stack.pop().unwrap())
+ }
+
+ fn from_walk_with_contents_first<P, F>(
+ p: P,
+ f: F,
+ ) -> io::Result<Tree>
+ where P: AsRef<Path>, F: FnOnce(WalkDir) -> WalkDir {
+ let mut contents_of_dir_at_depth = HashMap::new();
+ let mut min_depth = ::std::usize::MAX;
+ let top_level_path = p.as_ref().to_path_buf();
+ for result in f(WalkDir::new(p).contents_first(true)) {
+ let dentry = try!(result);
+
+ let tree =
+ if dentry.file_type().is_dir() {
+ let any_contents = contents_of_dir_at_depth.remove(
+ &(dentry.depth+1));
+ Tree::Dir(pb(dentry.file_name()), any_contents.unwrap_or_default())
+ } else {
+ if dentry.file_type().is_symlink() {
+ let src = try!(dentry.path().read_link());
+ let dst = pb(dentry.file_name());
+ let dir = dentry.path().is_dir();
+ Tree::Symlink { src: src, dst: dst, dir: dir }
+ } else {
+ Tree::File(pb(dentry.file_name()))
+ }
+ };
+ contents_of_dir_at_depth.entry(
+ dentry.depth).or_insert(vec!()).push(tree);
+ min_depth = cmp::min(min_depth, dentry.depth);
+ }
+ Ok(Tree::Dir(top_level_path,
+ contents_of_dir_at_depth.remove(&min_depth)
+ .unwrap_or_default()))
+ }
+
+ fn unwrap_singleton(self) -> Tree {
+ match self {
+ Tree::File(_) | Tree::Symlink { .. } => {
+ panic!("cannot unwrap file or link as dir");
+ }
+ Tree::Dir(_, mut childs) => {
+ assert_eq!(childs.len(), 1);
+ childs.pop().unwrap()
+ }
+ }
+ }
+
+ fn unwrap_dir(self) -> Vec<Tree> {
+ match self {
+ Tree::File(_) | Tree::Symlink { .. } => {
+ panic!("cannot unwrap file as dir");
+ }
+ Tree::Dir(_, childs) => childs,
+ }
+ }
+
+ fn children_mut(&mut self) -> &mut Vec<Tree> {
+ match *self {
+ Tree::File(_) | Tree::Symlink { .. } => {
+ panic!("files do not have children");
+ }
+ Tree::Dir(_, ref mut children) => children,
+ }
+ }
+
+ fn create_in<P: AsRef<Path>>(&self, parent: P) -> io::Result<()> {
+ let parent = parent.as_ref();
+ match *self {
+ Tree::Symlink { ref src, ref dst, dir } => {
+ if dir {
+ try!(soft_link_dir(src, parent.join(dst)));
+ } else {
+ try!(soft_link_file(src, parent.join(dst)));
+ }
+ }
+ Tree::File(ref p) => { try!(File::create(parent.join(p))); }
+ Tree::Dir(ref dir, ref children) => {
+ try!(fs::create_dir(parent.join(dir)));
+ for child in children {
+ try!(child.create_in(parent.join(dir)));
+ }
+ }
+ }
+ Ok(())
+ }
+
+ fn canonical(&self) -> Tree {
+ match *self {
+ Tree::Symlink { ref src, ref dst, dir } => {
+ Tree::Symlink { src: src.clone(), dst: dst.clone(), dir: dir }
+ }
+ Tree::File(ref p) => {
+ Tree::File(p.clone())
+ }
+ Tree::Dir(ref p, ref cs) => {
+ let mut cs: Vec<Tree> =
+ cs.iter().map(|c| c.canonical()).collect();
+ cs.sort();
+ Tree::Dir(p.clone(), cs)
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+enum WalkEvent {
+ Dir(DirEntry),
+ File(DirEntry),
+ Exit,
+}
+
+struct WalkEventIter {
+ depth: usize,
+ it: IntoIter,
+ next: Option<Result<DirEntry, Error>>,
+}
+
+impl From<WalkDir> for WalkEventIter {
+ fn from(it: WalkDir) -> WalkEventIter {
+ WalkEventIter { depth: 0, it: it.into_iter(), next: None }
+ }
+}
+
+impl Iterator for WalkEventIter {
+ type Item = io::Result<WalkEvent>;
+
+ fn next(&mut self) -> Option<io::Result<WalkEvent>> {
+ let dent = self.next.take().or_else(|| self.it.next());
+ let depth = match dent {
+ None => 0,
+ Some(Ok(ref dent)) => dent.depth(),
+ Some(Err(ref err)) => err.depth(),
+ };
+ if depth < self.depth {
+ self.depth -= 1;
+ self.next = dent;
+ return Some(Ok(WalkEvent::Exit));
+ }
+ self.depth = depth;
+ match dent {
+ None => None,
+ Some(Err(err)) => Some(Err(From::from(err))),
+ Some(Ok(dent)) => {
+ if dent.file_type().is_dir() {
+ self.depth += 1;
+ Some(Ok(WalkEvent::Dir(dent)))
+ } else {
+ Some(Ok(WalkEvent::File(dent)))
+ }
+ }
+ }
+ }
+}
+
+struct TempDir(PathBuf);
+
+impl TempDir {
+ fn path<'a>(&'a self) -> &'a Path {
+ &self.0
+ }
+}
+
+impl Drop for TempDir {
+ fn drop(&mut self) {
+ fs::remove_dir_all(&self.0).unwrap();
+ }
+}
+
+fn tmpdir() -> TempDir {
+ use std::sync::atomic::{AtomicUsize, Ordering};
+
+ static COUNTER: AtomicUsize = AtomicUsize::new(0);
+
+ let p = env::temp_dir();
+ let idx = COUNTER.fetch_add(1, Ordering::SeqCst);
+ let ret = p.join(&format!("rust-{}", idx));
+ fs::create_dir(&ret).unwrap();
+ TempDir(ret)
+}
+
+fn dir_setup_with<F>(t: &Tree, f: F) -> (TempDir, Tree)
+ where F: Fn(WalkDir) -> WalkDir {
+ let tmp = tmpdir();
+ t.create_in(tmp.path()).unwrap();
+ let got = Tree::from_walk_with(tmp.path(), &f).unwrap();
+ let got_cf = Tree::from_walk_with_contents_first(tmp.path(), &f).unwrap();
+ assert_eq!(got, got_cf);
+
+ (tmp, got.unwrap_singleton().unwrap_singleton())
+}
+
+fn dir_setup(t: &Tree) -> (TempDir, Tree) {
+ dir_setup_with(t, |wd| wd)
+}
+
+fn canon(unix: &str) -> String {
+ if cfg!(windows) {
+ unix.replace("/", "\\")
+ } else {
+ unix.to_string()
+ }
+}
+
+fn pb<P: AsRef<Path>>(p: P) -> PathBuf { p.as_ref().to_path_buf() }
+fn td<P: AsRef<Path>>(p: P, cs: Vec<Tree>) -> Tree {
+ Tree::Dir(pb(p), cs)
+}
+fn tf<P: AsRef<Path>>(p: P) -> Tree {
+ Tree::File(pb(p))
+}
+fn tld<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Tree {
+ Tree::Symlink { src: pb(src), dst: pb(dst), dir: true }
+}
+fn tlf<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Tree {
+ Tree::Symlink { src: pb(src), dst: pb(dst), dir: false }
+}
+
+#[cfg(unix)]
+fn soft_link_dir<P: AsRef<Path>, Q: AsRef<Path>>(
+ src: P,
+ dst: Q,
+) -> io::Result<()> {
+ use std::os::unix::fs::symlink;
+ symlink(src, dst)
+}
+
+#[cfg(unix)]
+fn soft_link_file<P: AsRef<Path>, Q: AsRef<Path>>(
+ src: P,
+ dst: Q,
+) -> io::Result<()> {
+ soft_link_dir(src, dst)
+}
+
+#[cfg(windows)]
+fn soft_link_dir<P: AsRef<Path>, Q: AsRef<Path>>(
+ src: P,
+ dst: Q,
+) -> io::Result<()> {
+ use std::os::windows::fs::symlink_dir;
+ symlink_dir(src, dst)
+}
+
+#[cfg(windows)]
+fn soft_link_file<P: AsRef<Path>, Q: AsRef<Path>>(
+ src: P,
+ dst: Q,
+) -> io::Result<()> {
+ use std::os::windows::fs::symlink_file;
+ symlink_file(src, dst)
+}
+
+macro_rules! assert_tree_eq {
+ ($e1:expr, $e2:expr) => {
+ assert_eq!($e1.canonical(), $e2.canonical());
+ }
+}
+
+#[test]
+fn walk_dir_1() {
+ let exp = td("foo", vec![]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_2() {
+ let exp = tf("foo");
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_3() {
+ let exp = td("foo", vec![tf("bar")]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_4() {
+ let exp = td("foo", vec![tf("foo"), tf("bar"), tf("baz")]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_5() {
+ let exp = td("foo", vec![td("bar", vec![])]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_6() {
+ let exp = td("foo", vec![
+ td("bar", vec![
+ tf("baz"), td("bat", vec![]),
+ ]),
+ ]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_7() {
+ let exp = td("foo", vec![
+ td("bar", vec![
+ tf("baz"), td("bat", vec![]),
+ ]),
+ td("a", vec![tf("b"), tf("c"), tf("d")]),
+ ]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_sym_1() {
+ let exp = td("foo", vec![tf("bar"), tlf("bar", "baz")]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_sym_2() {
+ let exp = td("foo", vec![
+ td("a", vec![tf("a1"), tf("a2")]),
+ tld("a", "alink"),
+ ]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+fn walk_dir_sym_root() {
+ let exp = td("foo", vec![
+ td("bar", vec![tf("a"), tf("b")]),
+ tld("bar", "alink"),
+ ]);
+ let tmp = tmpdir();
+ let tmp_path = tmp.path();
+ let tmp_len = tmp_path.to_str().unwrap().len();
+ exp.create_in(tmp_path).unwrap();
+
+ let it = WalkDir::new(tmp_path.join("foo").join("alink")).into_iter();
+ let mut got = it
+ .map(|d| d.unwrap().path().to_str().unwrap()[tmp_len+1..].into())
+ .collect::<Vec<String>>();
+ got.sort();
+ assert_eq!(got, vec![
+ canon("foo/alink"), canon("foo/alink/a"), canon("foo/alink/b"),
+ ]);
+
+ let it = WalkDir::new(tmp_path.join("foo/alink/")).into_iter();
+ let mut got = it
+ .map(|d| d.unwrap().path().to_str().unwrap()[tmp_len+1..].into())
+ .collect::<Vec<String>>();
+ got.sort();
+ assert_eq!(got, vec!["foo/alink/", "foo/alink/a", "foo/alink/b"]);
+}
+
+// See: https://github.com/BurntSushi/ripgrep/issues/984
+#[test]
+#[cfg(unix)]
+fn first_path_not_symlink() {
+ let exp = td("foo", vec![]);
+ let (tmp, _got) = dir_setup(&exp);
+
+ let dents = WalkDir::new(tmp.path().join("foo"))
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap();
+ assert_eq!(1, dents.len());
+ assert!(!dents[0].path_is_symlink());
+}
+
+// Like first_path_not_symlink, but checks that the first path is not reported
+// as a symlink even when we are supposed to be following them.
+#[test]
+#[cfg(unix)]
+fn first_path_not_symlink_follow() {
+ let exp = td("foo", vec![]);
+ let (tmp, _got) = dir_setup(&exp);
+
+ let dents = WalkDir::new(tmp.path().join("foo"))
+ .follow_links(true)
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap();
+ assert_eq!(1, dents.len());
+ assert!(!dents[0].path_is_symlink());
+}
+
+// See: https://github.com/BurntSushi/walkdir/issues/115
+#[test]
+#[cfg(unix)]
+fn first_path_is_followed() {
+ let exp = td("foo", vec![
+ td("a", vec![tf("a1"), tf("a2")]),
+ td("b", vec![tlf("../a/a1", "alink")]),
+ ]);
+ let (tmp, _got) = dir_setup(&exp);
+
+ let dents = WalkDir::new(tmp.path().join("foo/b/alink"))
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap();
+ assert_eq!(1, dents.len());
+ assert!(dents[0].file_type().is_symlink());
+ assert!(dents[0].metadata().unwrap().file_type().is_symlink());
+
+ let dents = WalkDir::new(tmp.path().join("foo/b/alink"))
+ .follow_links(true)
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>()
+ .unwrap();
+ assert_eq!(1, dents.len());
+ assert!(!dents[0].file_type().is_symlink());
+ assert!(!dents[0].metadata().unwrap().file_type().is_symlink());
+}
+
+#[test]
+#[cfg(unix)]
+fn walk_dir_sym_detect_no_follow_no_loop() {
+ let exp = td("foo", vec![
+ td("a", vec![tf("a1"), tf("a2")]),
+ td("b", vec![tld("../a", "alink")]),
+ ]);
+ let (_tmp, got) = dir_setup(&exp);
+ assert_tree_eq!(exp, got);
+}
+
+#[test]
+#[cfg(unix)]
+fn walk_dir_sym_follow_dir() {
+ let actual = td("foo", vec![
+ td("a", vec![tf("a1"), tf("a2")]),
+ td("b", vec![tld("../a", "alink")]),
+ ]);
+ let followed = td("foo", vec![
+ td("a", vec![tf("a1"), tf("a2")]),
+ td("b", vec![td("alink", vec![tf("a1"), tf("a2")])]),
+ ]);
+ let (_tmp, got) = dir_setup_with(&actual, |wd| wd.follow_links(true));
+ assert_tree_eq!(followed, got);
+}
+
+#[test]
+#[cfg(unix)]
+fn walk_dir_sym_detect_loop() {
+ let actual = td("foo", vec![
+ td("a", vec![tlf("../b", "blink"), tf("a1"), tf("a2")]),
+ td("b", vec![tlf("../a", "alink")]),
+ ]);
+ let tmp = tmpdir();
+ actual.create_in(tmp.path()).unwrap();
+ let got = WalkDir::new(tmp.path())
+ .follow_links(true)
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>();
+ match got {
+ Ok(x) => panic!("expected loop error, got no error: {:?}", x),
+ Err(err @ Error { inner: ErrorInner::Io { .. }, .. }) => {
+ panic!("expected loop error, got generic IO error: {:?}", err);
+ }
+ Err(Error { inner: ErrorInner::Loop { .. }, .. }) => {}
+ }
+}
+
+#[test]
+fn walk_dir_sym_infinite() {
+ let actual = tlf("a", "a");
+ let tmp = tmpdir();
+ actual.create_in(tmp.path()).unwrap();
+ let got = WalkDir::new(tmp.path())
+ .follow_links(true)
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>();
+ match got {
+ Ok(x) => panic!("expected IO error, got no error: {:?}", x),
+ Err(Error { inner: ErrorInner::Loop { .. }, .. }) => {
+ panic!("expected IO error, but got loop error");
+ }
+ Err(Error { inner: ErrorInner::Io { .. }, .. }) => {}
+ }
+}
+
+#[test]
+fn walk_dir_min_depth_1() {
+ let exp = td("foo", vec![tf("bar")]);
+ let (_tmp, got) = dir_setup_with(&exp, |wd| wd.min_depth(1));
+ assert_tree_eq!(tf("bar"), got);
+}
+
+#[test]
+fn walk_dir_min_depth_2() {
+ let exp = td("foo", vec![tf("bar"), tf("baz")]);
+ let tmp = tmpdir();
+ exp.create_in(tmp.path()).unwrap();
+ let got = Tree::from_walk_with(tmp.path(), |wd| wd.min_depth(2))
+ .unwrap().unwrap_dir();
+ let got_cf = Tree::from_walk_with_contents_first(
+ tmp.path(), |wd| wd.min_depth(2))
+ .unwrap().unwrap_dir();
+ assert_eq!(got, got_cf);
+ assert_tree_eq!(exp, td("foo", got));
+}
+
+#[test]
+fn walk_dir_min_depth_3() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("xyz")]),
+ tf("baz"),
+ ]);
+ let tmp = tmpdir();
+ exp.create_in(tmp.path()).unwrap();
+ let got = Tree::from_walk_with(tmp.path(), |wd| wd.min_depth(3))
+ .unwrap().unwrap_dir();
+ assert_eq!(vec![tf("xyz")], got);
+ let got_cf = Tree::from_walk_with_contents_first(
+ tmp.path(), |wd| wd.min_depth(3))
+ .unwrap().unwrap_dir();
+ assert_eq!(got, got_cf);
+}
+
+#[test]
+fn walk_dir_max_depth_1() {
+ let exp = td("foo", vec![tf("bar")]);
+ let (_tmp, got) = dir_setup_with(&exp, |wd| wd.max_depth(1));
+ assert_tree_eq!(td("foo", vec![]), got);
+}
+
+#[test]
+fn walk_dir_max_depth_2() {
+ let exp = td("foo", vec![tf("bar"), tf("baz")]);
+ let (_tmp, got) = dir_setup_with(&exp, |wd| wd.max_depth(1));
+ assert_tree_eq!(td("foo", vec![]), got);
+}
+
+#[test]
+fn walk_dir_max_depth_3() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("xyz")]),
+ tf("baz"),
+ ]);
+ let exp_trimmed = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![]),
+ tf("baz"),
+ ]);
+ let (_tmp, got) = dir_setup_with(&exp, |wd| wd.max_depth(2));
+ assert_tree_eq!(exp_trimmed, got);
+}
+
+#[test]
+fn walk_dir_min_max_depth() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("xyz")]),
+ tf("baz"),
+ ]);
+ let tmp = tmpdir();
+ exp.create_in(tmp.path()).unwrap();
+ let got = Tree::from_walk_with(tmp.path(),
+ |wd| wd.min_depth(2).max_depth(2))
+ .unwrap().unwrap_dir();
+ let got_cf = Tree::from_walk_with_contents_first(tmp.path(),
+ |wd| wd.min_depth(2).max_depth(2))
+ .unwrap().unwrap_dir();
+ assert_eq!(got, got_cf);
+ assert_tree_eq!(
+ td("foo", vec![tf("bar"), td("abc", vec![]), tf("baz")]),
+ td("foo", got));
+}
+
+#[test]
+fn walk_dir_skip() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("xyz")]),
+ tf("baz"),
+ ]);
+ let tmp = tmpdir();
+ exp.create_in(tmp.path()).unwrap();
+ let mut got = vec![];
+ let mut it = WalkDir::new(tmp.path()).min_depth(1).into_iter();
+ loop {
+ let dent = match it.next().map(|x| x.unwrap()) {
+ None => break,
+ Some(dent) => dent,
+ };
+ let name = dent.file_name().to_str().unwrap().to_owned();
+ if name == "abc" {
+ it.skip_current_dir();
+ }
+ got.push(name);
+ }
+ got.sort();
+ assert_eq!(got, vec!["abc", "bar", "baz", "foo"]); // missing xyz!
+}
+
+#[test]
+fn walk_dir_filter() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("fit")]),
+ tf("faz"),
+ ]);
+ let tmp = tmpdir();
+ let tmp_path = tmp.path().to_path_buf();
+ exp.create_in(tmp.path()).unwrap();
+ let it = WalkDir::new(tmp.path()).min_depth(1)
+ .into_iter()
+ .filter_entry(move |d| {
+ let n = d.file_name().to_string_lossy().into_owned();
+ !d.file_type().is_dir()
+ || n.starts_with("f")
+ || d.path() == &*tmp_path
+ });
+ let mut got = it.map(|d| d.unwrap().file_name().to_str().unwrap().into())
+ .collect::<Vec<String>>();
+ got.sort();
+ assert_eq!(got, vec!["bar", "faz", "foo"]);
+}
+
+#[test]
+fn walk_dir_sort() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("fit")]),
+ tf("faz"),
+ ]);
+ let tmp = tmpdir();
+ let tmp_path = tmp.path();
+ let tmp_len = tmp_path.to_str().unwrap().len();
+ exp.create_in(tmp_path).unwrap();
+ let it = WalkDir::new(tmp_path)
+ .sort_by(|a,b| a.file_name().cmp(b.file_name()))
+ .into_iter();
+ let got = it.map(|d| {
+ let path = d.unwrap();
+ let path = &path.path().to_str().unwrap()[tmp_len..];
+ path.replace("\\", "/")
+ }).collect::<Vec<String>>();
+ assert_eq!(
+ got,
+ ["", "/foo", "/foo/abc", "/foo/abc/fit", "/foo/bar", "/foo/faz"]);
+}
+
+#[test]
+fn walk_dir_sort_small_fd_max() {
+ let exp = td("foo", vec![
+ tf("bar"),
+ td("abc", vec![tf("fit")]),
+ tf("faz"),
+ ]);
+ let tmp = tmpdir();
+ let tmp_path = tmp.path();
+ let tmp_len = tmp_path.to_str().unwrap().len();
+ exp.create_in(tmp_path).unwrap();
+ let it = WalkDir::new(tmp_path)
+ .max_open(1)
+ .sort_by(|a,b| a.file_name().cmp(b.file_name()))
+ .into_iter();
+ let got = it.map(|d| {
+ let path = d.unwrap();
+ let path = &path.path().to_str().unwrap()[tmp_len..];
+ path.replace("\\", "/")
+ }).collect::<Vec<String>>();
+ assert_eq!(
+ got,
+ ["", "/foo", "/foo/abc", "/foo/abc/fit", "/foo/bar", "/foo/faz"]);
+}
+
+#[test]
+fn walk_dir_send_sync_traits() {
+ use FilterEntry;
+
+ fn assert_send<T: Send>() {}
+ fn assert_sync<T: Sync>() {}
+
+ assert_send::<WalkDir>();
+ assert_sync::<WalkDir>();
+ assert_send::<IntoIter>();
+ assert_sync::<IntoIter>();
+ assert_send::<FilterEntry<IntoIter, u8>>();
+ assert_sync::<FilterEntry<IntoIter, u8>>();
+}
+
+// We cannot mount different volumes for the sake of the test, but
+// on Linux systems we can assume that /sys is a mounted volume.
+#[test]
+#[cfg(target_os = "linux")]
+fn walk_dir_stay_on_file_system() {
+ // If for some reason /sys doesn't exist or isn't a directory, just skip
+ // this test.
+ if !Path::new("/sys").is_dir() {
+ return;
+ }
+
+ let actual = td("same_file", vec![
+ td("a", vec![tld("/sys", "alink")]),
+ ]);
+ let unfollowed = td("same_file", vec![
+ td("a", vec![tld("/sys", "alink")]),
+ ]);
+ let (_tmp, got) = dir_setup_with(&actual, |wd| wd);
+ assert_tree_eq!(unfollowed, got);
+
+ // Create a symlink to sys and enable following symlinks. If the
+ // same_file_system option doesn't work, then this probably will hit a
+ // permission error. Otherwise, it should just skip over the symlink
+ // completely.
+ let actual = td("same_file", vec![
+ td("a", vec![tld("/sys", "alink")]),
+ ]);
+ let followed = td("same_file", vec![
+ td("a", vec![td("alink", vec![])]),
+ ]);
+ let (_tmp, got) = dir_setup_with(&actual, |wd| {
+ wd.follow_links(true).same_file_system(true)
+ });
+ assert_tree_eq!(followed, got);
+}
+