diff --git a/tests/notify.rs b/tests/notify.rs index 7ab22c7..588d34b 100644 --- a/tests/notify.rs +++ b/tests/notify.rs @@ -6,32 +6,13 @@ extern crate time; mod utils; use notify::*; -use std::io::{self, Write}; -use std::path::Path; +use std::io::Write; use std::sync::mpsc::{self, channel, Sender}; use tempdir::TempDir; use tempfile::NamedTempFile; -use std::fs; -use std::thread; -use std::time::Duration; use utils::*; -#[cfg(not(target_os="windows"))] -use std::os::unix::fs::PermissionsExt; - -#[cfg(not(target_os="windows"))] -fn chmod(path: &Path) -> io::Result<()> { - fs::set_permissions(path, fs::Permissions::from_mode(777)) -} - -#[cfg(target_os="windows")] -fn chmod(path: &Path) -> io::Result<()> { - let mut permissions = try!(fs::metadata(path)).permissions(); - permissions.set_readonly(true); - fs::set_permissions(path, permissions) -} - fn validate_watch_single_file(ctor: F) where F: Fn(Sender) -> Result, W: Watcher { @@ -94,7 +75,7 @@ fn validate_watch_dir(ctor: F) where // OSX FsEvent needs some time to discard old events from its log. if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } w.watch(dir.path(), RecursiveMode::Recursive).unwrap(); @@ -148,165 +129,175 @@ fn watch_single_file_poll() { #[test] fn create_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("new_file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::File::create(path.as_path()).expect("failed to create file"); + tdir.create("file1"); if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("file1"), op::CREATE), + ]); } else { - assert_eq!(recv_events(&rx), vec![(path, op::CREATE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("file1"), op::CREATE), + ]); } } #[test] fn write_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut file = fs::File::create(path.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1" + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - file.write("some data".as_bytes()).expect("failed to write to file"); - file.sync_all().expect("failed to sync file"); - if cfg!(target_os="macos") { - drop(file); // file needs to be closed for fsevent - } + tdir.write("file1"); if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE | op::WRITE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("file1"), op::CREATE | op::WRITE), + ]); } else { - assert_eq!(recv_events(&rx), vec![(path, op::WRITE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("file1"), op::WRITE), + ]); } } #[test] #[ignore] fn modify_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1" + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - chmod(path.as_path()).expect("failed to chmod file"); + tdir.chmod("file1"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } if cfg!(target_os="windows") { - assert_eq!(recv_events(&rx), vec![(path, op::WRITE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("file1"), op::WRITE), + ]); panic!("windows cannot distinguish between chmod and write"); } else if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("file1"), op::CREATE), + ]); panic!("macos cannot distinguish between chmod and create"); } else { - assert_eq!(recv_events(&rx), vec![(path, op::CHMOD)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("file1"), op::CHMOD), + ]); } } #[test] fn delete_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1" + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::remove_file(path.as_path()).expect("failed to remove file"); + tdir.remove("file1"); if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE | op::REMOVE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("file1"), op::CREATE | op::REMOVE), + ]); } else { - assert_eq!(recv_events(&rx), vec![(path, op::REMOVE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("file1"), op::REMOVE), + ]); } } #[test] #[ignore] fn rename_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path1.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1a" + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename file"); + tdir.rename("file1a", "file1b"); if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::RENAME) + (tdir.mkpath("file1a"), op::CREATE | op::RENAME), + (tdir.mkpath("file1b"), op::RENAME) ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("file1a"), op::RENAME), + (tdir.mkpath("file1b"), op::CREATE) ]); } if cfg!(not(target_os="windows")) { @@ -317,47 +308,41 @@ fn rename_file() { #[test] #[ignore] fn move_out_create_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let sub_dir1 = TempDir::new_in(temp_dir.path(), "sub_dir1").expect("failed to create temporary directory"); - let sub_dir2 = TempDir::new_in(temp_dir.path(), "sub_dir2").expect("failed to create temporary directory"); - let mut path1a = canonicalize(sub_dir1.path()); - path1a.push("file1.bin"); - let mut path1b = canonicalize(sub_dir2.path()); - path1b.push("file1.bin"); - let mut path2 = canonicalize(sub_dir1.path()); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path1a.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "watch_dir/file1" + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(sub_dir1.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1a.as_path(), path1b.as_path()).expect("failed to rename file"); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.rename("watch_dir/file1", "file1b"); + tdir.create("watch_dir/file1"); if cfg!(target_os="windows") { assert_eq!(recv_events(&rx), vec![ - (path1a, op::REMOVE), // windows interprets a move out of the watched directory as a remove - (path2, op::CREATE) + (tdir.mkpath("watch_dir/file1"), op::REMOVE), // windows interprets a move out of the watched directory as a remove + (tdir.mkpath("watch_dir/file1"), op::CREATE) ]); } else if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1a, op::CREATE | op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("watch_dir/file1"), op::CREATE | op::RENAME), + (tdir.mkpath("watch_dir/file1"), op::CREATE) ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1a, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("watch_dir/file1"), op::RENAME), + (tdir.mkpath("watch_dir/file1"), op::CREATE) ]); } if cfg!(not(target_os="windows")) { @@ -368,92 +353,85 @@ fn move_out_create_file() { #[test] #[ignore] fn create_write_modify_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("new_file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - let mut file = fs::File::create(path.as_path()).expect("failed to create file"); - file.write("some data".as_bytes()).expect("failed to write to file"); - if cfg!(target_os="macos") { - drop(file); // file needs to be closed for fsevent - } - chmod(path.as_path()).expect("failed to chmod file"); + tdir.create("file1"); + tdir.write("file1"); + tdir.chmod("file1"); if cfg!(target_os="windows") { assert_eq!(recv_events(&rx), vec![ - (path.clone(), op::CREATE), - (path.clone(), op::WRITE), - (path, op::WRITE) + (tdir.mkpath("file1"), op::CREATE), + (tdir.mkpath("file1"), op::WRITE), + (tdir.mkpath("file1"), op::WRITE), ]); panic!("windows cannot distinguish between chmod and write"); } else if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path.clone(), op::CREATE | op::WRITE) + (tdir.mkpath("file1"), op::CREATE | op::WRITE), ]); panic!("macos cannot distinguish between chmod and create"); } else { assert_eq!(recv_events(&rx), vec![ - (path.clone(), op::CREATE), - (path.clone(), op::WRITE), - (path, op::CHMOD) + (tdir.mkpath("file1"), op::CREATE), + (tdir.mkpath("file1"), op::WRITE), + (tdir.mkpath("file1"), op::CHMOD), ]); } } #[test] fn create_rename_overwrite_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1b", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::File::create(path1.as_path()).expect("failed to create file"); - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename file"); + tdir.create("file1a"); + tdir.rename("file1a", "file1b"); if cfg!(target_os="windows") { // Windows interprets a move that overwrites a file as a delete of the source file and a write to the file that is being overwritten assert_eq!(recv_events(&rx), vec![ - (path1.clone(), op::CREATE), - (path1, op::REMOVE), - (path2, op::WRITE) + (tdir.mkpath("file1a"), op::CREATE), + (tdir.mkpath("file1a"), op::REMOVE), + (tdir.mkpath("file1b"), op::WRITE) ]); } else if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::CREATE | op::RENAME) + (tdir.mkpath("file1a"), op::CREATE | op::RENAME), + (tdir.mkpath("file1b"), op::CREATE | op::RENAME) ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1.clone(), op::CREATE), - (path1, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("file1a"), op::CREATE), + (tdir.mkpath("file1a"), op::RENAME), + (tdir.mkpath("file1b"), op::CREATE) ]); } } @@ -461,108 +439,110 @@ fn create_rename_overwrite_file() { #[test] #[ignore] fn rename_rename_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("file2.bin"); - let mut path3 = canonicalize(temp_dir.path()); - path3.push("file3.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path1.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1a", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename file"); - fs::rename(path2.as_path(), path3.as_path()).expect("failed to rename file"); + tdir.rename("file1a", "file1b"); + tdir.rename("file1b", "file1c"); if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::RENAME), - (path3, op::RENAME) + (tdir.mkpath("file1a"), op::CREATE | op::RENAME), + (tdir.mkpath("file1b"), op::RENAME), + (tdir.mkpath("file1c"), op::RENAME) ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1, op::RENAME), - (path2.clone(), op::CREATE), - (path2, op::RENAME), - (path3, op::CREATE) + (tdir.mkpath("file1a"), op::RENAME), + (tdir.mkpath("file1b"), op::CREATE), + (tdir.mkpath("file1b"), op::RENAME), + (tdir.mkpath("file1c"), op::CREATE) ]); } } #[test] fn create_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("new_dir"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::create_dir(path.as_path()).expect("failed to create directory"); + tdir.create("dir1"); if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("dir1"), op::CREATE), + ]); } else { - assert_eq!(recv_events(&rx), vec![(path, op::CREATE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("dir1"), op::CREATE), + ]); } } #[test] #[ignore] fn modify_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("dir"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(path.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - chmod(path.as_path()).expect("failed to chmod directory"); + tdir.chmod("dir1"); if cfg!(target_os="windows") { - assert_eq!(recv_events(&rx), vec![(path, op::WRITE)]); + assert_eq!(recv_events(&rx), vec![ + (tdir.mkpath("dir1"), op::WRITE), + ]); panic!("windows cannot distinguish between chmod and write"); } else if cfg!(target_os="macos") { - assert_eq!(inflate_events(recv_events(&rx)), vec![(path, op::CREATE)]); + assert_eq!(inflate_events(recv_events(&rx)), vec![ + (tdir.mkpath("dir1"), op::CREATE), + ]); panic!("macos cannot distinguish between chmod and create"); } else { // TODO: emit chmod event only once assert_eq!(recv_events(&rx), vec![ - (path.clone(), op::CHMOD), - (path, op::CHMOD) + (tdir.mkpath("dir1"), op::CHMOD), + (tdir.mkpath("dir1"), op::CHMOD), ]); } } @@ -570,38 +550,38 @@ fn modify_directory() { #[test] #[ignore] fn delete_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path = canonicalize(temp_dir.path()); - path.push("dir"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(path.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::remove_dir(path.as_path()).expect("failed to remove directory"); + tdir.remove("dir1"); if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path, op::CREATE | op::REMOVE) + (tdir.mkpath("dir1"), op::CREATE | op::REMOVE), ]); } else if cfg!(target_os="linux") { assert_eq!(recv_events(&rx), vec![ - (path.clone(), op::IGNORED), - (path, op::REMOVE) + (tdir.mkpath("dir1"), op::IGNORED), + (tdir.mkpath("dir1"), op::REMOVE), ]); } else { assert_eq!(recv_events(&rx), vec![ - (path.clone(), op::REMOVE) + (tdir.mkpath("dir1").clone(), op::REMOVE), ]); } } @@ -609,37 +589,35 @@ fn delete_directory() { #[test] #[ignore] fn rename_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("dir1"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("dir2"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(path1.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1a", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename directory"); + tdir.rename("dir1a", "dir1b"); if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::RENAME) + (tdir.mkpath("dir1a"), op::CREATE | op::RENAME), + (tdir.mkpath("dir1b"), op::RENAME), ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("dir1a"), op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE), ]); } if cfg!(not(target_os="windows")) { @@ -650,47 +628,41 @@ fn rename_directory() { #[test] #[ignore] fn move_out_create_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let sub_dir1 = TempDir::new_in(temp_dir.path(), "sub_dir1").expect("failed to create temporary directory"); - let sub_dir2 = TempDir::new_in(temp_dir.path(), "sub_dir2").expect("failed to create temporary directory"); - let mut path1a = canonicalize(sub_dir1.path()); - path1a.push("dir1.bin"); - let mut path1b = canonicalize(sub_dir2.path()); - path1b.push("dir1.bin"); - let mut path2 = canonicalize(sub_dir1.path()); - path2.push("dir2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::File::create(path1a.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "watch_dir/dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(sub_dir1.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1a.as_path(), path1b.as_path()).expect("failed to rename file"); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.rename("watch_dir/dir1", "dir1b"); + tdir.create("watch_dir/dir1"); if cfg!(target_os="windows") { assert_eq!(recv_events(&rx), vec![ - (path1a, op::REMOVE), // windows interprets a move out of the watched directory as a remove - (path2, op::CREATE) + (tdir.mkpath("watch_dir/dir1"), op::REMOVE), // windows interprets a move out of the watched directory as a remove + (tdir.mkpath("watch_dir/dir1"), op::CREATE), ]); } else if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1a, op::CREATE | op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("watch_dir/dir1"), op::CREATE | op::RENAME), + (tdir.mkpath("watch_dir/dir1"), op::CREATE), ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1a, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("watch_dir/dir1"), op::RENAME), + (tdir.mkpath("watch_dir/dir1"), op::CREATE), ]); } if cfg!(not(target_os="windows")) { @@ -701,47 +673,45 @@ fn move_out_create_directory() { #[test] #[ignore] fn create_rename_overwrite_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("dir1"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("dir2"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(path2.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1b", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::create_dir(path1.as_path()).expect("failed to create directory"); - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename directory"); + tdir.create("dir1a"); + tdir.rename("dir1a", "dir1b"); if cfg!(target_os="windows") { assert_eq!(recv_events(&rx), vec![ - (path1.clone(), op::CREATE), - (path1, op::RENAME), - (path2, op::CREATE) + (tdir.mkpath("dir1a"), op::CREATE), + (tdir.mkpath("dir1b"), op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE), ]); } else if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::CREATE | op::RENAME) + (tdir.mkpath("dir1a"), op::CREATE | op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE | op::RENAME), ]); } else if cfg!(target_os="linux") { assert_eq!(recv_events(&rx), vec![ - (path1.clone(), op::CREATE), - (path1, op::RENAME), - (path2.clone(), op::CREATE), - (path2.clone(), op::CHMOD), - (path2, op::IGNORED), + (tdir.mkpath("dir1a"), op::CREATE), + (tdir.mkpath("dir1a"), op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE), + (tdir.mkpath("dir1b"), op::CHMOD), + (tdir.mkpath("dir1b"), op::IGNORED), ]); } else { unimplemented!(); @@ -751,43 +721,39 @@ fn create_rename_overwrite_directory() { #[test] #[ignore] fn rename_rename_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("dir1"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("dir2"); - let mut path3 = canonicalize(temp_dir.path()); - path3.push("dir3"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(path1.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1a", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(path1.as_path(), path2.as_path()).expect("failed to rename directory"); - fs::rename(path2.as_path(), path3.as_path()).expect("failed to rename directory"); + tdir.rename("dir1a", "dir1b"); + tdir.rename("dir1b", "dir1c"); if cfg!(target_os="macos") { assert_eq!(inflate_events(recv_events(&rx)), vec![ - (path1, op::CREATE | op::RENAME), - (path2, op::RENAME), - (path3, op::RENAME) + (tdir.mkpath("dir1a"), op::CREATE | op::RENAME), + (tdir.mkpath("dir1b"), op::RENAME), + (tdir.mkpath("dir1c"), op::RENAME), ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1, op::RENAME), - (path2.clone(), op::CREATE), - (path2, op::RENAME), - (path3, op::CREATE) + (tdir.mkpath("dir1a"), op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE), + (tdir.mkpath("dir1b"), op::RENAME), + (tdir.mkpath("dir1c"), op::CREATE), ]); } } diff --git a/tests/utils.rs b/tests/utils.rs index cb402f9..54278fe 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -1,9 +1,19 @@ extern crate notify; extern crate time; +extern crate tempdir; + +use tempdir::TempDir; use notify::*; +use std::fs; +use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::mpsc::{Receiver, TryRecvError}; +use std::thread; +use std::time::Duration; + +#[cfg(not(target_os="windows"))] +use std::os::unix::fs::PermissionsExt; #[cfg(not(target_os="windows"))] const TIMEOUT_S: f64 = 0.1; @@ -66,3 +76,94 @@ pub fn canonicalize(path: &Path) -> PathBuf { pub fn canonicalize(path: &Path) -> PathBuf { path.canonicalize().expect("failed to canonalize path").to_owned() } + +// Sleep for `duration` in milliseconds +pub fn sleep(duration: u64) { + thread::sleep(Duration::from_millis(duration)); +} + +pub trait TestHelpers { + /// Return path relative to the TempDir. Directory separator must be a forward slash, and will be converted to the platform's native separator. + fn mkpath(&self, p: &str) -> PathBuf; + /// Create file or directory. Directories must contain the phrase "dir" otherwise they will be interpreted as files. + fn create(&self, p: &str); + /// Create all files and directories in the `paths` list. Directories must contain the phrase "dir" otherwise they will be interpreted as files. + fn create_all(&self, paths: Vec<&str>); + /// Rename file or directory. + fn rename(&self, a: &str, b: &str); + fn chmod(&self, p: &str); + fn write(&self, p: &str); + fn remove(&self, p: &str); +} + +impl TestHelpers for TempDir { + fn mkpath(&self, p: &str) -> PathBuf { + let mut path = self.path().canonicalize().expect("failed to canonalize path").to_owned(); + for part in p.split('/').collect::>() { + if part != "." { + path.push(part); + } + } + path + } + + fn create(&self, p: &str) { + let path = self.mkpath(p); + if path.components().last().unwrap().as_os_str().to_str().unwrap().contains("dir") { + fs::create_dir_all(path).expect("failed to create directory"); + } else { + let parent = path.parent().expect("failed to get parent directory").to_owned(); + if !parent.exists() { + fs::create_dir_all(parent).expect("failed to create parent directory"); + } + fs::File::create(path).expect("failed to create file"); + } + } + + fn create_all(&self, paths: Vec<&str>) { + for p in paths { + self.create(p); + } + } + + fn rename(&self, a: &str, b: &str) { + let path_a = self.mkpath(a); + let path_b = self.mkpath(b); + fs::rename(&path_a, &path_b).expect("failed to rename file or directory"); + } + + #[cfg(not(target_os="windows"))] + fn chmod(&self, p: &str) { + let path = self.mkpath(p); + fs::set_permissions(path, fs::Permissions::from_mode(777)).expect("failed to chmod file or directory"); + } + + #[cfg(target_os="windows")] + fn chmod(&self, p: &str) { + let path = self.mkpath(p); + let mut permissions = fs::metadata(&path).expect("failed to get metadata").permissions(); + permissions.set_readonly(true); + fs::set_permissions(path, permissions).expect("failed to chmod file or directory"); + } + + fn write(&self, p: &str) { + let path = self.mkpath(p); + + let mut file = fs::OpenOptions::new() + .write(true) + .open(path) + .expect("failed to open file"); + + file.write("some data".as_bytes()).expect("failed to write to file"); + file.sync_all().expect("failed to sync file"); + } + + fn remove(&self, p: &str) { + let path = self.mkpath(p); + if path.is_dir() { + fs::remove_dir(path).expect("failed to remove directory"); + } else { + fs::remove_file(path).expect("failed to remove file"); + } + } +} diff --git a/tests/watcher.rs b/tests/watcher.rs index f1c3626..f3dd89b 100644 --- a/tests/watcher.rs +++ b/tests/watcher.rs @@ -6,12 +6,9 @@ extern crate time; mod utils; use notify::*; -use std::io::Write; use std::sync::mpsc; use tempdir::TempDir; -use std::fs; use std::thread; -use std::time::Duration; use utils::*; @@ -82,41 +79,35 @@ fn test_watcher_sync() { #[test] fn watch_recursive_create_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut new_dir = canonicalize(temp_dir.path()); - new_dir.push("new_dir"); - let mut file1 = new_dir.clone(); - file1.push("file1"); - let mut file2 = new_dir.clone(); - file2.push("file2"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.path().to_owned(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(&tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::create_dir(new_dir.as_path()).expect("failed to create directory"); - thread::sleep(Duration::from_millis(10)); - fs::File::create(file1.as_path()).expect("failed to create file"); + tdir.create("dir1"); + sleep(10); + tdir.create("dir1/file1"); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - watcher.unwatch(temp_dir.into_path()).expect("failed to unwatch directory"); + watcher.unwatch(&tdir.mkpath(".")).expect("failed to unwatch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::File::create(file2.as_path()).expect("failed to create file"); + tdir.create("dir1/file2"); let actual = if cfg!(target_os="windows") { // Windows may sneak a write event in there @@ -130,44 +121,36 @@ fn watch_recursive_create_directory() { }; assert_eq!(actual, vec![ - (new_dir, op::CREATE), - (file1, op::CREATE) + (tdir.mkpath("dir1"), op::CREATE), + (tdir.mkpath("dir1/file1"), op::CREATE) ]); } #[test] #[ignore] fn watch_recursive_move() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = canonicalize(temp_dir.path()); - sub_dir1a.push("sub_dir1a"); - let mut sub_dir1b = canonicalize(temp_dir.path()); - sub_dir1b.push("sub_dir1b"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("sub_dir1a"); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("sub_dir1b"); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1a.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1a", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::File::create(path1.as_path()).expect("failed to create file"); - fs::rename(sub_dir1a.as_path(), sub_dir1b.as_path()).expect("failed to rename file"); - thread::sleep(Duration::from_millis(10)); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.create("dir1a/file1"); + tdir.rename("dir1a", "dir1b"); + sleep(10); + tdir.create("dir1b/file2"); let actual = if cfg!(target_os="windows") { // Windows may sneak a write event in there @@ -182,25 +165,25 @@ fn watch_recursive_move() { if cfg!(target_os="windows") { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::RENAME), - (sub_dir1b, op::RENAME), // should be a create - (path2, op::CREATE) + (tdir.mkpath("dir1a/file1"), op::CREATE), + (tdir.mkpath("dir1a"), op::RENAME), + (tdir.mkpath("dir1b"), op::RENAME), // should be a create + (tdir.mkpath("dir1b/file2"), op::CREATE) ]); panic!("move_to should be translated to create"); } else if cfg!(target_os="macos") { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::CREATE | op::RENAME), // excessive create event - (sub_dir1b, op::RENAME), // should be a create - (path2, op::CREATE) + (tdir.mkpath("dir1a/file1"), op::CREATE), + (tdir.mkpath("dir1a"), op::CREATE | op::RENAME), // excessive create event + (tdir.mkpath("dir1b"), op::RENAME), // should be a create + (tdir.mkpath("dir1b/file2"), op::CREATE) ]); } else { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::RENAME), - (sub_dir1b, op::CREATE), - (path2, op::CREATE) + (tdir.mkpath("dir1a/file1"), op::CREATE), + (tdir.mkpath("dir1a"), op::RENAME), + (tdir.mkpath("dir1b"), op::CREATE), + (tdir.mkpath("dir1b/file2"), op::CREATE) ]); } } @@ -208,37 +191,28 @@ fn watch_recursive_move() { #[test] #[ignore] fn watch_recursive_move_in() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1 = canonicalize(temp_dir.path()); - sub_dir1.push("sub_dir1"); - let mut sub_dir2 = sub_dir1.clone(); - sub_dir2.push("sub_dir2"); - let watch_dir = TempDir::new_in(temp_dir.path(), "watch_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = canonicalize(watch_dir.path()); - sub_dir1a.push("sub_dir1"); - let mut path = canonicalize(watch_dir.path()); - path.push("sub_dir1"); - path.push("sub_dir2"); - path.push("new_file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1.as_path()).expect("failed to create directory"); - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "watch_dir", + "dir1a/dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(watch_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(&tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::rename(sub_dir1.as_path(), sub_dir1a.as_path()).expect("failed to rename file"); - thread::sleep(Duration::from_millis(10)); - fs::File::create(path.as_path()).expect("failed to create file"); + tdir.rename("dir1a", "watch_dir/dir1b"); + sleep(10); + tdir.create("watch_dir/dir1b/dir1/file1"); let actual = if cfg!(target_os="windows") { // Windows may sneak a write event in there @@ -253,57 +227,42 @@ fn watch_recursive_move_in() { if cfg!(target_os="macos") { assert_eq!(actual, vec![ - (sub_dir1a, op::RENAME), // fsevents interprets a move_to as a rename event - (path, op::CREATE) + (tdir.mkpath("watch_dir/dir1b"), op::RENAME), // fsevents interprets a move_to as a rename event + (tdir.mkpath("watch_dir/dir1b/dir1/file1"), op::CREATE) ]); panic!("move event should be a create event"); } else { assert_eq!(actual, vec![ - (sub_dir1a, op::CREATE), - (path, op::CREATE) + (tdir.mkpath("watch_dir/dir1b"), op::CREATE), + (tdir.mkpath("watch_dir/dir1b/dir1/file1"), op::CREATE) ]); } } #[test] fn watch_recursive_move_out() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let watch_dir = TempDir::new_in(temp_dir.path(), "watch_dir").expect("failed to create temporary directory"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = canonicalize(watch_dir.path()); - sub_dir1a.push("sub_dir1a"); - let mut sub_dir1b = canonicalize(temp_dir.path()); - sub_dir1b.push("sub_dir1b"); - let mut sub_dir2 = sub_dir1a.clone(); - sub_dir2.push("sub_dir2"); - let mut path1 = canonicalize(watch_dir.path()); - path1.push("sub_dir1a"); - path1.push("sub_dir2"); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("sub_dir1b"); - path2.push("sub_dir2"); - path2.push("file2.bin"); - - fs::create_dir(sub_dir1a.as_path()).expect("failed to create directory"); - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "watch_dir/dir1a/dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(watch_dir.into_path(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::File::create(path1.as_path()).expect("failed to create file"); - fs::rename(sub_dir1a.as_path(), sub_dir1b.as_path()).expect("failed to rename file"); - thread::sleep(Duration::from_millis(10)); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.create("watch_dir/dir1a/dir1/file1"); + tdir.rename("watch_dir/dir1a", "dir1b"); + sleep(10); + tdir.create("dir1b/dir1/file2"); let actual = if cfg!(target_os="windows") { // Windows may sneak a write event in there @@ -318,371 +277,300 @@ fn watch_recursive_move_out() { if cfg!(target_os="windows") { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::REMOVE) // windows interprets a move out of the watched directory as a remove + (tdir.mkpath("watch_dir/dir1a/dir1/file1"), op::CREATE), + (tdir.mkpath("watch_dir/dir1a"), op::REMOVE) // windows interprets a move out of the watched directory as a remove ]); } else if cfg!(target_os="macos") { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::CREATE | op::RENAME) // excessive create event + (tdir.mkpath("watch_dir/dir1a/dir1/file1"), op::CREATE), + (tdir.mkpath("watch_dir/dir1a"), op::CREATE | op::RENAME) // excessive create event ]); } else { assert_eq!(actual, vec![ - (path1, op::CREATE), - (sub_dir1a, op::RENAME) + (tdir.mkpath("watch_dir/dir1a/dir1/file1"), op::CREATE), + (tdir.mkpath("watch_dir/dir1a"), op::RENAME) ]); } } #[test] fn watch_nonrecursive() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1 = canonicalize(temp_dir.path()); - sub_dir1.push("sub_dir1"); - let mut sub_dir2 = canonicalize(temp_dir.path()); - sub_dir2.push("sub_dir2"); - let mut file0 = canonicalize(temp_dir.path()); - file0.push("file0.bin"); - let mut file1 = sub_dir1.clone(); - file1.push("file1.bin"); - let mut file2 = sub_dir2.clone(); - file2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.into_path(), RecursiveMode::NonRecursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::NonRecursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); - thread::sleep(Duration::from_millis(10)); - fs::File::create(file0.as_path()).expect("failed to create file"); - fs::File::create(file1.as_path()).expect("failed to create file"); - fs::File::create(file2.as_path()).expect("failed to create file"); + tdir.create("dir2"); + sleep(10); + tdir.create_all(vec![ + "file0", + "dir1/file1", + "dir2/file2", + ]); assert_eq!(recv_events(&rx), vec![ - (sub_dir2, op::CREATE), - (file0, op::CREATE) + (tdir.mkpath("dir2"), op::CREATE), + (tdir.mkpath("file0"), op::CREATE) ]); } #[test] fn watch_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = canonicalize(temp_dir.path()); - path1.push("file1.bin"); - let mut path2 = canonicalize(temp_dir.path()); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut file1 = fs::File::create(path1.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1", + ]); if cfg!(target_os="macos") { - thread::sleep(Duration::from_millis(10)); + sleep(10); } let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("failed to create recommended watcher"); - watcher.watch(path1.clone(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch directory"); if cfg!(target_os="windows") { - thread::sleep(Duration::from_millis(100)); + sleep(100); } - file1.write("some data".as_bytes()).expect("failed to write to file"); - file1.sync_all().expect("failed to sync file"); - if cfg!(target_os="macos") { - drop(file1); // file needs to be closed for fsevent - } - - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.write("file1"); + tdir.create("file2"); if cfg!(target_os="macos") { assert_eq!(recv_events(&rx), vec![ - (path1, op::CREATE | op::WRITE) + (tdir.mkpath("file1"), op::CREATE | op::WRITE) ]); } else { assert_eq!(recv_events(&rx), vec![ - (path1, op::WRITE) + (tdir.mkpath("file1"), op::WRITE) ]); } } #[test] fn poll_watch_recursive_create_directory() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut new_dir = temp_dir.path().to_owned(); - new_dir.push("new_dir"); - let mut file1 = new_dir.clone(); - file1.push("file1"); - let mut file2 = new_dir.clone(); - file2.push("file2"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.path().to_owned(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::create_dir(new_dir.as_path()).expect("failed to create directory"); - fs::File::create(file1.as_path()).expect("failed to create file"); + tdir.create("dir1/file1"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - watcher.unwatch(temp_dir.path().to_owned()).expect("failed to unwatch directory"); + watcher.unwatch(tdir.mkpath(".")).expect("failed to unwatch directory"); - fs::File::create(file2.as_path()).expect("failed to create file"); + tdir.create("dir1/file2"); let mut actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); assert_eq!(actual, vec![ - (temp_dir.into_path(), op::WRITE), // parent directory gets modified - (new_dir, op::CREATE), - (file1, op::CREATE) + (tdir.mkpath("."), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1"), op::CREATE), + (tdir.mkpath("dir1/file1"), op::CREATE) ]); } #[test] fn poll_watch_recursive_move() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = temp_dir.path().to_owned(); - sub_dir1a.push("sub_dir1a"); - let mut sub_dir1b = temp_dir.path().to_owned(); - sub_dir1b.push("sub_dir1b"); - let mut path1a = temp_dir.path().to_owned(); - path1a.push("sub_dir1a"); - path1a.push("file1.bin"); - let mut path1b = temp_dir.path().to_owned(); - path1b.push("sub_dir1b"); - path1b.push("file1.bin"); - let mut path2 = temp_dir.path().to_owned(); - path2.push("sub_dir1b"); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1a.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1a", + ]); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.path().to_owned(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::Recursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::File::create(path1a.as_path()).expect("failed to create file"); + tdir.create("dir1a/file1"); let mut actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); assert_eq!(actual, vec![ - (sub_dir1a.clone(), op::WRITE), // parent directory gets modified - (path1a.clone(), op::CREATE), + (tdir.mkpath("dir1a"), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1a/file1"), op::CREATE), ]); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::rename(sub_dir1a.as_path(), sub_dir1b.as_path()).expect("failed to rename file"); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.rename("dir1a", "dir1b"); + tdir.create("dir1b/file2"); actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); if cfg!(target_os="windows") { assert_eq!(actual, vec![ - (temp_dir.into_path(), op::WRITE), // parent directory gets modified - (sub_dir1a, op::REMOVE), - (path1a, op::REMOVE), - (sub_dir1b.clone(), op::CREATE), - (sub_dir1b, op::WRITE), // parent directory gets modified - (path1b, op::CREATE), - (path2, op::CREATE), + (tdir.mkpath("."), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1a"), op::REMOVE), + (tdir.mkpath("dir1a/file1"), op::REMOVE), + (tdir.mkpath("dir1b"), op::CREATE), + (tdir.mkpath("dir1b"), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1b/file1"), op::CREATE), + (tdir.mkpath("dir1b/file2"), op::CREATE), ]); } else { assert_eq!(actual, vec![ - (temp_dir.into_path(), op::WRITE), // parent directory gets modified - (sub_dir1a, op::REMOVE), - (path1a, op::REMOVE), - (sub_dir1b, op::CREATE), - (path1b, op::CREATE), - (path2, op::CREATE), + (tdir.mkpath("."), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1a"), op::REMOVE), + (tdir.mkpath("dir1a/file1"), op::REMOVE), + (tdir.mkpath("dir1b"), op::CREATE), + (tdir.mkpath("dir1b/file1"), op::CREATE), + (tdir.mkpath("dir1b/file2"), op::CREATE), ]); } } #[test] fn poll_watch_recursive_move_in() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1 = temp_dir.path().to_owned(); - sub_dir1.push("sub_dir1"); - let mut sub_dir2 = sub_dir1.clone(); - sub_dir2.push("sub_dir2"); - let watch_dir = TempDir::new_in(temp_dir.path(), "watch_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = watch_dir.path().to_owned(); - sub_dir1a.push("sub_dir1"); - let mut sub_dir2a = sub_dir1a.clone(); - sub_dir2a.push("sub_dir2"); - let mut path = watch_dir.path().to_owned(); - path.push("sub_dir1"); - path.push("sub_dir2"); - path.push("new_file.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1.as_path()).expect("failed to create directory"); - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "watch_dir", + "dir1a/dir1", + ]); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(watch_dir.path().to_owned(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::rename(sub_dir1.as_path(), sub_dir1a.as_path()).expect("failed to rename file"); - fs::File::create(path.as_path()).expect("failed to create file"); + tdir.rename("dir1a", "watch_dir/dir1b"); + tdir.create("watch_dir/dir1b/dir1/file1"); let mut actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); if cfg!(target_os="windows") { assert_eq!(actual, vec![ - (watch_dir.into_path(), op::WRITE), // parent directory gets modified - (sub_dir1a, op::CREATE), - (sub_dir2a.clone(), op::CREATE), - (sub_dir2a, op::WRITE), // extra write event - (path, op::CREATE), + (tdir.mkpath("watch_dir"), op::WRITE), // parent directory gets modified + (tdir.mkpath("watch_dir/dir1b"), op::CREATE), + (tdir.mkpath("watch_dir/dir1b/dir1"), op::CREATE), + (tdir.mkpath("watch_dir/dir1b/dir1"), op::WRITE), // extra write event + (tdir.mkpath("watch_dir/dir1b/dir1/file1"), op::CREATE), ]); } else { assert_eq!(actual, vec![ - (watch_dir.into_path(), op::WRITE), // parent directory gets modified - (sub_dir1a, op::CREATE), - (sub_dir2a, op::CREATE), - (path, op::CREATE), + (tdir.mkpath("watch_dir"), op::WRITE), // parent directory gets modified + (tdir.mkpath("watch_dir/dir1b"), op::CREATE), + (tdir.mkpath("watch_dir/dir1b/dir1"), op::CREATE), + (tdir.mkpath("watch_dir/dir1b/dir1/file1"), op::CREATE), ]); } } #[test] fn poll_watch_recursive_move_out() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let watch_dir = TempDir::new_in(temp_dir.path(), "watch_dir").expect("failed to create temporary directory"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1a = watch_dir.path().to_owned(); - sub_dir1a.push("sub_dir1a"); - let mut sub_dir1b = temp_dir.path().to_owned(); - sub_dir1b.push("sub_dir1b"); - let mut sub_dir2 = sub_dir1a.clone(); - sub_dir2.push("sub_dir2"); - let mut path1 = watch_dir.path().to_owned(); - path1.push("sub_dir1a"); - path1.push("sub_dir2"); - path1.push("file1.bin"); - let mut path2 = temp_dir.path().to_owned(); - path2.push("sub_dir1b"); - path2.push("sub_dir2"); - path2.push("file2.bin"); - - fs::create_dir(sub_dir1a.as_path()).expect("failed to create directory"); - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "watch_dir/dir1a/dir1", + ]); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(watch_dir.path().to_owned(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("watch_dir"), RecursiveMode::Recursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::File::create(path1.as_path()).expect("failed to create file"); + tdir.create("watch_dir/dir1a/dir1/file1"); let mut actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); assert_eq!(actual, vec![ - (sub_dir2.clone(), op::WRITE), // parent directory gets modified - (path1.clone(), op::CREATE), + (tdir.mkpath("watch_dir/dir1a/dir1"), op::WRITE), // parent directory gets modified + (tdir.mkpath("watch_dir/dir1a/dir1/file1"), op::CREATE), ]); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::rename(sub_dir1a.as_path(), sub_dir1b.as_path()).expect("failed to rename file"); - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.rename("watch_dir/dir1a", "dir1b"); + tdir.create("dir1b/dir1/file2"); actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); assert_eq!(actual, vec![ - (watch_dir.into_path(), op::WRITE), // parent directory gets modified - (sub_dir1a, op::REMOVE), - (sub_dir2, op::REMOVE), - (path1, op::REMOVE), + (tdir.mkpath("watch_dir"), op::WRITE), // parent directory gets modified + (tdir.mkpath("watch_dir/dir1a"), op::REMOVE), + (tdir.mkpath("watch_dir/dir1a/dir1"), op::REMOVE), + (tdir.mkpath("watch_dir/dir1a/dir1/file1"), op::REMOVE), ]); } #[test] fn poll_watch_nonrecursive() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut sub_dir1 = temp_dir.path().to_owned(); - sub_dir1.push("sub_dir1"); - let mut sub_dir2 = temp_dir.path().to_owned(); - sub_dir2.push("sub_dir2"); - let mut file0 = temp_dir.path().to_owned(); - file0.push("file0.bin"); - let mut file1 = sub_dir1.clone(); - file1.push("file1.bin"); - let mut file2 = sub_dir2.clone(); - file2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - fs::create_dir(sub_dir1.as_path()).expect("failed to create directory"); + tdir.create_all(vec![ + "dir1", + ]); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(temp_dir.path().to_owned(), RecursiveMode::NonRecursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("."), RecursiveMode::NonRecursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - fs::create_dir(sub_dir2.as_path()).expect("failed to create directory"); - fs::File::create(file0.as_path()).expect("failed to create file"); - fs::File::create(file1.as_path()).expect("failed to create file"); - fs::File::create(file2.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1", + "dir1/file1", + "dir2/file1", + ]); let mut actual = recv_events(&rx); actual.sort_by(|a, b| a.0.cmp(&b.0)); assert_eq!(actual, vec![ - (temp_dir.into_path(), op::WRITE), // parent directory gets modified - (file0, op::CREATE), - (sub_dir1, op::WRITE), // parent directory gets modified - (sub_dir2, op::CREATE), + (tdir.mkpath("."), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir1"), op::WRITE), // parent directory gets modified + (tdir.mkpath("dir2"), op::CREATE), + (tdir.mkpath("file1"), op::CREATE), ]); } #[test] fn poll_watch_file() { - let temp_dir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut path1 = temp_dir.path().to_owned(); - path1.push("file1.bin"); - let mut path2 = temp_dir.path().to_owned(); - path2.push("file2.bin"); + let tdir = TempDir::new("temp_dir").expect("failed to create temporary directory"); - let mut file1 = fs::File::create(path1.as_path()).expect("failed to create file"); + tdir.create_all(vec![ + "file1", + ]); let (tx, rx) = mpsc::channel(); let mut watcher = PollWatcher::with_delay(tx, 100).expect("failed to create recommended watcher"); - watcher.watch(path1.clone(), RecursiveMode::Recursive).expect("failed to watch directory"); + watcher.watch(tdir.mkpath("file1"), RecursiveMode::Recursive).expect("failed to watch directory"); - thread::sleep(Duration::from_millis(1100)); // PollWatcher has only a resolution of 1 second + sleep(1100); // PollWatcher has only a resolution of 1 second - file1.write("some data".as_bytes()).expect("failed to write to file"); - file1.sync_all().expect("failed to sync file"); - if cfg!(target_os="macos") { - drop(file1); // file needs to be closed for fsevent - } - - fs::File::create(path2.as_path()).expect("failed to create file"); + tdir.write("file1"); + tdir.create("file2"); assert_eq!(recv_events(&rx), vec![ - (path1, op::WRITE) + (tdir.mkpath("file1"), op::WRITE) ]); }