use super::*;
use crate::tools::CrpMode;
fn no_policy() -> lean_ctx::core::policy::runtime::TestPolicyOverride {
lean_ctx::core::policy::runtime::TestPolicyOverride::set(None)
}
#[test]
fn search_output_is_byte_stable_across_calls() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
for i in 0..5 {
std::fs::write(
dir.path().join(format!("f{i}.rs")),
format!("fn target_{i}() {{}}\nfn other() {{}}\n"),
)
.unwrap();
}
let root = dir.path().to_string_lossy().into_owned();
let run = || {
handle(
"target",
&root,
Some("*.rs"),
20,
CrpMode::Off,
true,
true,
false,
)
.text
};
assert_eq!(run(), run(), "search output must be deterministic");
}
#[test]
fn invalid_regex_is_searched_literally_with_a_note() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(
dir.path().join("a.rs"),
"fn run(&self) {}\nlet x = items[0];\nrun_other();\n",
)
.unwrap();
let root = dir.path().to_string_lossy().into_owned();
for (pattern, expected) in [("fn run(&self", "a.rs"), ("items[0", "items[0]")] {
let out = handle(pattern, &root, None, 20, CrpMode::Off, true, true, false).text;
assert!(!out.starts_with("ERROR:"), "{pattern}: {out}");
assert!(
out.contains("searched for it literally"),
"{pattern}: {out}"
);
assert!(out.contains(expected), "{pattern}: {out}");
}
let regex = handle("run_\\w+", &root, None, 20, CrpMode::Off, true, true, false).text;
assert!(
!regex.contains("literally") && regex.contains("run_other"),
"valid regex is unchanged: {regex}"
);
}
#[test]
fn anchored_search_emits_line_hash_per_hit_opt_in_only() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.rs"), "let needle = 1;\nother\n").unwrap();
let root = dir.path().to_string_lossy().into_owned();
let plain = handle(
"needle",
&root,
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
!plain.contains("[anchored:"),
"default must carry no legend"
);
assert!(
plain.contains("a.rs:1 "),
"default keeps path:line content: {plain}"
);
let anchored = handle(
"needle",
&root,
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
true,
)
.text;
let hh = lean_ctx::core::anchor::line_hash("let needle = 1;");
assert!(anchored.contains("[anchored: path:line:hh → edit via ctx_patch]"));
assert!(
anchored.contains(&format!("a.rs:1:{hh} ")),
"anchored hit must carry the line hash: {anchored}"
);
}
#[test]
#[cfg(feature = "tree-sitter")]
fn hits_inside_multiline_symbols_carry_enclosing_tag() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(
dir.path().join("a.rs"),
"fn outer() {\n let needle = 1;\n needle\n}\nfn tiny() {}\n",
)
.unwrap();
let out = handle(
"needle",
dir.path().to_string_lossy().as_ref(),
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
out.contains("∈outer@L1"),
"hit must name its enclosing fn: {out}"
);
assert!(
!out.contains("[∈ enclosing symbol"),
"the legend line is gone: {out}"
);
}
#[test]
fn single_line_symbols_get_no_enclosing_tag() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.rs"), "fn one_liner() {}\n").unwrap();
let out = handle(
"one_liner",
dir.path().to_string_lossy().as_ref(),
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(!out.contains('∈'), "single-line symbol → no tag: {out}");
}
#[test]
fn search_results_are_deterministically_ordered_by_path() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
let a = dir.path().join("a.txt");
let b = dir.path().join("b.txt");
std::fs::write(&b, "match\n").unwrap();
std::fs::write(&a, "match\n").unwrap();
let out = handle(
"match",
dir.path().to_string_lossy().as_ref(),
Some("*.txt"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
let mut match_lines: Vec<&str> = out
.lines()
.filter(|l| l.contains(".txt:") && l.contains("match"))
.collect();
match_lines.truncate(2);
assert_eq!(match_lines.len(), 2);
assert!(
match_lines[0].contains("a.txt:"),
"first match should come from a.txt, got: {}",
match_lines[0]
);
assert!(
match_lines[1].contains("b.txt:"),
"second match should come from b.txt, got: {}",
match_lines[1]
);
}
#[test]
fn warm_index_and_content_cache_path_returns_correct_matches() {
let _no_policy = lean_ctx::core::policy::runtime::TestPolicyOverride::set(None);
let dir = tempfile::tempdir().unwrap();
std::fs::write(
dir.path().join("a.rs"),
"fn authenticate() {}\nlet x = 1;\n",
)
.unwrap();
std::fs::write(dir.path().join("b.rs"), "fn connect() {}\n").unwrap();
let root = dir.path().to_string_lossy().to_string();
assert!(
lean_ctx::core::search_index::warm_blocking(&root, true, false),
"index should warm for a small clean corpus"
);
let out = super::handle(
"authenticate",
&root,
None,
10,
CrpMode::Off,
true,
false,
false,
)
.text;
assert!(
out.contains("a.rs"),
"warm-index + cache search must find the match: {out}"
);
assert!(
out.contains("authenticate"),
"the matched line must be present: {out}"
);
assert!(
!out.contains("b.rs"),
"a non-matching file must not appear in results: {out}"
);
}
#[test]
fn search_finds_word_literals_added_after_index_warm() {
let _no_policy = no_policy();
let _lock = lean_ctx::core::data_dir::test_env_lock();
lean_ctx::test_env::remove_var("LEAN_CTX_DISABLE_SEARCH_INDEX");
lean_ctx::test_env::remove_var("LEAN_CTX_SEARCH_INDEX_COALESCE_MS");
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.rs"), "fn existing() {}\n").unwrap();
std::fs::write(dir.path().join("b.rs"), "fn other() {}\n").unwrap();
let root = dir.path().to_string_lossy().to_string();
assert!(
lean_ctx::core::search_index::warm_blocking(&root, true, false),
"index should warm for a small clean corpus"
);
std::fs::write(dir.path().join("c.rs"), "fn added_after_warm_zzz() {}\n").unwrap();
let out_new = handle(
"added_after_warm_zzz",
&root,
None,
10,
CrpMode::Off,
true,
false,
false,
)
.text;
assert!(
out_new.contains("c.rs") && out_new.contains("added_after_warm_zzz"),
"a file created after the index warm must be found: {out_new}"
);
std::fs::write(
dir.path().join("a.rs"),
"fn existing() {}\nfn edited_after_warm_zzz() {}\n",
)
.unwrap();
let out_edit = handle(
"edited_after_warm_zzz",
&root,
None,
10,
CrpMode::Off,
true,
false,
false,
)
.text;
assert!(
out_edit.contains("a.rs") && out_edit.contains("edited_after_warm_zzz"),
"content appended after the index warm must be found: {out_edit}"
);
}
#[test]
fn symbol_substitution_is_off_by_default() {
let _no_policy = no_policy();
let _lock = lean_ctx::core::data_dir::test_env_lock();
lean_ctx::test_env::remove_var("LEAN_CTX_SYMBOL_MAP");
let dir = tempfile::tempdir().unwrap();
let f = dir.path().join("a.rs");
std::fs::write(
&f,
"fn longIdentifierAlpha() {}\nfn longIdentifierBeta() {}\nfn longIdentifierGamma() {}\n",
)
.unwrap();
let out = handle(
"longIdentifier",
dir.path().to_string_lossy().as_ref(),
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
!out.contains("§MAP"),
"default agent-facing output must not carry a §MAP table: {out}"
);
assert!(
!out.contains('α'),
"default agent-facing output must not carry α-symbols: {out}"
);
assert!(
out.contains("longIdentifierAlpha"),
"identifiers should appear raw by default: {out}"
);
}
#[test]
fn secret_like_files_are_skipped_by_default() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
let secret = dir.path().join("key.pem");
let ok = dir.path().join("ok.txt");
std::fs::write(&secret, "match\n").unwrap();
std::fs::write(&ok, "match\n").unwrap();
let out = handle(
"match",
dir.path().to_string_lossy().as_ref(),
None,
10,
CrpMode::Off,
true,
false,
false,
)
.text;
assert!(out.contains("ok.txt:"), "expected ok.txt match, got: {out}");
assert!(
!out.contains("key.pem:"),
"secret-like file should be skipped, got: {out}"
);
assert!(
out.contains("secret-like files skipped"),
"expected boundary skip note, got: {out}"
);
}
#[test]
#[cfg(unix)]
fn search_skips_named_pipe_without_hanging() {
let _no_policy = no_policy();
use std::sync::mpsc;
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("real.txt"), "needle_here = 1\n").unwrap();
let fifo = dir.path().join("pipe.fifo");
let c = std::ffi::CString::new(fifo.to_string_lossy().as_bytes()).unwrap();
assert_eq!(
unsafe { libc::mkfifo(c.as_ptr(), 0o644) },
0,
"mkfifo failed"
);
let dir_path = dir.path().to_string_lossy().to_string();
let (tx, rx) = mpsc::channel();
std::thread::spawn(move || {
let out = handle(
"needle_here",
&dir_path,
None,
10,
CrpMode::Off,
true,
true,
false,
)
.text;
let _ = tx.send(out);
});
let out = rx
.recv_timeout(Duration::from_secs(5))
.expect("ctx_search hung on a FIFO (#336 regression)");
assert!(
out.contains("real.txt"),
"the real file must still match: {out}"
);
assert!(
out.contains("special files skipped"),
"the FIFO must be reported as a skipped special file: {out}"
);
}
#[test]
fn search_deadline_env_override_is_respected() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
lean_ctx::test_env::set_var("LEAN_CTX_SEARCH_DEADLINE_MS", "0");
assert!(search_deadline().is_none(), "0 must disable the deadline");
lean_ctx::test_env::set_var("LEAN_CTX_SEARCH_DEADLINE_MS", "250");
assert_eq!(search_deadline(), Some(Duration::from_millis(250)));
lean_ctx::test_env::remove_var("LEAN_CTX_SEARCH_DEADLINE_MS");
assert_eq!(
search_deadline(),
Some(Duration::from_secs(10)),
"default budget is 10s"
);
}
#[test]
fn extract_extensions_handles_single_brace_and_none() {
assert_eq!(extract_extensions(Some("*.rs")), vec!["rs"]);
assert_eq!(extract_extensions(Some("src/**/*.tsx")), vec!["tsx"]);
assert_eq!(extract_extensions(Some("*.{rs,ts}")), vec!["rs", "ts"]);
assert_eq!(
extract_extensions(Some("*.{rs, ts , js}")),
vec!["rs", "ts", "js"]
);
assert_eq!(extract_extensions(None), Vec::<String>::new());
}
#[test]
fn extract_extensions_ignores_dots_in_directory_segments() {
assert_eq!(
extract_extensions(Some("config.v2/src/**/*.rs")),
vec!["rs"]
);
assert_eq!(extract_extensions(Some("src/v2.0/*.module.ts")), vec!["ts"]);
assert_eq!(extract_extensions(Some("src/**/*")), Vec::<String>::new());
assert_eq!(
extract_extensions(Some("config.v2/Makefile")),
Vec::<String>::new()
);
}
#[test]
fn include_glob_filters_by_brace_expansion() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.rs"), "brace_glob_needle\n").unwrap();
std::fs::write(dir.path().join("b.ts"), "brace_glob_needle\n").unwrap();
std::fs::write(dir.path().join("c.py"), "brace_glob_needle\n").unwrap();
let out = handle(
"brace_glob_needle",
dir.path().to_string_lossy().as_ref(),
Some("*.{rs,ts}"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.contains("a.rs"), "rs file must match: {out}");
assert!(out.contains("b.ts"), "ts file must match: {out}");
assert!(!out.contains("c.py"), "py file must be excluded: {out}");
}
#[test]
fn comma_separated_include_is_a_glob_list() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.go"), "comma_glob_needle_1994\n").unwrap();
std::fs::write(dir.path().join("b.yaml"), "comma_glob_needle_1994\n").unwrap();
std::fs::write(dir.path().join("c.py"), "comma_glob_needle_1994\n").unwrap();
let out = handle(
"comma_glob_needle_1994",
dir.path().to_string_lossy().as_ref(),
Some("*.go, *.yaml"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.contains("a.go"), "go file must match: {out}");
assert!(out.contains("b.yaml"), "yaml file must match: {out}");
assert!(!out.contains("c.py"), "py file must be excluded: {out}");
assert_eq!(
extract_extensions(Some("*.go,*.{ts,tsx}")),
vec!["go", "ts", "tsx"]
);
}
#[test]
fn include_and_exclude_apply_to_a_file_root_by_its_name() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("main.rs");
std::fs::write(&file, "fn main() { let needle2059 = 1; }\n").unwrap();
let file = file.to_string_lossy().to_string();
let search = |include: Option<&str>, exclude: Option<&str>| {
handle_filtered(
"needle2059",
&file,
include,
10,
CrpMode::Off,
true,
false,
false,
exclude,
None,
)
.text
};
assert!(search(None, None).contains("let needle2059"));
for include in ["*.rs", "main.rs", "**/*.rs"] {
let hit = search(Some(include), None);
assert!(hit.contains("needle2059"), "include={include}: {hit}");
}
let filtered = search(Some("*.go"), None);
assert!(filtered.contains("(scanned 0 files)"), "{filtered}");
let excluded = search(None, Some("*.rs"));
assert!(!excluded.contains("let needle2059"), "{excluded}");
}
#[test]
fn zero_hits_state_the_scope_and_name_an_empty_filter() {
let _no_policy = no_policy();
let _lock = lean_ctx::core::data_dir::test_env_lock();
lean_ctx::test_env::remove_var("LEAN_CTX_DISABLE_SEARCH_INDEX");
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.go"), "package a\n").unwrap();
std::fs::write(dir.path().join("b.go"), "package b\n").unwrap();
let root = dir.path().to_string_lossy().to_string();
for warm in [false, true] {
if warm {
assert!(lean_ctx::core::search_index::warm_blocking(
&root, true, false
));
}
let search = |include: &str| {
handle(
"zzzqqqnomatch1994",
&root,
Some(include),
10,
CrpMode::Off,
true,
false,
false,
)
.text
};
let miss = search("*.go");
assert!(
miss.contains("(scanned 2 files)"),
"a genuine miss must report its scope (warm={warm}): {miss}"
);
assert!(!miss.contains("nothing was searched"), "{miss}");
let empty = search("*.nothing");
assert!(
empty.contains("(scanned 0 files)") && empty.contains("nothing was searched"),
"an empty filter must say so (warm={warm}): {empty}"
);
assert_ne!(miss, empty);
}
}
#[test]
fn bare_include_glob_matches_at_any_depth() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::create_dir_all(dir.path().join("a/deep/path")).unwrap();
std::fs::write(dir.path().join("a/deep/path/file.rs"), "needle\n").unwrap();
std::fs::write(dir.path().join("root.rs"), "needle\n").unwrap();
std::fs::write(dir.path().join("other.py"), "needle\n").unwrap();
let out = handle(
"needle",
dir.path().to_string_lossy().as_ref(),
Some("*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.contains("root.rs"), "root .rs file must match: {out}");
assert!(
out.contains("file.rs"),
"nested .rs file must match bare *.rs glob: {out}"
);
assert!(!out.contains("other.py"), ".py must be excluded: {out}");
let out2 = handle(
"needle",
dir.path().to_string_lossy().as_ref(),
Some("file.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
out2.contains("file.rs"),
"bare filename glob must match nested file: {out2}"
);
}
#[test]
fn include_glob_recursive_path_pattern() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::create_dir_all(dir.path().join("src/inner")).unwrap();
std::fs::write(dir.path().join("src/inner/deep.rs"), "needle\n").unwrap();
std::fs::write(dir.path().join("top.rs"), "needle\n").unwrap();
let out = handle(
"needle",
dir.path().to_string_lossy().as_ref(),
Some("src/**/*.rs"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.contains("deep.rs"), "nested match expected: {out}");
assert!(
!out.contains("top.rs"),
"root file outside src/ must be excluded: {out}"
);
}
#[test]
fn explicit_manifest_file_matches_its_include_glob() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("Cargo.toml");
std::fs::write(&file, "[package]\nname = \"manifest_include_2059\"\n").unwrap();
let out = handle(
"^\\[package\\]",
file.to_string_lossy().as_ref(),
Some("*.toml"),
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
out.contains("[package]") && out.contains("(scanned 1)"),
"the explicit Cargo.toml must be scanned: {out}"
);
}
#[test]
fn exclude_glob_drops_paths_and_exclude_pattern_drops_lines() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("app.rs"), "needle\n// needle skip me\n").unwrap();
std::fs::write(dir.path().join("app_test.rs"), "needle\n").unwrap();
let root = dir.path().to_string_lossy().into_owned();
let out = handle_filtered(
"needle",
&root,
None,
10,
CrpMode::Off,
true,
true,
false,
Some("*_test.rs"),
None,
)
.text;
assert!(out.contains("app.rs"), "app.rs must match: {out}");
assert!(
!out.contains("app_test.rs"),
"excluded path must be dropped: {out}"
);
let out2 = handle_filtered(
"needle",
&root,
Some("app.rs"),
10,
CrpMode::Off,
true,
true,
false,
None,
Some("skip me"),
)
.text;
assert!(out2.contains("1 matches"), "one line kept: {out2}");
assert!(!out2.contains("skip me"), "grep -v line dropped: {out2}");
}
#[test]
fn invalid_exclude_pattern_is_ignored_not_fatal() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("a.rs"), "needle\n").unwrap();
let root = dir.path().to_string_lossy().into_owned();
let out = handle_filtered(
"needle",
&root,
None,
10,
CrpMode::Off,
true,
true,
false,
None,
Some("([unclosed"),
)
.text;
assert!(out.contains("a.rs"), "invalid exclude → no filter: {out}");
}
#[test]
fn search_refuses_home_directory_root() {
let _env = lean_ctx::core::data_dir::test_env_lock();
let _no_policy = no_policy();
let home = dirs::home_dir().expect("home dir in test env");
let out = handle(
"needle",
home.to_string_lossy().as_ref(),
None,
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
out.starts_with("ERROR:") && out.contains("refusing to scan"),
"home root must be refused: {out}"
);
}
#[test]
fn match_count_reports_matched_files_not_scanned_files() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
for i in 0..8 {
std::fs::write(dir.path().join(format!("quiet{i}.rs")), "fn nothing() {}\n").unwrap();
}
std::fs::write(
dir.path().join("hit_a.rs"),
"let needle = 1;\nlet needle = 2;\n",
)
.unwrap();
std::fs::write(dir.path().join("hit_b.rs"), "let needle = 3;\n").unwrap();
let out = handle(
"needle",
&dir.path().to_string_lossy(),
Some("*.rs"),
50,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(
out.starts_with("3 matches in 2 files"),
"the headline count must be files that matched, not files walked: {out}"
);
assert!(
out.contains("scanned 10"),
"the scanned count stays visible, explicitly labelled: {out}"
);
}
#[test]
fn result_cap_is_announced_instead_of_looking_exhaustive() {
let _no_policy = no_policy();
use std::fmt::Write as _;
let fixture = |token: &str| {
let dir = tempfile::tempdir().unwrap();
let mut many = String::new();
for i in 0..12 {
writeln!(&mut many, "const {token}_{i} = \"/api/v{i}\";").unwrap();
}
std::fs::write(dir.path().join("a.ts"), many).unwrap();
std::fs::write(
dir.path().join("b.ts"),
format!("const {token}_B = \"/api/b\";\n"),
)
.unwrap();
std::fs::create_dir_all(dir.path().join("nested")).unwrap();
std::fs::write(
dir.path().join("nested/c.ts"),
format!("const {token}_C = \"/api/c\";\n"),
)
.unwrap();
dir
};
let search = |dir: &tempfile::TempDir, token: &str, max: usize| {
handle(
token,
&dir.path().to_string_lossy(),
Some("*.ts"),
max,
CrpMode::Off,
true,
true,
false,
)
.text
};
let capped_dir = fixture("CAPPED_ENDPOINT");
let capped = search(&capped_dir, "CAPPED_ENDPOINT", 10);
assert!(
capped.contains("stopped at max_results=10:"),
"hitting the cap must be stated, not inferred: {capped}"
);
assert!(
capped.contains("of 3 files scanned"),
"the notice must contrast files scanned with files eligible: {capped}"
);
assert!(
capped.contains("floor, not a total"),
"the counts must be labelled as a lower bound: {capped}"
);
let full_dir = fixture("FULL_ENDPOINT");
let complete = search(&full_dir, "FULL_ENDPOINT", 40);
assert!(
complete.starts_with("14 matches in 3 files"),
"the uncapped search must find every match: {complete}"
);
assert!(
!complete.contains("stopped at max_results"),
"an exhaustive search must not warn about a cap it never reached: {complete}"
);
}
fn large_log(needle: &str) -> String {
let mut body = "2026-09-29 INFO routine line without anything special\n".repeat(11_000);
body.push_str(needle);
body.push('\n');
assert!(body.len() as u64 > MAX_FILE_SIZE);
body
}
#[test]
fn explicitly_named_large_file_is_searched() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("big.log");
std::fs::write(&file, large_log("NEEDLE_1917 found")).unwrap();
let out = handle(
"NEEDLE_1917",
file.to_string_lossy().as_ref(),
None,
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.starts_with("1 matches"), "{out}");
assert!(out.contains("NEEDLE_1917 found"), "{out}");
}
#[test]
fn directory_walk_names_the_large_files_it_skipped() {
let _no_policy = no_policy();
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("big.log"), large_log("NEEDLE_1917")).unwrap();
std::fs::write(dir.path().join("small.txt"), "nothing here\n").unwrap();
let out = handle(
"NEEDLE_1917",
dir.path().to_string_lossy().as_ref(),
None,
10,
CrpMode::Off,
true,
true,
false,
)
.text;
assert!(out.starts_with("0 matches"), "{out}");
assert!(out.contains("large files skipped"), "{out}");
assert!(out.contains("big.log"), "skipped file must be named: {out}");
}
#[test]
fn name_skipped_caps_the_list() {
let names: Vec<String> = ["a", "b", "c"].iter().map(|s| (*s).to_string()).collect();
assert_eq!(name_skipped(&names, 3), "a, b, c");
assert_eq!(name_skipped(&names, 7), "a, b, c, +4 more");
}
#[test]
fn spent_protected_read_budget_is_not_reported_as_policy_withholding() {
let _no_test_policy = lean_ctx::core::policy::runtime::lock_test_override();
let _data = lean_ctx::core::data_dir::isolated_data_dir();
let dir = tempfile::tempdir().unwrap();
let root = dir.path().canonicalize().unwrap();
std::fs::create_dir_all(root.join(".lean-ctx")).unwrap();
std::fs::write(
root.join(".lean-ctx/policy.toml"),
"name = 'budget'\nversion = '1.0.0'\ndescription = 'test'\n[redaction]\ncustomer = 'CUS-[0-9]{4}'\n",
)
.unwrap();
let filler = "// filler line of the budget fixture\n".repeat(12_500);
for i in 0..10 {
std::fs::write(
root.join(format!("f{i}.rs")),
format!("fn needle_{i}() {{}}\n{filler}"),
)
.unwrap();
}
let root_str = root.to_string_lossy().to_string();
let out = lean_ctx::core::policy::runtime::REQUEST_PROJECT.sync_scope(
std::cell::RefCell::new(Some(root.clone())),
|| {
handle(
"needle_",
&root_str,
None,
50,
CrpMode::Off,
true,
false,
false,
)
.text
},
);
assert!(
!out.contains("withheld under policy"),
"unscanned files were counted as withheld: {out}"
);
assert!(
out.contains("read budget of this search is spent")
|| out.contains("search stopped after the"),
"the early stop is not explained: {out}"
);
}