use squeez::context::summarize::{apply_with_format, SummaryFormat};
fn make_cargo_lines() -> Vec<String> {
let mut lines: Vec<String> = Vec::with_capacity(1000);
for i in 0..500 {
lines.push(format!(" Compiling crate_{} v0.1.{}", i % 50, i));
}
lines.push("error: cannot find value `UNIQUE_ERROR_ALPHA` in this scope".to_string());
lines.push("error: mismatched types UNIQUE_ERROR_BETA expected `usize`".to_string());
for i in 500..998 {
lines.push(format!(" Compiling extra_{} v1.0.{}", i % 20, i));
}
lines
}
#[test]
fn structured_first_line_is_json_envelope() {
let lines = make_cargo_lines();
let out = apply_with_format(lines, "cargo build", SummaryFormat::Structured);
assert!(!out.is_empty(), "output must not be empty");
let first = &out[0];
assert!(
first.starts_with("{\"squeez\":\"summary\""),
"first line should start with JSON envelope, got: {}",
&first[..first.len().min(80)]
);
assert!(
first.ends_with('}'),
"first line should end with '}}', got: ...{}",
&first[first.len().saturating_sub(20)..]
);
assert!(!first.contains('\n'), "JSON line must not contain newlines");
}
#[test]
fn structured_is_at_most_half_prose_bytes() {
let lines = make_cargo_lines();
let prose_out = apply_with_format(lines.clone(), "cargo build", SummaryFormat::Prose);
let structured_out = apply_with_format(lines, "cargo build", SummaryFormat::Structured);
let prose_bytes: usize = prose_out.iter().map(|l| l.len()).sum();
let structured_bytes: usize = structured_out.iter().map(|l| l.len()).sum();
assert!(
structured_bytes * 2 <= prose_bytes,
"structured ({} bytes) must be <= 50% of prose ({} bytes)",
structured_bytes,
prose_bytes,
);
}
#[test]
fn both_formats_preserve_errors() {
let lines = make_cargo_lines();
let prose_out = apply_with_format(lines.clone(), "cargo build", SummaryFormat::Prose);
let structured_out = apply_with_format(lines, "cargo build", SummaryFormat::Structured);
for out in [&prose_out, &structured_out] {
let joined = out.join("\n");
assert!(
joined.contains("UNIQUE_ERROR_ALPHA"),
"output must contain UNIQUE_ERROR_ALPHA"
);
assert!(
joined.contains("UNIQUE_ERROR_BETA"),
"output must contain UNIQUE_ERROR_BETA"
);
}
}
#[test]
fn auto_mode_selects_format_by_intensity() {
use squeez::config::Config;
use squeez::context::intensity::Intensity;
let lines = make_cargo_lines();
let resolve_format = |cfg: &Config, intensity: Intensity| -> SummaryFormat {
match cfg.summary_format.as_str() {
"prose" => SummaryFormat::Prose,
"structured" => SummaryFormat::Structured,
_ => {
if intensity == Intensity::Ultra {
SummaryFormat::Structured
} else {
SummaryFormat::Prose
}
}
}
};
let mut cfg = Config::default();
cfg.summary_format = "auto".to_string();
let fmt_full = resolve_format(&cfg, Intensity::Full);
assert_eq!(fmt_full, SummaryFormat::Prose, "auto+Full should give Prose");
let fmt_ultra = resolve_format(&cfg, Intensity::Ultra);
assert_eq!(fmt_ultra, SummaryFormat::Structured, "auto+Ultra should give Structured");
let prose_out = apply_with_format(lines.clone(), "cargo build", fmt_full);
let joined_prose = prose_out.join("\n");
assert!(joined_prose.contains("squeez:summary"), "Prose output should contain squeez:summary");
let struct_out = apply_with_format(lines, "cargo build", fmt_ultra);
assert!(
struct_out[0].starts_with("{\"squeez\":\"summary\""),
"Structured output first line must be JSON"
);
}
#[test]
fn explicit_overrides_ignore_intensity() {
use squeez::config::Config;
use squeez::context::intensity::Intensity;
let lines = make_cargo_lines();
let resolve_format = |cfg: &Config, intensity: Intensity| -> SummaryFormat {
match cfg.summary_format.as_str() {
"prose" => SummaryFormat::Prose,
"structured" => SummaryFormat::Structured,
_ => {
if intensity == Intensity::Ultra {
SummaryFormat::Structured
} else {
SummaryFormat::Prose
}
}
}
};
let mut cfg_prose = Config::default();
cfg_prose.summary_format = "prose".to_string();
for intensity in [Intensity::Lite, Intensity::Full, Intensity::Ultra] {
let fmt = resolve_format(&cfg_prose, intensity);
assert_eq!(fmt, SummaryFormat::Prose, "prose override must always give Prose (intensity={:?})", intensity);
}
let mut cfg_struct = Config::default();
cfg_struct.summary_format = "structured".to_string();
for intensity in [Intensity::Lite, Intensity::Full, Intensity::Ultra] {
let fmt = resolve_format(&cfg_struct, intensity);
assert_eq!(fmt, SummaryFormat::Structured, "structured override must always give Structured (intensity={:?})", intensity);
}
let prose_out = apply_with_format(lines.clone(), "cargo build", SummaryFormat::Prose);
assert!(prose_out.join("\n").contains("squeez:summary"));
let struct_out = apply_with_format(lines, "cargo build", SummaryFormat::Structured);
assert!(struct_out[0].starts_with("{\"squeez\":\"summary\""));
}