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