use crate::tests::{init_test, init_test_workspace, start_debug_session};use dap::requests::{StackTrace, Threads};use debugger_tools::LogStore;use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};use project::Project;use serde_json::json;use std::cell::OnceCell;use util::path; #[gpui::test]async fn test_dap_logger_captures_all_session_rpc_messages( executor: BackgroundExecutor, cx: &mut TestAppContext,) { let log_store_cell = std::rc::Rc::new(OnceCell::new()); cx.update(|cx| { let log_store_cell = log_store_cell.clone(); cx.observe_new::<LogStore>(move |_, _, cx| { log_store_cell.set(cx.entity()).unwrap(); }) .detach(); debugger_tools::init(cx); }); init_test(cx); let log_store = log_store_cell.get().unwrap().clone(); // Create a filesystem with a simple project let fs = project::FakeFs::new(executor.clone()); fs.insert_tree( path!("/project"), json!({ "main.rs": "fn main() {\n println!(\"Hello, world!\");\n}" }), ) .await; assert!( log_store.read_with(cx, |log_store, _| !log_store.has_projects()), "log_store shouldn't contain any projects before any projects were created" ); let project = Project::test(fs, [path!("/project").as_ref()], cx).await; let workspace = init_test_workspace(&project, cx).await; assert!( log_store.read_with(cx, |log_store, _| log_store.has_projects()), "log_store shouldn't contain any projects before any projects were created" ); assert!( log_store.read_with(cx, |log_store, _| log_store .contained_session_ids(&project.downgrade()) .is_empty()), "log_store shouldn't contain any projects before any projects were created" ); let cx = &mut VisualTestContext::from_window(*workspace, cx); // Start a debug session let session = start_debug_session(&workspace, cx, |_| {}).unwrap(); let session_id = session.read_with(cx, |session, _| session.session_id()); let client = session.update(cx, |session, _| session.adapter_client().unwrap()); assert_eq!( log_store.read_with(cx, |log_store, _| log_store .contained_session_ids(&project.downgrade()) .len()), 1, ); assert!( log_store.read_with(cx, |log_store, _| log_store .contained_session_ids(&project.downgrade()) .contains(&session_id)), "log_store should contain the session IDs of the started session" ); assert!( !log_store.read_with(cx, |log_store, _| log_store .rpc_messages_for_session_id(&project.downgrade(), session_id) .is_empty()), "We should have the initialization sequence in the log store" ); // Set up basic responses for common requests client.on_request::<Threads, _>(move |_, _| { Ok(dap::ThreadsResponse { threads: vec![dap::Thread { id: 1, name: "Thread 1".into(), }], }) }); client.on_request::<StackTrace, _>(move |_, _| { Ok(dap::StackTraceResponse { stack_frames: Vec::default(), total_frames: None, }) }); // Run until all pending tasks are executed cx.run_until_parked(); // Simulate a stopped event to generate more DAP messages client .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { reason: dap::StoppedEventReason::Pause, description: None, thread_id: Some(1), preserve_focus_hint: None, text: None, all_threads_stopped: None, hit_breakpoint_ids: None, })) .await;}
use crate::tests::{init_test, init_test_workspace, start_debug_session};
use dap::requests::{StackTrace, Threads};
use debugger_tools::LogStore;
use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
use project::Project;
use serde_json::json;
use std::cell::OnceCell;
use util::path;
#[gpui::test]
async fn test_dap_logger_captures_all_session_rpc_messages(
executor: BackgroundExecutor,
cx: &mut TestAppContext,
) {
let log_store_cell = std::rc::Rc::new(OnceCell::new());
cx.update(|cx| {
let log_store_cell = log_store_cell.clone();
cx.observe_new::<LogStore>(move |_, _, cx| {
log_store_cell.set(cx.entity()).unwrap();
})
.detach();
debugger_tools::init(cx);
});
init_test(cx);
let log_store = log_store_cell.get().unwrap().clone();
// Create a filesystem with a simple project
let fs = project::FakeFs::new(executor.clone());
fs.insert_tree(
path!("/project"),
json!({
"main.rs": "fn main() {\n println!(\"Hello, world!\");\n}"
}),
)
.await;
assert!(
log_store.read_with(cx, |log_store, _| !log_store.has_projects()),
"log_store shouldn't contain any projects before any projects were created"
);
let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
let workspace = init_test_workspace(&project, cx).await;
assert!(
log_store.read_with(cx, |log_store, _| log_store.has_projects()),
"log_store shouldn't contain any projects before any projects were created"
);
assert!(
log_store.read_with(cx, |log_store, _| log_store
.contained_session_ids(&project.downgrade())
.is_empty()),
"log_store shouldn't contain any projects before any projects were created"
);
let cx = &mut VisualTestContext::from_window(*workspace, cx);
// Start a debug session
let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
let session_id = session.read_with(cx, |session, _| session.session_id());
let client = session.update(cx, |session, _| session.adapter_client().unwrap());
assert_eq!(
log_store.read_with(cx, |log_store, _| log_store
.contained_session_ids(&project.downgrade())
.len()),
1,
);
assert!(
log_store.read_with(cx, |log_store, _| log_store
.contained_session_ids(&project.downgrade())
.contains(&session_id)),
"log_store should contain the session IDs of the started session"
);
assert!(
!log_store.read_with(cx, |log_store, _| log_store
.rpc_messages_for_session_id(&project.downgrade(), session_id)
.is_empty()),
"We should have the initialization sequence in the log store"
);
// Set up basic responses for common requests
client.on_request::<Threads, _>(move |_, _| {
Ok(dap::ThreadsResponse {
threads: vec![dap::Thread {
id: 1,
name: "Thread 1".into(),
}],
})
});
client.on_request::<StackTrace, _>(move |_, _| {
Ok(dap::StackTraceResponse {
stack_frames: Vec::default(),
total_frames: None,
})
});
// Run until all pending tasks are executed
cx.run_until_parked();
// Simulate a stopped event to generate more DAP messages
client
.fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
reason: dap::StoppedEventReason::Pause,
description: None,
thread_id: Some(1),
preserve_focus_hint: None,
text: None,
all_threads_stopped: None,
hit_breakpoint_ids: None,
}))
.await;
}