Add fixture expectations and CLI scan test
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -733,6 +733,7 @@ dependencies = [
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"toml",
|
||||
"vid-repair-core",
|
||||
]
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
52
vid-repair/tests/cli.rs
Normal 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");
|
||||
}
|
||||
Reference in New Issue
Block a user