use serde_json::Value;
use std::path::{Path, PathBuf};
use std::process::Command;
fn bin() -> &'static str {
env!("CARGO_BIN_EXE_cargo-treemap")
}
fn analyze(manifest: &Path, extra: &[&str]) -> Value {
let out = Command::new(bin())
.args(["treemap", "--release", "--format", "json", "--manifest-path"])
.arg(manifest)
.args(extra)
.output()
.expect("failed to run cargo-treemap");
assert!(
out.status.success(),
"cargo-treemap exited {}:\n{}",
out.status,
String::from_utf8_lossy(&out.stderr)
);
serde_json::from_slice(&out.stdout).expect("report is valid JSON")
}
fn crate_labels(report: &Value) -> Vec<String> {
report["tree"]["groups"]
.as_array()
.expect("tree.groups is an array")
.iter()
.map(|g| g["label"].as_str().unwrap().to_string())
.collect()
}
#[test]
fn analyzes_a_fixture_with_a_dependency() {
let dir = std::env::temp_dir().join(format!("cargo-treemap-fixture-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(dir.join("src")).unwrap();
std::fs::write(
dir.join("Cargo.toml"),
r#"[package]
name = "ctm_fixture"
version = "0.0.0"
edition = "2021"
[dependencies]
itoa = "1"
"#,
)
.unwrap();
std::fs::write(
dir.join("src/main.rs"),
r#"fn main() {
let mut buf = itoa::Buffer::new();
println!("{}", buf.format(std::env::args().count()));
}
"#,
)
.unwrap();
let report = analyze(&dir.join("Cargo.toml"), &[]);
let fmt = report["meta"]["format"].as_str().unwrap();
assert!(["Mach-O", "ELF", "PE"].contains(&fmt), "unexpected format {fmt}");
assert!(report["meta"]["total_text"].as_u64().unwrap() > 0);
assert!(report["tree"]["text"].as_u64().unwrap() > 0);
let labels = crate_labels(&report);
assert!(labels.contains(&"ctm_fixture".to_string()), "crates: {labels:?}");
assert!(labels.contains(&"itoa".to_string()), "crates: {labels:?}");
assert!(labels.contains(&"std".to_string()), "crates: {labels:?}");
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
fn json_report_is_stable_shaped() {
let dir = std::env::temp_dir().join(format!("cargo-treemap-plain-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(dir.join("src")).unwrap();
std::fs::write(
dir.join("Cargo.toml"),
"[package]\nname = \"ctm_plain\"\nversion = \"0.0.0\"\nedition = \"2021\"\n",
)
.unwrap();
std::fs::write(dir.join("src/main.rs"), "fn main() { println!(\"hi\"); }\n").unwrap();
let report = analyze(&dir.join("Cargo.toml"), &[]);
for key in ["meta", "dependencies", "crates", "tree"] {
assert!(report.get(key).is_some(), "report missing `{key}`");
}
assert!(crate_labels(&report).contains(&"ctm_plain".to_string()));
let _ = std::fs::remove_dir_all(&dir);
}
#[test]
#[ignore = "builds ripgrep; run with `cargo test -- --ignored`"]
fn analyzes_ripgrep() {
let root = std::env::var("RIPGREP").unwrap_or_else(|_| "/tmp/ripgrep".to_string());
let manifest = PathBuf::from(&root).join("Cargo.toml");
if !manifest.exists() {
eprintln!("skipping: no ripgrep checkout at {root} (set RIPGREP=...)");
return;
}
let report = analyze(&manifest, &["--bin", "rg"]);
let labels = crate_labels(&report);
assert!(
labels.contains(&"regex_automata".to_string()),
"expected regex_automata in {labels:?}"
);
assert!(report["meta"]["total_text"].as_u64().unwrap() > 500_000);
}