Skip to content

Commit

Permalink
[dual] Explicitely support more than one watcher on a channel
Browse files Browse the repository at this point in the history
  • Loading branch information
passcod committed Apr 20, 2019
1 parent 9a46afb commit 2a035c8
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ impl EventKind {
pub fn is_other(&self) -> bool {
match *self {
EventKind::Other => true,
_ => false
_ => false,
}
}
}
Expand Down
39 changes: 33 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,9 @@
//! # use notify::{Watcher, RecommendedWatcher, RecursiveMode, Result};
//! #
//! # fn main() -> Result<()> {
//! # // Create a channel to receive the events.
//! # let (tx, rx) = unbounded();
//! #
//! # // Create a watcher object, delivering raw events.
//! # // The notification back-end is selected based on the platform.
//! let mut watcher: RecommendedWatcher = Watcher::new_immediate(tx)?;
//! #
//! # // Add a path to be watched. All files and directories at that path and
//! # // below will be monitored for changes.
//! # watcher.watch(".", RecursiveMode::Recursive)?;
//! #
//! # loop {
Expand All @@ -113,6 +107,39 @@
//! # Ok(())
//! # }
//! ```
//!
//! ## With different configurations
//!
//! It is possible to create several watchers with different configurations or implementations that
//! all send to the same channel. This can accomodate advanced behaviour or work around limits.
//!
//! ```
//! # extern crate crossbeam_channel;
//! # extern crate notify;
//! #
//! # use crossbeam_channel::unbounded;
//! # use notify::{Watcher, RecommendedWatcher, RecursiveMode, Result};
//! #
//! # fn main() -> Result<()> {
//! # let (tx, rx) = unbounded();
//! #
//! let mut watcher1: RecommendedWatcher = Watcher::new_immediate(tx.clone())?;
//! let mut watcher2: RecommendedWatcher = Watcher::new_immediate(tx)?;
//! #
//! # watcher1.watch(".", RecursiveMode::Recursive)?;
//! # watcher2.watch(".", RecursiveMode::Recursive)?;
//! #
//! loop {
//! # break;
//! match rx.recv() {
//! Ok(event) => println!("event: {:?}", event),
//! Err(e) => println!("watch error: {:?}", e),
//! }
//! }
//! #
//! # Ok(())
//! # }
//! ```
#![deny(missing_docs)]

Expand Down
33 changes: 33 additions & 0 deletions tests/debounce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1476,3 +1476,36 @@ fn one_file_many_events() {
);
io_thread.join().unwrap();
}

#[test]
fn dual_create_file() {
let tdir1 = TempDir::new("temp_dir1").expect("failed to create temporary directory");
let tdir2 = TempDir::new("temp_dir2").expect("failed to create temporary directory");

sleep_macos(10);

let (tx, rx) = unbounded();
let mut watcher1: RecommendedWatcher =
Watcher::new(tx.clone(), Duration::from_millis(DELAY_MS))
.expect("failed to create debounced watcher");
let mut watcher2: RecommendedWatcher = Watcher::new(tx, Duration::from_millis(DELAY_MS))
.expect("failed to create debounced watcher");

watcher1
.watch(tdir1.mkpath("."), RecursiveMode::Recursive)
.expect("failed to watch directory");
watcher2
.watch(tdir2.mkpath("."), RecursiveMode::Recursive)
.expect("failed to watch directory");

tdir1.create("file1");
tdir2.create("file2");

assert_eq!(
recv_events_debounced(&rx),
vec![
(Kind::Create, vec![tdir1.mkpath("file1")], false),
(Kind::Create, vec![tdir2.mkpath("file2")], false),
]
);
}
115 changes: 63 additions & 52 deletions tests/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ fn new_recommended() {
assert!(w.is_ok());
}

#[test]
fn new_dual() {
let (tx, _) = unbounded();
let w1: Result<RecommendedWatcher> = Watcher::new_immediate(tx.clone());
let w2: Result<RecommendedWatcher> = Watcher::new_immediate(tx);
assert!(w1.is_ok());
assert!(w2.is_ok());
}

// if this test builds, it means RecommendedWatcher is Send.
#[test]
fn test_watcher_send() {
Expand Down Expand Up @@ -144,67 +153,68 @@ fn watch_relative() {
}
}
}
if cfg!(target_os = "windows") && !NETWORK_PATH.is_empty() {
// watch_relative_network_directory
let tdir = TempDir::new_in(NETWORK_PATH, "temp_dir")
.expect("failed to create temporary directory");
tdir.create("dir1");

env::set_current_dir(tdir.path()).expect("failed to change working directory");

let (tx, _) = unbounded();
let mut watcher: RecommendedWatcher =
Watcher::new_immediate(tx).expect("failed to create recommended watcher");
watcher
.watch("dir1", RecursiveMode::Recursive)
.expect("failed to watch directory");

watcher
.unwatch("dir1")
.expect("failed to unwatch directory");

if cfg!(not(target_os = "windows")) {
match watcher.unwatch("dir1") {
Err(Error::WatchNotFound) => (),
Err(e) => panic!("{:?}", e),
Ok(o) => panic!("{:?}", o),
// To run: set a valid NETWORK_PATH.
if cfg!(target_os = "windows") && cfg!(feature = "manual_tests") {
{
// watch_relative_network_directory
let tdir = TempDir::new_in(NETWORK_PATH, "temp_dir")
.expect("failed to create temporary directory");
tdir.create("dir1");

env::set_current_dir(tdir.path()).expect("failed to change working directory");

let (tx, _) = unbounded();
let mut watcher: RecommendedWatcher =
Watcher::new_immediate(tx).expect("failed to create recommended watcher");
watcher
.watch("dir1", RecursiveMode::Recursive)
.expect("failed to watch directory");

watcher
.unwatch("dir1")
.expect("failed to unwatch directory");

if cfg!(not(target_os = "windows")) {
match watcher.unwatch("dir1") {
Err(Error::WatchNotFound) => (),
Err(e) => panic!("{:?}", e),
Ok(o) => panic!("{:?}", o),
}
}
}
}
if cfg!(target_os = "windows") && !NETWORK_PATH.is_empty() {
// watch_relative_network_file
let tdir = TempDir::new_in(NETWORK_PATH, "temp_dir")
.expect("failed to create temporary directory");
tdir.create("file1");

env::set_current_dir(tdir.path()).expect("failed to change working directory");

let (tx, _) = unbounded();
let mut watcher: RecommendedWatcher =
Watcher::new_immediate(tx).expect("failed to create recommended watcher");
watcher
.watch("file1", RecursiveMode::Recursive)
.expect("failed to watch file");

watcher.unwatch("file1").expect("failed to unwatch file");

if cfg!(not(target_os = "windows")) {
match watcher.unwatch("file1") {
Err(Error::WatchNotFound) => (),
Err(e) => panic!("{:?}", e),
Ok(o) => panic!("{:?}", o),
{
// watch_relative_network_file
let tdir = TempDir::new_in(NETWORK_PATH, "temp_dir")
.expect("failed to create temporary directory");
tdir.create("file1");

env::set_current_dir(tdir.path()).expect("failed to change working directory");

let (tx, _) = unbounded();
let mut watcher: RecommendedWatcher =
Watcher::new_immediate(tx).expect("failed to create recommended watcher");
watcher
.watch("file1", RecursiveMode::Recursive)
.expect("failed to watch file");

watcher.unwatch("file1").expect("failed to unwatch file");

if cfg!(not(target_os = "windows")) {
match watcher.unwatch("file1") {
Err(Error::WatchNotFound) => (),
Err(e) => panic!("{:?}", e),
Ok(o) => panic!("{:?}", o),
}
}
}
}
}

#[test]
#[cfg(target_os = "windows")]
#[cfg(all(feature = "manual_tests", target_os = "windows"))]
// To run: set a valid NETWORK_PATH.
fn watch_absolute_network_directory() {
if NETWORK_PATH.is_empty() {
return;
}

let tdir =
TempDir::new_in(NETWORK_PATH, "temp_dir").expect("failed to create temporary directory");
tdir.create("dir1");
Expand All @@ -230,7 +240,8 @@ fn watch_absolute_network_directory() {
}

#[test]
#[cfg(target_os = "windows")]
#[cfg(all(feature = "manual_tests", target_os = "windows"))]
// To run: set a valid NETWORK_PATH.
fn watch_absolute_network_file() {
if NETWORK_PATH.is_empty() {
return;
Expand Down

0 comments on commit 2a035c8

Please sign in to comment.