//! 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); }