// Core Formats Integration Tests use std::fs; use std::io::Read; use tempfile::TempDir; use crate::archive::processor::check_decompression_ratio; use crate::archive::tests::test_helpers::*; use crate::archive::*; #[test] fn test_zip_processor_full_workflow() { let temp_dir = TempDir::new().unwrap(); let zip_path = create_test_zip(&temp_dir); // Initialize processor let mut processor = processors::core::ZipProcessor::new(); // Test open let metadata = processor.open(&zip_path).unwrap(); assert_eq!(metadata.format, ArchiveFormat::Zip); assert_eq!(metadata.total_files, 3); // Test list_entries let entries = processor.list_entries().unwrap(); assert_eq!(entries.len(), 3); // Verify entry names let names: Vec<&str> = entries.iter().map(|e| e.path.to_str().unwrap()).collect(); assert!(names.contains(&"file1.txt")); assert!(names.contains(&"file2.txt")); assert!(names.contains(&"subdir/file3.txt")); // Test extract_all let extract_dir = temp_dir.path().join("extracted"); fs::create_dir_all(&extract_dir).unwrap(); let result = processor.extract_all(&extract_dir).unwrap(); assert_eq!(result.success_files, 3); assert_eq!(result.failed_files.len(), 0); // Verify extracted files assert!(extract_dir.join("file1.txt").exists()); assert!(extract_dir.join("file2.txt").exists()); assert!(extract_dir.join("subdir/file3.txt").exists()); // Verify content let content1 = fs::read_to_string(extract_dir.join("file1.txt")).unwrap(); assert_eq!(content1, "content of file 1"); } #[test] fn test_tar_processor_full_workflow() { let temp_dir = TempDir::new().unwrap(); let tar_path = create_test_tar(&temp_dir); let mut processor = processors::core::TarProcessor::new(); // Test open let metadata = processor.open(&tar_path).unwrap(); assert_eq!(metadata.format, ArchiveFormat::Tar); // Test list_entries let entries = processor.list_entries().unwrap(); assert!(entries.len() >= 3); // TAR may include directory entries // Test extract_all let extract_dir = temp_dir.path().join("extracted_tar"); fs::create_dir_all(&extract_dir).unwrap(); let result = processor.extract_all(&extract_dir).unwrap(); assert!(result.success_files >= 3); // Verify extracted files exist assert!(extract_dir.join("file1.txt").exists()); assert!(extract_dir.join("file2.txt").exists()); } #[test] fn test_gzip_processor_full_workflow() { let temp_dir = TempDir::new().unwrap(); let gz_path = create_test_gzip(&temp_dir); let mut processor = processors::core::GzipProcessor::new(); // Test open let metadata = processor.open(&gz_path).unwrap(); assert_eq!(metadata.format, ArchiveFormat::Gzip); assert_eq!(metadata.total_files, 1); // GZIP is single file // Test extract_all let extract_dir = temp_dir.path().join("extracted_gz"); fs::create_dir_all(&extract_dir).unwrap(); let result = processor.extract_all(&extract_dir).unwrap(); assert_eq!(result.success_files, 1); // Verify extracted file (should strip .gz extension) let extracted_file = extract_dir.join("test.txt"); assert!(extracted_file.exists()); // Verify content let content = fs::read_to_string(&extracted_file).unwrap(); assert_eq!(content, "test gzip content for validation"); } #[test] fn test_tar_gz_processor_workflow() { let temp_dir = TempDir::new().unwrap(); let tar_gz_path = create_test_tar_gz(&temp_dir); let mut processor = processors::core::TarGzipProcessor::new(); // Test open let metadata = processor.open(&tar_gz_path).unwrap(); assert_eq!(metadata.format, ArchiveFormat::TarGzip); // Test extract_all let extract_dir = temp_dir.path().join("extracted_tar_gz"); fs::create_dir_all(&extract_dir).unwrap(); let result = processor.extract_all(&extract_dir).unwrap(); assert!(result.success_files >= 2); // Verify extracted TAR files assert!(extract_dir.join("file1.txt").exists()); assert!(extract_dir.join("file2.txt").exists()); } #[test] fn test_format_detection_auto() { let temp_dir = TempDir::new().unwrap(); // Test ZIP detection let zip_path = create_test_zip(&temp_dir); let detector = FormatDetector::new(); let format = detector.detect(&zip_path).unwrap(); assert_eq!(format, ArchiveFormat::Zip); // Test TAR detection let tar_path = create_test_tar(&temp_dir); let format = detector.detect(&tar_path).unwrap(); assert_eq!(format, ArchiveFormat::Tar); // Test GZIP detection let gz_path = create_test_gzip(&temp_dir); let format = detector.detect(&gz_path).unwrap(); assert_eq!(format, ArchiveFormat::Gzip); } #[test] fn test_processor_registry_core_formats() { let config = ArchiveConfig::default(); let mut registry = ProcessorRegistry::new(config); registry.initialize().unwrap(); let formats = registry.enabled_formats(); // Should have 9 core formats assert!(formats.len() >= 4); // At least the ones we implemented // Verify format support assert!(formats.contains(&ArchiveFormat::Zip)); assert!(formats.contains(&ArchiveFormat::Tar)); assert!(formats.contains(&ArchiveFormat::Gzip)); assert!(formats.contains(&ArchiveFormat::TarGzip)); } #[test] fn test_zip_slip_protection() { let temp_dir = TempDir::new().unwrap(); let zip_bomb_data = create_zip_slip_test(); // Write malicious ZIP to file let evil_zip_path = temp_dir.path().join("evil.zip"); fs::write(&evil_zip_path, &zip_bomb_data).unwrap(); let mut processor = processors::core::ZipProcessor::new(); processor.open(&evil_zip_path).unwrap(); // Attempt extraction should fail due to Zip Slip protection let extract_dir = temp_dir.path().join("should_fail"); fs::create_dir_all(&extract_dir).unwrap(); let result = processor.extract_all(&extract_dir); // Should either fail or have empty extracted files // (validate_extraction_path prevents malicious paths) if result.is_ok() { let result = result.unwrap(); // If extraction succeeded, malicious file should not exist assert!(!extract_dir.join("etc/passwd").exists()); } } #[test] fn test_zip_bomb_detection() { // Test decompression ratio check let result = check_decompression_ratio(42_000, 5_000_000_000, 1000); assert!(result.is_err()); // Should detect as Zip Bomb // Test normal ratio let result = check_decompression_ratio(1000, 5000, 1000); assert!(result.is_ok()); // Normal ratio should pass } #[test] fn test_metadata_compression_ratio() { let metadata = ArchiveMetadata { format: ArchiveFormat::Zip, total_files: 10, total_size: 5000, compressed_size: 1000, compression_ratio: 0.0, is_encrypted: false, is_multi_volume: false, created_time: None, modified_time: None, }; assert_eq!(metadata.actual_ratio(), 5.0); // 5000/1000 = 5.0 assert!(!metadata.check_zip_bomb(10)); // ratio 5.0 < 10, not a bomb assert!(metadata.check_zip_bomb(4)); // ratio 5.0 > 4, detected as bomb } #[test] fn test_config_validation() { let config = ArchiveConfig { max_decompression_ratio: 5, // Too low ..Default::default() }; assert!(config.validate().is_err()); let valid_config = ArchiveConfig::default(); assert!(valid_config.validate().is_ok()); }