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",
|
"rayon",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
"toml",
|
"toml",
|
||||||
"vid-repair-core",
|
"vid-repair-core",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -17,3 +17,13 @@ fix_tier = "reencode"
|
|||||||
stop_scan = false
|
stop_scan = false
|
||||||
patterns = ["(?i)File ended prematurely"]
|
patterns = ["(?i)File ended prematurely"]
|
||||||
notes = "File appears truncated."
|
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")
|
.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]
|
#[test]
|
||||||
fn scan_clean_fixture_has_no_issues() {
|
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");
|
eprintln!("ffmpeg/ffprobe not available; skipping fixture test");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,3 +88,76 @@ fn scan_clean_fixture_has_no_issues() {
|
|||||||
|
|
||||||
assert!(scan.issues.is_empty(), "Expected no issues, got {}", scan.issues.len());
|
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 }
|
toml = { workspace = true }
|
||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
vid-repair-core = { path = "../vid-repair-core" }
|
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