attach_modal.rs

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