use super::*;
use pathfinder_common::config::PathfinderConfig;
use pathfinder_common::sandbox::Sandbox;
use pathfinder_common::types::WorkspaceRoot;
use pathfinder_search::MockScout;
use pathfinder_treesitter::mock::MockSurgeon;
use std::sync::Arc;
fn make_server(ws: WorkspaceRoot, mock_surgeon: MockSurgeon) -> PathfinderServer {
let config = PathfinderConfig::default();
let sandbox = Sandbox::new(ws.path(), &config.sandbox);
PathfinderServer::with_engines(
ws,
config,
sandbox,
Arc::new(MockScout::default()),
Arc::new(mock_surgeon),
)
}
#[tokio::test]
async fn test_get_semantic_path_found() {
let ws_dir = tempfile::tempdir().expect("temp dir");
let file_rel = "src/auth.rs";
let file_abs = ws_dir.path().join(file_rel);
std::fs::create_dir_all(file_abs.parent().unwrap()).expect("create dir");
std::fs::write(&file_abs, "fn login() {}").expect("write file");
let ws = WorkspaceRoot::new(ws_dir.path()).expect("valid root");
let mock_surgeon = MockSurgeon::new();
mock_surgeon
.enclosing_symbol_results
.lock()
.unwrap()
.push(Ok(Some("login".to_owned())));
let server = make_server(ws, mock_surgeon);
let params = LocateParams {
file: Some(file_rel.to_owned()),
line: Some(1),
..Default::default()
};
let result = server.get_semantic_path_impl(params).await;
assert!(result.is_ok(), "expected Ok, got: {:?}", result.err());
let call = result.unwrap();
let meta: GetSemanticPathResult =
serde_json::from_value(call.structured_content.unwrap()).unwrap();
assert_eq!(meta.semantic_path, Some("src/auth.rs::login".to_owned()));
assert_eq!(meta.symbol, Some("login".to_owned()));
assert_eq!(meta.line, 1);
}
#[tokio::test]
async fn test_get_semantic_path_not_in_symbol() {
let ws_dir = tempfile::tempdir().expect("temp dir");
let file_rel = "src/lib.rs";
let file_abs = ws_dir.path().join(file_rel);
std::fs::create_dir_all(file_abs.parent().unwrap()).expect("create dir");
std::fs::write(&file_abs, "use std::io;").expect("write file");
let ws = WorkspaceRoot::new(ws_dir.path()).expect("valid root");
let mock_surgeon = MockSurgeon::new();
mock_surgeon
.enclosing_symbol_results
.lock()
.unwrap()
.push(Ok(None));
let server = make_server(ws, mock_surgeon);
let params = LocateParams {
file: Some(file_rel.to_owned()),
line: Some(1),
..Default::default()
};
let result = server.get_semantic_path_impl(params).await;
assert!(result.is_ok());
let call = result.unwrap();
let meta: GetSemanticPathResult =
serde_json::from_value(call.structured_content.unwrap()).unwrap();
assert!(meta.semantic_path.is_none());
assert!(meta.symbol.is_none());
}
#[tokio::test]
async fn test_get_semantic_path_file_not_found() {
let ws_dir = tempfile::tempdir().expect("temp dir");
let ws = WorkspaceRoot::new(ws_dir.path()).expect("valid root");
let mock_surgeon = MockSurgeon::new();
let server = make_server(ws, mock_surgeon);
let params = LocateParams {
file: Some("nonexistent.rs".to_owned()),
line: Some(5),
..Default::default()
};
let result = server.get_semantic_path_impl(params).await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code, rmcp::model::ErrorCode::INVALID_PARAMS);
}
#[tokio::test]
async fn test_get_semantic_path_sandbox_denied() {
let ws_dir = tempfile::tempdir().expect("temp dir");
let ws = WorkspaceRoot::new(ws_dir.path()).expect("valid root");
let mock_surgeon = MockSurgeon::new();
let server = make_server(ws, mock_surgeon);
let params = LocateParams {
file: Some(".env".to_owned()),
line: Some(1),
..Default::default()
};
let result = server.get_semantic_path_impl(params).await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code, rmcp::model::ErrorCode(-32001));
}