complete test
This commit is contained in:
parent
1d5eaefe8a
commit
d032a1a4e8
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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",
|
||||
|
@ -18,3 +18,4 @@ ra_arena = { path = "../ra_arena" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
flexi_logger = "0.10.0"
|
||||
|
@ -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(),
|
||||
|
@ -39,7 +39,6 @@ fn from_debounced_event(ev: DebouncedEvent) -> Option<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 @@ fn from_debounced_event(ev: DebouncedEvent) -> Option<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 @@ pub fn change_receiver(&self) -> &Receiver<WatcherChange> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user