1487 lines · 44.5 KB · Rust
RawDownload
use crate::*;use dap::{    client::SessionId,    requests::{        Continue, Disconnect, Launch, Next, RunInTerminal, SetBreakpoints, StackTrace,        StartDebugging, StepBack, StepIn, StepOut, Threads,    },    ErrorResponse, RunInTerminalRequestArguments, SourceBreakpoint, StartDebuggingRequestArguments,    StartDebuggingRequestArgumentsRequest,};use editor::{    actions::{self},    Editor, EditorMode, MultiBuffer,};use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};use project::{    debugger::session::{ThreadId, ThreadStatus},    FakeFs, Project,};use serde_json::json;use std::{    path::Path,    sync::{        atomic::{AtomicBool, Ordering},        Arc,    },};use task::LaunchConfig;use terminal_view::{terminal_panel::TerminalPanel, TerminalView};use tests::{active_debug_session_panel, init_test, init_test_workspace};use util::path;use workspace::{dock::Panel, Item}; #[gpui::test]async fn test_basic_show_debug_panel(executor: BackgroundExecutor, cx: &mut TestAppContext) {    init_test(cx);     let fs = FakeFs::new(executor.clone());     fs.insert_tree(        "/project",        json!({            "main.rs": "First line\nSecond line\nThird line\nFourth line",        }),    )    .await;     let project = Project::test(fs, ["/project".as_ref()], cx).await;    let workspace = init_test_workspace(&project, cx).await;    let cx = &mut VisualTestContext::from_window(*workspace, cx);     let task = project.update(cx, |project, cx| {        project.fake_debug_session(            dap::DebugRequestType::Launch(LaunchConfig::default()),            None,            false,            cx,        )    });     let session = task.await.unwrap();    let client = session.update(cx, |session, _| session.adapter_client().unwrap());     client        .on_request::<Threads, _>(move |_, _| {            Ok(dap::ThreadsResponse {                threads: vec![dap::Thread {                    id: 1,                    name: "Thread 1".into(),                }],            })        })        .await;     client        .on_request::<StackTrace, _>(move |_, _| {            Ok(dap::StackTraceResponse {                stack_frames: Vec::default(),                total_frames: None,            })        })        .await;     // assert we have a debug panel item before the session has stopped    workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();            let active_session = debug_panel.update(cx, |debug_panel, cx| {                debug_panel.active_session(cx).unwrap()            });             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             debug_panel.update(cx, |this, cx| {                assert!(this.active_session(cx).is_some());                // we have one active session and one inert item                assert_eq!(2, this.pane().unwrap().read(cx).items_len());                assert!(running_state.read(cx).selected_thread_id().is_none());            });        })        .unwrap();     client        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {            reason: dap::StoppedEventReason::Pause,            description: None,            thread_id: Some(1),            preserve_focus_hint: None,            text: None,            all_threads_stopped: None,            hit_breakpoint_ids: None,        }))        .await;     cx.run_until_parked();     workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();            let active_session = debug_panel                .update(cx, |this, cx| this.active_session(cx))                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             // we have one active session and one inert item            assert_eq!(                2,                debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())            );            assert_eq!(client.id(), running_state.read(cx).session_id());            assert_eq!(                ThreadId(1),                running_state.read(cx).selected_thread_id().unwrap()            );        })        .unwrap();     let shutdown_session = project.update(cx, |project, cx| {        project.dap_store().update(cx, |dap_store, cx| {            dap_store.shutdown_session(session.read(cx).session_id(), cx)        })    });     shutdown_session.await.unwrap();     // assert we still have a debug panel item after the client shutdown    workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();             let active_session = debug_panel                .update(cx, |this, cx| this.active_session(cx))                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             debug_panel.update(cx, |this, cx| {                assert!(this.active_session(cx).is_some());                assert_eq!(2, this.pane().unwrap().read(cx).items_len());                assert_eq!(                    ThreadId(1),                    running_state.read(cx).selected_thread_id().unwrap()                );            });        })        .unwrap();} #[gpui::test]async fn test_we_can_only_have_one_panel_per_debug_session(    executor: BackgroundExecutor,    cx: &mut TestAppContext,) {    init_test(cx);     let fs = FakeFs::new(executor.clone());     fs.insert_tree(        "/project",        json!({            "main.rs": "First line\nSecond line\nThird line\nFourth line",        }),    )    .await;     let project = Project::test(fs, ["/project".as_ref()], cx).await;    let workspace = init_test_workspace(&project, cx).await;    let cx = &mut VisualTestContext::from_window(*workspace, cx);     let task = project.update(cx, |project, cx| {        project.fake_debug_session(            dap::DebugRequestType::Launch(LaunchConfig::default()),            None,            false,            cx,        )    });     let session = task.await.unwrap();    let client = session.update(cx, |session, _| session.adapter_client().unwrap());     client        .on_request::<Threads, _>(move |_, _| {            Ok(dap::ThreadsResponse {                threads: vec![dap::Thread {                    id: 1,                    name: "Thread 1".into(),                }],            })        })        .await;     client        .on_request::<StackTrace, _>(move |_, _| {            Ok(dap::StackTraceResponse {                stack_frames: Vec::default(),                total_frames: None,            })        })        .await;     // assert we have a debug panel item before the session has stopped    workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();             debug_panel.update(cx, |this, cx| {                assert!(this.active_session(cx).is_some());                // we have one active session and one inert item                assert_eq!(2, this.pane().unwrap().read(cx).items_len());            });        })        .unwrap();     client        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {            reason: dap::StoppedEventReason::Pause,            description: None,            thread_id: Some(1),            preserve_focus_hint: None,            text: None,            all_threads_stopped: None,            hit_breakpoint_ids: None,        }))        .await;     cx.run_until_parked();     // assert we added a debug panel item    workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();            let active_session = debug_panel                .update(cx, |this, cx| this.active_session(cx))                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             // we have one active session and one inert item            assert_eq!(                2,                debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())            );            assert_eq!(client.id(), active_session.read(cx).session_id(cx).unwrap());            assert_eq!(                ThreadId(1),                running_state.read(cx).selected_thread_id().unwrap()            );        })        .unwrap();     client        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {            reason: dap::StoppedEventReason::Pause,            description: None,            thread_id: Some(2),            preserve_focus_hint: None,            text: None,            all_threads_stopped: None,            hit_breakpoint_ids: None,        }))        .await;     cx.run_until_parked();     workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();            let active_session = debug_panel                .update(cx, |this, cx| this.active_session(cx))                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             // we have one active session and one inert item            assert_eq!(                2,                debug_panel.update(cx, |this, cx| this.pane().unwrap().read(cx).items_len())            );            assert_eq!(client.id(), active_session.read(cx).session_id(cx).unwrap());            assert_eq!(                ThreadId(1),                running_state.read(cx).selected_thread_id().unwrap()            );        })        .unwrap();     let shutdown_session = project.update(cx, |project, cx| {        project.dap_store().update(cx, |dap_store, cx| {            dap_store.shutdown_session(session.read(cx).session_id(), cx)        })    });     shutdown_session.await.unwrap();     // assert we still have a debug panel item after the client shutdown    workspace        .update(cx, |workspace, _window, cx| {            let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();            let active_session = debug_panel                .update(cx, |this, cx| this.active_session(cx))                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             debug_panel.update(cx, |this, cx| {                assert!(this.active_session(cx).is_some());                assert_eq!(2, this.pane().unwrap().read(cx).items_len());                assert_eq!(                    ThreadId(1),                    running_state.read(cx).selected_thread_id().unwrap()                );            });        })        .unwrap();} #[gpui::test]async fn test_handle_successful_run_in_terminal_reverse_request(    executor: BackgroundExecutor,    cx: &mut TestAppContext,) {    init_test(cx);     let send_response = Arc::new(AtomicBool::new(false));     let fs = FakeFs::new(executor.clone());     fs.insert_tree(        "/project",        json!({            "main.rs": "First line\nSecond line\nThird line\nFourth line",        }),    )    .await;     let project = Project::test(fs, ["/project".as_ref()], cx).await;    let workspace = init_test_workspace(&project, cx).await;    let cx = &mut VisualTestContext::from_window(*workspace, cx);     let task = project.update(cx, |project, cx| {        project.fake_debug_session(            dap::DebugRequestType::Launch(LaunchConfig::default()),            None,            false,            cx,        )    });     let session = task.await.unwrap();    let client = session.update(cx, |session, _| session.adapter_client().unwrap());     client        .on_response::<RunInTerminal, _>({            let send_response = send_response.clone();            move |response| {                send_response.store(true, Ordering::SeqCst);                 assert!(response.success);                assert!(response.body.is_some());            }        })        .await;     client        .fake_reverse_request::<RunInTerminal>(RunInTerminalRequestArguments {            kind: None,            title: None,            cwd: std::env::temp_dir().to_string_lossy().to_string(),            args: vec![],            env: None,            args_can_be_interpreted_by_shell: None,        })        .await;     cx.run_until_parked();     assert!(        send_response.load(std::sync::atomic::Ordering::SeqCst),        "Expected to receive response from reverse request"    );     workspace        .update(cx, |workspace, _window, cx| {            let terminal_panel = workspace.panel::<TerminalPanel>(cx).unwrap();             let panel = terminal_panel.read(cx).pane().unwrap().read(cx);             assert_eq!(1, panel.items_len());            assert!(panel                .active_item()                .unwrap()                .downcast::<TerminalView>()                .unwrap()                .read(cx)                .terminal()                .read(cx)                .debug_terminal());        })        .unwrap();     let shutdown_session = project.update(cx, |project, cx| {        project.dap_store().update(cx, |dap_store, cx| {            dap_store.shutdown_session(session.read(cx).session_id(), cx)        })    });     shutdown_session.await.unwrap();} // // covers that we always send a response back, if something when wrong,// // while spawning the terminal#[gpui::test]async fn test_handle_error_run_in_terminal_reverse_request(    executor: BackgroundExecutor,    cx: &mut TestAppContext,) {    init_test(cx);     let send_response = Arc::new(AtomicBool::new(false));     let fs = FakeFs::new(executor.clone());     fs.insert_tree(        "/project",        json!({            "main.rs": "First line\nSecond line\nThird line\nFourth line",        }),    )    .await;     let project = Project::test(fs, ["/project".as_ref()], cx).await;    let workspace = init_test_workspace(&project, cx).await;    let cx = &mut VisualTestContext::from_window(*workspace, cx);     let task = project.update(cx, |project, cx| {        project.fake_debug_session(            dap::DebugRequestType::Launch(LaunchConfig::default()),            None,            false,            cx,        )    });

Lines 1–500 of 1487.