use std::process::Command;
const FILE_COUNT: usize = 20_000;
const MAX_STATUS_PEAK_RSS_BYTES: u64 = 48 * 1024 * 1024;
fn grit_binary() -> std::path::PathBuf {
if let Ok(p) = std::env::var("GRIT_BIN") {
let path = std::path::PathBuf::from(p);
if path.is_file() {
return path;
}
}
let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace = manifest.parent().expect("workspace root");
let target_dir = std::env::var("CARGO_TARGET_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| workspace.join("target"));
let release = target_dir.join("release/grit");
assert!(
release.is_file(),
"grit binary not found at {} — run `cargo build --release -p grit-cli` or set GRIT_BIN",
release.display()
);
release
}
fn grit_bench_binary() -> std::path::PathBuf {
let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace = manifest.parent().expect("workspace root");
let target_dir = std::env::var("CARGO_TARGET_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|_| workspace.join("target"));
let release = target_dir.join("release/grit-bench");
assert!(
release.is_file(),
"grit-bench not found at {} — run `cargo build --release -p grit-utils`",
release.display()
);
release
}
fn build_fixture(root: &std::path::Path) {
grit_test_support::git(root, &["init", "-q", "-b", "main", "."]);
grit_test_support::git(root, &["config", "user.email", "t@example.com"]);
grit_test_support::git(root, &["config", "user.name", "Test"]);
let mut script = String::from("import os,random\nrandom.seed(2373)\nroot=r'''");
script.push_str(&root.to_string_lossy());
script.push_str("'''\n");
script.push_str(&format!(
"for i in range({FILE_COUNT}):\n depth=random.randint(3,8)\n p='/'.join([f'd{{random.randint(0,6)}}' for _ in range(depth)])+f'/f{{i}}.txt'\n path=os.path.join(root,p); os.makedirs(os.path.dirname(path),exist_ok=True); open(path,'w').write(f'c{{i}}\\n')\n"
));
std::process::Command::new("python3")
.arg("-c")
.arg(&script)
.status()
.expect("python fixture");
grit_test_support::git(root, &["add", "-A"]);
grit_test_support::git(root, &["commit", "-qm", "base"]);
}
fn peak_rss_status(
root: &std::path::Path,
grit: &std::path::Path,
grit_bench: &std::path::Path,
) -> u64 {
let cmd = format!("{} status", grit.display());
let out = Command::new(grit_bench)
.arg("measure-rss")
.arg("--cwd")
.arg(root)
.env("GRIT_BENCH_MEASURE_CMD", cmd)
.output()
.expect("measure-rss");
assert!(
out.status.success(),
"measure-rss failed: {}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout)
.trim()
.parse::<u64>()
.expect("peak RSS bytes")
}
#[test]
fn status_peak_rss_bounded_on_20k_file_repo() {
if std::env::var("GRIT_STATUS_MEMORY").ok().as_deref() != Some("1") {
eprintln!("skip status_scan_memory (set GRIT_STATUS_MEMORY=1)");
return;
}
let tmp = tempfile::TempDir::new().expect("tempdir");
build_fixture(tmp.path());
let grit = grit_binary();
let grit_bench = grit_bench_binary();
let peak = peak_rss_status(tmp.path(), &grit, &grit_bench);
eprintln!("grit status peak RSS on {FILE_COUNT} files: {peak} bytes");
assert!(
peak <= MAX_STATUS_PEAK_RSS_BYTES,
"peak RSS {peak} exceeded bound {MAX_STATUS_PEAK_RSS_BYTES}"
);
}