test.rs

 1use std::{path::Path, sync::Arc};
 2
 3use anyhow::Result;
 4use dap::{DebugRequestType, client::DebugAdapterClient};
 5use gpui::{App, AppContext, Entity, Subscription, Task};
 6use task::DebugTaskDefinition;
 7
 8use crate::Project;
 9
10use super::session::Session;
11
12pub fn intercept_debug_sessions<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
13    cx: &mut gpui::TestAppContext,
14    configure: T,
15) -> Subscription {
16    cx.update(|cx| {
17        cx.observe_new::<Session>(move |session, _, cx| {
18            let client = session.adapter_client().unwrap();
19            register_default_handlers(session, &client, cx);
20            configure(&client);
21            cx.background_spawn(async move {
22                client
23                    .fake_event(dap::messages::Events::Initialized(Some(Default::default())))
24                    .await
25            })
26            .detach();
27        })
28    })
29}
30
31pub fn start_debug_session_with<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
32    project: &Entity<Project>,
33    cx: &mut gpui::TestAppContext,
34    config: DebugTaskDefinition,
35    configure: T,
36) -> Task<Result<Entity<Session>>> {
37    let subscription = intercept_debug_sessions(cx, configure);
38    let task = project.update(cx, |project, cx| project.start_debug_session(config, cx));
39    cx.spawn(async move |_| {
40        let result = task.await;
41        drop(subscription);
42        result
43    })
44}
45
46pub fn start_debug_session<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
47    project: &Entity<Project>,
48    cx: &mut gpui::TestAppContext,
49    configure: T,
50) -> Task<Result<Entity<Session>>> {
51    start_debug_session_with(
52        project,
53        cx,
54        DebugTaskDefinition {
55            adapter: "fake-adapter".to_string(),
56            request: DebugRequestType::Launch(Default::default()),
57            label: "test".to_string(),
58            initialize_args: None,
59            tcp_connection: None,
60            locator: None,
61            stop_on_entry: None,
62        },
63        configure,
64    )
65}
66
67fn register_default_handlers(session: &Session, client: &Arc<DebugAdapterClient>, cx: &mut App) {
68    client.on_request::<dap::requests::Initialize, _>(move |_, _| Ok(Default::default()));
69    let paths = session
70        .as_local()
71        .unwrap()
72        .breakpoint_store
73        .read(cx)
74        .breakpoint_paths();
75
76    client.on_request::<dap::requests::SetBreakpoints, _>(move |_, args| {
77        let p = Arc::from(Path::new(&args.source.path.unwrap()));
78        if !paths.contains(&p) {
79            panic!("Sent breakpoints for path without any")
80        }
81
82        Ok(dap::SetBreakpointsResponse {
83            breakpoints: Vec::default(),
84        })
85    });
86
87    client.on_request::<dap::requests::Launch, _>(move |_, _| Ok(()));
88
89    client.on_request::<dap::requests::SetExceptionBreakpoints, _>(move |_, _| {
90        Ok(dap::SetExceptionBreakpointsResponse { breakpoints: None })
91    });
92
93    client.on_request::<dap::requests::Disconnect, _>(move |_, _| Ok(()));
94
95    client.on_request::<dap::requests::Threads, _>(move |_, _| {
96        Ok(dap::ThreadsResponse { threads: vec![] })
97    });
98}