console.rs

  1use crate::{
  2    tests::{active_debug_session_panel, start_debug_session},
  3    *,
  4};
  5use dap::requests::StackTrace;
  6use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
  7use project::{FakeFs, Project};
  8use serde_json::json;
  9use tests::{init_test, init_test_workspace};
 10use util::path;
 11
 12#[gpui::test]
 13async fn test_handle_output_event(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    workspace
 30        .update(cx, |workspace, window, cx| {
 31            workspace.focus_panel::<DebugPanel>(window, cx);
 32        })
 33        .unwrap();
 34
 35    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
 36    let client = session.read_with(cx, |session, _| session.adapter_client().unwrap());
 37
 38    client.on_request::<StackTrace, _>(move |_, _| {
 39        Ok(dap::StackTraceResponse {
 40            stack_frames: Vec::default(),
 41            total_frames: None,
 42        })
 43    });
 44
 45    client
 46        .fake_event(dap::messages::Events::Output(dap::OutputEvent {
 47            category: None,
 48            output: "First console output line before thread stopped!".to_string(),
 49            data: None,
 50            variables_reference: None,
 51            source: None,
 52            line: None,
 53            column: None,
 54            group: None,
 55            location_reference: None,
 56        }))
 57        .await;
 58
 59    client
 60        .fake_event(dap::messages::Events::Output(dap::OutputEvent {
 61            category: Some(dap::OutputEventCategory::Stdout),
 62            output: "First output line before thread stopped!".to_string(),
 63            data: None,
 64            variables_reference: None,
 65            source: None,
 66            line: None,
 67            column: None,
 68            group: None,
 69            location_reference: None,
 70        }))
 71        .await;
 72
 73    client
 74        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
 75            reason: dap::StoppedEventReason::Pause,
 76            description: None,
 77            thread_id: Some(1),
 78            preserve_focus_hint: None,
 79            text: None,
 80            all_threads_stopped: None,
 81            hit_breakpoint_ids: None,
 82        }))
 83        .await;
 84
 85    cx.run_until_parked();
 86
 87    let running_state =
 88        active_debug_session_panel(workspace, cx).update_in(cx, |item, window, cx| {
 89            cx.focus_self(window);
 90            item.running_state().clone()
 91        });
 92
 93    cx.run_until_parked();
 94
 95    // assert we have output from before the thread stopped
 96    workspace
 97        .update(cx, |workspace, _window, cx| {
 98            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
 99            let active_debug_session_panel = debug_panel
100                .update(cx, |this, _| this.active_session())
101                .unwrap();
102
103            assert_eq!(
104                "First console output line before thread stopped!\nFirst output line before thread stopped!\n",
105                active_debug_session_panel.read(cx).running_state().read(cx).console().read(cx).editor().read(cx).text(cx).as_str()
106            );
107        })
108        .unwrap();
109
110    client
111        .fake_event(dap::messages::Events::Output(dap::OutputEvent {
112            category: Some(dap::OutputEventCategory::Stdout),
113            output: "Second output line after thread stopped!".to_string(),
114            data: None,
115            variables_reference: None,
116            source: None,
117            line: None,
118            column: None,
119            group: None,
120            location_reference: None,
121        }))
122        .await;
123
124    client
125        .fake_event(dap::messages::Events::Output(dap::OutputEvent {
126            category: Some(dap::OutputEventCategory::Console),
127            output: "Second console output line after thread stopped!".to_string(),
128            data: None,
129            variables_reference: None,
130            source: None,
131            line: None,
132            column: None,
133            group: None,
134            location_reference: None,
135        }))
136        .await;
137
138    cx.run_until_parked();
139    running_state.update(cx, |_, cx| {
140        cx.refresh_windows();
141    });
142    cx.run_until_parked();
143
144    // assert we have output from before and after the thread stopped
145    workspace
146        .update(cx, |workspace, _window, cx| {
147            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
148            let active_session_panel = debug_panel
149                .update(cx, |this, _| this.active_session())
150                .unwrap();
151
152            assert_eq!(
153                "First console output line before thread stopped!\nFirst output line before thread stopped!\nSecond output line after thread stopped!\nSecond console output line after thread stopped!\n",
154                active_session_panel.read(cx).running_state().read(cx).console().read(cx).editor().read(cx).text(cx).as_str()
155            );
156        })
157        .unwrap();
158}
159
160// #[gpui::test]
161// async fn test_grouped_output(executor: BackgroundExecutor, cx: &mut TestAppContext) {
162//     init_test(cx);
163
164//     let fs = FakeFs::new(executor.clone());
165
166//     fs.insert_tree(
167//         "/project",
168//         json!({
169//             "main.rs": "First line\nSecond line\nThird line\nFourth line",
170//         }),
171//     )
172//     .await;
173
174//     let project = Project::test(fs, ["/project".as_ref()], cx).await;
175//     let workspace = init_test_workspace(&project, cx).await;
176//     let cx = &mut VisualTestContext::from_window(*workspace, cx);
177
178//     let task = project.update(cx, |project, cx| {
179//         project.start_debug_session(
180//             dap::test_config(dap::DebugRequestType::Launch, None, None),
181//             cx,
182//         )
183//     });
184
185//     let session = task.await.unwrap();
186//     let client = session.update(cx, |session, _| session.adapter_client().unwrap());
187
188//     client
189//         .on_request::<StackTrace, _>(move |_, _| {
190//             Ok(dap::StackTraceResponse {
191//                 stack_frames: Vec::default(),
192//                 total_frames: None,
193//             })
194//         })
195//         .await;
196
197//     client
198//         .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
199//             reason: dap::StoppedEventReason::Pause,
200//             description: None,
201//             thread_id: Some(1),
202//             preserve_focus_hint: None,
203//             text: None,
204//             all_threads_stopped: None,
205//             hit_breakpoint_ids: None,
206//         }))
207//         .await;
208
209//     client
210//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
211//             category: None,
212//             output: "First line".to_string(),
213//             data: None,
214//             variables_reference: None,
215//             source: None,
216//             line: None,
217//             column: None,
218//             group: None,
219//             location_reference: None,
220//         }))
221//         .await;
222
223//     client
224//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
225//             category: Some(dap::OutputEventCategory::Stdout),
226//             output: "First group".to_string(),
227//             data: None,
228//             variables_reference: None,
229//             source: None,
230//             line: None,
231//             column: None,
232//             group: Some(dap::OutputEventGroup::Start),
233//             location_reference: None,
234//         }))
235//         .await;
236
237//     client
238//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
239//             category: Some(dap::OutputEventCategory::Stdout),
240//             output: "First item in group 1".to_string(),
241//             data: None,
242//             variables_reference: None,
243//             source: None,
244//             line: None,
245//             column: None,
246//             group: None,
247//             location_reference: None,
248//         }))
249//         .await;
250
251//     client
252//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
253//             category: Some(dap::OutputEventCategory::Stdout),
254//             output: "Second item in group 1".to_string(),
255//             data: None,
256//             variables_reference: None,
257//             source: None,
258//             line: None,
259//             column: None,
260//             group: None,
261//             location_reference: None,
262//         }))
263//         .await;
264
265//     client
266//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
267//             category: Some(dap::OutputEventCategory::Stdout),
268//             output: "Second group".to_string(),
269//             data: None,
270//             variables_reference: None,
271//             source: None,
272//             line: None,
273//             column: None,
274//             group: Some(dap::OutputEventGroup::Start),
275//             location_reference: None,
276//         }))
277//         .await;
278
279//     client
280//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
281//             category: Some(dap::OutputEventCategory::Stdout),
282//             output: "First item in group 2".to_string(),
283//             data: None,
284//             variables_reference: None,
285//             source: None,
286//             line: None,
287//             column: None,
288//             group: None,
289//             location_reference: None,
290//         }))
291//         .await;
292
293//     client
294//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
295//             category: Some(dap::OutputEventCategory::Stdout),
296//             output: "Second item in group 2".to_string(),
297//             data: None,
298//             variables_reference: None,
299//             source: None,
300//             line: None,
301//             column: None,
302//             group: None,
303//             location_reference: None,
304//         }))
305//         .await;
306
307//     client
308//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
309//             category: Some(dap::OutputEventCategory::Stdout),
310//             output: "End group 2".to_string(),
311//             data: None,
312//             variables_reference: None,
313//             source: None,
314//             line: None,
315//             column: None,
316//             group: Some(dap::OutputEventGroup::End),
317//             location_reference: None,
318//         }))
319//         .await;
320
321//     client
322//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
323//             category: Some(dap::OutputEventCategory::Stdout),
324//             output: "Third group".to_string(),
325//             data: None,
326//             variables_reference: None,
327//             source: None,
328//             line: None,
329//             column: None,
330//             group: Some(dap::OutputEventGroup::StartCollapsed),
331//             location_reference: None,
332//         }))
333//         .await;
334
335//     client
336//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
337//             category: Some(dap::OutputEventCategory::Stdout),
338//             output: "First item in group 3".to_string(),
339//             data: None,
340//             variables_reference: None,
341//             source: None,
342//             line: None,
343//             column: None,
344//             group: None,
345//             location_reference: None,
346//         }))
347//         .await;
348
349//     client
350//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
351//             category: Some(dap::OutputEventCategory::Stdout),
352//             output: "Second item in group 3".to_string(),
353//             data: None,
354//             variables_reference: None,
355//             source: None,
356//             line: None,
357//             column: None,
358//             group: None,
359//             location_reference: None,
360//         }))
361//         .await;
362
363//     client
364//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
365//             category: Some(dap::OutputEventCategory::Stdout),
366//             output: "End group 3".to_string(),
367//             data: None,
368//             variables_reference: None,
369//             source: None,
370//             line: None,
371//             column: None,
372//             group: Some(dap::OutputEventGroup::End),
373//             location_reference: None,
374//         }))
375//         .await;
376
377//     client
378//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
379//             category: Some(dap::OutputEventCategory::Stdout),
380//             output: "Third item in group 1".to_string(),
381//             data: None,
382//             variables_reference: None,
383//             source: None,
384//             line: None,
385//             column: None,
386//             group: None,
387//             location_reference: None,
388//         }))
389//         .await;
390
391//     client
392//         .fake_event(dap::messages::Events::Output(dap::OutputEvent {
393//             category: Some(dap::OutputEventCategory::Stdout),
394//             output: "Second item".to_string(),
395//             data: None,
396//             variables_reference: None,
397//             source: None,
398//             line: None,
399//             column: None,
400//             group: Some(dap::OutputEventGroup::End),
401//             location_reference: None,
402//         }))
403//         .await;
404
405//     cx.run_until_parked();
406
407//     active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
408//         debug_panel_item
409//             .mode()
410//             .as_running()
411//             .unwrap()
412//             .update(cx, |running_state, cx| {
413//                 running_state.console().update(cx, |console, cx| {
414//                     console.editor().update(cx, |editor, cx| {
415//                         pretty_assertions::assert_eq!(
416//                             "
417//                         First line
418//                         First group
419//                             First item in group 1
420//                             Second item in group 1
421//                             Second group
422//                                 First item in group 2
423//                                 Second item in group 2
424//                             End group 2
425//                         ⋯    End group 3
426//                             Third item in group 1
427//                         Second item
428//                     "
429//                             .unindent(),
430//                             editor.display_text(cx)
431//                         );
432//                     })
433//                 });
434//             });
435//     });
436
437//     let shutdown_session = project.update(cx, |project, cx| {
438//         project.dap_store().update(cx, |dap_store, cx| {
439//             dap_store.shutdown_session(session.read(cx).session_id(), cx)
440//         })
441//     });
442
443//     shutdown_session.await.unwrap();
444// }
445
446// todo(debugger): enable this again
447// #[gpui::test]
448// async fn test_evaluate_expression(executor: BackgroundExecutor, cx: &mut TestAppContext) {
449//     init_test(cx);
450
451//     const NEW_VALUE: &str = "{nested1: \"Nested 1 updated\", nested2: \"Nested 2 updated\"}";
452
453//     let called_evaluate = Arc::new(AtomicBool::new(false));
454
455//     let fs = FakeFs::new(executor.clone());
456
457//     let test_file_content = r#"
458//         const variable1 = {
459//             nested1: "Nested 1",
460//             nested2: "Nested 2",
461//         };
462//         const variable2 = "Value 2";
463//         const variable3 = "Value 3";
464//     "#
465//     .unindent();
466
467//     fs.insert_tree(
468//         "/project",
469//         json!({
470//            "src": {
471//                "test.js": test_file_content,
472//            }
473//         }),
474//     )
475//     .await;
476
477//     let project = Project::test(fs, ["/project".as_ref()], cx).await;
478//     let workspace = init_test_workspace(&project, cx).await;
479//     let cx = &mut VisualTestContext::from_window(*workspace, cx);
480
481//     let task = project.update(cx, |project, cx| {
482//         project.start_debug_session(dap::test_config(None), cx)
483//     });
484
485//     let session = task.await.unwrap();
486//     let client = session.update(cx, |session, _| session.adapter_client().unwrap());
487
488//     client
489//         .on_request::<Threads, _>(move |_, _| {
490//             Ok(dap::ThreadsResponse {
491//                 threads: vec![dap::Thread {
492//                     id: 1,
493//                     name: "Thread 1".into(),
494//                 }],
495//             })
496//         })
497//         .await;
498
499//     let stack_frames = vec![StackFrame {
500//         id: 1,
501//         name: "Stack Frame 1".into(),
502//         source: Some(dap::Source {
503//             name: Some("test.js".into()),
504//             path: Some("/project/src/test.js".into()),
505//             source_reference: None,
506//             presentation_hint: None,
507//             origin: None,
508//             sources: None,
509//             adapter_data: None,
510//             checksums: None,
511//         }),
512//         line: 3,
513//         column: 1,
514//         end_line: None,
515//         end_column: None,
516//         can_restart: None,
517//         instruction_pointer_reference: None,
518//         module_id: None,
519//         presentation_hint: None,
520//     }];
521
522//     client
523//         .on_request::<StackTrace, _>({
524//             let stack_frames = Arc::new(stack_frames.clone());
525//             move |_, args| {
526//                 assert_eq!(1, args.thread_id);
527
528//                 Ok(dap::StackTraceResponse {
529//                     stack_frames: (*stack_frames).clone(),
530//                     total_frames: None,
531//                 })
532//             }
533//         })
534//         .await;
535
536//     let scopes = vec![
537//         Scope {
538//             name: "Scope 1".into(),
539//             presentation_hint: None,
540//             variables_reference: 2,
541//             named_variables: None,
542//             indexed_variables: None,
543//             expensive: false,
544//             source: None,
545//             line: None,
546//             column: None,
547//             end_line: None,
548//             end_column: None,
549//         },
550//         Scope {
551//             name: "Scope 2".into(),
552//             presentation_hint: None,
553//             variables_reference: 4,
554//             named_variables: None,
555//             indexed_variables: None,
556//             expensive: false,
557//             source: None,
558//             line: None,
559//             column: None,
560//             end_line: None,
561//             end_column: None,
562//         },
563//     ];
564
565//     client
566//         .on_request::<Scopes, _>({
567//             let scopes = Arc::new(scopes.clone());
568//             move |_, args| {
569//                 assert_eq!(1, args.frame_id);
570
571//                 Ok(dap::ScopesResponse {
572//                     scopes: (*scopes).clone(),
573//                 })
574//             }
575//         })
576//         .await;
577
578//     let scope1_variables = Arc::new(Mutex::new(vec![
579//         Variable {
580//             name: "variable1".into(),
581//             value: "{nested1: \"Nested 1\", nested2: \"Nested 2\"}".into(),
582//             type_: None,
583//             presentation_hint: None,
584//             evaluate_name: None,
585//             variables_reference: 3,
586//             named_variables: None,
587//             indexed_variables: None,
588//             memory_reference: None,
589//             declaration_location_reference: None,
590//             value_location_reference: None,
591//         },
592//         Variable {
593//             name: "variable2".into(),
594//             value: "Value 2".into(),
595//             type_: None,
596//             presentation_hint: None,
597//             evaluate_name: None,
598//             variables_reference: 0,
599//             named_variables: None,
600//             indexed_variables: None,
601//             memory_reference: None,
602//             declaration_location_reference: None,
603//             value_location_reference: None,
604//         },
605//     ]));
606
607//     let nested_variables = vec![
608//         Variable {
609//             name: "nested1".into(),
610//             value: "Nested 1".into(),
611//             type_: None,
612//             presentation_hint: None,
613//             evaluate_name: None,
614//             variables_reference: 0,
615//             named_variables: None,
616//             indexed_variables: None,
617//             memory_reference: None,
618//             declaration_location_reference: None,
619//             value_location_reference: None,
620//         },
621//         Variable {
622//             name: "nested2".into(),
623//             value: "Nested 2".into(),
624//             type_: None,
625//             presentation_hint: None,
626//             evaluate_name: None,
627//             variables_reference: 0,
628//             named_variables: None,
629//             indexed_variables: None,
630//             memory_reference: None,
631//             declaration_location_reference: None,
632//             value_location_reference: None,
633//         },
634//     ];
635
636//     let scope2_variables = vec![Variable {
637//         name: "variable3".into(),
638//         value: "Value 3".into(),
639//         type_: None,
640//         presentation_hint: None,
641//         evaluate_name: None,
642//         variables_reference: 0,
643//         named_variables: None,
644//         indexed_variables: None,
645//         memory_reference: None,
646//         declaration_location_reference: None,
647//         value_location_reference: None,
648//     }];
649
650//     client
651//         .on_request::<Variables, _>({
652//             let scope1_variables = scope1_variables.clone();
653//             let nested_variables = Arc::new(nested_variables.clone());
654//             let scope2_variables = Arc::new(scope2_variables.clone());
655//             move |_, args| match args.variables_reference {
656//                 4 => Ok(dap::VariablesResponse {
657//                     variables: (*scope2_variables).clone(),
658//                 }),
659//                 3 => Ok(dap::VariablesResponse {
660//                     variables: (*nested_variables).clone(),
661//                 }),
662//                 2 => Ok(dap::VariablesResponse {
663//                     variables: scope1_variables.lock().unwrap().clone(),
664//                 }),
665//                 id => unreachable!("unexpected variables reference {id}"),
666//             }
667//         })
668//         .await;
669
670//     client
671//         .on_request::<Evaluate, _>({
672//             let called_evaluate = called_evaluate.clone();
673//             let scope1_variables = scope1_variables.clone();
674//             move |_, args| {
675//                 called_evaluate.store(true, Ordering::SeqCst);
676
677//                 assert_eq!(format!("$variable1 = {}", NEW_VALUE), args.expression);
678//                 assert_eq!(Some(1), args.frame_id);
679//                 assert_eq!(Some(dap::EvaluateArgumentsContext::Variables), args.context);
680
681//                 scope1_variables.lock().unwrap()[0].value = NEW_VALUE.to_string();
682
683//                 Ok(dap::EvaluateResponse {
684//                     result: NEW_VALUE.into(),
685//                     type_: None,
686//                     presentation_hint: None,
687//                     variables_reference: 0,
688//                     named_variables: None,
689//                     indexed_variables: None,
690//                     memory_reference: None,
691//                     value_location_reference: None,
692//                 })
693//             }
694//         })
695//         .await;
696
697//     client
698//         .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
699//             reason: dap::StoppedEventReason::Pause,
700//             description: None,
701//             thread_id: Some(1),
702//             preserve_focus_hint: None,
703//             text: None,
704//             all_threads_stopped: None,
705//             hit_breakpoint_ids: None,
706//         }))
707//         .await;
708
709//     cx.run_until_parked();
710
711//     // toggle nested variables for scope 1
712//     active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
713//         debug_panel_item
714//             .mode()
715//             .as_running()
716//             .unwrap()
717//             .update(cx, |running_state, cx| {
718//                 running_state
719//                     .variable_list()
720//                     .update(cx, |variable_list, cx| {
721//                         variable_list.toggle_variable(
722//                             &VariablePath {
723//                                 indices: Arc::from([scopes[0].variables_reference]),
724//                             },
725//                             cx,
726//                         );
727//                     });
728//             });
729//     });
730
731//     cx.run_until_parked();
732
733//     active_debug_session_panel(workspace, cx).update_in(cx, |debug_panel_item, window, cx| {
734//         debug_panel_item
735//             .mode()
736//             .as_running()
737//             .unwrap()
738//             .update(cx, |running_state, cx| {
739//                 running_state.console().update(cx, |console, item_cx| {
740//                     console
741//                         .query_bar()
742//                         .update(item_cx, |query_bar, console_cx| {
743//                             query_bar.set_text(
744//                                 format!("$variable1 = {}", NEW_VALUE),
745//                                 window,
746//                                 console_cx,
747//                             );
748//                         });
749
750//                     console.evaluate(&menu::Confirm, window, item_cx);
751//                 });
752//             });
753//     });
754
755//     cx.run_until_parked();
756
757//     active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
758//         assert_eq!(
759//             "",
760//             debug_panel_item
761//                 .mode()
762//                 .as_running()
763//                 .unwrap()
764//                 .read(cx)
765//                 .console()
766//                 .read(cx)
767//                 .query_bar()
768//                 .read(cx)
769//                 .text(cx)
770//                 .as_str()
771//         );
772
773//         assert_eq!(
774//             format!("{}\n", NEW_VALUE),
775//             debug_panel_item
776//                 .mode()
777//                 .as_running()
778//                 .unwrap()
779//                 .read(cx)
780//                 .console()
781//                 .read(cx)
782//                 .editor()
783//                 .read(cx)
784//                 .text(cx)
785//                 .as_str()
786//         );
787
788//         debug_panel_item
789//             .mode()
790//             .as_running()
791//             .unwrap()
792//             .update(cx, |running_state, cx| {
793//                 running_state
794//                     .variable_list()
795//                     .update(cx, |variable_list, _| {
796//                         let scope1_variables = scope1_variables.lock().unwrap().clone();
797
798//                         // scope 1
799//                         // assert_eq!(
800//                         //     vec![
801//                         //         VariableContainer {
802//                         //             container_reference: scopes[0].variables_reference,
803//                         //             variable: scope1_variables[0].clone(),
804//                         //             depth: 1,
805//                         //         },
806//                         //         VariableContainer {
807//                         //             container_reference: scope1_variables[0].variables_reference,
808//                         //             variable: nested_variables[0].clone(),
809//                         //             depth: 2,
810//                         //         },
811//                         //         VariableContainer {
812//                         //             container_reference: scope1_variables[0].variables_reference,
813//                         //             variable: nested_variables[1].clone(),
814//                         //             depth: 2,
815//                         //         },
816//                         //         VariableContainer {
817//                         //             container_reference: scopes[0].variables_reference,
818//                         //             variable: scope1_variables[1].clone(),
819//                         //             depth: 1,
820//                         //         },
821//                         //     ],
822//                         //     variable_list.variables_by_scope(1, 2).unwrap().variables()
823//                         // );
824
825//                         // scope 2
826//                         // assert_eq!(
827//                         //     vec![VariableContainer {
828//                         //         container_reference: scopes[1].variables_reference,
829//                         //         variable: scope2_variables[0].clone(),
830//                         //         depth: 1,
831//                         //     }],
832//                         //     variable_list.variables_by_scope(1, 4).unwrap().variables()
833//                         // );
834
835//                         variable_list.assert_visual_entries(vec![
836//                             "v Scope 1",
837//                             "    v variable1",
838//                             "       > nested1",
839//                             "       > nested2",
840//                             "    > variable2",
841//                         ]);
842
843//                         // assert visual entries
844//                         // assert_eq!(
845//                         //     vec![
846//                         //         VariableListEntry::Scope(scopes[0].clone()),
847//                         //         VariableListEntry::Variable {
848//                         //             depth: 1,
849//                         //             scope: Arc::new(scopes[0].clone()),
850//                         //             has_children: true,
851//                         //             variable: Arc::new(scope1_variables[0].clone()),
852//                         //             container_reference: scopes[0].variables_reference,
853//                         //         },
854//                         //         VariableListEntry::Variable {
855//                         //             depth: 2,
856//                         //             scope: Arc::new(scopes[0].clone()),
857//                         //             has_children: false,
858//                         //             variable: Arc::new(nested_variables[0].clone()),
859//                         //             container_reference: scope1_variables[0].variables_reference,
860//                         //         },
861//                         //         VariableListEntry::Variable {
862//                         //             depth: 2,
863//                         //             scope: Arc::new(scopes[0].clone()),
864//                         //             has_children: false,
865//                         //             variable: Arc::new(nested_variables[1].clone()),
866//                         //             container_reference: scope1_variables[0].variables_reference,
867//                         //         },
868//                         //         VariableListEntry::Variable {
869//                         //             depth: 1,
870//                         //             scope: Arc::new(scopes[0].clone()),
871//                         //             has_children: false,
872//                         //             variable: Arc::new(scope1_variables[1].clone()),
873//                         //             container_reference: scopes[0].variables_reference,
874//                         //         },
875//                         //         VariableListEntry::Scope(scopes[1].clone()),
876//                         //     ],
877//                         //     variable_list.entries().get(&1).unwrap().clone()
878//                         // );
879//                     });
880//             });
881//     });
882
883//     assert!(
884//         called_evaluate.load(std::sync::atomic::Ordering::SeqCst),
885//         "Expected evaluate request to be called"
886//     );
887
888//     let shutdown_session = project.update(cx, |project, cx| {
889//         project.dap_store().update(cx, |dap_store, cx| {
890//             dap_store.shutdown_session(&session.read(cx).session_id(), cx)
891//         })
892//     });
893
894//     shutdown_session.await.unwrap();
895// }