1390 lines · 41.9 KB · Rust
RawDownload
use crate::*;use dap::{    ErrorResponse, Message, RunInTerminalRequestArguments, SourceBreakpoint,    StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest,    client::SessionId,    requests::{        Continue, Disconnect, Launch, Next, RunInTerminal, SetBreakpoints, StackTrace,        StartDebugging, StepBack, StepIn, StepOut, Threads,    },};use editor::{    Editor, EditorMode, MultiBuffer,    actions::{self},};use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};use project::{    FakeFs, Project,    debugger::session::{ThreadId, ThreadStatus},};use serde_json::json;use std::{    path::Path,    sync::{        Arc,        atomic::{AtomicBool, Ordering},    },};use terminal_view::{TerminalView, terminal_panel::TerminalPanel};use tests::{active_debug_session_panel, init_test, init_test_workspace};use util::path;use workspace::{Item, dock::Panel}; #[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 session = debugger::test::start_debug_session(&project, cx, |_| {})        .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(),            }],        })    });     client.on_request::<StackTrace, _>(move |_, _| {        Ok(dap::StackTraceResponse {            stack_frames: Vec::default(),            total_frames: None,        })    });     cx.run_until_parked();     // 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, _| debug_panel.active_session().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().is_some());                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, _| this.active_session())                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             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, _| this.active_session())                .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().is_some());                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 session = debugger::test::start_debug_session(&project, cx, |_| {})        .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(),            }],        })    });     client.on_request::<StackTrace, _>(move |_, _| {        Ok(dap::StackTraceResponse {            stack_frames: Vec::default(),            total_frames: None,        })    });     cx.run_until_parked();     // 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, _| {                assert!(this.active_session().is_some());            });        })        .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, _| this.active_session())                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             assert_eq!(client.id(), active_session.read(cx).session_id(cx));            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, _| this.active_session())                .unwrap();             let running_state = active_session.update(cx, |active_session, _| {                active_session                    .mode()                    .as_running()                    .expect("Session should be running by this point")                    .clone()            });             assert_eq!(client.id(), active_session.read(cx).session_id(cx));            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, _| this.active_session())                .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().is_some());                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 session = debugger::test::start_debug_session(&project, cx, |_| {})        .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 session = debugger::test::start_debug_session(&project, cx, |_| {})        .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: "/non-existing/path".into(), // invalid/non-existing path will cause the terminal spawn to fail            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();             assert_eq!(                0,                terminal_panel.read(cx).pane().unwrap().read(cx).items_len()            );        })        .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();}

Lines 1–500 of 1390.