Add test option for faking reverse requests
This commit is contained in:
@@ -270,6 +270,17 @@ impl DebugAdapterClient {
|
||||
transport.as_fake().on_request::<R, F>(handler).await;
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub async fn fake_reverse_request<R: dap_types::requests::Request>(&self, args: R::Arguments) {
|
||||
self.send_message(Message::Request(dap_types::messages::Request {
|
||||
seq: self.sequence_count.load(Ordering::Relaxed),
|
||||
command: R::COMMAND.into(),
|
||||
arguments: serde_json::to_value(args).ok(),
|
||||
}))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub async fn fake_event(&self, event: dap_types::messages::Events) {
|
||||
self.send_message(Message::Event(Box::new(event)))
|
||||
@@ -285,10 +296,13 @@ mod tests {
|
||||
adapters::FakeAdapter, client::DebugAdapterClient, debugger_settings::DebuggerSettings,
|
||||
};
|
||||
use dap_types::{
|
||||
messages::Events, requests::Initialize, Capabilities, InitializeRequestArguments,
|
||||
InitializeRequestArgumentsPathFormat,
|
||||
messages::Events,
|
||||
requests::{Initialize, Request, RunInTerminal},
|
||||
Capabilities, InitializeRequestArguments, InitializeRequestArgumentsPathFormat,
|
||||
RunInTerminalRequestArguments,
|
||||
};
|
||||
use gpui::TestAppContext;
|
||||
use serde_json::json;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -430,4 +444,71 @@ mod tests {
|
||||
|
||||
client.shutdown().await.unwrap();
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
pub async fn test_calls_event_handler_for_reverse_request(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
let adapter = Arc::new(FakeAdapter::new());
|
||||
let called_event_handler = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let mut client = DebugAdapterClient::new(
|
||||
crate::client::DebugAdapterClientId(1),
|
||||
adapter,
|
||||
DebugAdapterBinary {
|
||||
command: "command".into(),
|
||||
arguments: Default::default(),
|
||||
envs: Default::default(),
|
||||
cwd: None,
|
||||
},
|
||||
&mut cx.to_async(),
|
||||
);
|
||||
|
||||
client
|
||||
.start(
|
||||
{
|
||||
let called_event_handler = called_event_handler.clone();
|
||||
move |event, _| {
|
||||
called_event_handler.store(true, Ordering::SeqCst);
|
||||
|
||||
assert_eq!(
|
||||
Message::Request(dap_types::messages::Request {
|
||||
seq: 1,
|
||||
command: RunInTerminal::COMMAND.into(),
|
||||
arguments: Some(json!({
|
||||
"cwd": "/project/path/src",
|
||||
"args": ["node", "test.js"],
|
||||
}))
|
||||
}),
|
||||
event
|
||||
);
|
||||
}
|
||||
},
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
client
|
||||
.fake_reverse_request::<RunInTerminal>(RunInTerminalRequestArguments {
|
||||
kind: None,
|
||||
title: None,
|
||||
cwd: "/project/path/src".into(),
|
||||
args: vec!["node".into(), "test.js".into()],
|
||||
env: None,
|
||||
args_can_be_interpreted_by_shell: None,
|
||||
})
|
||||
.await;
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
assert!(
|
||||
called_event_handler.load(std::sync::atomic::Ordering::SeqCst),
|
||||
"Event handler was not called"
|
||||
);
|
||||
|
||||
client.shutdown().await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,6 +809,7 @@ impl Transport for FakeTransport {
|
||||
_binary: &DebugAdapterBinary,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<TransportPipe> {
|
||||
use dap_types::requests::{Request, RunInTerminal, StartDebugging};
|
||||
use serde_json::json;
|
||||
|
||||
let (stdin_writer, stdin_reader) = async_pipe::pipe();
|
||||
@@ -817,51 +818,69 @@ impl Transport for FakeTransport {
|
||||
let handlers = self.request_handlers.clone();
|
||||
let stdout_writer = Arc::new(Mutex::new(stdout_writer));
|
||||
|
||||
cx.background_executor().spawn(async move {
|
||||
let mut reader = BufReader::new(stdin_reader);
|
||||
let mut buffer = String::new();
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
let mut reader = BufReader::new(stdin_reader);
|
||||
let mut buffer = String::new();
|
||||
|
||||
loop {
|
||||
let message = TransportDelegate::receive_server_message(
|
||||
&mut reader,
|
||||
&mut buffer,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
match message {
|
||||
Err(error) => {
|
||||
break anyhow!(error);
|
||||
}
|
||||
Ok(Message::Request(request)) => {
|
||||
if let Some(handle) =
|
||||
handlers.lock().await.get_mut(request.command.as_str())
|
||||
{
|
||||
handle(
|
||||
request.seq,
|
||||
request.arguments.unwrap_or(json!({})),
|
||||
stdout_writer.clone(),
|
||||
)
|
||||
loop {
|
||||
let message =
|
||||
TransportDelegate::receive_server_message(&mut reader, &mut buffer, None)
|
||||
.await;
|
||||
} else {
|
||||
log::debug!("No handler for {}", request.command);
|
||||
|
||||
match message {
|
||||
Err(error) => {
|
||||
break anyhow!(error);
|
||||
}
|
||||
Ok(message) => {
|
||||
if let Message::Request(request) = message {
|
||||
// redirect reverse requests to stdout writer/reader
|
||||
if request.command == RunInTerminal::COMMAND
|
||||
|| request.command == StartDebugging::COMMAND
|
||||
{
|
||||
let message =
|
||||
serde_json::to_string(&Message::Request(request)).unwrap();
|
||||
|
||||
let mut writer = stdout_writer.lock().await;
|
||||
writer
|
||||
.write_all(
|
||||
TransportDelegate::build_rpc_message(message)
|
||||
.as_bytes(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
writer.flush().await.unwrap();
|
||||
} else {
|
||||
if let Some(handle) =
|
||||
handlers.lock().await.get_mut(request.command.as_str())
|
||||
{
|
||||
handle(
|
||||
request.seq,
|
||||
request.arguments.unwrap_or(json!({})),
|
||||
stdout_writer.clone(),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
log::debug!("No handler for {}", request.command);
|
||||
}
|
||||
}
|
||||
} else if let Message::Event(event) = message {
|
||||
let message = serde_json::to_string(&Message::Event(event)).unwrap();
|
||||
|
||||
let mut writer = stdout_writer.lock().await;
|
||||
writer
|
||||
.write_all(TransportDelegate::build_rpc_message(message).as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
writer.flush().await.unwrap();
|
||||
} else {
|
||||
unreachable!("You can only send a request and an event that is redirected to the output reader")
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Message::Event(event)) => {
|
||||
let message = serde_json::to_string(&Message::Event(event)).unwrap();
|
||||
|
||||
let mut writer = stdout_writer.lock().await;
|
||||
writer
|
||||
.write_all(TransportDelegate::build_rpc_message(message).as_bytes())
|
||||
.await
|
||||
.unwrap();
|
||||
writer.flush().await.unwrap();
|
||||
}
|
||||
_ => unreachable!("You can only send a request and an event that is redirected to the output reader"),
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(TransportPipe::new(
|
||||
Box::new(stdin_writer),
|
||||
|
||||
Reference in New Issue
Block a user