Request definitions as guests in random collaboration integration test

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-02-22 12:03:45 -08:00
parent 64098247cb
commit dbe9c54857

View file

@ -1165,7 +1165,7 @@ mod tests {
use serde_json::json; use serde_json::json;
use sqlx::types::time::OffsetDateTime; use sqlx::types::time::OffsetDateTime;
use std::{ use std::{
cell::{Cell, RefCell}, cell::Cell,
env, env,
ops::Deref, ops::Deref,
path::Path, path::Path,
@ -3840,7 +3840,7 @@ mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10); .unwrap_or(10);
let rng = Rc::new(RefCell::new(rng)); let rng = Arc::new(Mutex::new(rng));
let guest_lang_registry = Arc::new(LanguageRegistry::new()); let guest_lang_registry = Arc::new(LanguageRegistry::new());
let (language_server_config, _fake_language_servers) = LanguageServerConfig::fake(); let (language_server_config, _fake_language_servers) = LanguageServerConfig::fake();
@ -3906,7 +3906,7 @@ mod tests {
while operations.get() < max_operations { while operations.get() < max_operations {
cx.background().simulate_random_delay().await; cx.background().simulate_random_delay().await;
if clients.len() < max_peers && rng.borrow_mut().gen_bool(0.05) { if clients.len() < max_peers && rng.lock().gen_bool(0.05) {
operations.set(operations.get() + 1); operations.set(operations.get() + 1);
let guest_id = clients.len(); let guest_id = clients.len();
@ -4233,39 +4233,66 @@ mod tests {
mut language_server_config: LanguageServerConfig, mut language_server_config: LanguageServerConfig,
operations: Rc<Cell<usize>>, operations: Rc<Cell<usize>>,
max_operations: usize, max_operations: usize,
rng: Rc<RefCell<StdRng>>, rng: Arc<Mutex<StdRng>>,
mut cx: TestAppContext, mut cx: TestAppContext,
) -> impl Future<Output = (Self, TestAppContext)> { ) -> impl Future<Output = (Self, TestAppContext)> {
let files: Arc<Mutex<Vec<PathBuf>>> = Default::default();
// Set up a fake language server. // Set up a fake language server.
language_server_config.set_fake_initializer(|fake_server| { language_server_config.set_fake_initializer({
fake_server.handle_request::<lsp::request::Completion, _>(|_| { let rng = rng.clone();
Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem { let files = files.clone();
text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit { move |fake_server| {
range: lsp::Range::new( fake_server.handle_request::<lsp::request::Completion, _>(|_| {
lsp::Position::new(0, 0), Some(lsp::CompletionResponse::Array(vec![lsp::CompletionItem {
lsp::Position::new(0, 0), text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
), range: lsp::Range::new(
new_text: "the-new-text".to_string(), lsp::Position::new(0, 0),
})), lsp::Position::new(0, 0),
..Default::default() ),
}])) new_text: "the-new-text".to_string(),
}); })),
fake_server.handle_request::<lsp::request::CodeActionRequest, _>(|_| {
Some(vec![lsp::CodeActionOrCommand::CodeAction(
lsp::CodeAction {
title: "the-code-action".to_string(),
..Default::default() ..Default::default()
}, }]))
)]) });
});
fake_server.handle_request::<lsp::request::PrepareRenameRequest, _>(|params| { fake_server.handle_request::<lsp::request::CodeActionRequest, _>(|_| {
Some(lsp::PrepareRenameResponse::Range(lsp::Range::new( Some(vec![lsp::CodeActionOrCommand::CodeAction(
params.position, lsp::CodeAction {
params.position, title: "the-code-action".to_string(),
))) ..Default::default()
}); },
)])
});
fake_server.handle_request::<lsp::request::PrepareRenameRequest, _>(|params| {
Some(lsp::PrepareRenameResponse::Range(lsp::Range::new(
params.position,
params.position,
)))
});
fake_server.handle_request::<lsp::request::GotoDefinition, _>({
let files = files.clone();
let rng = rng.clone();
move |_| {
let files = files.lock();
let mut rng = rng.lock();
let count = rng.gen_range::<usize, _>(1..3);
Some(lsp::GotoDefinitionResponse::Array(
(0..count)
.map(|_| {
let file = files.choose(&mut *rng).unwrap().as_path();
lsp::Location {
uri: lsp::Url::from_file_path(file).unwrap(),
range: Default::default(),
}
})
.collect(),
))
}
});
}
}); });
project.update(&mut cx, |project, _| { project.update(&mut cx, |project, _| {
@ -4282,17 +4309,17 @@ mod tests {
async move { async move {
let fs = project.read_with(&cx, |project, _| project.fs().clone()); let fs = project.read_with(&cx, |project, _| project.fs().clone());
let mut files: Vec<PathBuf> = Default::default();
while operations.get() < max_operations { while operations.get() < max_operations {
operations.set(operations.get() + 1); operations.set(operations.get() + 1);
let distribution = rng.borrow_mut().gen_range(0..100); let distribution = rng.lock().gen_range::<usize, _>(0..100);
match distribution { match distribution {
0..=20 if !files.is_empty() => { 0..=20 if !files.lock().is_empty() => {
let mut path = files.choose(&mut *rng.borrow_mut()).unwrap().as_path(); let path = files.lock().choose(&mut *rng.lock()).unwrap().clone();
let mut path = path.as_path();
while let Some(parent_path) = path.parent() { while let Some(parent_path) = path.parent() {
path = parent_path; path = parent_path;
if rng.borrow_mut().gen() { if rng.lock().gen() {
break; break;
} }
} }
@ -4305,9 +4332,9 @@ mod tests {
.await .await
.unwrap(); .unwrap();
} }
10..=80 if !files.is_empty() => { 10..=80 if !files.lock().is_empty() => {
let buffer = if self.buffers.is_empty() || rng.borrow_mut().gen() { let buffer = if self.buffers.is_empty() || rng.lock().gen() {
let file = files.choose(&mut *rng.borrow_mut()).unwrap(); let file = files.lock().choose(&mut *rng.lock()).unwrap().clone();
let (worktree, path) = project let (worktree, path) = project
.update(&mut cx, |project, cx| { .update(&mut cx, |project, cx| {
project.find_or_create_local_worktree(file, false, cx) project.find_or_create_local_worktree(file, false, cx)
@ -4328,12 +4355,12 @@ mod tests {
} else { } else {
self.buffers self.buffers
.iter() .iter()
.choose(&mut *rng.borrow_mut()) .choose(&mut *rng.lock())
.unwrap() .unwrap()
.clone() .clone()
}; };
if rng.borrow_mut().gen_bool(0.1) { if rng.lock().gen_bool(0.1) {
cx.update(|cx| { cx.update(|cx| {
log::info!( log::info!(
"Host: dropping buffer {:?}", "Host: dropping buffer {:?}",
@ -4348,26 +4375,27 @@ mod tests {
"Host: updating buffer {:?}", "Host: updating buffer {:?}",
buffer.file().unwrap().full_path(cx) buffer.file().unwrap().full_path(cx)
); );
buffer.randomly_edit(&mut *rng.borrow_mut(), 5, cx) buffer.randomly_edit(&mut *rng.lock(), 5, cx)
}); });
} }
} }
_ => loop { _ => loop {
let path_component_count = rng.borrow_mut().gen_range(1..=5); let path_component_count = rng.lock().gen_range::<usize, _>(1..=5);
let mut path = PathBuf::new(); let mut path = PathBuf::new();
path.push("/"); path.push("/");
for _ in 0..path_component_count { for _ in 0..path_component_count {
let letter = rng.borrow_mut().gen_range(b'a'..=b'z'); let letter = rng.lock().gen_range(b'a'..=b'z');
path.push(std::str::from_utf8(&[letter]).unwrap()); path.push(std::str::from_utf8(&[letter]).unwrap());
} }
path.set_extension("rs"); path.set_extension("rs");
let parent_path = path.parent().unwrap(); let parent_path = path.parent().unwrap();
log::info!("Host: creating file {:?}", path); log::info!("Host: creating file {:?}", path,);
if fs.create_dir(&parent_path).await.is_ok() if fs.create_dir(&parent_path).await.is_ok()
&& fs.create_file(&path, Default::default()).await.is_ok() && fs.create_file(&path, Default::default()).await.is_ok()
{ {
files.push(path); files.lock().push(path);
break; break;
} else { } else {
log::info!("Host: cannot create file"); log::info!("Host: cannot create file");
@ -4389,18 +4417,18 @@ mod tests {
project: ModelHandle<Project>, project: ModelHandle<Project>,
operations: Rc<Cell<usize>>, operations: Rc<Cell<usize>>,
max_operations: usize, max_operations: usize,
rng: Rc<RefCell<StdRng>>, rng: Arc<Mutex<StdRng>>,
mut cx: TestAppContext, mut cx: TestAppContext,
) -> (Self, TestAppContext) { ) -> (Self, TestAppContext) {
while operations.get() < max_operations { while operations.get() < max_operations {
let buffer = if self.buffers.is_empty() || rng.borrow_mut().gen() { let buffer = if self.buffers.is_empty() || rng.lock().gen() {
let worktree = if let Some(worktree) = project.read_with(&cx, |project, cx| { let worktree = if let Some(worktree) = project.read_with(&cx, |project, cx| {
project project
.worktrees(&cx) .worktrees(&cx)
.filter(|worktree| { .filter(|worktree| {
worktree.read(cx).entries(false).any(|e| e.is_file()) worktree.read(cx).entries(false).any(|e| e.is_file())
}) })
.choose(&mut *rng.borrow_mut()) .choose(&mut *rng.lock())
}) { }) {
worktree worktree
} else { } else {
@ -4413,7 +4441,7 @@ mod tests {
let entry = worktree let entry = worktree
.entries(false) .entries(false)
.filter(|e| e.is_file()) .filter(|e| e.is_file())
.choose(&mut *rng.borrow_mut()) .choose(&mut *rng.lock())
.unwrap(); .unwrap();
(worktree.id(), entry.path.clone()) (worktree.id(), entry.path.clone())
}); });
@ -4429,12 +4457,12 @@ mod tests {
self.buffers self.buffers
.iter() .iter()
.choose(&mut *rng.borrow_mut()) .choose(&mut *rng.lock())
.unwrap() .unwrap()
.clone() .clone()
}; };
let choice = rng.borrow_mut().gen_range(0..100); let choice = rng.lock().gen_range(0..100);
match choice { match choice {
0..=9 => { 0..=9 => {
cx.update(|cx| { cx.update(|cx| {
@ -4454,13 +4482,13 @@ mod tests {
guest_id, guest_id,
buffer.read(cx).file().unwrap().full_path(cx) buffer.read(cx).file().unwrap().full_path(cx)
); );
let offset = rng.borrow_mut().gen_range(0..=buffer.read(cx).len()); let offset = rng.lock().gen_range(0..=buffer.read(cx).len());
project.completions(&buffer, offset, cx) project.completions(&buffer, offset, cx)
}); });
let completions = cx.background().spawn(async move { let completions = cx.background().spawn(async move {
completions.await.expect("completions request failed"); completions.await.expect("completions request failed");
}); });
if rng.borrow_mut().gen_bool(0.3) { if rng.lock().gen_bool(0.3) {
log::info!("Guest {}: detaching completions request", guest_id); log::info!("Guest {}: detaching completions request", guest_id);
completions.detach(); completions.detach();
} else { } else {
@ -4474,14 +4502,13 @@ mod tests {
guest_id, guest_id,
buffer.read(cx).file().unwrap().full_path(cx) buffer.read(cx).file().unwrap().full_path(cx)
); );
let range = let range = buffer.read(cx).random_byte_range(0, &mut *rng.lock());
buffer.read(cx).random_byte_range(0, &mut *rng.borrow_mut());
project.code_actions(&buffer, range, cx) project.code_actions(&buffer, range, cx)
}); });
let code_actions = cx.background().spawn(async move { let code_actions = cx.background().spawn(async move {
code_actions.await.expect("code actions request failed"); code_actions.await.expect("code actions request failed");
}); });
if rng.borrow_mut().gen_bool(0.3) { if rng.lock().gen_bool(0.3) {
log::info!("Guest {}: detaching code actions request", guest_id); log::info!("Guest {}: detaching code actions request", guest_id);
code_actions.detach(); code_actions.detach();
} else { } else {
@ -4504,7 +4531,7 @@ mod tests {
assert!(saved_version.observed_all(&requested_version)); assert!(saved_version.observed_all(&requested_version));
}); });
}); });
if rng.borrow_mut().gen_bool(0.3) { if rng.lock().gen_bool(0.3) {
log::info!("Guest {}: detaching save request", guest_id); log::info!("Guest {}: detaching save request", guest_id);
save.detach(); save.detach();
} else { } else {
@ -4518,19 +4545,39 @@ mod tests {
guest_id, guest_id,
buffer.read(cx).file().unwrap().full_path(cx) buffer.read(cx).file().unwrap().full_path(cx)
); );
let offset = rng.borrow_mut().gen_range(0..=buffer.read(cx).len()); let offset = rng.lock().gen_range(0..=buffer.read(cx).len());
project.prepare_rename(buffer, offset, cx) project.prepare_rename(buffer, offset, cx)
}); });
let prepare_rename = cx.background().spawn(async move { let prepare_rename = cx.background().spawn(async move {
prepare_rename.await.expect("prepare rename request failed"); prepare_rename.await.expect("prepare rename request failed");
}); });
if rng.borrow_mut().gen_bool(0.3) { if rng.lock().gen_bool(0.3) {
log::info!("Guest {}: detaching prepare rename request", guest_id); log::info!("Guest {}: detaching prepare rename request", guest_id);
prepare_rename.detach(); prepare_rename.detach();
} else { } else {
prepare_rename.await; prepare_rename.await;
} }
} }
46..=49 => {
let definitions = project.update(&mut cx, |project, cx| {
log::info!(
"Guest {}: requesting defintions for buffer {:?}",
guest_id,
buffer.read(cx).file().unwrap().full_path(cx)
);
let offset = rng.lock().gen_range(0..=buffer.read(cx).len());
project.definition(&buffer, offset, cx)
});
let definitions = cx.background().spawn(async move {
definitions.await.expect("definitions request failed");
});
if rng.lock().gen_bool(0.3) {
log::info!("Guest {}: detaching definitions request", guest_id);
definitions.detach();
} else {
definitions.await;
}
}
_ => { _ => {
buffer.update(&mut cx, |buffer, cx| { buffer.update(&mut cx, |buffer, cx| {
log::info!( log::info!(
@ -4538,7 +4585,7 @@ mod tests {
guest_id, guest_id,
buffer.file().unwrap().full_path(cx) buffer.file().unwrap().full_path(cx)
); );
buffer.randomly_edit(&mut *rng.borrow_mut(), 5, cx) buffer.randomly_edit(&mut *rng.lock(), 5, cx)
}); });
} }
} }