Files
yvgude--lean-ctx/rust/tests/ctx_compose_scenarios.rs
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

144 lines
5.2 KiB
Rust

//! End-to-end coverage for the `ctx_compose` task composer.
//!
//! The library unit tests only cover keyword extraction; these exercise the
//! full `handle()` path (semantic ranking + exact match + symbol body) and the
//! H1 hardening: the semantic stage must never stall the call beyond its budget.
use std::sync::Mutex;
use std::time::{Duration, Instant};
use lean_ctx::tools::CrpMode;
use lean_ctx::tools::ctx_compose;
/// `LEAN_CTX_COMPOSE_BUDGET_MS` is process-global; serialize tests that set it.
static ENV_GUARD: Mutex<()> = Mutex::new(());
fn write_corpus() -> tempfile::TempDir {
let dir = tempfile::tempdir().unwrap();
std::fs::write(
dir.path().join("auth.rs"),
"pub fn authenticate_user(token: &str) -> bool {\n \
validate_token(token) && !token.is_empty()\n}\n\n\
fn validate_token(token: &str) -> bool {\n token.len() > 8\n}\n",
)
.unwrap();
std::fs::write(
dir.path().join("config.rs"),
"pub fn parse_config(path: &str) -> String {\n \
std::fs::read_to_string(path).unwrap_or_default()\n}\n",
)
.unwrap();
dir
}
#[test]
fn compose_returns_all_sections_with_symbol_body() {
let _guard = ENV_GUARD
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
let dir = write_corpus();
let (out, tokens) = ctx_compose::handle(
"how does authenticate_user validate the token",
&dir.path().to_string_lossy(),
CrpMode::Off,
);
assert!(out.contains("TASK:"), "must echo the task header");
assert!(
out.contains("## Ranked files (semantic)"),
"must contain the semantic ranking section"
);
assert!(
out.contains("## Exact matches"),
"must contain the exact-match section"
);
assert!(
out.contains("authenticate_user"),
"exact matches / symbol body must surface the queried symbol:\n{out}"
);
assert!(tokens > 0, "token count must be reported");
}
#[test]
fn compose_degrades_under_tight_budget_without_stalling() {
let _guard = ENV_GUARD
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
// A 1 ms budget guarantees the semantic worker cannot finish in time, so the
// call must degrade gracefully instead of blocking on the (cold) build.
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("LEAN_CTX_COMPOSE_BUDGET_MS", "1") };
let dir = write_corpus();
let start = Instant::now();
let (out, _tokens) = ctx_compose::handle(
"how does authenticate_user validate the token",
&dir.path().to_string_lossy(),
CrpMode::Off,
);
let elapsed = start.elapsed();
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
// The exact-match + symbol stages are synchronous and index-backed, so the
// whole call should still return promptly even when ranking is deferred.
assert!(
elapsed < Duration::from_secs(10),
"tight budget must not stall the call (took {elapsed:?})"
);
assert!(
out.contains("## Ranked files (semantic)"),
"section header is always present"
);
assert!(
out.contains("## Exact matches"),
"exact matches remain authoritative under degradation"
);
}
#[test]
fn compose_rejects_empty_task() {
let _guard = ENV_GUARD
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let (out, tokens) = ctx_compose::handle(" ", "/tmp", CrpMode::Off);
assert!(out.starts_with("ERROR"));
assert_eq!(tokens, 0);
}
#[test]
fn compose_surfaces_associative_neighbours() {
let _guard = ENV_GUARD
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
// Generous graph budget so the (tiny) index build never times out here.
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("LEAN_CTX_COMPOSE_GRAPH_BUDGET_MS", "8000") };
let dir = write_corpus();
// `authenticate_user` lives in auth.rs; config.rs is a same-dir sibling, so
// the graph connects them and spreading activation from the auth.rs seed
// must surface config.rs as an associative neighbour.
let (out, _tokens) = ctx_compose::handle(
"explain authenticate_user",
&dir.path().to_string_lossy(),
CrpMode::Off,
);
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_GRAPH_BUDGET_MS") };
assert!(
out.contains("## Related (associative"),
"associative section should appear when the graph connects files:\n{out}"
);
assert!(
out.contains("config.rs"),
"the sibling neighbour should be surfaced via spreading activation:\n{out}"
);
}