use assert_cmd::Command;
fn sdkt() -> Command {
Command::cargo_bin("sdkt").unwrap()
}
#[test]
fn diff_help_documents_offline_comparison() {
sdkt()
.args(["diff", "--help"])
.assert()
.success()
.stdout(predicates::str::contains("Offline diff"))
.stdout(predicates::str::contains("OLD"))
.stdout(predicates::str::contains("NEW"));
}
#[test]
fn diff_missing_old_file_errors() {
sdkt()
.args([
"diff",
"--old-wasm",
"/no/such/old.wasm",
"--new-wasm",
"/no/such/new.wasm",
])
.assert()
.failure()
.stderr(predicates::str::contains("Failed to read OLD WASM"));
}
#[test]
fn diff_accepts_json_format_flag() {
sdkt()
.args([
"diff",
"--old-wasm",
"/no/such/old.wasm",
"--new-wasm",
"/no/such/new.wasm",
"--format",
"json",
])
.assert()
.failure();
}
fn fixture(name: &str) -> String {
format!("{}/tests/fixtures/{}", env!("CARGO_MANIFEST_DIR"), name)
}
#[test]
fn diff_json_reports_size_delta_fields_and_keeps_existing_schema() {
let out = sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--format",
"json",
])
.assert()
.success()
.get_output()
.stdout
.clone();
let v: serde_json::Value = serde_json::from_slice(&out).expect("valid JSON");
assert_eq!(v["size_delta_bytes"], 332);
assert_eq!(v["size_delta_pct"], 167.7);
assert!(v.get("old").is_some());
assert!(v.get("new").is_some());
assert!(v.get("added_functions").is_some());
assert!(v.get("changed_types").is_some());
assert_eq!(v["old"]["size_bytes"], 198);
assert_eq!(v["new"]["size_bytes"], 530);
}
#[test]
fn diff_equal_artifacts_report_zero_delta() {
let out = sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_old.wasm"),
"--format",
"json",
])
.assert()
.success()
.get_output()
.stdout
.clone();
let v: serde_json::Value = serde_json::from_slice(&out).expect("valid JSON");
assert_eq!(v["size_delta_bytes"], 0);
assert_eq!(v["size_delta_pct"], 0.0);
}
#[test]
fn diff_growth_at_threshold_passes_but_one_below_fails() {
sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--max-growth-pct",
"167.7",
])
.assert()
.success();
sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--max-growth-pct",
"167.6",
])
.assert()
.failure()
.stderr(predicates::str::contains("size policy violation"))
.stderr(predicates::str::contains("--max-growth-pct"));
}
#[test]
fn diff_abs_size_boundary_is_inclusive() {
let big = fixture("us_new.wasm"); let small = fixture("us_old.wasm"); sdkt()
.args([
"diff",
"--old-wasm",
&small,
"--new-wasm",
&big,
"--max-size-bytes",
"530",
])
.assert()
.success();
sdkt()
.args([
"diff",
"--old-wasm",
&small,
"--new-wasm",
&big,
"--max-size-bytes",
"529",
])
.assert()
.failure()
.stderr(predicates::str::contains("exceeds --max-size-bytes 529"));
}
#[test]
fn diff_negative_growth_is_reported_but_never_violates() {
let out = sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_new.wasm"),
"--new-wasm",
&fixture("us_old.wasm"),
"--max-growth-pct",
"0",
"--format",
"json",
])
.assert()
.success()
.get_output()
.stdout
.clone();
let v: serde_json::Value = serde_json::from_slice(&out).expect("valid JSON");
assert_eq!(v["size_delta_bytes"], -332);
assert!(v["size_delta_pct"].as_f64().unwrap() < 0.0);
}
#[test]
fn diff_rejects_invalid_threshold_inputs() {
sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--max-growth-pct=-5",
])
.assert()
.failure()
.stderr(predicates::str::contains("must not be negative"));
sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--max-size-bytes",
"0",
])
.assert()
.failure()
.stderr(predicates::str::contains("greater than 0"));
}
#[test]
fn diff_size_policy_cannot_mix_with_upgrade_safety() {
sdkt()
.args([
"diff",
"--old-wasm",
&fixture("us_old.wasm"),
"--new-wasm",
&fixture("us_new.wasm"),
"--upgrade-safety",
"--max-size-bytes",
"100000",
])
.assert()
.failure()
.stderr(predicates::str::contains(
"cannot be combined with --upgrade-safety",
));
}
#[test]
fn diff_zero_byte_baseline_fails_before_policy() {
let tmp = tempfile::NamedTempFile::new().unwrap();
std::fs::write(tmp.path(), b"").unwrap();
sdkt()
.args([
"diff",
"--old-wasm",
tmp.path().to_str().unwrap(),
"--new-wasm",
&fixture("us_new.wasm"),
"--max-growth-pct",
"10",
])
.assert()
.failure();
}