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