1use call::ActiveCall;
2use dap::DebugRequestType;
3use dap::requests::{Initialize, Launch, StackTrace};
4use dap::{SourceBreakpoint, requests::SetBreakpoints};
5use debugger_ui::debugger_panel::DebugPanel;
6use debugger_ui::session::DebugSession;
7use editor::Editor;
8use gpui::{Entity, TestAppContext, VisualTestContext};
9use project::{Project, ProjectPath, WorktreeId};
10use serde_json::json;
11use std::sync::Arc;
12use std::{
13 path::Path,
14 sync::atomic::{AtomicBool, Ordering},
15};
16use workspace::{Workspace, dock::Panel};
17
18use super::{TestClient, TestServer};
19
20pub fn init_test(cx: &mut gpui::TestAppContext) {
21 if std::env::var("RUST_LOG").is_ok() {
22 env_logger::try_init().ok();
23 }
24
25 cx.update(|cx| {
26 theme::init(theme::LoadThemes::JustBase, cx);
27 command_palette_hooks::init(cx);
28 language::init(cx);
29 workspace::init_settings(cx);
30 project::Project::init_settings(cx);
31 debugger_ui::init(cx);
32 editor::init(cx);
33 });
34}
35
36async fn add_debugger_panel(workspace: &Entity<Workspace>, cx: &mut VisualTestContext) {
37 let debugger_panel = workspace
38 .update_in(cx, |_workspace, window, cx| {
39 cx.spawn_in(window, DebugPanel::load)
40 })
41 .await
42 .unwrap();
43
44 workspace.update_in(cx, |workspace, window, cx| {
45 workspace.add_panel(debugger_panel, window, cx);
46 });
47}
48
49pub fn _active_session(
50 workspace: Entity<Workspace>,
51 cx: &mut VisualTestContext,
52) -> Entity<DebugSession> {
53 workspace.update_in(cx, |workspace, _window, cx| {
54 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
55 debug_panel
56 .update(cx, |this, cx| this.active_session(cx))
57 .unwrap()
58 })
59}
60
61struct ZedInstance<'a> {
62 client: TestClient,
63 project: Option<Entity<Project>>,
64 active_call: Entity<ActiveCall>,
65 cx: &'a mut TestAppContext,
66}
67
68impl<'a> ZedInstance<'a> {
69 fn new(client: TestClient, cx: &'a mut TestAppContext) -> Self {
70 ZedInstance {
71 project: None,
72 client,
73 active_call: cx.read(ActiveCall::global),
74 cx,
75 }
76 }
77
78 async fn host_project(
79 &mut self,
80 project_files: Option<serde_json::Value>,
81 ) -> (u64, WorktreeId) {
82 let (project, worktree_id) = self.client.build_local_project("/project", self.cx).await;
83 self.active_call
84 .update(self.cx, |call, cx| call.set_location(Some(&project), cx))
85 .await
86 .unwrap();
87
88 if let Some(tree) = project_files {
89 self.client.fs().insert_tree("/project", tree).await;
90 }
91
92 self.project = Some(project.clone());
93
94 let project_id = self
95 .active_call
96 .update(self.cx, |call, cx| call.share_project(project, cx))
97 .await
98 .unwrap();
99
100 (project_id, worktree_id)
101 }
102
103 async fn join_project(&mut self, project_id: u64) {
104 let remote_project = self.client.join_remote_project(project_id, self.cx).await;
105 self.project = Some(remote_project);
106
107 self.active_call
108 .update(self.cx, |call, cx| {
109 call.set_location(self.project.as_ref(), cx)
110 })
111 .await
112 .unwrap();
113 }
114
115 async fn expand(
116 &'a mut self,
117 ) -> (
118 &'a TestClient,
119 Entity<Workspace>,
120 Entity<Project>,
121 &'a mut VisualTestContext,
122 ) {
123 let (workspace, cx) = self.client.build_workspace(
124 self.project
125 .as_ref()
126 .expect("Project should be hosted or built before expanding"),
127 self.cx,
128 );
129 add_debugger_panel(&workspace, cx).await;
130 (&self.client, workspace, self.project.clone().unwrap(), cx)
131 }
132}
133
134async fn _setup_three_member_test<'a, 'b, 'c>(
135 server: &mut TestServer,
136 host_cx: &'a mut TestAppContext,
137 first_remote_cx: &'b mut TestAppContext,
138 second_remote_cx: &'c mut TestAppContext,
139) -> (ZedInstance<'a>, ZedInstance<'b>, ZedInstance<'c>) {
140 let host_client = server.create_client(host_cx, "user_host").await;
141 let first_remote_client = server.create_client(first_remote_cx, "user_remote_1").await;
142 let second_remote_client = server
143 .create_client(second_remote_cx, "user_remote_2")
144 .await;
145
146 init_test(host_cx);
147 init_test(first_remote_cx);
148 init_test(second_remote_cx);
149
150 server
151 .create_room(&mut [
152 (&host_client, host_cx),
153 (&first_remote_client, first_remote_cx),
154 (&second_remote_client, second_remote_cx),
155 ])
156 .await;
157
158 let host_zed = ZedInstance::new(host_client, host_cx);
159 let first_remote_zed = ZedInstance::new(first_remote_client, first_remote_cx);
160 let second_remote_zed = ZedInstance::new(second_remote_client, second_remote_cx);
161
162 (host_zed, first_remote_zed, second_remote_zed)
163}
164
165async fn setup_two_member_test<'a, 'b>(
166 server: &mut TestServer,
167 host_cx: &'a mut TestAppContext,
168 remote_cx: &'b mut TestAppContext,
169) -> (ZedInstance<'a>, ZedInstance<'b>) {
170 let host_client = server.create_client(host_cx, "user_host").await;
171 let remote_client = server.create_client(remote_cx, "user_remote").await;
172
173 init_test(host_cx);
174 init_test(remote_cx);
175
176 server
177 .create_room(&mut [(&host_client, host_cx), (&remote_client, remote_cx)])
178 .await;
179
180 let host_zed = ZedInstance::new(host_client, host_cx);
181 let remote_zed = ZedInstance::new(remote_client, remote_cx);
182
183 (host_zed, remote_zed)
184}
185
186#[gpui::test]
187async fn test_debug_panel_item_opens_on_remote(
188 host_cx: &mut TestAppContext,
189 remote_cx: &mut TestAppContext,
190) {
191 let executor = host_cx.executor();
192 let mut server = TestServer::start(executor).await;
193
194 let (mut host_zed, mut remote_zed) =
195 setup_two_member_test(&mut server, host_cx, remote_cx).await;
196
197 let (host_project_id, _) = host_zed.host_project(None).await;
198 remote_zed.join_project(host_project_id).await;
199
200 let (_client_host, _host_workspace, host_project, host_cx) = host_zed.expand().await;
201 let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
202
203 remote_cx.run_until_parked();
204
205 let task = host_project.update(host_cx, |project, cx| {
206 project.start_debug_session(dap::test_config(DebugRequestType::Launch, None, None), cx)
207 });
208
209 let session = task.await.unwrap();
210 let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
211
212 client
213 .on_request::<Initialize, _>(move |_, _| {
214 Ok(dap::Capabilities {
215 supports_step_back: Some(false),
216 ..Default::default()
217 })
218 })
219 .await;
220
221 client.on_request::<Launch, _>(move |_, _| Ok(())).await;
222
223 client
224 .on_request::<StackTrace, _>(move |_, _| {
225 Ok(dap::StackTraceResponse {
226 stack_frames: Vec::default(),
227 total_frames: None,
228 })
229 })
230 .await;
231
232 client
233 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
234 reason: dap::StoppedEventReason::Pause,
235 description: None,
236 thread_id: Some(1),
237 preserve_focus_hint: None,
238 text: None,
239 all_threads_stopped: None,
240 hit_breakpoint_ids: None,
241 }))
242 .await;
243
244 host_cx.run_until_parked();
245 remote_cx.run_until_parked();
246
247 remote_workspace.update(remote_cx, |workspace, cx| {
248 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
249 let _active_session = debug_panel
250 .update(cx, |this, cx| this.active_session(cx))
251 .unwrap();
252
253 assert_eq!(
254 1,
255 debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
256 );
257 // assert_eq!(client.id(), active_session.read(cx).());
258 // assert_eq!(1, active_session.read(cx).thread_id().0);
259 // todo(debugger) check selected thread id
260 });
261
262 let shutdown_client = host_project.update(host_cx, |project, cx| {
263 project.dap_store().update(cx, |dap_store, cx| {
264 dap_store.shutdown_session(session.read(cx).session_id(), cx)
265 })
266 });
267
268 shutdown_client.await.unwrap();
269}
270
271#[gpui::test]
272async fn test_active_debug_panel_item_set_on_join_project(
273 host_cx: &mut TestAppContext,
274 remote_cx: &mut TestAppContext,
275) {
276 let executor = host_cx.executor();
277 let mut server = TestServer::start(executor).await;
278
279 let (mut host_zed, mut remote_zed) =
280 setup_two_member_test(&mut server, host_cx, remote_cx).await;
281
282 let (host_project_id, _) = host_zed.host_project(None).await;
283
284 let (_client_host, _host_workspace, host_project, host_cx) = host_zed.expand().await;
285
286 host_cx.run_until_parked();
287
288 let task = host_project.update(host_cx, |project, cx| {
289 project.start_debug_session(dap::test_config(DebugRequestType::Launch, None, None), cx)
290 });
291
292 let session = task.await.unwrap();
293 let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
294
295 client
296 .on_request::<Initialize, _>(move |_, _| {
297 Ok(dap::Capabilities {
298 supports_step_back: Some(false),
299 ..Default::default()
300 })
301 })
302 .await;
303
304 client.on_request::<Launch, _>(move |_, _| Ok(())).await;
305
306 client
307 .on_request::<StackTrace, _>(move |_, _| {
308 Ok(dap::StackTraceResponse {
309 stack_frames: Vec::default(),
310 total_frames: None,
311 })
312 })
313 .await;
314
315 client
316 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
317 reason: dap::StoppedEventReason::Pause,
318 description: None,
319 thread_id: Some(1),
320 preserve_focus_hint: None,
321 text: None,
322 all_threads_stopped: None,
323 hit_breakpoint_ids: None,
324 }))
325 .await;
326
327 // Give host_client time to send a debug panel item to collab server
328 host_cx.run_until_parked();
329
330 remote_zed.join_project(host_project_id).await;
331 let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
332
333 host_cx.run_until_parked();
334 remote_cx.run_until_parked();
335
336 remote_workspace.update(remote_cx, |workspace, cx| {
337 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
338 let _active_session = debug_panel
339 .update(cx, |this, cx| this.active_session(cx))
340 .unwrap();
341
342 assert_eq!(
343 1,
344 debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
345 );
346 // assert_eq!(cl, active_session.read(cx).client_id());
347 // assert_eq!(1, active_session.read(cx).thread_id().0);
348 // todo(debugger)
349 });
350
351 let shutdown_client = host_project.update(host_cx, |project, cx| {
352 project.dap_store().update(cx, |dap_store, cx| {
353 dap_store.shutdown_session(session.read(cx).session_id(), cx)
354 })
355 });
356
357 shutdown_client.await.unwrap();
358
359 remote_cx.run_until_parked();
360
361 // assert we don't have a debug panel item anymore because the client shutdown
362 remote_workspace.update(remote_cx, |workspace, cx| {
363 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
364
365 debug_panel.update(cx, |this, cx| {
366 assert!(this.active_session(cx).is_none());
367 assert_eq!(0, this.pane().unwrap().read(cx).items_len());
368 });
369 });
370}
371
372#[gpui::test]
373async fn test_debug_panel_remote_button_presses(
374 _host_cx: &mut TestAppContext,
375 _remote_cx: &mut TestAppContext,
376) {
377 unimplemented!("Collab is still being refactored");
378 // let executor = host_cx.executor();
379 // let mut server = TestServer::start(executor).await;
380
381 // let (mut host_zed, mut remote_zed) =
382 // setup_two_member_test(&mut server, host_cx, remote_cx).await;
383
384 // let (host_project_id, _) = host_zed.host_project(None).await;
385 // remote_zed.join_project(host_project_id).await;
386
387 // let (_client_host, host_workspace, host_project, host_cx) = host_zed.expand().await;
388 // let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
389
390 // let task = host_project.update(host_cx, |project, cx| {
391 // project.start_debug_session(dap::test_config(None), cx)
392 // });
393
394 // let session = task.await.unwrap();
395 // let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
396
397 // client
398 // .on_request::<Initialize, _>(move |_, _| {
399 // Ok(dap::Capabilities {
400 // supports_step_back: Some(true),
401 // ..Default::default()
402 // })
403 // })
404 // .await;
405
406 // client.on_request::<Launch, _>(move |_, _| Ok(())).await;
407
408 // client
409 // .on_request::<StackTrace, _>(move |_, _| {
410 // Ok(dap::StackTraceResponse {
411 // stack_frames: Vec::default(),
412 // total_frames: None,
413 // })
414 // })
415 // .await;
416
417 // client
418 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
419 // reason: dap::StoppedEventReason::Pause,
420 // description: None,
421 // thread_id: Some(1),
422 // preserve_focus_hint: None,
423 // text: None,
424 // all_threads_stopped: None,
425 // hit_breakpoint_ids: None,
426 // }))
427 // .await;
428
429 // client
430 // .on_request::<dap::requests::Continue, _>(move |_, _| {
431 // Ok(dap::ContinueResponse {
432 // all_threads_continued: Some(true),
433 // })
434 // })
435 // .await;
436
437 // host_cx.run_until_parked();
438 // remote_cx.run_until_parked();
439
440 // let remote_debug_item = remote_workspace.update(remote_cx, |workspace, cx| {
441 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
442 // let active_session = debug_panel
443 // .update(cx, |this, cx| this.active_session(cx))
444 // .unwrap();
445
446 // assert_eq!(
447 // 1,
448 // debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
449 // );
450 // // assert_eq!(client.id(), active_session.read(cx).client_id());
451 // // assert_eq!(1, active_session.read(cx).thread_id().0);
452 // // todo(debugger)
453 // active_session
454 // });
455
456 // let local_debug_item = host_workspace.update(host_cx, |workspace, cx| {
457 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
458 // let active_session = debug_panel
459 // .update(cx, |this, cx| this.active_session(cx))
460 // .unwrap();
461
462 // assert_eq!(
463 // 1,
464 // debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
465 // );
466 // // assert_eq!(client.id(), active_session.read(cx).client_id());
467 // // assert_eq!(1, active_session.read(cx).thread_id().0);
468 // // todo(debugger)
469 // active_session
470 // });
471
472 // remote_debug_item.update(remote_cx, |this, cx| {
473 // this.continue_thread(cx);
474 // });
475
476 // host_cx.run_until_parked();
477 // remote_cx.run_until_parked();
478
479 // local_debug_item.update(host_cx, |debug_panel_item, cx| {
480 // assert_eq!(
481 // debugger_ui::debugger_panel::ThreadStatus::Running,
482 // debug_panel_item.thread_state().read(cx).status,
483 // );
484 // });
485
486 // remote_debug_item.update(remote_cx, |debug_panel_item, cx| {
487 // assert_eq!(
488 // debugger_ui::debugger_panel::ThreadStatus::Running,
489 // debug_panel_item.thread_state().read(cx).status,
490 // );
491 // });
492
493 // client
494 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
495 // reason: dap::StoppedEventReason::Pause,
496 // description: None,
497 // thread_id: Some(1),
498 // preserve_focus_hint: None,
499 // text: None,
500 // all_threads_stopped: None,
501 // hit_breakpoint_ids: None,
502 // }))
503 // .await;
504
505 // client
506 // .on_request::<StackTrace, _>(move |_, _| {
507 // Ok(dap::StackTraceResponse {
508 // stack_frames: Vec::default(),
509 // total_frames: None,
510 // })
511 // })
512 // .await;
513
514 // host_cx.run_until_parked();
515 // remote_cx.run_until_parked();
516
517 // local_debug_item.update(host_cx, |debug_panel_item, cx| {
518 // assert_eq!(
519 // debugger_ui::debugger_panel::ThreadStatus::Stopped,
520 // debug_panel_item.thread_state().read(cx).status,
521 // );
522 // });
523
524 // remote_debug_item.update(remote_cx, |debug_panel_item, cx| {
525 // assert_eq!(
526 // debugger_ui::debugger_panel::ThreadStatus::Stopped,
527 // debug_panel_item.thread_state().read(cx).status,
528 // );
529 // });
530
531 // client
532 // .on_request::<dap::requests::Continue, _>(move |_, _| {
533 // Ok(dap::ContinueResponse {
534 // all_threads_continued: Some(true),
535 // })
536 // })
537 // .await;
538
539 // local_debug_item.update(host_cx, |this, cx| {
540 // this.continue_thread(cx);
541 // });
542
543 // host_cx.run_until_parked();
544 // remote_cx.run_until_parked();
545
546 // local_debug_item.update(host_cx, |debug_panel_item, cx| {
547 // assert_eq!(
548 // debugger_ui::debugger_panel::ThreadStatus::Running,
549 // debug_panel_item.thread_state().read(cx).status,
550 // );
551 // });
552
553 // remote_debug_item.update(remote_cx, |debug_panel_item, cx| {
554 // assert_eq!(
555 // debugger_ui::debugger_panel::ThreadStatus::Running,
556 // debug_panel_item.thread_state().read(cx).status,
557 // );
558 // });
559
560 // client
561 // .on_request::<dap::requests::Pause, _>(move |_, _| Ok(()))
562 // .await;
563
564 // client
565 // .on_request::<StackTrace, _>(move |_, _| {
566 // Ok(dap::StackTraceResponse {
567 // stack_frames: Vec::default(),
568 // total_frames: None,
569 // })
570 // })
571 // .await;
572
573 // client
574 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
575 // reason: dap::StoppedEventReason::Pause,
576 // description: None,
577 // thread_id: Some(1),
578 // preserve_focus_hint: None,
579 // text: None,
580 // all_threads_stopped: None,
581 // hit_breakpoint_ids: None,
582 // }))
583 // .await;
584
585 // remote_debug_item.update(remote_cx, |this, cx| {
586 // this.pause_thread(cx);
587 // });
588
589 // remote_cx.run_until_parked();
590 // host_cx.run_until_parked();
591
592 // client
593 // .on_request::<dap::requests::StepOut, _>(move |_, _| Ok(()))
594 // .await;
595
596 // remote_debug_item.update(remote_cx, |this, cx| {
597 // this.step_out(cx);
598 // });
599
600 // client
601 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
602 // reason: dap::StoppedEventReason::Pause,
603 // description: None,
604 // thread_id: Some(1),
605 // preserve_focus_hint: None,
606 // text: None,
607 // all_threads_stopped: None,
608 // hit_breakpoint_ids: None,
609 // }))
610 // .await;
611
612 // remote_cx.run_until_parked();
613 // host_cx.run_until_parked();
614
615 // client
616 // .on_request::<dap::requests::Next, _>(move |_, _| Ok(()))
617 // .await;
618
619 // remote_debug_item.update(remote_cx, |this, cx| {
620 // this.step_over(cx);
621 // });
622
623 // client
624 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
625 // reason: dap::StoppedEventReason::Pause,
626 // description: None,
627 // thread_id: Some(1),
628 // preserve_focus_hint: None,
629 // text: None,
630 // all_threads_stopped: None,
631 // hit_breakpoint_ids: None,
632 // }))
633 // .await;
634
635 // remote_cx.run_until_parked();
636 // host_cx.run_until_parked();
637
638 // client
639 // .on_request::<dap::requests::StepIn, _>(move |_, _| Ok(()))
640 // .await;
641
642 // remote_debug_item.update(remote_cx, |this, cx| {
643 // this.step_in(cx);
644 // });
645
646 // client
647 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
648 // reason: dap::StoppedEventReason::Pause,
649 // description: None,
650 // thread_id: Some(1),
651 // preserve_focus_hint: None,
652 // text: None,
653 // all_threads_stopped: None,
654 // hit_breakpoint_ids: None,
655 // }))
656 // .await;
657
658 // remote_cx.run_until_parked();
659 // host_cx.run_until_parked();
660
661 // client
662 // .on_request::<dap::requests::StepBack, _>(move |_, _| Ok(()))
663 // .await;
664
665 // remote_debug_item.update(remote_cx, |this, cx| {
666 // this.step_back(cx);
667 // });
668
669 // client
670 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
671 // reason: dap::StoppedEventReason::Pause,
672 // description: None,
673 // thread_id: Some(1),
674 // preserve_focus_hint: None,
675 // text: None,
676 // all_threads_stopped: None,
677 // hit_breakpoint_ids: None,
678 // }))
679 // .await;
680
681 // remote_cx.run_until_parked();
682 // host_cx.run_until_parked();
683
684 // remote_debug_item.update(remote_cx, |this, cx| {
685 // this.stop_thread(cx);
686 // });
687
688 // host_cx.run_until_parked();
689 // remote_cx.run_until_parked();
690
691 // // assert we don't have a debug panel item anymore because the client shutdown
692 // remote_workspace.update(remote_cx, |workspace, cx| {
693 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
694
695 // debug_panel.update(cx, |this, cx| {
696 // assert!(this.active_session(cx).is_none());
697 // assert_eq!(0, this.pane().unwrap().read(cx).items_len());
698 // });
699 // });
700}
701
702#[gpui::test]
703async fn test_restart_stack_frame(_host_cx: &mut TestAppContext, _remote_cx: &mut TestAppContext) {
704 unimplemented!("Collab is still being refactored");
705 // let executor = host_cx.executor();
706 // let mut server = TestServer::start(executor).await;
707
708 // let (mut host_zed, mut remote_zed) =
709 // setup_two_member_test(&mut server, host_cx, remote_cx).await;
710
711 // let (host_project_id, _) = host_zed.host_project(None).await;
712 // remote_zed.join_project(host_project_id).await;
713
714 // let (_client_host, _host_workspace, host_project, host_cx) = host_zed.expand().await;
715 // let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
716
717 // let called_restart_frame = Arc::new(AtomicBool::new(false));
718
719 // let task = host_project.update(host_cx, |project, cx| {
720 // project.start_debug_session(dap::test_config(None), cx)
721 // });
722
723 // let session = task.await.unwrap();
724 // let client = session.read(cx).adapter_client().unwrap();
725
726 // client
727 // .on_request::<Initialize, _>(move |_, _| {
728 // Ok(dap::Capabilities {
729 // supports_restart_frame: Some(true),
730 // ..Default::default()
731 // })
732 // })
733 // .await;
734
735 // client.on_request::<Launch, _>(move |_, _| Ok(())).await;
736
737 // let stack_frames = vec![StackFrame {
738 // id: 1,
739 // name: "Stack Frame 1".into(),
740 // source: Some(dap::Source {
741 // name: Some("test.js".into()),
742 // path: Some("/project/src/test.js".into()),
743 // source_reference: None,
744 // presentation_hint: None,
745 // origin: None,
746 // sources: None,
747 // adapter_data: None,
748 // checksums: None,
749 // }),
750 // line: 3,
751 // column: 1,
752 // end_line: None,
753 // end_column: None,
754 // can_restart: None,
755 // instruction_pointer_reference: None,
756 // module_id: None,
757 // presentation_hint: None,
758 // }];
759
760 // client
761 // .on_request::<StackTrace, _>({
762 // let stack_frames = Arc::new(stack_frames.clone());
763 // move |_, args| {
764 // assert_eq!(1, args.thread_id);
765
766 // Ok(dap::StackTraceResponse {
767 // stack_frames: (*stack_frames).clone(),
768 // total_frames: None,
769 // })
770 // }
771 // })
772 // .await;
773
774 // client
775 // .on_request::<RestartFrame, _>({
776 // let called_restart_frame = called_restart_frame.clone();
777 // move |_, args| {
778 // assert_eq!(1, args.frame_id);
779
780 // called_restart_frame.store(true, Ordering::SeqCst);
781
782 // Ok(())
783 // }
784 // })
785 // .await;
786
787 // client
788 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
789 // reason: dap::StoppedEventReason::Pause,
790 // description: None,
791 // thread_id: Some(1),
792 // preserve_focus_hint: None,
793 // text: None,
794 // all_threads_stopped: None,
795 // hit_breakpoint_ids: None,
796 // }))
797 // .await;
798
799 // host_cx.run_until_parked();
800 // remote_cx.run_until_parked();
801
802 // // try to restart stack frame 1 from the guest side
803 // remote_workspace.update(remote_cx, |workspace, cx| {
804 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
805 // let active_session = debug_panel
806 // .update(cx, |this, cx| this.active_session(cx))
807 // .unwrap();
808
809 // active_session.update(cx, |debug_panel_item, cx| {
810 // debug_panel_item
811 // .stack_frame_list()
812 // .update(cx, |stack_frame_list, cx| {
813 // stack_frame_list.restart_stack_frame(1, cx);
814 // });
815 // });
816 // });
817
818 // host_cx.run_until_parked();
819 // remote_cx.run_until_parked();
820
821 // assert!(
822 // called_restart_frame.load(std::sync::atomic::Ordering::SeqCst),
823 // "Restart stack frame was not called"
824 // );
825
826 // let shutdown_client = host_project.update(host_cx, |project, cx| {
827 // project.dap_store().update(cx, |dap_store, cx| {
828 // dap_store.shutdown_session(&session.read(cx).session_id(), cx)
829 // })
830 // });
831
832 // shutdown_client.await.unwrap();
833}
834
835#[gpui::test]
836async fn test_updated_breakpoints_send_to_dap(
837 host_cx: &mut TestAppContext,
838 remote_cx: &mut TestAppContext,
839) {
840 let executor = host_cx.executor();
841 let mut server = TestServer::start(executor).await;
842
843 let (mut host_zed, mut remote_zed) =
844 setup_two_member_test(&mut server, host_cx, remote_cx).await;
845
846 let (host_project_id, worktree_id) = host_zed
847 .host_project(Some(json!({"test.txt": "one\ntwo\nthree\nfour\nfive"})))
848 .await;
849
850 remote_zed.join_project(host_project_id).await;
851
852 let (_client_host, host_workspace, host_project, host_cx) = host_zed.expand().await;
853 let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
854
855 let project_path = ProjectPath {
856 worktree_id,
857 path: Arc::from(Path::new(&"test.txt")),
858 };
859
860 let task = host_project.update(host_cx, |project, cx| {
861 project.start_debug_session(dap::test_config(DebugRequestType::Launch, None, None), cx)
862 });
863
864 let session = task.await.unwrap();
865 let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
866
867 client
868 .on_request::<Initialize, _>(move |_, _| {
869 Ok(dap::Capabilities {
870 supports_restart_frame: Some(true),
871 ..Default::default()
872 })
873 })
874 .await;
875
876 client.on_request::<Launch, _>(move |_, _| Ok(())).await;
877 client
878 .on_request::<StackTrace, _>(move |_, _| {
879 Ok(dap::StackTraceResponse {
880 stack_frames: Vec::default(),
881 total_frames: None,
882 })
883 })
884 .await;
885
886 let called_set_breakpoints = Arc::new(AtomicBool::new(false));
887 client
888 .on_request::<SetBreakpoints, _>({
889 let called_set_breakpoints = called_set_breakpoints.clone();
890 move |_, args| {
891 assert_eq!("/project/test.txt", args.source.path.unwrap());
892 assert_eq!(
893 vec![SourceBreakpoint {
894 line: 3,
895 column: None,
896 condition: None,
897 hit_condition: None,
898 log_message: None,
899 mode: None
900 }],
901 args.breakpoints.unwrap()
902 );
903 // assert!(!args.source_modified.unwrap());
904 // todo(debugger): Implement source_modified handling
905
906 called_set_breakpoints.store(true, Ordering::SeqCst);
907
908 Ok(dap::SetBreakpointsResponse {
909 breakpoints: Vec::default(),
910 })
911 }
912 })
913 .await;
914
915 client
916 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
917 reason: dap::StoppedEventReason::Pause,
918 description: None,
919 thread_id: Some(1),
920 preserve_focus_hint: None,
921 text: None,
922 all_threads_stopped: None,
923 hit_breakpoint_ids: None,
924 }))
925 .await;
926
927 host_cx.run_until_parked();
928 remote_cx.run_until_parked();
929
930 // Client B opens an editor.
931 let editor_b = remote_workspace
932 .update_in(remote_cx, |workspace, window, cx| {
933 workspace.open_path(project_path.clone(), None, true, window, cx)
934 })
935 .await
936 .unwrap()
937 .downcast::<Editor>()
938 .unwrap();
939
940 editor_b.update_in(remote_cx, |editor, window, cx| {
941 editor.move_down(&editor::actions::MoveDown, window, cx);
942 editor.move_down(&editor::actions::MoveDown, window, cx);
943 editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
944 });
945
946 // Client A opens an editor.
947 let editor_a = host_workspace
948 .update_in(host_cx, |workspace, window, cx| {
949 workspace.open_path(project_path.clone(), None, true, window, cx)
950 })
951 .await
952 .unwrap()
953 .downcast::<Editor>()
954 .unwrap();
955
956 host_cx.run_until_parked();
957 remote_cx.run_until_parked();
958
959 let called_set_breakpoints = Arc::new(AtomicBool::new(false));
960 client
961 .on_request::<SetBreakpoints, _>({
962 let called_set_breakpoints = called_set_breakpoints.clone();
963 move |_, args| {
964 assert_eq!("/project/test.txt", args.source.path.unwrap());
965 assert!(args.breakpoints.unwrap().is_empty());
966 // assert!(!args.source_modified.unwrap());
967 // todo(debugger) Implement source modified support
968
969 called_set_breakpoints.store(true, Ordering::SeqCst);
970
971 Ok(dap::SetBreakpointsResponse {
972 breakpoints: Vec::default(),
973 })
974 }
975 })
976 .await;
977
978 // remove the breakpoint that client B added
979 editor_a.update_in(host_cx, |editor, window, cx| {
980 editor.move_down(&editor::actions::MoveDown, window, cx);
981 editor.move_down(&editor::actions::MoveDown, window, cx);
982 editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
983 });
984
985 host_cx.run_until_parked();
986 remote_cx.run_until_parked();
987
988 assert!(
989 called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
990 "SetBreakpoint request must be called"
991 );
992
993 let called_set_breakpoints = Arc::new(AtomicBool::new(false));
994 client
995 .on_request::<SetBreakpoints, _>({
996 let called_set_breakpoints = called_set_breakpoints.clone();
997 move |_, args| {
998 assert_eq!("/project/test.txt", args.source.path.unwrap());
999 let mut breakpoints = args.breakpoints.unwrap();
1000 breakpoints.sort_by_key(|b| b.line);
1001 assert_eq!(
1002 vec![
1003 SourceBreakpoint {
1004 line: 2,
1005 column: None,
1006 condition: None,
1007 hit_condition: None,
1008 log_message: None,
1009 mode: None
1010 },
1011 SourceBreakpoint {
1012 line: 3,
1013 column: None,
1014 condition: None,
1015 hit_condition: None,
1016 log_message: None,
1017 mode: None
1018 }
1019 ],
1020 breakpoints
1021 );
1022 // assert!(!args.source_modified.unwrap());
1023 // todo(debugger) Implement source modified support
1024
1025 called_set_breakpoints.store(true, Ordering::SeqCst);
1026
1027 Ok(dap::SetBreakpointsResponse {
1028 breakpoints: Vec::default(),
1029 })
1030 }
1031 })
1032 .await;
1033
1034 // Add our own breakpoint now
1035 editor_a.update_in(host_cx, |editor, window, cx| {
1036 editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
1037 editor.move_up(&editor::actions::MoveUp, window, cx);
1038 editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
1039 });
1040
1041 host_cx.run_until_parked();
1042 remote_cx.run_until_parked();
1043
1044 assert!(
1045 called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
1046 "SetBreakpoint request must be called"
1047 );
1048
1049 let shutdown_client = host_project.update(host_cx, |project, cx| {
1050 project.dap_store().update(cx, |dap_store, cx| {
1051 dap_store.shutdown_session(session.read(cx).session_id(), cx)
1052 })
1053 });
1054
1055 shutdown_client.await.unwrap();
1056}
1057
1058#[gpui::test]
1059async fn test_module_list(
1060 _host_cx: &mut TestAppContext,
1061 _remote_cx: &mut TestAppContext,
1062 _late_join_cx: &mut TestAppContext,
1063) {
1064 unimplemented!("Collab is still being refactored");
1065 // let executor = host_cx.executor();
1066 // let mut server = TestServer::start(executor).await;
1067
1068 // let (mut host_zed, mut remote_zed, mut late_join_zed) =
1069 // setup_three_member_test(&mut server, host_cx, remote_cx, late_join_cx).await;
1070
1071 // let (host_project_id, _worktree_id) = host_zed.host_project(None).await;
1072
1073 // remote_zed.join_project(host_project_id).await;
1074
1075 // let (_client_host, host_workspace, host_project, host_cx) = host_zed.expand().await;
1076 // let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
1077
1078 // let task = host_project.update(host_cx, |project, cx| {
1079 // project.start_debug_session(dap::test_config(None), cx)
1080 // });
1081
1082 // let session = task.await.unwrap();
1083 // let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
1084
1085 // let called_initialize = Arc::new(AtomicBool::new(false));
1086
1087 // client
1088 // .on_request::<Initialize, _>({
1089 // let called_initialize = called_initialize.clone();
1090 // move |_, _| {
1091 // called_initialize.store(true, Ordering::SeqCst);
1092 // Ok(dap::Capabilities {
1093 // supports_restart_frame: Some(true),
1094 // supports_modules_request: Some(true),
1095 // ..Default::default()
1096 // })
1097 // }
1098 // })
1099 // .await;
1100
1101 // client.on_request::<Launch, _>(move |_, _| Ok(())).await;
1102 // client
1103 // .on_request::<StackTrace, _>(move |_, _| {
1104 // Ok(dap::StackTraceResponse {
1105 // stack_frames: Vec::default(),
1106 // total_frames: None,
1107 // })
1108 // })
1109 // .await;
1110
1111 // let called_modules = Arc::new(AtomicBool::new(false));
1112 // let modules = vec![
1113 // dap::Module {
1114 // id: dap::ModuleId::Number(1),
1115 // name: "First Module".into(),
1116 // address_range: None,
1117 // date_time_stamp: None,
1118 // path: None,
1119 // symbol_file_path: None,
1120 // symbol_status: None,
1121 // version: None,
1122 // is_optimized: None,
1123 // is_user_code: None,
1124 // },
1125 // dap::Module {
1126 // id: dap::ModuleId::Number(2),
1127 // name: "Second Module".into(),
1128 // address_range: None,
1129 // date_time_stamp: None,
1130 // path: None,
1131 // symbol_file_path: None,
1132 // symbol_status: None,
1133 // version: None,
1134 // is_optimized: None,
1135 // is_user_code: None,
1136 // },
1137 // ];
1138
1139 // client
1140 // .on_request::<dap::requests::Modules, _>({
1141 // let called_modules = called_modules.clone();
1142 // let modules = modules.clone();
1143 // move |_, _| unsafe {
1144 // static mut REQUEST_COUNT: i32 = 1;
1145 // assert_eq!(
1146 // 1, REQUEST_COUNT,
1147 // "This request should only be called once from the host"
1148 // );
1149 // REQUEST_COUNT += 1;
1150 // called_modules.store(true, Ordering::SeqCst);
1151
1152 // Ok(dap::ModulesResponse {
1153 // modules: modules.clone(),
1154 // total_modules: Some(2u64),
1155 // })
1156 // }
1157 // })
1158 // .await;
1159
1160 // host_cx.run_until_parked();
1161 // remote_cx.run_until_parked();
1162
1163 // assert!(
1164 // called_initialize.load(std::sync::atomic::Ordering::SeqCst),
1165 // "Request Initialize must be called"
1166 // );
1167
1168 // client
1169 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1170 // reason: dap::StoppedEventReason::Pause,
1171 // description: None,
1172 // thread_id: Some(1),
1173 // preserve_focus_hint: None,
1174 // text: None,
1175 // all_threads_stopped: None,
1176 // hit_breakpoint_ids: None,
1177 // }))
1178 // .await;
1179
1180 // host_cx.run_until_parked();
1181 // remote_cx.run_until_parked();
1182
1183 // assert!(
1184 // called_modules.load(std::sync::atomic::Ordering::SeqCst),
1185 // "Request Modules must be called"
1186 // );
1187
1188 // host_workspace.update(host_cx, |workspace, cx| {
1189 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1190 // let debug_panel_item = debug_panel
1191 // .update(cx, |this, cx| this.active_session(cx))
1192 // .unwrap();
1193
1194 // debug_panel_item.update(cx, |item, cx| {
1195 // assert_eq!(
1196 // true,
1197 // item.capabilities(cx).supports_modules_request.unwrap(),
1198 // "Local supports modules request should be true"
1199 // );
1200
1201 // let local_module_list = item.module_list().update(cx, |list, cx| list.modules(cx));
1202
1203 // assert_eq!(
1204 // 2usize,
1205 // local_module_list.len(),
1206 // "Local module list should have two items in it"
1207 // );
1208 // assert_eq!(
1209 // modules.clone(),
1210 // local_module_list,
1211 // "Local module list should match module list from response"
1212 // );
1213 // })
1214 // });
1215
1216 // remote_workspace.update(remote_cx, |workspace, cx| {
1217 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1218 // let debug_panel_item = debug_panel
1219 // .update(cx, |this, cx| this.active_session(cx))
1220 // .unwrap();
1221
1222 // debug_panel_item.update(cx, |item, cx| {
1223 // assert_eq!(
1224 // true,
1225 // item.capabilities(cx).supports_modules_request.unwrap(),
1226 // "Remote capabilities supports modules request should be true"
1227 // );
1228 // let remote_module_list = item.module_list().update(cx, |list, cx| list.modules(cx));
1229
1230 // assert_eq!(
1231 // 2usize,
1232 // remote_module_list.len(),
1233 // "Remote module list should have two items in it"
1234 // );
1235 // assert_eq!(
1236 // modules.clone(),
1237 // remote_module_list,
1238 // "Remote module list should match module list from response"
1239 // );
1240 // })
1241 // });
1242
1243 // late_join_zed.join_project(host_project_id).await;
1244 // let (_late_join_client, late_join_workspace, _late_join_project, late_join_cx) =
1245 // late_join_zed.expand().await;
1246
1247 // late_join_workspace.update(late_join_cx, |workspace, cx| {
1248 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1249 // let debug_panel_item = debug_panel
1250 // .update(cx, |this, cx| this.active_session(cx))
1251 // .unwrap();
1252
1253 // debug_panel_item.update(cx, |item, cx| {
1254 // assert_eq!(
1255 // true,
1256 // item.capabilities(cx).supports_modules_request.unwrap(),
1257 // "Remote (mid session join) capabilities supports modules request should be true"
1258 // );
1259 // let remote_module_list = item.module_list().update(cx, |list, cx| list.modules(cx));
1260
1261 // assert_eq!(
1262 // 2usize,
1263 // remote_module_list.len(),
1264 // "Remote (mid session join) module list should have two items in it"
1265 // );
1266 // assert_eq!(
1267 // modules.clone(),
1268 // remote_module_list,
1269 // "Remote (mid session join) module list should match module list from response"
1270 // );
1271 // })
1272 // });
1273
1274 // let shutdown_client = host_project.update(host_cx, |project, cx| {
1275 // project.dap_store().update(cx, |dap_store, cx| {
1276 // dap_store.shutdown_session(&session.read(cx).id(), cx)
1277 // })
1278 // });
1279
1280 // shutdown_client.await.unwrap();
1281}
1282
1283// #[gpui::test]
1284// async fn test_variable_list(
1285// host_cx: &mut TestAppContext,
1286// remote_cx: &mut TestAppContext,
1287// late_join_cx: &mut TestAppContext,
1288// ) {
1289// let executor = host_cx.executor();
1290// let mut server = TestServer::start(executor).await;
1291
1292// let (mut host_zed, mut remote_zed, mut late_join_zed) =
1293// setup_three_member_test(&mut server, host_cx, remote_cx, late_join_cx).await;
1294
1295// let (host_project_id, _worktree_id) = host_zed
1296// .host_project(Some(json!({"test.txt": "one\ntwo\nthree\nfour\nfive"})))
1297// .await;
1298
1299// remote_zed.join_project(host_project_id).await;
1300
1301// let (_client_host, host_workspace, host_project, host_cx) = host_zed.expand().await;
1302// let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
1303
1304// let task = host_project.update(host_cx, |project, cx| {
1305// project.start_debug_session(
1306// dap::DebugAdapterConfig {
1307// label: "test config".into(),
1308// kind: dap::DebugAdapterKind::Fake,
1309// request: dap::DebugRequestType::Launch,
1310// program: None,
1311// cwd: None,
1312// initialize_args: None,
1313// },
1314// cx,
1315// )
1316// });
1317
1318// let (session, client) = task.await.unwrap();
1319
1320// client
1321// .on_request::<Initialize, _>(move |_, _| {
1322// Ok(dap::Capabilities {
1323// supports_step_back: Some(true),
1324// ..Default::default()
1325// })
1326// })
1327// .await;
1328
1329// client.on_request::<Launch, _>(move |_, _| Ok(())).await;
1330
1331// let stack_frames = vec![dap::StackFrame {
1332// id: 1,
1333// name: "Stack Frame 1".into(),
1334// source: Some(dap::Source {
1335// name: Some("test.js".into()),
1336// path: Some("/project/src/test.js".into()),
1337// source_reference: None,
1338// presentation_hint: None,
1339// origin: None,
1340// sources: None,
1341// adapter_data: None,
1342// checksums: None,
1343// }),
1344// line: 1,
1345// column: 1,
1346// end_line: None,
1347// end_column: None,
1348// can_restart: None,
1349// instruction_pointer_reference: None,
1350// module_id: None,
1351// presentation_hint: None,
1352// }];
1353
1354// let scopes = vec![Scope {
1355// name: "Scope 1".into(),
1356// presentation_hint: None,
1357// variables_reference: 1,
1358// named_variables: None,
1359// indexed_variables: None,
1360// expensive: false,
1361// source: None,
1362// line: None,
1363// column: None,
1364// end_line: None,
1365// end_column: None,
1366// }];
1367
1368// let variable_1 = Variable {
1369// name: "variable 1".into(),
1370// value: "1".into(),
1371// type_: None,
1372// presentation_hint: None,
1373// evaluate_name: None,
1374// variables_reference: 2,
1375// named_variables: None,
1376// indexed_variables: None,
1377// memory_reference: None,
1378// };
1379
1380// let variable_2 = Variable {
1381// name: "variable 2".into(),
1382// value: "2".into(),
1383// type_: None,
1384// presentation_hint: None,
1385// evaluate_name: None,
1386// variables_reference: 3,
1387// named_variables: None,
1388// indexed_variables: None,
1389// memory_reference: None,
1390// };
1391
1392// let variable_3 = Variable {
1393// name: "variable 3".into(),
1394// value: "hello world".into(),
1395// type_: None,
1396// presentation_hint: None,
1397// evaluate_name: None,
1398// variables_reference: 4,
1399// named_variables: None,
1400// indexed_variables: None,
1401// memory_reference: None,
1402// };
1403
1404// let variable_4 = Variable {
1405// name: "variable 4".into(),
1406// value: "hello world this is the final variable".into(),
1407// type_: None,
1408// presentation_hint: None,
1409// evaluate_name: None,
1410// variables_reference: 0,
1411// named_variables: None,
1412// indexed_variables: None,
1413// memory_reference: None,
1414// };
1415
1416// client
1417// .on_request::<StackTrace, _>({
1418// let stack_frames = std::sync::Arc::new(stack_frames.clone());
1419// move |_, args| {
1420// assert_eq!(1, args.thread_id);
1421
1422// Ok(dap::StackTraceResponse {
1423// stack_frames: (*stack_frames).clone(),
1424// total_frames: None,
1425// })
1426// }
1427// })
1428// .await;
1429
1430// client
1431// .on_request::<Scopes, _>({
1432// let scopes = Arc::new(scopes.clone());
1433// move |_, args| {
1434// assert_eq!(1, args.frame_id);
1435
1436// Ok(dap::ScopesResponse {
1437// scopes: (*scopes).clone(),
1438// })
1439// }
1440// })
1441// .await;
1442
1443// let first_variable_request = vec![variable_1.clone(), variable_2.clone()];
1444
1445// client
1446// .on_request::<Variables, _>({
1447// move |_, args| {
1448// assert_eq!(1, args.variables_reference);
1449
1450// Ok(dap::VariablesResponse {
1451// variables: first_variable_request.clone(),
1452// })
1453// }
1454// })
1455// .await;
1456
1457// client
1458// .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1459// reason: dap::StoppedEventReason::Pause,
1460// description: None,
1461// thread_id: Some(1),
1462// preserve_focus_hint: None,
1463// text: None,
1464// all_threads_stopped: None,
1465// hit_breakpoint_ids: None,
1466// }))
1467// .await;
1468
1469// host_cx.run_until_parked();
1470// remote_cx.run_until_parked();
1471
1472// let local_debug_item = host_workspace.update(host_cx, |workspace, cx| {
1473// let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1474// let active_debug_panel_item = debug_panel
1475// .update(cx, |this, cx| this.active_debug_panel_item(cx))
1476// .unwrap();
1477
1478// assert_eq!(
1479// 1,
1480// debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
1481// );
1482// assert_eq!(client.id(), active_debug_panel_item.read(cx).client_id());
1483// assert_eq!(1, active_debug_panel_item.read(cx).thread_id());
1484// active_debug_panel_item
1485// });
1486
1487// let remote_debug_item = remote_workspace.update(remote_cx, |workspace, cx| {
1488// let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1489// let active_debug_panel_item = debug_panel
1490// .update(cx, |this, cx| this.active_debug_panel_item(cx))
1491// .unwrap();
1492
1493// assert_eq!(
1494// 1,
1495// debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
1496// );
1497// assert_eq!(client.id(), active_debug_panel_item.read(cx).client_id());
1498// assert_eq!(1, active_debug_panel_item.read(cx).thread_id());
1499// active_debug_panel_item
1500// });
1501
1502// let first_visual_entries = vec!["v Scope 1", " > variable 1", " > variable 2"];
1503// let first_variable_containers = vec![
1504// VariableContainer {
1505// container_reference: scopes[0].variables_reference,
1506// variable: variable_1.clone(),
1507// depth: 1,
1508// },
1509// VariableContainer {
1510// container_reference: scopes[0].variables_reference,
1511// variable: variable_2.clone(),
1512// depth: 1,
1513// },
1514// ];
1515
1516// local_debug_item
1517// .update(host_cx, |this, _| this.variable_list().clone())
1518// .update(host_cx, |variable_list, cx| {
1519// assert_eq!(1, variable_list.scopes().len());
1520// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1521// assert_eq!(&first_variable_containers, &variable_list.variables());
1522
1523// variable_list.assert_visual_entries(first_visual_entries.clone(), cx);
1524// });
1525
1526// client
1527// .on_request::<Variables, _>({
1528// let variables = Arc::new(vec![variable_3.clone()]);
1529// move |_, args| {
1530// assert_eq!(2, args.variables_reference);
1531
1532// Ok(dap::VariablesResponse {
1533// variables: (*variables).clone(),
1534// })
1535// }
1536// })
1537// .await;
1538
1539// remote_debug_item
1540// .update(remote_cx, |this, _| this.variable_list().clone())
1541// .update(remote_cx, |variable_list, cx| {
1542// assert_eq!(1, variable_list.scopes().len());
1543// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1544// assert_eq!(&first_variable_containers, &variable_list.variables());
1545
1546// variable_list.assert_visual_entries(first_visual_entries.clone(), cx);
1547
1548// variable_list.toggle_variable(&scopes[0], &variable_1, 1, cx);
1549// });
1550
1551// host_cx.run_until_parked();
1552// remote_cx.run_until_parked();
1553
1554// let second_req_variable_list = vec![
1555// VariableContainer {
1556// container_reference: scopes[0].variables_reference,
1557// variable: variable_1.clone(),
1558// depth: 1,
1559// },
1560// VariableContainer {
1561// container_reference: variable_1.variables_reference,
1562// variable: variable_3.clone(),
1563// depth: 2,
1564// },
1565// VariableContainer {
1566// container_reference: scopes[0].variables_reference,
1567// variable: variable_2.clone(),
1568// depth: 1,
1569// },
1570// ];
1571
1572// remote_debug_item
1573// .update(remote_cx, |this, _| this.variable_list().clone())
1574// .update(remote_cx, |variable_list, cx| {
1575// assert_eq!(1, variable_list.scopes().len());
1576// assert_eq!(3, variable_list.variables().len());
1577// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1578// assert_eq!(&second_req_variable_list, &variable_list.variables());
1579
1580// variable_list.assert_visual_entries(
1581// vec![
1582// "v Scope 1",
1583// " v variable 1",
1584// " > variable 3",
1585// " > variable 2",
1586// ],
1587// cx,
1588// );
1589// });
1590
1591// client
1592// .on_request::<Variables, _>({
1593// let variables = Arc::new(vec![variable_4.clone()]);
1594// move |_, args| {
1595// assert_eq!(3, args.variables_reference);
1596
1597// Ok(dap::VariablesResponse {
1598// variables: (*variables).clone(),
1599// })
1600// }
1601// })
1602// .await;
1603
1604// local_debug_item
1605// .update(host_cx, |this, _| this.variable_list().clone())
1606// .update(host_cx, |variable_list, cx| {
1607// assert_eq!(1, variable_list.scopes().len());
1608// assert_eq!(3, variable_list.variables().len());
1609// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1610// assert_eq!(&second_req_variable_list, &variable_list.variables());
1611
1612// variable_list.assert_visual_entries(first_visual_entries.clone(), cx);
1613
1614// variable_list.toggle_variable(&scopes[0], &variable_2.clone(), 1, cx);
1615// });
1616
1617// host_cx.run_until_parked();
1618// remote_cx.run_until_parked();
1619
1620// let final_variable_containers: Vec<VariableContainer> = vec![
1621// VariableContainer {
1622// container_reference: scopes[0].variables_reference,
1623// variable: variable_1.clone(),
1624// depth: 1,
1625// },
1626// VariableContainer {
1627// container_reference: variable_1.variables_reference,
1628// variable: variable_3.clone(),
1629// depth: 2,
1630// },
1631// VariableContainer {
1632// container_reference: scopes[0].variables_reference,
1633// variable: variable_2.clone(),
1634// depth: 1,
1635// },
1636// VariableContainer {
1637// container_reference: variable_2.variables_reference,
1638// variable: variable_4.clone(),
1639// depth: 2,
1640// },
1641// ];
1642
1643// remote_debug_item
1644// .update(remote_cx, |this, _| this.variable_list().clone())
1645// .update(remote_cx, |variable_list, cx| {
1646// assert_eq!(1, variable_list.scopes().len());
1647// assert_eq!(4, variable_list.variables().len());
1648// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1649// assert_eq!(&final_variable_containers, &variable_list.variables());
1650
1651// variable_list.assert_visual_entries(
1652// vec![
1653// "v Scope 1",
1654// " v variable 1",
1655// " > variable 3",
1656// " > variable 2",
1657// ],
1658// cx,
1659// );
1660// });
1661
1662// local_debug_item
1663// .update(host_cx, |this, _| this.variable_list().clone())
1664// .update(host_cx, |variable_list, cx| {
1665// assert_eq!(1, variable_list.scopes().len());
1666// assert_eq!(4, variable_list.variables().len());
1667// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1668// assert_eq!(&final_variable_containers, &variable_list.variables());
1669
1670// variable_list.assert_visual_entries(
1671// vec![
1672// "v Scope 1",
1673// " > variable 1",
1674// " v variable 2",
1675// " > variable 4",
1676// ],
1677// cx,
1678// );
1679// });
1680
1681// late_join_zed.join_project(host_project_id).await;
1682// let (_late_join_client, late_join_workspace, _late_join_project, late_join_cx) =
1683// late_join_zed.expand().await;
1684
1685// late_join_cx.run_until_parked();
1686
1687// let last_join_remote_item = late_join_workspace.update(late_join_cx, |workspace, cx| {
1688// let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1689// let active_debug_panel_item = debug_panel
1690// .update(cx, |this, cx| this.active_debug_panel_item(cx))
1691// .unwrap();
1692
1693// assert_eq!(
1694// 1,
1695// debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
1696// );
1697// assert_eq!(client.id(), active_debug_panel_item.read(cx).client_id());
1698// assert_eq!(1, active_debug_panel_item.read(cx).thread_id());
1699// active_debug_panel_item
1700// });
1701
1702// last_join_remote_item
1703// .update(late_join_cx, |this, _| this.variable_list().clone())
1704// .update(late_join_cx, |variable_list, cx| {
1705// assert_eq!(1, variable_list.scopes().len());
1706// assert_eq!(4, variable_list.variables().len());
1707// assert_eq!(scopes, variable_list.scopes().get(&1).unwrap().clone());
1708// assert_eq!(final_variable_containers, variable_list.variables());
1709
1710// variable_list.assert_visual_entries(first_visual_entries, cx);
1711// });
1712
1713// let shutdown_client = host_project.update(host_cx, |project, cx| {
1714// project.dap_store().update(cx, |dap_store, cx| {
1715// dap_store.shutdown_session(&session.read(cx).id(), cx)
1716// })
1717// });
1718
1719// shutdown_client.await.unwrap();
1720// }
1721
1722#[gpui::test]
1723async fn test_ignore_breakpoints(
1724 _host_cx: &mut TestAppContext,
1725 _remote_cx: &mut TestAppContext,
1726 _cx_c: &mut TestAppContext,
1727) {
1728 unimplemented!("Collab is still being refactored");
1729 // let executor = host_cx.executor();
1730 // let mut server = TestServer::start(executor).await;
1731
1732 // let (mut host_zed, mut remote_zed, mut late_join_zed) =
1733 // setup_three_member_test(&mut server, host_cx, remote_cx, cx_c).await;
1734
1735 // let (host_project_id, worktree_id) = host_zed
1736 // .host_project(Some(json!({"test.txt": "one\ntwo\nthree\nfour\nfive"})))
1737 // .await;
1738
1739 // remote_zed.join_project(host_project_id).await;
1740
1741 // let (_client_host, host_workspace, host_project, host_cx) = host_zed.expand().await;
1742 // let (_client_remote, remote_workspace, remote_project, remote_cx) = remote_zed.expand().await;
1743
1744 // let project_path = ProjectPath {
1745 // worktree_id,
1746 // path: Arc::from(Path::new(&"test.txt")),
1747 // };
1748
1749 // let local_editor = host_workspace
1750 // .update_in(host_cx, |workspace, window, cx| {
1751 // workspace.open_path(project_path.clone(), None, true, window, cx)
1752 // })
1753 // .await
1754 // .unwrap()
1755 // .downcast::<Editor>()
1756 // .unwrap();
1757
1758 // local_editor.update_in(host_cx, |editor, window, cx| {
1759 // editor.move_down(&editor::actions::MoveDown, window, cx);
1760 // editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx); // Line 2
1761 // editor.move_down(&editor::actions::MoveDown, window, cx);
1762 // editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
1763 // // Line 3
1764 // });
1765
1766 // host_cx.run_until_parked();
1767 // remote_cx.run_until_parked();
1768
1769 // let task = host_project.update(host_cx, |project, cx| {
1770 // project.start_debug_session(dap::test_config(None), cx)
1771 // });
1772
1773 // let session = task.await.unwrap();
1774 // let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
1775 // let client_id = client.id();
1776
1777 // client
1778 // .on_request::<Initialize, _>(move |_, _| {
1779 // Ok(dap::Capabilities {
1780 // supports_configuration_done_request: Some(true),
1781 // ..Default::default()
1782 // })
1783 // })
1784 // .await;
1785
1786 // let called_set_breakpoints = Arc::new(AtomicBool::new(false));
1787 // client
1788 // .on_request::<SetBreakpoints, _>({
1789 // let called_set_breakpoints = called_set_breakpoints.clone();
1790 // move |_, args| {
1791 // assert_eq!("/project/test.txt", args.source.path.unwrap());
1792
1793 // let mut actual_breakpoints = args.breakpoints.unwrap();
1794 // actual_breakpoints.sort_by_key(|b| b.line);
1795
1796 // let expected_breakpoints = vec![
1797 // SourceBreakpoint {
1798 // line: 2,
1799 // column: None,
1800 // condition: None,
1801 // hit_condition: None,
1802 // log_message: None,
1803 // mode: None,
1804 // },
1805 // SourceBreakpoint {
1806 // line: 3,
1807 // column: None,
1808 // condition: None,
1809 // hit_condition: None,
1810 // log_message: None,
1811 // mode: None,
1812 // },
1813 // ];
1814
1815 // assert_eq!(actual_breakpoints, expected_breakpoints);
1816
1817 // called_set_breakpoints.store(true, Ordering::SeqCst);
1818
1819 // Ok(dap::SetBreakpointsResponse {
1820 // breakpoints: Vec::default(),
1821 // })
1822 // }
1823 // })
1824 // .await;
1825
1826 // client.on_request::<Launch, _>(move |_, _| Ok(())).await;
1827 // client
1828 // .on_request::<StackTrace, _>(move |_, _| {
1829 // Ok(dap::StackTraceResponse {
1830 // stack_frames: Vec::default(),
1831 // total_frames: None,
1832 // })
1833 // })
1834 // .await;
1835
1836 // client
1837 // .fake_event(dap::messages::Events::Initialized(Some(
1838 // dap::Capabilities {
1839 // supports_configuration_done_request: Some(true),
1840 // ..Default::default()
1841 // },
1842 // )))
1843 // .await;
1844
1845 // host_cx.run_until_parked();
1846 // remote_cx.run_until_parked();
1847
1848 // assert!(
1849 // called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
1850 // "SetBreakpoint request must be called when starting debug session"
1851 // );
1852
1853 // client
1854 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1855 // reason: dap::StoppedEventReason::Pause,
1856 // description: None,
1857 // thread_id: Some(1),
1858 // preserve_focus_hint: None,
1859 // text: None,
1860 // all_threads_stopped: None,
1861 // hit_breakpoint_ids: None,
1862 // }))
1863 // .await;
1864
1865 // host_cx.run_until_parked();
1866 // remote_cx.run_until_parked();
1867
1868 // let remote_debug_item = remote_workspace.update(remote_cx, |workspace, cx| {
1869 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1870 // let active_session = debug_panel
1871 // .update(cx, |this, cx| this.active_session(cx))
1872 // .unwrap();
1873
1874 // assert_eq!(
1875 // 1,
1876 // debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
1877 // );
1878
1879 // let session_id = debug_panel.update(cx, |this, cx| {
1880 // this.dap_store()
1881 // .read(cx)
1882 // .session_by_client_id(client.id())
1883 // .unwrap()
1884 // .read(cx)
1885 // .id()
1886 // });
1887
1888 // let breakpoints_ignored = active_session.read(cx).are_breakpoints_ignored(cx);
1889
1890 // assert_eq!(session_id, active_session.read(cx).session().read(cx).id());
1891 // assert_eq!(false, breakpoints_ignored);
1892 // assert_eq!(client.id(), active_session.read(cx).client_id());
1893 // assert_eq!(1, active_session.read(cx).thread_id().0);
1894 // active_session
1895 // });
1896
1897 // called_set_breakpoints.store(false, Ordering::SeqCst);
1898
1899 // client
1900 // .on_request::<SetBreakpoints, _>({
1901 // let called_set_breakpoints = called_set_breakpoints.clone();
1902 // move |_, args| {
1903 // assert_eq!("/project/test.txt", args.source.path.unwrap());
1904 // assert_eq!(args.breakpoints, Some(vec![]));
1905
1906 // called_set_breakpoints.store(true, Ordering::SeqCst);
1907
1908 // Ok(dap::SetBreakpointsResponse {
1909 // breakpoints: Vec::default(),
1910 // })
1911 // }
1912 // })
1913 // .await;
1914
1915 // let local_debug_item = host_workspace.update(host_cx, |workspace, cx| {
1916 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
1917 // let active_session = debug_panel
1918 // .update(cx, |this, cx| this.active_session(cx))
1919 // .unwrap();
1920
1921 // assert_eq!(
1922 // 1,
1923 // debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
1924 // );
1925
1926 // assert_eq!(false, active_session.read(cx).are_breakpoints_ignored(cx));
1927 // assert_eq!(client.id(), active_session.read(cx).client_id());
1928 // assert_eq!(1, active_session.read(cx).thread_id().0);
1929
1930 // active_session
1931 // });
1932
1933 // local_debug_item.update(host_cx, |item, cx| {
1934 // item.toggle_ignore_breakpoints(cx); // Set to true
1935 // assert_eq!(true, item.are_breakpoints_ignored(cx));
1936 // });
1937
1938 // host_cx.run_until_parked();
1939 // remote_cx.run_until_parked();
1940
1941 // assert!(
1942 // called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
1943 // "SetBreakpoint request must be called to ignore breakpoints"
1944 // );
1945
1946 // client
1947 // .on_request::<SetBreakpoints, _>({
1948 // let called_set_breakpoints = called_set_breakpoints.clone();
1949 // move |_, _args| {
1950 // called_set_breakpoints.store(true, Ordering::SeqCst);
1951
1952 // Ok(dap::SetBreakpointsResponse {
1953 // breakpoints: Vec::default(),
1954 // })
1955 // }
1956 // })
1957 // .await;
1958
1959 // let remote_editor = remote_workspace
1960 // .update_in(remote_cx, |workspace, window, cx| {
1961 // workspace.open_path(project_path.clone(), None, true, window, cx)
1962 // })
1963 // .await
1964 // .unwrap()
1965 // .downcast::<Editor>()
1966 // .unwrap();
1967
1968 // called_set_breakpoints.store(false, std::sync::atomic::Ordering::SeqCst);
1969
1970 // remote_editor.update_in(remote_cx, |editor, window, cx| {
1971 // // Line 1
1972 // editor.toggle_breakpoint(&editor::actions::ToggleBreakpoint, window, cx);
1973 // });
1974
1975 // host_cx.run_until_parked();
1976 // remote_cx.run_until_parked();
1977
1978 // assert!(
1979 // called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
1980 // "SetBreakpoint request be called whenever breakpoints are toggled but with not breakpoints"
1981 // );
1982
1983 // remote_debug_item.update(remote_cx, |debug_panel, cx| {
1984 // let breakpoints_ignored = debug_panel.are_breakpoints_ignored(cx);
1985
1986 // assert_eq!(true, breakpoints_ignored);
1987 // assert_eq!(client.id(), debug_panel.client_id());
1988 // assert_eq!(1, debug_panel.thread_id().0);
1989 // });
1990
1991 // client
1992 // .on_request::<SetBreakpoints, _>({
1993 // let called_set_breakpoints = called_set_breakpoints.clone();
1994 // move |_, args| {
1995 // assert_eq!("/project/test.txt", args.source.path.unwrap());
1996
1997 // let mut actual_breakpoints = args.breakpoints.unwrap();
1998 // actual_breakpoints.sort_by_key(|b| b.line);
1999
2000 // let expected_breakpoints = vec![
2001 // SourceBreakpoint {
2002 // line: 1,
2003 // column: None,
2004 // condition: None,
2005 // hit_condition: None,
2006 // log_message: None,
2007 // mode: None,
2008 // },
2009 // SourceBreakpoint {
2010 // line: 2,
2011 // column: None,
2012 // condition: None,
2013 // hit_condition: None,
2014 // log_message: None,
2015 // mode: None,
2016 // },
2017 // SourceBreakpoint {
2018 // line: 3,
2019 // column: None,
2020 // condition: None,
2021 // hit_condition: None,
2022 // log_message: None,
2023 // mode: None,
2024 // },
2025 // ];
2026
2027 // assert_eq!(actual_breakpoints, expected_breakpoints);
2028
2029 // called_set_breakpoints.store(true, Ordering::SeqCst);
2030
2031 // Ok(dap::SetBreakpointsResponse {
2032 // breakpoints: Vec::default(),
2033 // })
2034 // }
2035 // })
2036 // .await;
2037
2038 // late_join_zed.join_project(host_project_id).await;
2039 // let (_late_join_client, late_join_workspace, late_join_project, late_join_cx) =
2040 // late_join_zed.expand().await;
2041
2042 // late_join_cx.run_until_parked();
2043
2044 // let last_join_remote_item = late_join_workspace.update(late_join_cx, |workspace, cx| {
2045 // let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
2046 // let active_session = debug_panel
2047 // .update(cx, |this, cx| this.active_session(cx))
2048 // .unwrap();
2049
2050 // let breakpoints_ignored = active_session.read(cx).are_breakpoints_ignored(cx);
2051
2052 // assert_eq!(true, breakpoints_ignored);
2053
2054 // assert_eq!(
2055 // 1,
2056 // debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())
2057 // );
2058 // assert_eq!(client.id(), active_session.read(cx).client_id());
2059 // assert_eq!(1, active_session.read(cx).thread_id().0);
2060 // active_session
2061 // });
2062
2063 // remote_debug_item.update(remote_cx, |item, cx| {
2064 // item.toggle_ignore_breakpoints(cx);
2065 // });
2066
2067 // host_cx.run_until_parked();
2068 // remote_cx.run_until_parked();
2069 // late_join_cx.run_until_parked();
2070
2071 // assert!(
2072 // called_set_breakpoints.load(std::sync::atomic::Ordering::SeqCst),
2073 // "SetBreakpoint request should be called to update breakpoints"
2074 // );
2075
2076 // client
2077 // .on_request::<SetBreakpoints, _>({
2078 // let called_set_breakpoints = called_set_breakpoints.clone();
2079 // move |_, args| {
2080 // assert_eq!("/project/test.txt", args.source.path.unwrap());
2081 // assert_eq!(args.breakpoints, Some(vec![]));
2082
2083 // called_set_breakpoints.store(true, Ordering::SeqCst);
2084
2085 // Ok(dap::SetBreakpointsResponse {
2086 // breakpoints: Vec::default(),
2087 // })
2088 // }
2089 // })
2090 // .await;
2091
2092 // local_debug_item.update(host_cx, |debug_panel_item, cx| {
2093 // assert_eq!(
2094 // false,
2095 // debug_panel_item.are_breakpoints_ignored(cx),
2096 // "Remote client set this to false"
2097 // );
2098 // });
2099
2100 // remote_debug_item.update(remote_cx, |debug_panel_item, cx| {
2101 // assert_eq!(
2102 // false,
2103 // debug_panel_item.are_breakpoints_ignored(cx),
2104 // "Remote client set this to false"
2105 // );
2106 // });
2107
2108 // last_join_remote_item.update(late_join_cx, |debug_panel_item, cx| {
2109 // assert_eq!(
2110 // false,
2111 // debug_panel_item.are_breakpoints_ignored(cx),
2112 // "Remote client set this to false"
2113 // );
2114 // });
2115
2116 // let shutdown_client = host_project.update(host_cx, |project, cx| {
2117 // project.dap_store().update(cx, |dap_store, cx| {
2118 // dap_store.shutdown_session(&session.read(cx).id(), cx)
2119 // })
2120 // });
2121
2122 // shutdown_client.await.unwrap();
2123
2124 // host_cx.run_until_parked();
2125 // remote_cx.run_until_parked();
2126
2127 // remote_project.update(remote_cx, |project, cx| {
2128 // project.dap_store().update(cx, |dap_store, _cx| {
2129 // let sessions = dap_store.sessions().collect::<Vec<_>>();
2130
2131 // assert_eq!(
2132 // None,
2133 // dap_store.session_by_client_id(&client_id),
2134 // "No client_id to session mapping should exist after shutdown"
2135 // );
2136 // assert_eq!(
2137 // 0,
2138 // sessions.len(),
2139 // "No sessions should be left after shutdown"
2140 // );
2141 // })
2142 // });
2143
2144 // late_join_project.update(late_join_cx, |project, cx| {
2145 // project.dap_store().update(cx, |dap_store, _cx| {
2146 // let sessions = dap_store.sessions().collect::<Vec<_>>();
2147
2148 // assert_eq!(
2149 // None,
2150 // dap_store.session_by_client_id(&client_id),
2151 // "No client_id to session mapping should exist after shutdown"
2152 // );
2153 // assert_eq!(
2154 // 0,
2155 // sessions.len(),
2156 // "No sessions should be left after shutdown"
2157 // );
2158 // })
2159 // });
2160}
2161
2162#[gpui::test]
2163async fn test_debug_panel_console(_host_cx: &mut TestAppContext, _remote_cx: &mut TestAppContext) {
2164 unimplemented!("Collab is still being refactored");
2165 // let executor = host_cx.executor();
2166 // let mut server = TestServer::start(executor).await;
2167
2168 // let (mut host_zed, mut remote_zed) =
2169 // setup_two_member_test(&mut server, host_cx, remote_cx).await;
2170
2171 // let (host_project_id, _) = host_zed.host_project(None).await;
2172 // remote_zed.join_project(host_project_id).await;
2173
2174 // let (_client_host, _host_workspace, host_project, host_cx) = host_zed.expand().await;
2175 // let (_client_remote, remote_workspace, _remote_project, remote_cx) = remote_zed.expand().await;
2176
2177 // remote_cx.run_until_parked();
2178
2179 // let task = host_project.update(host_cx, |project, cx| {
2180 // project.start_debug_session(dap::test_config(None), cx)
2181 // });
2182
2183 // let session = task.await.unwrap();
2184 // let client = session.read_with(host_cx, |project, _| project.adapter_client().unwrap());
2185
2186 // client
2187 // .on_request::<Initialize, _>(move |_, _| {
2188 // Ok(dap::Capabilities {
2189 // supports_step_back: Some(false),
2190 // ..Default::default()
2191 // })
2192 // })
2193 // .await;
2194
2195 // client.on_request::<Launch, _>(move |_, _| Ok(())).await;
2196
2197 // client
2198 // .on_request::<StackTrace, _>(move |_, _| {
2199 // Ok(dap::StackTraceResponse {
2200 // stack_frames: Vec::default(),
2201 // total_frames: None,
2202 // })
2203 // })
2204 // .await;
2205
2206 // client
2207 // .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
2208 // reason: dap::StoppedEventReason::Pause,
2209 // description: None,
2210 // thread_id: Some(1),
2211 // preserve_focus_hint: None,
2212 // text: None,
2213 // all_threads_stopped: None,
2214 // hit_breakpoint_ids: None,
2215 // }))
2216 // .await;
2217
2218 // client
2219 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2220 // category: None,
2221 // output: "First line".to_string(),
2222 // data: None,
2223 // variables_reference: None,
2224 // source: None,
2225 // line: None,
2226 // column: None,
2227 // group: None,
2228 // location_reference: None,
2229 // }))
2230 // .await;
2231
2232 // client
2233 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2234 // category: Some(dap::OutputEventCategory::Stdout),
2235 // output: "First group".to_string(),
2236 // data: None,
2237 // variables_reference: None,
2238 // source: None,
2239 // line: None,
2240 // column: None,
2241 // group: Some(dap::OutputEventGroup::Start),
2242 // location_reference: None,
2243 // }))
2244 // .await;
2245
2246 // client
2247 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2248 // category: Some(dap::OutputEventCategory::Stdout),
2249 // output: "First item in group 1".to_string(),
2250 // data: None,
2251 // variables_reference: None,
2252 // source: None,
2253 // line: None,
2254 // column: None,
2255 // group: None,
2256 // location_reference: None,
2257 // }))
2258 // .await;
2259
2260 // client
2261 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2262 // category: Some(dap::OutputEventCategory::Stdout),
2263 // output: "Second item in group 1".to_string(),
2264 // data: None,
2265 // variables_reference: None,
2266 // source: None,
2267 // line: None,
2268 // column: None,
2269 // group: None,
2270 // location_reference: None,
2271 // }))
2272 // .await;
2273
2274 // client
2275 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2276 // category: Some(dap::OutputEventCategory::Stdout),
2277 // output: "Second group".to_string(),
2278 // data: None,
2279 // variables_reference: None,
2280 // source: None,
2281 // line: None,
2282 // column: None,
2283 // group: Some(dap::OutputEventGroup::Start),
2284 // location_reference: None,
2285 // }))
2286 // .await;
2287
2288 // client
2289 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2290 // category: Some(dap::OutputEventCategory::Stdout),
2291 // output: "First item in group 2".to_string(),
2292 // data: None,
2293 // variables_reference: None,
2294 // source: None,
2295 // line: None,
2296 // column: None,
2297 // group: None,
2298 // location_reference: None,
2299 // }))
2300 // .await;
2301
2302 // client
2303 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2304 // category: Some(dap::OutputEventCategory::Stdout),
2305 // output: "Second item in group 2".to_string(),
2306 // data: None,
2307 // variables_reference: None,
2308 // source: None,
2309 // line: None,
2310 // column: None,
2311 // group: None,
2312 // location_reference: None,
2313 // }))
2314 // .await;
2315
2316 // client
2317 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2318 // category: Some(dap::OutputEventCategory::Stdout),
2319 // output: "End group 2".to_string(),
2320 // data: None,
2321 // variables_reference: None,
2322 // source: None,
2323 // line: None,
2324 // column: None,
2325 // group: Some(dap::OutputEventGroup::End),
2326 // location_reference: None,
2327 // }))
2328 // .await;
2329
2330 // client
2331 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2332 // category: Some(dap::OutputEventCategory::Stdout),
2333 // output: "Third group".to_string(),
2334 // data: None,
2335 // variables_reference: None,
2336 // source: None,
2337 // line: None,
2338 // column: None,
2339 // group: Some(dap::OutputEventGroup::StartCollapsed),
2340 // location_reference: None,
2341 // }))
2342 // .await;
2343
2344 // client
2345 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2346 // category: Some(dap::OutputEventCategory::Stdout),
2347 // output: "First item in group 3".to_string(),
2348 // data: None,
2349 // variables_reference: None,
2350 // source: None,
2351 // line: None,
2352 // column: None,
2353 // group: None,
2354 // location_reference: None,
2355 // }))
2356 // .await;
2357
2358 // client
2359 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2360 // category: Some(dap::OutputEventCategory::Stdout),
2361 // output: "Second item in group 3".to_string(),
2362 // data: None,
2363 // variables_reference: None,
2364 // source: None,
2365 // line: None,
2366 // column: None,
2367 // group: None,
2368 // location_reference: None,
2369 // }))
2370 // .await;
2371
2372 // client
2373 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2374 // category: Some(dap::OutputEventCategory::Stdout),
2375 // output: "End group 3".to_string(),
2376 // data: None,
2377 // variables_reference: None,
2378 // source: None,
2379 // line: None,
2380 // column: None,
2381 // group: Some(dap::OutputEventGroup::End),
2382 // location_reference: None,
2383 // }))
2384 // .await;
2385
2386 // client
2387 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2388 // category: Some(dap::OutputEventCategory::Stdout),
2389 // output: "Third item in group 1".to_string(),
2390 // data: None,
2391 // variables_reference: None,
2392 // source: None,
2393 // line: None,
2394 // column: None,
2395 // group: None,
2396 // location_reference: None,
2397 // }))
2398 // .await;
2399
2400 // client
2401 // .fake_event(dap::messages::Events::Output(dap::OutputEvent {
2402 // category: Some(dap::OutputEventCategory::Stdout),
2403 // output: "Second item".to_string(),
2404 // data: None,
2405 // variables_reference: None,
2406 // source: None,
2407 // line: None,
2408 // column: None,
2409 // group: Some(dap::OutputEventGroup::End),
2410 // location_reference: None,
2411 // }))
2412 // .await;
2413
2414 // host_cx.run_until_parked();
2415 // remote_cx.run_until_parked();
2416
2417 // active_session(remote_workspace, remote_cx).update(remote_cx, |session_item, cx| {
2418 // session_item
2419 // .mode()
2420 // .as_running()
2421 // .unwrap()
2422 // .read(cx)
2423 // .console()
2424 // .update(cx, |console, cx| {
2425 // console.editor().update(cx, |editor, cx| {
2426 // pretty_assertions::assert_eq!(
2427 // "
2428 // <First line
2429 // First group
2430 // First item in group 1
2431 // Second item in group 1
2432 // Second group
2433 // First item in group 2
2434 // Second item in group 2
2435 // End group 2
2436 // ⋯ End group 3
2437 // Third item in group 1
2438 // Second item
2439 // "
2440 // .unindent(),
2441 // editor.display_text(cx)
2442 // );
2443 // })
2444 // });
2445 // });
2446
2447 // let shutdown_client = host_project.update(host_cx, |project, cx| {
2448 // project.dap_store().update(cx, |dap_store, cx| {
2449 // dap_store.shutdown_session(&session.read(cx).session_id(), cx)
2450 // })
2451 // });
2452
2453 // shutdown_client.await.unwrap();
2454}