aboutsummaryrefslogtreecommitdiff
path: root/crates/server/tests/heavy_tests
diff options
context:
space:
mode:
Diffstat (limited to 'crates/server/tests/heavy_tests')
-rw-r--r--crates/server/tests/heavy_tests/main.rs36
-rw-r--r--crates/server/tests/heavy_tests/support.rs65
2 files changed, 89 insertions, 12 deletions
diff --git a/crates/server/tests/heavy_tests/main.rs b/crates/server/tests/heavy_tests/main.rs
index 94c8243b0..9c0196f22 100644
--- a/crates/server/tests/heavy_tests/main.rs
+++ b/crates/server/tests/heavy_tests/main.rs
@@ -1,5 +1,6 @@
1extern crate tempdir; 1#[macro_use]
2extern crate crossbeam_channel; 2extern crate crossbeam_channel;
3extern crate tempdir;
3extern crate languageserver_types; 4extern crate languageserver_types;
4extern crate serde; 5extern crate serde;
5extern crate serde_json; 6extern crate serde_json;
@@ -9,10 +10,12 @@ extern crate m;
9 10
10mod support; 11mod support;
11 12
12use m::req::{Runnables, RunnablesParams}; 13use m::req::{Runnables, RunnablesParams, DidReloadWorkspace};
13 14
14use support::project; 15use support::project;
15 16
17const LOG: &'static str = "WARN";
18
16#[test] 19#[test]
17fn test_runnables() { 20fn test_runnables() {
18 let server = project(r" 21 let server = project(r"
@@ -40,3 +43,32 @@ fn foo() {
40 ]"# 43 ]"#
41 ); 44 );
42} 45}
46
47#[test]
48fn test_project_model() {
49 let server = project(r#"
50//- Cargo.toml
51[package]
52name = "foo"
53version = "0.0.0"
54
55//- src/lib.rs
56pub fn foo() {}
57"#);
58 server.notification::<DidReloadWorkspace>(r#"[
59 {
60 "packages": [
61 {
62 "manifest": "$PROJECT_ROOT$/Cargo.toml",
63 "name": "foo",
64 "targets": [ 0 ]
65 }
66 ],
67 "targets": [
68 { "kind": "Lib", "name": "foo", "pkg": 0, "root": "$PROJECT_ROOT$/src/lib.rs" }
69 ],
70 "ws_members": [ 0 ]
71 }
72]"#
73 );
74}
diff --git a/crates/server/tests/heavy_tests/support.rs b/crates/server/tests/heavy_tests/support.rs
index 36ca56af3..006926216 100644
--- a/crates/server/tests/heavy_tests/support.rs
+++ b/crates/server/tests/heavy_tests/support.rs
@@ -3,16 +3,18 @@ use std::{
3 thread, 3 thread,
4 cell::{Cell, RefCell}, 4 cell::{Cell, RefCell},
5 path::PathBuf, 5 path::PathBuf,
6 time::Duration,
7 sync::Once,
6}; 8};
7 9
8use tempdir::TempDir; 10use tempdir::TempDir;
9use crossbeam_channel::{bounded, Sender, Receiver}; 11use crossbeam_channel::{bounded, after, Sender, Receiver};
10use flexi_logger::Logger; 12use flexi_logger::Logger;
11use languageserver_types::{ 13use languageserver_types::{
12 Url, 14 Url,
13 TextDocumentIdentifier, 15 TextDocumentIdentifier,
14 request::{Request, Shutdown}, 16 request::{Request, Shutdown},
15 notification::DidOpenTextDocument, 17 notification::{Notification, DidOpenTextDocument},
16 DidOpenTextDocumentParams, 18 DidOpenTextDocumentParams,
17 TextDocumentItem, 19 TextDocumentItem,
18}; 20};
@@ -23,7 +25,8 @@ use gen_lsp_server::{RawMessage, RawRequest, RawNotification};
23use m::{Result, main_loop}; 25use m::{Result, main_loop};
24 26
25pub fn project(fixture: &str) -> Server { 27pub fn project(fixture: &str) -> Server {
26 Logger::with_env_or_str("").start().unwrap(); 28 static INIT: Once = Once::new();
29 INIT.call_once(|| Logger::with_env_or_str(::LOG).start().unwrap());
27 30
28 let tmp_dir = TempDir::new("test-project") 31 let tmp_dir = TempDir::new("test-project")
29 .unwrap(); 32 .unwrap();
@@ -34,6 +37,7 @@ pub fn project(fixture: &str) -> Server {
34 () => { 37 () => {
35 if let Some(file_name) = file_name { 38 if let Some(file_name) = file_name {
36 let path = tmp_dir.path().join(file_name); 39 let path = tmp_dir.path().join(file_name);
40 fs::create_dir_all(path.parent().unwrap()).unwrap();
37 fs::write(path.as_path(), buf.as_bytes()).unwrap(); 41 fs::write(path.as_path(), buf.as_bytes()).unwrap();
38 paths.push((path, buf.clone())); 42 paths.push((path, buf.clone()));
39 } 43 }
@@ -121,6 +125,25 @@ impl Server {
121 ); 125 );
122 } 126 }
123 127
128 pub fn notification<N>(
129 &self,
130 expected: &str,
131 )
132 where
133 N: Notification,
134 {
135 let expected = expected.replace("$PROJECT_ROOT$", &self.dir.path().display().to_string());
136 let expected: Value = from_str(&expected).unwrap();
137 let actual = self.wait_for_notification(N::METHOD);
138 assert_eq!(
139 expected, actual,
140 "Expected:\n{}\n\
141 Actual:\n{}\n",
142 to_string_pretty(&expected).unwrap(),
143 to_string_pretty(&actual).unwrap(),
144 );
145 }
146
124 fn send_request<R>(&self, id: u64, params: R::Params) -> Value 147 fn send_request<R>(&self, id: u64, params: R::Params) -> Value
125 where 148 where
126 R: Request, 149 R: Request,
@@ -130,7 +153,6 @@ impl Server {
130 self.sender.as_ref() 153 self.sender.as_ref()
131 .unwrap() 154 .unwrap()
132 .send(RawMessage::Request(r)); 155 .send(RawMessage::Request(r));
133
134 while let Some(msg) = self.recv() { 156 while let Some(msg) = self.recv() {
135 match msg { 157 match msg {
136 RawMessage::Request(req) => panic!("unexpected request: {:?}", req), 158 RawMessage::Request(req) => panic!("unexpected request: {:?}", req),
@@ -146,15 +168,38 @@ impl Server {
146 } 168 }
147 panic!("no response"); 169 panic!("no response");
148 } 170 }
171 fn wait_for_notification(&self, method: &str) -> Value {
172 let f = |msg: &RawMessage| match msg {
173 RawMessage::Notification(n) if n.method == method => {
174 Some(n.params.clone())
175 }
176 _ => None,
177 };
178
179 for msg in self.messages.borrow().iter() {
180 if let Some(res) = f(msg) {
181 return res;
182 }
183 }
184 while let Some(msg) = self.recv() {
185 if let Some(res) = f(&msg) {
186 return res;
187 }
188 }
189 panic!("no response")
190 }
149 fn recv(&self) -> Option<RawMessage> { 191 fn recv(&self) -> Option<RawMessage> {
150 self.receiver.recv() 192 let timeout = Duration::from_secs(5);
151 .map(|msg| { 193 let msg = select! {
152 self.messages.borrow_mut().push(msg.clone()); 194 recv(&self.receiver, msg) => msg,
153 msg 195 recv(after(timeout)) => panic!("timed out"),
154 }) 196 };
197 msg.map(|msg| {
198 self.messages.borrow_mut().push(msg.clone());
199 msg
200 })
155 } 201 }
156 fn send_notification(&self, not: RawNotification) { 202 fn send_notification(&self, not: RawNotification) {
157
158 self.sender.as_ref() 203 self.sender.as_ref()
159 .unwrap() 204 .unwrap()
160 .send(RawMessage::Notification(not)); 205 .send(RawMessage::Notification(not));