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 = [
"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)",
"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)",
"notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"ra_arena 0.1.0",

View File

@ -18,3 +18,4 @@ ra_arena = { path = "../ra_arena" }
[dev-dependencies]
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>) {
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 {
roots: Arena::default(),

View File

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

View File

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