diff options
Diffstat (limited to 'crates/ra_vfs/tests/vfs.rs')
-rw-r--r-- | crates/ra_vfs/tests/vfs.rs | 156 |
1 files changed, 117 insertions, 39 deletions
diff --git a/crates/ra_vfs/tests/vfs.rs b/crates/ra_vfs/tests/vfs.rs index f56fc4603..357e1c775 100644 --- a/crates/ra_vfs/tests/vfs.rs +++ b/crates/ra_vfs/tests/vfs.rs | |||
@@ -1,24 +1,47 @@ | |||
1 | use std::{ | 1 | use std::{collections::HashSet, fs, time::Duration}; |
2 | fs, | ||
3 | collections::HashSet, | ||
4 | }; | ||
5 | 2 | ||
3 | // use flexi_logger::Logger; | ||
4 | use crossbeam_channel::RecvTimeoutError; | ||
5 | use ra_vfs::{Vfs, VfsChange}; | ||
6 | use tempfile::tempdir; | 6 | use tempfile::tempdir; |
7 | 7 | ||
8 | use ra_vfs::{Vfs, VfsChange}; | 8 | fn process_tasks(vfs: &mut Vfs, num_tasks: u32) { |
9 | for _ in 0..num_tasks { | ||
10 | let task = vfs | ||
11 | .task_receiver() | ||
12 | .recv_timeout(Duration::from_secs(3)) | ||
13 | .unwrap(); | ||
14 | log::debug!("{:?}", task); | ||
15 | vfs.handle_task(task); | ||
16 | } | ||
17 | } | ||
18 | |||
19 | macro_rules! assert_match { | ||
20 | ($x:expr, $pat:pat) => { | ||
21 | assert_match!($x, $pat, ()) | ||
22 | }; | ||
23 | ($x:expr, $pat:pat, $assert:expr) => { | ||
24 | match $x { | ||
25 | $pat => $assert, | ||
26 | x => assert!(false, "Expected {}, got {:?}", stringify!($pat), x), | ||
27 | }; | ||
28 | }; | ||
29 | } | ||
9 | 30 | ||
10 | #[test] | 31 | #[test] |
11 | fn test_vfs_works() -> std::io::Result<()> { | 32 | fn test_vfs_works() -> std::io::Result<()> { |
33 | // Logger::with_str("vfs=debug,ra_vfs=debug").start().unwrap(); | ||
34 | |||
12 | let files = [ | 35 | let files = [ |
13 | ("a/foo.rs", "hello"), | 36 | ("a/foo.rs", "hello"), |
14 | ("a/bar.rs", "world"), | 37 | ("a/bar.rs", "world"), |
15 | ("a/b/baz.rs", "nested hello"), | 38 | ("a/b/baz.rs", "nested hello"), |
16 | ]; | 39 | ]; |
17 | 40 | ||
18 | let dir = tempdir()?; | 41 | let dir = tempdir().unwrap(); |
19 | for (path, text) in files.iter() { | 42 | for (path, text) in files.iter() { |
20 | let file_path = dir.path().join(path); | 43 | let file_path = dir.path().join(path); |
21 | fs::create_dir_all(file_path.parent().unwrap())?; | 44 | fs::create_dir_all(file_path.parent().unwrap()).unwrap(); |
22 | fs::write(file_path, text)? | 45 | fs::write(file_path, text)? |
23 | } | 46 | } |
24 | 47 | ||
@@ -26,10 +49,7 @@ fn test_vfs_works() -> std::io::Result<()> { | |||
26 | let b_root = dir.path().join("a/b"); | 49 | let b_root = dir.path().join("a/b"); |
27 | 50 | ||
28 | let (mut vfs, _) = Vfs::new(vec![a_root, b_root]); | 51 | let (mut vfs, _) = Vfs::new(vec![a_root, b_root]); |
29 | for _ in 0..2 { | 52 | process_tasks(&mut vfs, 2); |
30 | let task = vfs.task_receiver().recv().unwrap(); | ||
31 | vfs.handle_task(task); | ||
32 | } | ||
33 | { | 53 | { |
34 | let files = vfs | 54 | let files = vfs |
35 | .commit_changes() | 55 | .commit_changes() |
@@ -58,43 +78,101 @@ fn test_vfs_works() -> std::io::Result<()> { | |||
58 | assert_eq!(files, expected_files); | 78 | assert_eq!(files, expected_files); |
59 | } | 79 | } |
60 | 80 | ||
61 | vfs.add_file_overlay(&dir.path().join("a/b/baz.rs"), "quux".to_string()); | 81 | fs::write(&dir.path().join("a/b/baz.rs"), "quux").unwrap(); |
62 | let change = vfs.commit_changes().pop().unwrap(); | 82 | process_tasks(&mut vfs, 1); |
63 | match change { | 83 | assert_match!( |
64 | VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "quux"), | 84 | vfs.commit_changes().as_slice(), |
65 | _ => panic!("unexpected change"), | 85 | [VfsChange::ChangeFile { text, .. }], |
66 | } | 86 | assert_eq!(text.as_str(), "quux") |
87 | ); | ||
67 | 88 | ||
68 | vfs.change_file_overlay(&dir.path().join("a/b/baz.rs"), "m".to_string()); | 89 | vfs.add_file_overlay(&dir.path().join("a/b/baz.rs"), "m".to_string()); |
69 | let change = vfs.commit_changes().pop().unwrap(); | 90 | assert_match!( |
70 | match change { | 91 | vfs.commit_changes().as_slice(), |
71 | VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "m"), | 92 | [VfsChange::ChangeFile { text, .. }], |
72 | _ => panic!("unexpected change"), | 93 | assert_eq!(text.as_str(), "m") |
73 | } | 94 | ); |
74 | 95 | ||
96 | // changing file on disk while overlayed doesn't generate a VfsChange | ||
97 | fs::write(&dir.path().join("a/b/baz.rs"), "corge").unwrap(); | ||
98 | process_tasks(&mut vfs, 1); | ||
99 | assert_match!(vfs.commit_changes().as_slice(), []); | ||
100 | |||
101 | // removing overlay restores data on disk | ||
75 | vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs")); | 102 | vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs")); |
76 | let change = vfs.commit_changes().pop().unwrap(); | 103 | assert_match!( |
77 | match change { | 104 | vfs.commit_changes().as_slice(), |
78 | VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "nested hello"), | 105 | [VfsChange::ChangeFile { text, .. }], |
79 | _ => panic!("unexpected change"), | 106 | assert_eq!(text.as_str(), "corge") |
80 | } | 107 | ); |
81 | 108 | ||
82 | vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); | 109 | vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string()); |
83 | let change = vfs.commit_changes().pop().unwrap(); | 110 | assert_match!( |
84 | match change { | 111 | vfs.commit_changes().as_slice(), |
85 | VfsChange::AddFile { text, path, .. } => { | 112 | [VfsChange::AddFile { text, path, .. }], |
86 | assert_eq!(&*text, "spam"); | 113 | { |
114 | assert_eq!(text.as_str(), "spam"); | ||
87 | assert_eq!(path, "spam.rs"); | 115 | assert_eq!(path, "spam.rs"); |
88 | } | 116 | } |
89 | _ => panic!("unexpected change"), | 117 | ); |
90 | } | ||
91 | 118 | ||
92 | vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); | 119 | vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs")); |
93 | let change = vfs.commit_changes().pop().unwrap(); | 120 | assert_match!( |
94 | match change { | 121 | vfs.commit_changes().as_slice(), |
95 | VfsChange::RemoveFile { .. } => (), | 122 | [VfsChange::RemoveFile { path, .. }], |
96 | _ => panic!("unexpected change"), | 123 | assert_eq!(path, "spam.rs") |
97 | } | 124 | ); |
125 | |||
126 | fs::create_dir_all(dir.path().join("a/sub1/sub2")).unwrap(); | ||
127 | fs::write(dir.path().join("a/sub1/sub2/new.rs"), "new hello").unwrap(); | ||
128 | process_tasks(&mut vfs, 1); | ||
129 | assert_match!( | ||
130 | vfs.commit_changes().as_slice(), | ||
131 | [VfsChange::AddFile { text, path, .. }], | ||
132 | { | ||
133 | assert_eq!(text.as_str(), "new hello"); | ||
134 | assert_eq!(path, "sub1/sub2/new.rs"); | ||
135 | } | ||
136 | ); | ||
137 | |||
138 | fs::rename( | ||
139 | &dir.path().join("a/sub1/sub2/new.rs"), | ||
140 | &dir.path().join("a/sub1/sub2/new1.rs"), | ||
141 | ) | ||
142 | .unwrap(); | ||
143 | process_tasks(&mut vfs, 2); | ||
144 | assert_match!( | ||
145 | vfs.commit_changes().as_slice(), | ||
146 | [VfsChange::RemoveFile { | ||
147 | path: removed_path, .. | ||
148 | }, VfsChange::AddFile { | ||
149 | text, | ||
150 | path: added_path, | ||
151 | .. | ||
152 | }], | ||
153 | { | ||
154 | assert_eq!(removed_path, "sub1/sub2/new.rs"); | ||
155 | assert_eq!(added_path, "sub1/sub2/new1.rs"); | ||
156 | assert_eq!(text.as_str(), "new hello"); | ||
157 | } | ||
158 | ); | ||
159 | |||
160 | fs::remove_file(&dir.path().join("a/sub1/sub2/new1.rs")).unwrap(); | ||
161 | process_tasks(&mut vfs, 1); | ||
162 | assert_match!( | ||
163 | vfs.commit_changes().as_slice(), | ||
164 | [VfsChange::RemoveFile { path, .. }], | ||
165 | assert_eq!(path, "sub1/sub2/new1.rs") | ||
166 | ); | ||
167 | |||
168 | // should be ignored | ||
169 | fs::create_dir_all(dir.path().join("a/target")).unwrap(); | ||
170 | fs::write(&dir.path().join("a/target/new.rs"), "ignore me").unwrap(); | ||
171 | |||
172 | assert_match!( | ||
173 | vfs.task_receiver().recv_timeout(Duration::from_millis(300)), // slightly more than watcher debounce delay | ||
174 | Err(RecvTimeoutError::Timeout) | ||
175 | ); | ||
98 | 176 | ||
99 | vfs.shutdown().unwrap(); | 177 | vfs.shutdown().unwrap(); |
100 | Ok(()) | 178 | Ok(()) |