Add fixture expectations and CLI scan test

This commit is contained in:
2025-12-31 22:31:53 -05:00
parent d7f2a1cec3
commit 8b4273e7cb
5 changed files with 154 additions and 1 deletions

1
Cargo.lock generated
View File

@@ -733,6 +733,7 @@ dependencies = [
"rayon",
"serde",
"serde_json",
"tempfile",
"toml",
"vid-repair-core",
]

View File

@@ -17,3 +17,13 @@ fix_tier = "reencode"
stop_scan = false
patterns = ["(?i)File ended prematurely"]
notes = "File appears truncated."
[[rule]]
id = "ERROR_WHILE_DECODING"
domain = "decode"
severity = "high"
confidence = 0.5
fix_tier = "reencode"
stop_scan = false
patterns = ["(?i)Error while decoding"]
notes = "Decoder reported an error while decoding stream."

View File

@@ -23,9 +23,23 @@ fn ruleset_dir() -> PathBuf {
.join("rulesets")
}
fn fixture_dir() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.expect("workspace root")
.join("tests")
.join("fixtures")
.join("generated")
}
fn should_skip() -> bool {
!command_available("ffmpeg") || !command_available("ffprobe")
}
#[test]
fn scan_clean_fixture_has_no_issues() {
if !command_available("ffmpeg") || !command_available("ffprobe") {
if should_skip() {
eprintln!("ffmpeg/ffprobe not available; skipping fixture test");
return;
}
@@ -74,3 +88,76 @@ fn scan_clean_fixture_has_no_issues() {
assert!(scan.issues.is_empty(), "Expected no issues, got {}", scan.issues.len());
}
#[test]
fn scan_truncated_fixture_has_errors() {
if should_skip() {
eprintln!("ffmpeg/ffprobe not available; skipping fixture test");
return;
}
let path = fixture_dir().join("truncated.mp4");
if !path.exists() {
eprintln!("fixture not found: {}; skipping", path.display());
return;
}
let config = Config::default();
let ruleset = RuleSet::load_from_dir(&ruleset_dir()).expect("ruleset load");
let scan = scan_file(&path, &config, &ruleset).expect("scan file");
let allowed = [
"FILE_ENDED_PREMATURELY",
"INVALID_DATA_FOUND",
"ERROR_WHILE_DECODING",
];
let matched = scan
.issues
.iter()
.any(|issue| allowed.contains(&issue.code.as_str()));
assert!(
matched,
"Expected truncated fixture to match one of {:?}, got {:?}",
allowed,
scan.issues.iter().map(|i| i.code.clone()).collect::<Vec<_>>()
);
}
#[test]
fn scan_corrupt_fixture_has_errors() {
if should_skip() {
eprintln!("ffmpeg/ffprobe not available; skipping fixture test");
return;
}
let path = fixture_dir().join("corrupt_mid.mp4");
if !path.exists() {
eprintln!("fixture not found: {}; skipping", path.display());
return;
}
let config = Config::default();
let ruleset = RuleSet::load_from_dir(&ruleset_dir()).expect("ruleset load");
let scan = scan_file(&path, &config, &ruleset).expect("scan file");
let allowed = [
"INVALID_NAL_UNIT_SIZE",
"MISSING_PICTURE_ACCESS_UNIT",
"INVALID_DATA_FOUND",
"ERROR_WHILE_DECODING",
];
let matched = scan
.issues
.iter()
.any(|issue| allowed.contains(&issue.code.as_str()));
assert!(
matched,
"Expected corrupt fixture to match one of {:?}, got {:?}",
allowed,
scan.issues.iter().map(|i| i.code.clone()).collect::<Vec<_>>()
);
}

View File

@@ -11,3 +11,6 @@ serde_json = { workspace = true }
toml = { workspace = true }
rayon = { workspace = true }
vid-repair-core = { path = "../vid-repair-core" }
[dev-dependencies]
tempfile = { workspace = true }

52
vid-repair/tests/cli.rs Normal file
View File

@@ -0,0 +1,52 @@
use std::path::PathBuf;
use std::process::Command;
use tempfile::tempdir;
fn command_available(cmd: &str) -> bool {
Command::new(cmd)
.arg("-version")
.output()
.map(|out| out.status.success())
.unwrap_or(false)
}
fn fixture_dir() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.expect("workspace root")
.join("tests")
.join("fixtures")
.join("generated")
}
#[test]
fn cli_scan_summarizes_fixtures() {
if !command_available("ffmpeg") || !command_available("ffprobe") {
eprintln!("ffmpeg/ffprobe not available; skipping cli test");
return;
}
let fixture_dir = fixture_dir();
if !fixture_dir.exists() {
eprintln!("fixture dir missing; skipping cli test");
return;
}
let temp = tempdir().expect("tempdir");
let bin = env!("CARGO_BIN_EXE_vid-repair");
let output = Command::new(bin)
.current_dir(fixture_dir.parent().unwrap().parent().unwrap().parent().unwrap())
.env("XDG_CONFIG_HOME", temp.path())
.arg("scan")
.arg(fixture_dir)
.output()
.expect("run vid-repair");
assert!(output.status.success(), "cli scan failed");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Summary:"), "missing summary in output");
}