
- Event-driven file stability tracking - FFmpeg video conversion with hardware acceleration - NFO file generation for Kodi compatibility - Environment-based configuration - Disk space monitoring and shutdown handling - Comprehensive logging with tracing
211 lines
7.3 KiB
Rust
211 lines
7.3 KiB
Rust
use std::path::PathBuf;
|
|
use std::fs;
|
|
use std::env;
|
|
use tempfile::TempDir;
|
|
use video_processing::{VideoProcessingConfig, VideoConverter};
|
|
|
|
#[tokio::test]
|
|
async fn test_video_converter_creation() {
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
// Basic smoke test that converter was created
|
|
assert!(true);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_video_converter_with_custom_config() {
|
|
// Set custom environment variables
|
|
env::set_var("FFMPEG_BINARY", "custom_ffmpeg");
|
|
env::set_var("VIDEO_CODEC", "h264");
|
|
env::set_var("AUDIO_CODEC", "aac");
|
|
env::set_var("VIDEO_BITRATE", "8M");
|
|
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
// Test that converter was created with custom config
|
|
assert!(true);
|
|
|
|
// Clean up
|
|
env::remove_var("FFMPEG_BINARY");
|
|
env::remove_var("VIDEO_CODEC");
|
|
env::remove_var("AUDIO_CODEC");
|
|
env::remove_var("VIDEO_BITRATE");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_conversion_with_missing_input_file() {
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("nonexistent.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
// Should fail when input file doesn't exist
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_conversion_output_verification() {
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("input.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
// Create a fake input video file
|
|
fs::write(&input_file, create_minimal_mp4_content()).unwrap();
|
|
|
|
// The conversion will likely fail due to invalid video content or missing ffmpeg,
|
|
// but we can test that the converter handles the failure gracefully
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
|
|
// We expect this to fail since we don't have real video content or ffmpeg might not be available
|
|
// The important thing is that it doesn't panic and returns a proper error
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_conversion_safety_no_overwrite() {
|
|
let mut config = VideoProcessingConfig::from_env();
|
|
// Use a fake ffmpeg binary to test the command construction without actually running ffmpeg
|
|
config.ffmpeg_binary = "echo".to_string(); // Use echo as a safe substitute
|
|
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("input.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
// Create both input and output files
|
|
fs::write(&input_file, "fake video content").unwrap();
|
|
fs::write(&output_file, "existing output").unwrap();
|
|
|
|
// The converter should use -n flag to never overwrite, so this should fail
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
|
|
// When using echo, it will succeed, but with real ffmpeg and -n flag,
|
|
// it would fail if output exists. We test the command construction here.
|
|
// The actual behavior depends on whether we're using echo or real ffmpeg
|
|
match result {
|
|
Ok(_) => {
|
|
// If using echo as substitute, it might succeed
|
|
println!("Command executed (likely using echo substitute)");
|
|
},
|
|
Err(e) => {
|
|
// If using real ffmpeg with -n, it should fail when output exists
|
|
println!("Conversion failed as expected: {}", e);
|
|
}
|
|
}
|
|
|
|
// The important thing is no panic occurred
|
|
assert!(true);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_hardware_acceleration_config() {
|
|
// Test with QSV hardware acceleration
|
|
env::set_var("HW_ACCEL", "qsv");
|
|
env::set_var("HW_DEVICE", "qsv=hw");
|
|
env::set_var("VIDEO_CODEC", "av1_qsv");
|
|
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("input.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
// Create a fake input file
|
|
fs::write(&input_file, "fake video").unwrap();
|
|
|
|
// Test that hardware acceleration settings are used
|
|
// This will likely fail due to missing hardware or ffmpeg, but shouldn't panic
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
|
|
// We expect failure but no panic
|
|
assert!(result.is_err() || result.is_ok());
|
|
|
|
// Clean up
|
|
env::remove_var("HW_ACCEL");
|
|
env::remove_var("HW_DEVICE");
|
|
env::remove_var("VIDEO_CODEC");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_no_hardware_acceleration() {
|
|
// Test without hardware acceleration
|
|
env::set_var("HW_ACCEL", "none");
|
|
env::set_var("HW_DEVICE", "");
|
|
env::set_var("VIDEO_CODEC", "libx264");
|
|
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("input.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
// Create a fake input file
|
|
fs::write(&input_file, "fake video").unwrap();
|
|
|
|
// Test conversion without hardware acceleration
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
|
|
// We expect failure but no panic
|
|
assert!(result.is_err() || result.is_ok());
|
|
|
|
// Clean up
|
|
env::remove_var("HW_ACCEL");
|
|
env::remove_var("HW_DEVICE");
|
|
env::remove_var("VIDEO_CODEC");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_audio_codec_settings() {
|
|
// Test different audio codec settings
|
|
let test_cases = vec![
|
|
("copy", ""),
|
|
("aac", "128k"),
|
|
("libopus", "192k"),
|
|
("mp3", "256k"),
|
|
];
|
|
|
|
for (audio_codec, audio_bitrate) in test_cases {
|
|
env::set_var("AUDIO_CODEC", audio_codec);
|
|
env::set_var("AUDIO_BITRATE", audio_bitrate);
|
|
|
|
let config = VideoProcessingConfig::from_env();
|
|
let converter = VideoConverter::new(config);
|
|
|
|
let temp_dir = TempDir::new().unwrap();
|
|
let input_file = temp_dir.path().join("input.mp4");
|
|
let output_file = temp_dir.path().join("output.mp4");
|
|
|
|
fs::write(&input_file, "fake video").unwrap();
|
|
|
|
// Test that different audio settings don't cause panics
|
|
let result = converter.convert_video(&input_file, &output_file).await;
|
|
assert!(result.is_err() || result.is_ok());
|
|
|
|
env::remove_var("AUDIO_CODEC");
|
|
env::remove_var("AUDIO_BITRATE");
|
|
}
|
|
}
|
|
|
|
// Helper function to create minimal MP4-like content for testing
|
|
fn create_minimal_mp4_content() -> Vec<u8> {
|
|
// This is just fake binary content that looks like it could be a video file
|
|
// Real MP4 files have complex structure, but for testing we just need some binary data
|
|
let mut content = Vec::new();
|
|
|
|
// Add some MP4-like header bytes (these are not valid but sufficient for testing)
|
|
content.extend_from_slice(b"\x00\x00\x00\x20ftypmp41"); // Fake ftyp box
|
|
content.extend_from_slice(&[0u8; 1000]); // Add some padding
|
|
|
|
content
|
|
} |