attach_modal.rs

  1use crate::{attach_modal::Candidate, tests::start_debug_session_with, *};
  2use attach_modal::AttachModal;
  3use dap::{FakeAdapter, adapters::DebugTaskDefinition};
  4use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
  5use menu::Confirm;
  6use project::{FakeFs, Project};
  7use serde_json::json;
  8use task::{AttachRequest, TcpArgumentsTemplate};
  9use tests::{init_test, init_test_workspace};
 10use util::path;
 11
 12#[gpui::test]
 13async fn test_direct_attach_to_process(executor: BackgroundExecutor, cx: &mut TestAppContext) {
 14    init_test(cx);
 15
 16    let fs = FakeFs::new(executor.clone());
 17
 18    fs.insert_tree(
 19        path!("/project"),
 20        json!({
 21            "main.rs": "First line\nSecond line\nThird line\nFourth line",
 22        }),
 23    )
 24    .await;
 25
 26    let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
 27    let workspace = init_test_workspace(&project, cx).await;
 28    let cx = &mut VisualTestContext::from_window(*workspace, cx);
 29
 30    let session = start_debug_session_with(
 31        &workspace,
 32        cx,
 33        DebugTaskDefinition {
 34            adapter: "fake-adapter".into(),
 35            request: dap::DebugRequest::Attach(AttachRequest {
 36                process_id: Some(10),
 37            }),
 38            label: "label".into(),
 39            initialize_args: None,
 40            tcp_connection: None,
 41            stop_on_entry: None,
 42        },
 43        |client| {
 44            client.on_request::<dap::requests::Attach, _>(move |_, args| {
 45                let raw = &args.raw;
 46                assert_eq!(raw["request"], "attach");
 47                assert_eq!(raw["process_id"], 10);
 48
 49                Ok(())
 50            });
 51        },
 52    )
 53    .unwrap();
 54
 55    cx.run_until_parked();
 56
 57    // assert we didn't show the attach modal
 58    workspace
 59        .update(cx, |workspace, _window, cx| {
 60            assert!(workspace.active_modal::<AttachModal>(cx).is_none());
 61        })
 62        .unwrap();
 63
 64    let shutdown_session = project.update(cx, |project, cx| {
 65        project.dap_store().update(cx, |dap_store, cx| {
 66            dap_store.shutdown_session(session.read(cx).session_id(), cx)
 67        })
 68    });
 69
 70    shutdown_session.await.unwrap();
 71}
 72
 73#[gpui::test]
 74async fn test_show_attach_modal_and_select_process(
 75    executor: BackgroundExecutor,
 76    cx: &mut TestAppContext,
 77) {
 78    init_test(cx);
 79
 80    let fs = FakeFs::new(executor.clone());
 81
 82    fs.insert_tree(
 83        path!("/project"),
 84        json!({
 85            "main.rs": "First line\nSecond line\nThird line\nFourth line",
 86        }),
 87    )
 88    .await;
 89
 90    let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
 91    let workspace = init_test_workspace(&project, cx).await;
 92    let cx = &mut VisualTestContext::from_window(*workspace, cx);
 93    // Set up handlers for sessions spawned via modal.
 94    let _initialize_subscription =
 95        project::debugger::test::intercept_debug_sessions(cx, |client| {
 96            client.on_request::<dap::requests::Attach, _>(move |_, args| {
 97                let raw = &args.raw;
 98                assert_eq!(raw["request"], "attach");
 99                assert_eq!(raw["process_id"], 1);
100
101                Ok(())
102            });
103        });
104    let attach_modal = workspace
105        .update(cx, |workspace, window, cx| {
106            let workspace_handle = cx.weak_entity();
107            workspace.toggle_modal(window, cx, |window, cx| {
108                AttachModal::with_processes(
109                    workspace_handle,
110                    DebugTaskDefinition {
111                        adapter: FakeAdapter::ADAPTER_NAME.into(),
112
113                        request: dap::DebugRequest::Attach(AttachRequest::default()),
114                        label: "attach example".into(),
115                        initialize_args: None,
116                        tcp_connection: Some(TcpArgumentsTemplate::default()),
117                        stop_on_entry: None,
118                    },
119                    vec![
120                        Candidate {
121                            pid: 0,
122                            name: "fake-binary-1".into(),
123                            command: vec![],
124                        },
125                        Candidate {
126                            pid: 3,
127                            name: "real-binary-1".into(),
128                            command: vec![],
129                        },
130                        Candidate {
131                            pid: 1,
132                            name: "fake-binary-2".into(),
133                            command: vec![],
134                        },
135                    ]
136                    .into_iter()
137                    .collect(),
138                    true,
139                    window,
140                    cx,
141                )
142            });
143
144            workspace.active_modal::<AttachModal>(cx).unwrap()
145        })
146        .unwrap();
147
148    cx.run_until_parked();
149
150    // assert we got the expected processes
151    workspace
152        .update(cx, |_, window, cx| {
153            let names =
154                attach_modal.update(cx, |modal, cx| attach_modal::_process_names(&modal, cx));
155            // Initially all processes are visible.
156            assert_eq!(3, names.len());
157            attach_modal.update(cx, |this, cx| {
158                this.picker.update(cx, |this, cx| {
159                    this.set_query("fakb", window, cx);
160                })
161            })
162        })
163        .unwrap();
164    cx.run_until_parked();
165    // assert we got the expected processes
166    workspace
167        .update(cx, |_, _, cx| {
168            let names =
169                attach_modal.update(cx, |modal, cx| attach_modal::_process_names(&modal, cx));
170            // Initially all processes are visible.
171            assert_eq!(2, names.len());
172        })
173        .unwrap();
174    // select the only existing process
175    cx.dispatch_action(Confirm);
176
177    cx.run_until_parked();
178
179    // assert attach modal was dismissed
180    workspace
181        .update(cx, |workspace, _window, cx| {
182            assert!(workspace.active_modal::<AttachModal>(cx).is_none());
183        })
184        .unwrap();
185}