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