console.rs

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