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