1mod go_locator {
2 use collections::HashMap;
3 use dap::{DapLocator, adapters::DebugAdapterName};
4 use gpui::TestAppContext;
5 use project::debugger::locators::go::{DelveLaunchRequest, GoLocator};
6 use task::{HideStrategy, RevealStrategy, RevealTarget, Shell, TaskTemplate};
7 #[gpui::test]
8 async fn test_create_scenario_for_go_build(_: &mut TestAppContext) {
9 let locator = GoLocator;
10 let task = TaskTemplate {
11 label: "go build".into(),
12 command: "go".into(),
13 args: vec!["build".into(), ".".into()],
14 env: Default::default(),
15 cwd: Some("${ZED_WORKTREE_ROOT}".into()),
16 use_new_terminal: false,
17 allow_concurrent_runs: false,
18 reveal: RevealStrategy::Always,
19 reveal_target: RevealTarget::Dock,
20 hide: HideStrategy::Never,
21 shell: Shell::System,
22 tags: vec![],
23 show_summary: true,
24 show_command: true,
25 };
26
27 let scenario = locator
28 .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
29 .await;
30
31 assert!(scenario.is_none());
32 }
33
34 #[gpui::test]
35 async fn test_skip_non_go_commands_with_non_delve_adapter(_: &mut TestAppContext) {
36 let locator = GoLocator;
37 let task = TaskTemplate {
38 label: "cargo build".into(),
39 command: "cargo".into(),
40 args: vec!["build".into()],
41 env: Default::default(),
42 cwd: Some("${ZED_WORKTREE_ROOT}".into()),
43 use_new_terminal: false,
44 allow_concurrent_runs: false,
45 reveal: RevealStrategy::Always,
46 reveal_target: RevealTarget::Dock,
47 hide: HideStrategy::Never,
48 shell: Shell::System,
49 tags: vec![],
50 show_summary: true,
51 show_command: true,
52 };
53
54 let scenario = locator
55 .create_scenario(
56 &task,
57 "test label",
58 &DebugAdapterName("SomeOtherAdapter".into()),
59 )
60 .await;
61 assert!(scenario.is_none());
62
63 let scenario = locator
64 .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
65 .await;
66 assert!(scenario.is_none());
67 }
68 #[gpui::test]
69 async fn test_go_locator_run(_: &mut TestAppContext) {
70 let locator = GoLocator;
71 let delve = DebugAdapterName("Delve".into());
72
73 let task = TaskTemplate {
74 label: "go run with flags".into(),
75 command: "go".into(),
76 args: vec![
77 "run".to_string(),
78 "-race".to_string(),
79 "-ldflags".to_string(),
80 "-X main.version=1.0".to_string(),
81 "./cmd/myapp".to_string(),
82 "--config".to_string(),
83 "production.yaml".to_string(),
84 "--verbose".to_string(),
85 ],
86 env: {
87 let mut env = HashMap::default();
88 env.insert("GO_ENV".to_string(), "production".to_string());
89 env
90 },
91 cwd: Some("/project/root".into()),
92 ..Default::default()
93 };
94
95 let scenario = locator
96 .create_scenario(&task, "test run label", &delve)
97 .await
98 .unwrap();
99
100 let config: DelveLaunchRequest = serde_json::from_value(scenario.config).unwrap();
101
102 assert_eq!(
103 config,
104 DelveLaunchRequest {
105 request: "launch".to_string(),
106 mode: "debug".to_string(),
107 program: "./cmd/myapp".to_string(),
108 build_flags: vec![
109 "-race".to_string(),
110 "-ldflags".to_string(),
111 "-X main.version=1.0".to_string()
112 ],
113 args: vec![
114 "--config".to_string(),
115 "production.yaml".to_string(),
116 "--verbose".to_string(),
117 ],
118 env: {
119 let mut env = HashMap::default();
120 env.insert("GO_ENV".to_string(), "production".to_string());
121 env
122 },
123 cwd: Some("/project/root".to_string()),
124 }
125 );
126 }
127
128 #[gpui::test]
129 async fn test_go_locator_test(_: &mut TestAppContext) {
130 let locator = GoLocator;
131 let delve = DebugAdapterName("Delve".into());
132
133 // Test with tags and run flag
134 let task_with_tags = TaskTemplate {
135 label: "test".into(),
136 command: "go".into(),
137 args: vec![
138 "test".to_string(),
139 "-tags".to_string(),
140 "integration,unit".to_string(),
141 "-run".to_string(),
142 "Foo".to_string(),
143 ".".to_string(),
144 ],
145 ..Default::default()
146 };
147 let result = locator
148 .create_scenario(&task_with_tags, "", &delve)
149 .await
150 .unwrap();
151
152 let config: DelveLaunchRequest = serde_json::from_value(result.config).unwrap();
153
154 assert_eq!(
155 config,
156 DelveLaunchRequest {
157 request: "launch".to_string(),
158 mode: "test".to_string(),
159 program: ".".to_string(),
160 build_flags: vec!["-tags".to_string(), "integration,unit".to_string(),],
161 args: vec![
162 "-test.run".to_string(),
163 "Foo".to_string(),
164 "-test.v".to_string()
165 ],
166 env: Default::default(),
167 cwd: None,
168 }
169 );
170 }
171
172 #[gpui::test]
173 async fn test_skip_unsupported_go_commands(_: &mut TestAppContext) {
174 let locator = GoLocator;
175 let task = TaskTemplate {
176 label: "go clean".into(),
177 command: "go".into(),
178 args: vec!["clean".into()],
179 env: Default::default(),
180 cwd: Some("${ZED_WORKTREE_ROOT}".into()),
181 use_new_terminal: false,
182 allow_concurrent_runs: false,
183 reveal: RevealStrategy::Always,
184 reveal_target: RevealTarget::Dock,
185 hide: HideStrategy::Never,
186 shell: Shell::System,
187 tags: vec![],
188 show_summary: true,
189 show_command: true,
190 };
191
192 let scenario = locator
193 .create_scenario(&task, "test label", &DebugAdapterName("Delve".into()))
194 .await;
195 assert!(scenario.is_none());
196 }
197}
198
199mod python_locator {
200 use dap::{DapLocator, adapters::DebugAdapterName};
201 use serde_json::json;
202
203 use project::debugger::locators::python::*;
204 use task::{DebugScenario, TaskTemplate};
205
206 #[gpui::test]
207 async fn test_python_locator() {
208 let adapter = DebugAdapterName("Debugpy".into());
209 let build_task = TaskTemplate {
210 label: "run module '$ZED_FILE'".into(),
211 command: "$ZED_CUSTOM_PYTHON_ACTIVE_ZED_TOOLCHAIN".into(),
212 args: vec!["-m".into(), "$ZED_CUSTOM_PYTHON_MODULE_NAME".into()],
213 env: Default::default(),
214 cwd: Some("$ZED_WORKTREE_ROOT".into()),
215 use_new_terminal: false,
216 allow_concurrent_runs: false,
217 reveal: task::RevealStrategy::Always,
218 reveal_target: task::RevealTarget::Dock,
219 hide: task::HideStrategy::Never,
220 tags: vec!["python-module-main-method".into()],
221 shell: task::Shell::System,
222 show_summary: false,
223 show_command: false,
224 };
225
226 let expected_scenario = DebugScenario {
227 adapter: "Debugpy".into(),
228 label: "run module 'main.py'".into(),
229 build: None,
230 config: json!({
231 "request": "launch",
232 "python": "$ZED_CUSTOM_PYTHON_ACTIVE_ZED_TOOLCHAIN",
233 "args": [],
234 "cwd": "$ZED_WORKTREE_ROOT",
235 "module": "$ZED_CUSTOM_PYTHON_MODULE_NAME",
236 }),
237 tcp_connection: None,
238 };
239
240 assert_eq!(
241 PythonLocator
242 .create_scenario(&build_task, "run module 'main.py'", &adapter)
243 .await
244 .expect("Failed to create a scenario"),
245 expected_scenario
246 );
247 }
248}
249
250mod memory {
251 use project::debugger::{
252 MemoryCell,
253 memory::{MemoryIterator, PageAddress, PageContents},
254 };
255
256 #[test]
257 fn iterate_over_unmapped_memory() {
258 let empty_iterator = MemoryIterator::new(0..=127, Default::default());
259 let actual = empty_iterator.collect::<Vec<_>>();
260 let expected = vec![MemoryCell(None); 128];
261 assert_eq!(actual.len(), expected.len());
262 assert_eq!(actual, expected);
263 }
264
265 #[test]
266 fn iterate_over_partially_mapped_memory() {
267 let it = MemoryIterator::new(
268 0..=127,
269 vec![(PageAddress(5), PageContents::mapped(vec![1]))].into_iter(),
270 );
271 let actual = it.collect::<Vec<_>>();
272 let expected = std::iter::repeat_n(MemoryCell(None), 5)
273 .chain(std::iter::once(MemoryCell(Some(1))))
274 .chain(std::iter::repeat_n(MemoryCell(None), 122))
275 .collect::<Vec<_>>();
276 assert_eq!(actual.len(), expected.len());
277 assert_eq!(actual, expected);
278 }
279
280 #[test]
281 fn reads_from_the_middle_of_a_page() {
282 let partial_iter = MemoryIterator::new(
283 20..=30,
284 vec![(PageAddress(0), PageContents::mapped((0..255).collect()))].into_iter(),
285 );
286 let actual = partial_iter.collect::<Vec<_>>();
287 let expected = (20..=30)
288 .map(|val| MemoryCell(Some(val)))
289 .collect::<Vec<_>>();
290 assert_eq!(actual.len(), expected.len());
291 assert_eq!(actual, expected);
292 }
293}