#![allow(clippy::too_many_lines)]
mod support;
use serde_json::json;
use sqry_daemon::ipc::protocol::JsonRpcPayload;
use support::ipc::{TestIpcClient, TestServer, expect_error, expect_success};
async fn fresh_loaded() -> (TestServer, tempfile::TempDir, TestIpcClient, String) {
let server = TestServer::new().await;
let dir = tempfile::tempdir().unwrap();
let path = dir.path().to_string_lossy().to_string();
let mut client = TestIpcClient::connect(&server.path).await;
client.hello(1).await;
expect_success(
&client
.request("daemon/load", json!({ "index_root": &path }))
.await,
);
(server, dir, client, path)
}
fn assert_loaded_fresh_envelope(result: &serde_json::Value) {
assert_eq!(
result["meta"]["workspace_state"],
json!("Loaded"),
"workspace_state must be Loaded: {result}"
);
assert_eq!(
result["meta"]["stale"],
json!(false),
"stale must be false on Fresh Loaded arm: {result}"
);
}
fn assert_method_reachable(resp: &sqry_daemon::ipc::protocol::JsonRpcResponse) {
match &resp.payload {
JsonRpcPayload::Success { result } => {
assert_loaded_fresh_envelope(result);
}
JsonRpcPayload::Error { error } => {
assert_eq!(
error.code, -32603,
"method reachable must surface success or -32603, got {error:?}"
);
}
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn relation_query() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"relation_query",
json!({
"symbol": "main",
"relation_type": "callers",
"path": &path,
"max_results": 10,
"max_depth": 1,
"page_size": 50,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn direct_callers() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"direct_callers",
json!({
"symbol": "main",
"path": &path,
"max_results": 10,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn direct_callees() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"direct_callees",
json!({
"symbol": "main",
"path": &path,
"max_results": 10,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn find_unused() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"find_unused",
json!({
"path": &path,
"scope": "all",
"language": [],
"symbol_kind": [],
"max_results": 10,
}),
)
.await;
let result = expect_success(&resp);
assert_loaded_fresh_envelope(result);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn is_node_in_cycle() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"is_node_in_cycle",
json!({
"symbol": "main",
"path": &path,
"cycle_type": "calls",
"min_depth": 2,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn trace_path() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"trace_path",
json!({
"from_symbol": "main",
"to_symbol": "main",
"path": &path,
"max_hops": 5,
"max_paths": 5,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn subgraph() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"subgraph",
json!({
"symbols": ["main"],
"path": &path,
"max_depth": 2,
"max_nodes": 10,
"page_size": 50,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn export_graph() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"export_graph",
json!({
"path": &path,
"symbol_name": "main",
"format": "json",
"max_depth": 2,
"max_results": 10,
"page_size": 200,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn complexity_metrics() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"complexity_metrics",
json!({
"path": &path,
"max_results": 10,
}),
)
.await;
let result = expect_success(&resp);
assert_loaded_fresh_envelope(result);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn semantic_diff() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"semantic_diff",
json!({
"path": &path,
"base": {"ref": "HEAD~1"},
"target": {"ref": "HEAD"},
"max_results": 10,
"page_size": 100,
}),
)
.await;
let err = expect_error(&resp);
assert_eq!(err.code, -32603, "semantic_diff: {err:?}");
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn dependency_impact() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"dependency_impact",
json!({
"symbol": "main",
"path": &path,
"max_depth": 3,
"max_results": 10,
"page_size": 100,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn show_dependencies() {
let (server, _dir, mut client, path) = fresh_loaded().await;
let resp = client
.request(
"show_dependencies",
json!({
"symbol_name": "main",
"path": &path,
"max_depth": 2,
"max_results": 10,
"page_size": 100,
}),
)
.await;
assert_method_reachable(&resp);
drop(client);
server.stop().await;
}