Files
vid-repair/vid-repair-core/tests/fixtures.rs

164 lines
4.1 KiB
Rust

use std::path::PathBuf;
use std::process::Command;
use tempfile::tempdir;
use vid_repair_core::config::Config;
use vid_repair_core::rules::RuleSet;
use vid_repair_core::scan::scan_file;
fn command_available(cmd: &str) -> bool {
Command::new(cmd)
.arg("-version")
.output()
.map(|out| out.status.success())
.unwrap_or(false)
}
fn ruleset_dir() -> PathBuf {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
manifest_dir
.parent()
.expect("workspace root")
.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 should_skip() {
eprintln!("ffmpeg/ffprobe not available; skipping fixture test");
return;
}
let dir = tempdir().expect("tempdir");
let output = dir.path().join("clean.mp4");
let status = Command::new("ffmpeg")
.args([
"-y",
"-hide_banner",
"-loglevel",
"error",
"-f",
"lavfi",
"-i",
"testsrc=size=128x72:rate=30",
"-f",
"lavfi",
"-i",
"sine=frequency=1000:sample_rate=44100",
"-t",
"1",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-c:a",
"aac",
"-movflags",
"+faststart",
output.to_str().unwrap(),
])
.status()
.expect("ffmpeg run");
if !status.success() {
eprintln!("ffmpeg failed to create fixture");
return;
}
let config = Config::default();
let ruleset = RuleSet::load_from_dir(&ruleset_dir()).expect("ruleset load");
let scan = scan_file(&output, &config, &ruleset).expect("scan file");
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<_>>()
);
}