309 lines
11 KiB
Rust
309 lines
11 KiB
Rust
//! Integration tests for the tvai library
|
|
|
|
use tempfile::TempDir;
|
|
use tvai::*;
|
|
|
|
/// Test basic library initialization and configuration
|
|
#[tokio::test]
|
|
async fn test_library_initialization() {
|
|
// Test global settings
|
|
let settings_manager = global_settings();
|
|
let settings = settings_manager.get_settings();
|
|
|
|
assert!(settings.max_concurrent_jobs > 0);
|
|
assert!(settings.default_quality_preset.len() > 0);
|
|
|
|
// Test preset management
|
|
let presets = global_presets();
|
|
let preset_manager = presets.lock().unwrap();
|
|
|
|
let video_presets = preset_manager.list_video_presets();
|
|
let image_presets = preset_manager.list_image_presets();
|
|
|
|
assert!(!video_presets.is_empty(), "Should have video presets");
|
|
assert!(!image_presets.is_empty(), "Should have image presets");
|
|
|
|
// Test specific presets exist
|
|
assert!(preset_manager.get_video_preset("general_2x").is_some());
|
|
assert!(preset_manager.get_image_preset("photo_2x").is_some());
|
|
}
|
|
|
|
/// Test GPU detection and optimization
|
|
#[tokio::test]
|
|
async fn test_gpu_detection() {
|
|
let gpu_info = GpuManager::detect_detailed_gpu_info();
|
|
|
|
// Basic GPU info should be available
|
|
assert!(gpu_info.devices.len() > 0, "Should detect at least one GPU device");
|
|
|
|
// Test GPU suitability check
|
|
let suitable = GpuManager::is_gpu_suitable_for_ai();
|
|
println!("GPU suitable for AI: {}", suitable);
|
|
|
|
// Test GPU benchmark
|
|
let benchmark_result = GpuManager::benchmark_gpu_performance().await;
|
|
assert!(benchmark_result.is_ok(), "GPU benchmark should complete");
|
|
|
|
let benchmark = benchmark_result.unwrap();
|
|
assert!(benchmark.processing_time.as_millis() > 0);
|
|
assert!(benchmark.compute_score > 0);
|
|
}
|
|
|
|
/// Test performance monitoring
|
|
#[tokio::test]
|
|
async fn test_performance_monitoring() {
|
|
let settings = optimize_for_system();
|
|
let mut monitor = PerformanceMonitor::new(settings);
|
|
|
|
// Test operation monitoring
|
|
let metrics = {
|
|
let _permit = monitor.acquire_slot().await.expect("Should acquire slot");
|
|
let operation_monitor = monitor.start_operation("test_operation", 50.0);
|
|
|
|
// Simulate some work
|
|
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
|
|
|
operation_monitor.finish(100.0)
|
|
};
|
|
|
|
// Record metrics after permit is dropped
|
|
monitor.record_metrics(metrics.clone());
|
|
|
|
assert_eq!(metrics.operation_type, "test_operation");
|
|
assert_eq!(metrics.input_size_mb, 50.0);
|
|
assert_eq!(metrics.output_size_mb, 100.0);
|
|
assert!(metrics.processing_time.as_millis() >= 10);
|
|
|
|
// Test performance summary
|
|
let summary = monitor.get_summary();
|
|
assert_eq!(summary.total_operations, 1);
|
|
}
|
|
|
|
/// Test error handling and user-friendly messages
|
|
#[test]
|
|
fn test_error_handling() {
|
|
let errors = vec![
|
|
TvaiError::TopazNotFound("/invalid/path".to_string()),
|
|
TvaiError::FfmpegError("Test error".to_string()),
|
|
TvaiError::InvalidParameter("Test parameter".to_string()),
|
|
TvaiError::GpuError("Test GPU error".to_string()),
|
|
TvaiError::UnsupportedFormat("WEBM".to_string()),
|
|
TvaiError::InsufficientResources("Test resources".to_string()),
|
|
TvaiError::PermissionDenied("Test permission".to_string()),
|
|
];
|
|
|
|
for error in errors {
|
|
// Test user-friendly messages
|
|
let friendly_msg = error.user_friendly_message();
|
|
assert!(!friendly_msg.is_empty(), "Should have user-friendly message");
|
|
|
|
// Some errors have suggestions, others just return the basic message
|
|
if matches!(error,
|
|
TvaiError::TopazNotFound(_) |
|
|
TvaiError::FfmpegError(_) |
|
|
TvaiError::InvalidParameter(_) |
|
|
TvaiError::GpuError(_) |
|
|
TvaiError::UnsupportedFormat(_) |
|
|
TvaiError::InsufficientResources(_) |
|
|
TvaiError::PermissionDenied(_)
|
|
) {
|
|
assert!(friendly_msg.contains("Suggestions:") || friendly_msg.contains("Suggestion:"),
|
|
"Should contain suggestions for error: {}", error);
|
|
}
|
|
|
|
// Test error categorization
|
|
let category = error.category();
|
|
assert!(!category.is_empty(), "Should have error category");
|
|
|
|
// Test recoverability
|
|
let recoverable = error.is_recoverable();
|
|
println!("Error {} is recoverable: {}", category, recoverable);
|
|
}
|
|
}
|
|
|
|
/// Test configuration management
|
|
#[tokio::test]
|
|
async fn test_configuration_management() {
|
|
let temp_dir = TempDir::new().expect("Should create temp dir");
|
|
let config_path = temp_dir.path().join("test_config.toml");
|
|
|
|
// Create settings manager with custom config file
|
|
let settings_manager = SettingsManager::with_config_file(&config_path);
|
|
|
|
// Update some settings
|
|
settings_manager.set_default_use_gpu(false).expect("Should update GPU setting");
|
|
settings_manager.set_max_concurrent_jobs(3).expect("Should update concurrent jobs");
|
|
|
|
// Save settings
|
|
settings_manager.save_to_file().expect("Should save settings");
|
|
|
|
// Verify file was created
|
|
assert!(config_path.exists(), "Config file should be created");
|
|
|
|
// Load settings in new manager
|
|
let new_manager = SettingsManager::with_config_file(&config_path);
|
|
let loaded_settings = new_manager.get_settings();
|
|
|
|
assert_eq!(loaded_settings.default_use_gpu, false);
|
|
assert_eq!(loaded_settings.max_concurrent_jobs, 3);
|
|
}
|
|
|
|
/// Test model and parameter validation
|
|
#[test]
|
|
fn test_model_validation() {
|
|
// Test upscale models
|
|
let models = [
|
|
UpscaleModel::Iris3,
|
|
UpscaleModel::Nyx3,
|
|
UpscaleModel::Thf4,
|
|
UpscaleModel::Ghq5,
|
|
];
|
|
|
|
for model in models {
|
|
let model_str = model.as_str();
|
|
assert!(!model_str.is_empty(), "Model should have string representation");
|
|
|
|
let description = model.description();
|
|
assert!(!description.is_empty(), "Model should have description");
|
|
|
|
// Test forced scale (if any)
|
|
if let Some(scale) = model.forces_scale() {
|
|
assert!(scale > 0.0, "Forced scale should be positive");
|
|
}
|
|
}
|
|
|
|
// Test interpolation models
|
|
let interp_models = [
|
|
InterpolationModel::Apo8,
|
|
InterpolationModel::Chr2,
|
|
InterpolationModel::Apf1,
|
|
InterpolationModel::Chf3,
|
|
];
|
|
|
|
for model in interp_models {
|
|
let model_str = model.as_str();
|
|
assert!(!model_str.is_empty(), "Interpolation model should have string representation");
|
|
|
|
let description = model.description();
|
|
assert!(!description.is_empty(), "Interpolation model should have description");
|
|
}
|
|
}
|
|
|
|
/// Test image format handling
|
|
#[test]
|
|
fn test_image_formats() {
|
|
let formats = [
|
|
ImageFormat::Png,
|
|
ImageFormat::Jpg,
|
|
ImageFormat::Tiff,
|
|
ImageFormat::Bmp,
|
|
];
|
|
|
|
for format in formats {
|
|
let extension = format.extension();
|
|
assert!(!extension.is_empty(), "Format should have extension");
|
|
|
|
let ffmpeg_format = format.ffmpeg_format();
|
|
assert!(!ffmpeg_format.is_empty(), "Format should have FFmpeg format");
|
|
}
|
|
}
|
|
|
|
/// Test parameter presets
|
|
#[test]
|
|
fn test_parameter_presets() {
|
|
// Test video upscale presets
|
|
let video_presets = [
|
|
VideoUpscaleParams::for_old_video(),
|
|
VideoUpscaleParams::for_game_content(),
|
|
VideoUpscaleParams::for_animation(),
|
|
VideoUpscaleParams::for_portrait(),
|
|
];
|
|
|
|
for preset in video_presets {
|
|
assert!(preset.scale_factor > 0.0, "Scale factor should be positive");
|
|
assert!(preset.scale_factor <= 4.0, "Scale factor should be reasonable");
|
|
assert!(preset.compression >= -1.0 && preset.compression <= 1.0, "Compression should be in valid range");
|
|
assert!(preset.blend >= 0.0 && preset.blend <= 1.0, "Blend should be in valid range");
|
|
}
|
|
|
|
// Test image upscale presets
|
|
let image_presets = [
|
|
ImageUpscaleParams::for_photo(),
|
|
ImageUpscaleParams::for_artwork(),
|
|
ImageUpscaleParams::for_screenshot(),
|
|
ImageUpscaleParams::for_portrait(),
|
|
];
|
|
|
|
for preset in image_presets {
|
|
assert!(preset.scale_factor > 0.0, "Scale factor should be positive");
|
|
assert!(preset.scale_factor <= 4.0, "Scale factor should be reasonable");
|
|
assert!(preset.compression >= -1.0 && preset.compression <= 1.0, "Compression should be in valid range");
|
|
assert!(preset.blend >= 0.0 && preset.blend <= 1.0, "Blend should be in valid range");
|
|
}
|
|
|
|
// Test interpolation presets
|
|
let slow_motion = InterpolationParams::for_slow_motion(30, 2.0);
|
|
assert_eq!(slow_motion.input_fps, 30);
|
|
assert_eq!(slow_motion.multiplier, 2.0);
|
|
|
|
let animation = InterpolationParams::for_animation(24, 2.0);
|
|
assert_eq!(animation.input_fps, 24);
|
|
assert_eq!(animation.multiplier, 2.0);
|
|
}
|
|
|
|
/// Test utility functions
|
|
#[tokio::test]
|
|
async fn test_utility_functions() {
|
|
// Test Topaz detection
|
|
let topaz_path = detect_topaz_installation();
|
|
if let Some(path) = topaz_path {
|
|
assert!(path.exists(), "Detected Topaz path should exist");
|
|
println!("Detected Topaz at: {}", path.display());
|
|
} else {
|
|
println!("Topaz Video AI not detected (this is expected in CI)");
|
|
}
|
|
|
|
// Test FFmpeg detection
|
|
let ffmpeg_info = detect_ffmpeg();
|
|
println!("System FFmpeg available: {}", ffmpeg_info.system_available);
|
|
println!("Topaz FFmpeg available: {}", ffmpeg_info.topaz_available);
|
|
|
|
// Test GPU detection
|
|
let gpu_info = detect_gpu_support();
|
|
assert!(gpu_info.available, "Should detect GPU availability");
|
|
println!("GPU available: {}", gpu_info.available);
|
|
println!("CUDA available: {}", gpu_info.cuda_available);
|
|
}
|
|
|
|
/// Test temporary file management
|
|
#[tokio::test]
|
|
async fn test_temp_file_management() {
|
|
let temp_dir = TempDir::new().expect("Should create temp dir");
|
|
let mut temp_manager = TempFileManager::new(Some(temp_dir.path())).expect("Should create temp manager");
|
|
|
|
// Test temp path creation
|
|
let temp_path1 = temp_manager.create_temp_path("test_op", "file1.txt");
|
|
let temp_path2 = temp_manager.create_unique_temp_path("file2.txt");
|
|
|
|
assert_eq!(temp_manager.file_count(), 2);
|
|
assert!(temp_manager.is_tracked(&temp_path1));
|
|
assert!(temp_manager.is_tracked(&temp_path2));
|
|
|
|
// Create actual files
|
|
std::fs::write(&temp_path1, "test content 1").expect("Should write file");
|
|
std::fs::write(&temp_path2, "test content 2").expect("Should write file");
|
|
|
|
assert!(temp_path1.exists());
|
|
assert!(temp_path2.exists());
|
|
|
|
// Test cleanup
|
|
temp_manager.cleanup_operation("test_op").expect("Should cleanup operation");
|
|
assert!(!temp_path1.exists(), "File should be cleaned up");
|
|
assert!(temp_path2.exists(), "Other file should remain");
|
|
|
|
// Test cleanup all
|
|
temp_manager.cleanup_all().expect("Should cleanup all");
|
|
assert!(!temp_path2.exists(), "All files should be cleaned up");
|
|
assert_eq!(temp_manager.file_count(), 0);
|
|
}
|