hprof-analyzer 0.2.0

Fast, low-memory Java HPROF heap-dump analyzer with Eclipse MAT-parity reports (System Overview, Leak Suspects, Top Consumers).
use std::path::Path;
use std::process::Command;

/// Golden-file regression test for `compare reports` output.
///
/// Runs `hprof-analyzer compare reports <r1.json> <r2.json>` and compares
/// stdout to the committed baseline, stripping the `Generated by` timestamp
/// line so reruns are stable.
#[test]
fn compare_golden() {
    let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures");
    let r1 = dir.join("dump_1_mnemonics_report.json");
    let r2 = dir.join("dump_4_philosophers_report.json");
    let baseline = dir.join("compare_1_4_ours.md");

    // Both JSON files are needed; skip when either is absent (large-file policy).
    let present = |p: &std::path::Path| {
        std::fs::metadata(p)
            .map(|m| m.len() >= 1024)
            .unwrap_or(false)
    };
    if !present(&r1) || !present(&r2) || !present(&baseline) {
        eprintln!("skipping compare_golden: one or more fixture files missing");
        return;
    }

    let out = Command::new(env!("CARGO_BIN_EXE_hprof-analyzer"))
        .args(["compare", "reports"])
        .arg(&r1)
        .arg(&r2)
        .output()
        .expect("failed to run hprof-analyzer compare reports");

    assert!(
        out.status.success(),
        "compare reports exited non-zero: {}",
        String::from_utf8_lossy(&out.stderr)
    );

    let strip = |s: &str| -> String {
        s.lines()
            .filter(|l| !l.contains("Generated by hprof-analyzer views"))
            .collect::<Vec<_>>()
            .join("\n")
    };

    let got = strip(&String::from_utf8_lossy(&out.stdout));
    let want = strip(&std::fs::read_to_string(&baseline).unwrap());

    if got != want {
        // Show first differing line for quick diagnosis.
        let got_lines: Vec<_> = got.lines().collect();
        let want_lines: Vec<_> = want.lines().collect();
        for (i, (g, w)) in got_lines.iter().zip(&want_lines).enumerate() {
            if g != w {
                panic!(
                    "compare_golden mismatch at line {}:\n  got:  {}\n  want: {}",
                    i + 1,
                    g,
                    w
                );
            }
        }
        panic!(
            "compare_golden length mismatch: got {} lines, want {} lines",
            got_lines.len(),
            want_lines.len()
        );
    }
}