complete test

This commit is contained in:
Bernardo 2019-01-06 18:36:22 +01:00 committed by Aleksey Kladov
parent 1d5eaefe8a
commit d032a1a4e8
5 changed files with 95 additions and 52 deletions

1
Cargo.lock generated
View file

@ -1009,6 +1009,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"ra_arena 0.1.0", "ra_arena 0.1.0",

View file

@ -18,3 +18,4 @@ ra_arena = { path = "../ra_arena" }
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"
flexi_logger = "0.10.0"

View file

@ -98,7 +98,7 @@ impl Vfs {
pub fn new(mut roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) { pub fn new(mut roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) {
let (worker, worker_handle) = io::start(); let (worker, worker_handle) = io::start();
let watcher = Watcher::new().unwrap(); // TODO return Result? let watcher = Watcher::start().unwrap(); // TODO return Result?
let mut res = Vfs { let mut res = Vfs {
roots: Arena::default(), roots: Arena::default(),

View file

@ -39,7 +39,6 @@ impl WatcherChange {
DebouncedEvent::Remove(path) => Some(WatcherChange::Remove(path)), DebouncedEvent::Remove(path) => Some(WatcherChange::Remove(path)),
DebouncedEvent::Rename(src, dst) => Some(WatcherChange::Rename(src, dst)), DebouncedEvent::Rename(src, dst) => Some(WatcherChange::Rename(src, dst)),
DebouncedEvent::Error(err, path) => { DebouncedEvent::Error(err, path) => {
// TODO
log::warn!("watch error {}, {:?}", err, path); log::warn!("watch error {}, {:?}", err, path);
None None
} }
@ -48,23 +47,17 @@ impl WatcherChange {
} }
impl Watcher { impl Watcher {
pub fn new() -> Result<Watcher, Box<std::error::Error>> { pub fn start() -> Result<Watcher, Box<std::error::Error>> {
let (input_sender, input_receiver) = mpsc::channel(); let (input_sender, input_receiver) = mpsc::channel();
let watcher = notify::watcher(input_sender, Duration::from_millis(250))?; let watcher = notify::watcher(input_sender, Duration::from_millis(250))?;
let (output_sender, output_receiver) = crossbeam_channel::unbounded(); let (output_sender, output_receiver) = crossbeam_channel::unbounded();
let thread = thread::spawn(move || loop { let thread = thread::spawn(move || {
match input_receiver.recv() { input_receiver
Ok(ev) => { .into_iter()
// forward relevant events only // forward relevant events only
if let Some(change) = WatcherChange::from_debounced_event(ev) { .filter_map(WatcherChange::from_debounced_event)
output_sender.send(change).unwrap(); .try_for_each(|change| output_sender.send(change))
} .unwrap()
}
Err(err) => {
log::debug!("Watcher stopped ({})", err);
break;
}
}
}); });
Ok(Watcher { Ok(Watcher {
receiver: output_receiver, receiver: output_receiver,
@ -86,11 +79,13 @@ impl Watcher {
pub fn shutdown(mut self) -> thread::Result<()> { pub fn shutdown(mut self) -> thread::Result<()> {
self.bomb.defuse(); self.bomb.defuse();
drop(self.watcher); drop(self.watcher);
let res = self.thread.join(); // TODO this doesn't terminate for some reason
match &res { // let res = self.thread.join();
Ok(()) => log::info!("... Watcher terminated with ok"), // match &res {
Err(_) => log::error!("... Watcher terminated with err"), // Ok(()) => log::info!("... Watcher terminated with ok"),
} // Err(_) => log::error!("... Watcher terminated with err"),
res // }
// res
Ok(())
} }
} }

View file

@ -1,14 +1,13 @@
use std::{ use std::{collections::HashSet, fs};
fs,
collections::HashSet,
};
use tempfile::tempdir;
use flexi_logger::Logger;
use ra_vfs::{Vfs, VfsChange}; use ra_vfs::{Vfs, VfsChange};
use tempfile::tempdir;
#[test] #[test]
fn test_vfs_works() -> std::io::Result<()> { fn test_vfs_works() -> std::io::Result<()> {
Logger::with_str("debug").start().unwrap();
let files = [ let files = [
("a/foo.rs", "hello"), ("a/foo.rs", "hello"),
("a/bar.rs", "world"), ("a/bar.rs", "world"),
@ -58,42 +57,89 @@ fn test_vfs_works() -> std::io::Result<()> {
assert_eq!(files, expected_files); assert_eq!(files, expected_files);
} }
vfs.add_file_overlay(&dir.path().join("a/b/baz.rs"), "quux".to_string()); // on disk change
let change = vfs.commit_changes().pop().unwrap(); fs::write(&dir.path().join("a/b/baz.rs"), "quux").unwrap();
match change { let change = vfs.change_receiver().recv().unwrap();
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "quux"), vfs.handle_change(change);
_ => panic!("unexpected change"), match vfs.commit_changes().as_slice() {
[VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "quux"),
_ => panic!("unexpected changes"),
} }
vfs.change_file_overlay(&dir.path().join("a/b/baz.rs"), "m".to_string()); // in memory change
let change = vfs.commit_changes().pop().unwrap(); vfs.change_file_overlay(&dir.path().join("a/b/baz.rs"), Some("m".to_string()));
match change { match vfs.commit_changes().as_slice() {
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "m"), [VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "m"),
_ => panic!("unexpected change"), _ => panic!("unexpected changes"),
} }
// in memory remove, restores data on disk
vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs")); vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs"));
let change = vfs.commit_changes().pop().unwrap(); match vfs.commit_changes().as_slice() {
match change { [VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "quux"),
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "nested hello"), _ => panic!("unexpected changes"),
_ => panic!("unexpected change"),
} }
vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); // in memory add
let change = vfs.commit_changes().pop().unwrap(); vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), Some("spam".to_string()));
match change { match vfs.commit_changes().as_slice() {
VfsChange::AddFile { text, path, .. } => { [VfsChange::AddFile { text, path, .. }] => {
assert_eq!(&*text, "spam"); assert_eq!(text.as_str(), "spam");
assert_eq!(path, "spam.rs"); assert_eq!(path, "spam.rs");
} }
_ => panic!("unexpected change"), _ => panic!("unexpected changes"),
} }
// in memory remove
vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs"));
let change = vfs.commit_changes().pop().unwrap(); match vfs.commit_changes().as_slice() {
match change { [VfsChange::RemoveFile { path, .. }] => assert_eq!(path, "spam.rs"),
VfsChange::RemoveFile { .. } => (), _ => panic!("unexpected changes"),
_ => panic!("unexpected change"), }
// on disk add
fs::write(&dir.path().join("a/new.rs"), "new hello").unwrap();
let change = vfs.change_receiver().recv().unwrap();
vfs.handle_change(change);
match vfs.commit_changes().as_slice() {
[VfsChange::AddFile { text, path, .. }] => {
assert_eq!(text.as_str(), "new hello");
assert_eq!(path, "new.rs");
}
_ => panic!("unexpected changes"),
}
// on disk rename
fs::rename(&dir.path().join("a/new.rs"), &dir.path().join("a/new1.rs")).unwrap();
let change = vfs.change_receiver().recv().unwrap();
vfs.handle_change(change);
match vfs.commit_changes().as_slice() {
[VfsChange::RemoveFile {
path: removed_path, ..
}, VfsChange::AddFile {
text,
path: added_path,
..
}] => {
assert_eq!(removed_path, "new.rs");
assert_eq!(added_path, "new1.rs");
assert_eq!(text.as_str(), "new hello");
}
_ => panic!("unexpected changes"),
}
// on disk remove
fs::remove_file(&dir.path().join("a/new1.rs")).unwrap();
let change = vfs.change_receiver().recv().unwrap();
vfs.handle_change(change);
match vfs.commit_changes().as_slice() {
[VfsChange::RemoveFile { path, .. }] => assert_eq!(path, "new1.rs"),
_ => panic!("unexpected changes"),
}
match vfs.change_receiver().try_recv() {
Err(crossbeam_channel::TryRecvError::Empty) => (),
res => panic!("unexpected {:?}", res),
} }
vfs.shutdown().unwrap(); vfs.shutdown().unwrap();