mod go_locator { use collections::HashMap; use dap::{DapLocator, adapters::DebugAdapterName}; use gpui::TestAppContext; use project::debugger::locators::go::{DelveLaunchRequest, GoLocator}; use task::{HideStrategy, RevealStrategy, RevealTarget, SaveStrategy, Shell, TaskTemplate}; #[gpui::test] async fn test_create_scenario_for_go_build(_: &mut TestAppContext) { let locator = GoLocator; let task = TaskTemplate { label: "go build".into(), command: "go".into(), args: vec!["build".into(), ".".into()], env: Default::default(), cwd: Some("${ZED_WORKTREE_ROOT}".into()), use_new_terminal: false, allow_concurrent_runs: false, reveal: RevealStrategy::Always, reveal_target: RevealTarget::Dock, hide: HideStrategy::Never, shell: Shell::System, tags: vec![], show_summary: true, show_command: true, save: SaveStrategy::default(), hooks: Default::default(), }; let scenario = locator .create_scenario(&task, "test label", &DebugAdapterName("Delve".into())) .await; assert!(scenario.is_none()); } #[gpui::test] async fn test_skip_non_go_commands_with_non_delve_adapter(_: &mut TestAppContext) { let locator = GoLocator; let task = TaskTemplate { label: "cargo build".into(), command: "cargo".into(), args: vec!["build".into()], env: Default::default(), cwd: Some("${ZED_WORKTREE_ROOT}".into()), use_new_terminal: false, allow_concurrent_runs: false, reveal: RevealStrategy::Always, reveal_target: RevealTarget::Dock, hide: HideStrategy::Never, shell: Shell::System, tags: vec![], show_summary: true, show_command: true, save: SaveStrategy::default(), hooks: Default::default(), }; let scenario = locator .create_scenario( &task, "test label", &DebugAdapterName("SomeOtherAdapter".into()), ) .await; assert!(scenario.is_none()); let scenario = locator .create_scenario(&task, "test label", &DebugAdapterName("Delve".into())) .await; assert!(scenario.is_none()); } #[gpui::test] async fn test_go_locator_run(_: &mut TestAppContext) { let locator = GoLocator; let delve = DebugAdapterName("Delve".into()); let task = TaskTemplate { label: "go run with flags".into(), command: "go".into(), args: vec![ "run".to_string(), "-race".to_string(), "-ldflags".to_string(), "-X main.version=1.0".to_string(), "./cmd/myapp".to_string(), "--config".to_string(), "production.yaml".to_string(), "--verbose".to_string(), ], env: { let mut env = HashMap::default(); env.insert("GO_ENV".to_string(), "production".to_string()); env }, cwd: Some("/project/root".into()), ..Default::default() }; let scenario = locator .create_scenario(&task, "test run label", &delve) .await .unwrap(); let config: DelveLaunchRequest = serde_json::from_value(scenario.config).unwrap(); assert_eq!( config, DelveLaunchRequest { request: "launch".to_string(), mode: "debug".to_string(), program: "./cmd/myapp".to_string(), build_flags: vec![ "-race".to_string(), "-ldflags".to_string(), "-X main.version=1.0".to_string() ], args: vec![ "--config".to_string(), "production.yaml".to_string(), "--verbose".to_string(), ], env: { let mut env = HashMap::default(); env.insert("GO_ENV".to_string(), "production".to_string()); env }, cwd: Some("/project/root".to_string()), } ); } #[gpui::test] async fn test_go_locator_test(_: &mut TestAppContext) { let locator = GoLocator; let delve = DebugAdapterName("Delve".into()); // Test with tags and run flag let task_with_tags = TaskTemplate { label: "test".into(), command: "go".into(), args: vec![ "test".to_string(), "-tags".to_string(), "integration,unit".to_string(), "-run".to_string(), "Foo".to_string(), ".".to_string(), ], ..Default::default() }; let result = locator .create_scenario(&task_with_tags, "", &delve) .await .unwrap(); let config: DelveLaunchRequest = serde_json::from_value(result.config).unwrap(); assert_eq!( config, DelveLaunchRequest { request: "launch".to_string(), mode: "test".to_string(), program: ".".to_string(), build_flags: vec!["-tags".to_string(), "integration,unit".to_string(),], args: vec![ "-test.run".to_string(), "Foo".to_string(), "-test.v".to_string() ], env: Default::default(), cwd: None, } ); } #[gpui::test] async fn test_skip_unsupported_go_commands(_: &mut TestAppContext) { let locator = GoLocator; let task = TaskTemplate { label: "go clean".into(), command: "go".into(), args: vec!["clean".into()], env: Default::default(), cwd: Some("${ZED_WORKTREE_ROOT}".into()), use_new_terminal: false, allow_concurrent_runs: false, reveal: RevealStrategy::Always, reveal_target: RevealTarget::Dock, hide: HideStrategy::Never, shell: Shell::System, tags: vec![], show_summary: true, show_command: true, save: SaveStrategy::default(), hooks: Default::default(), }; let scenario = locator .create_scenario(&task, "test label", &DebugAdapterName("Delve".into())) .await; assert!(scenario.is_none()); } } mod python_locator { use dap::{DapLocator, adapters::DebugAdapterName}; use serde_json::json; use project::debugger::locators::python::*; use task::{DebugScenario, TaskTemplate}; #[gpui::test] async fn test_python_locator() { let adapter = DebugAdapterName("Debugpy".into()); let build_task = TaskTemplate { label: "run module '$ZED_FILE'".into(), command: "$ZED_CUSTOM_PYTHON_ACTIVE_ZED_TOOLCHAIN".into(), args: vec!["-m".into(), "$ZED_CUSTOM_PYTHON_MODULE_NAME".into()], env: Default::default(), cwd: Some("$ZED_WORKTREE_ROOT".into()), use_new_terminal: false, allow_concurrent_runs: false, reveal: task::RevealStrategy::Always, reveal_target: task::RevealTarget::Dock, hide: task::HideStrategy::Never, tags: vec!["python-module-main-method".into()], shell: task::Shell::System, show_summary: false, show_command: false, save: task::SaveStrategy::default(), hooks: Default::default(), }; let expected_scenario = DebugScenario { adapter: "Debugpy".into(), label: "run module 'main.py'".into(), build: None, config: json!({ "request": "launch", "python": "$ZED_CUSTOM_PYTHON_ACTIVE_ZED_TOOLCHAIN", "args": [], "cwd": "$ZED_WORKTREE_ROOT", "module": "$ZED_CUSTOM_PYTHON_MODULE_NAME", }), tcp_connection: None, }; assert_eq!( PythonLocator .create_scenario(&build_task, "run module 'main.py'", &adapter) .await .expect("Failed to create a scenario"), expected_scenario ); } } mod memory { use project::debugger::{ MemoryCell, memory::{MemoryIterator, PageAddress, PageContents}, }; #[test] fn iterate_over_unmapped_memory() { let empty_iterator = MemoryIterator::new(0..=127, Default::default()); let actual = empty_iterator.collect::>(); let expected = vec![MemoryCell(None); 128]; assert_eq!(actual.len(), expected.len()); assert_eq!(actual, expected); } #[test] fn iterate_over_partially_mapped_memory() { let it = MemoryIterator::new( 0..=127, vec![(PageAddress(5), PageContents::mapped(vec![1]))].into_iter(), ); let actual = it.collect::>(); let expected = std::iter::repeat_n(MemoryCell(None), 5) .chain(std::iter::once(MemoryCell(Some(1)))) .chain(std::iter::repeat_n(MemoryCell(None), 122)) .collect::>(); assert_eq!(actual.len(), expected.len()); assert_eq!(actual, expected); } #[test] fn reads_from_the_middle_of_a_page() { let partial_iter = MemoryIterator::new( 20..=30, vec![(PageAddress(0), PageContents::mapped((0..255).collect()))].into_iter(), ); let actual = partial_iter.collect::>(); let expected = (20..=30) .map(|val| MemoryCell(Some(val))) .collect::>(); assert_eq!(actual.len(), expected.len()); assert_eq!(actual, expected); } }