use pixstrip_core::operations::MetadataConfig; use pixstrip_core::operations::metadata::strip_metadata; use std::path::Path; fn create_test_jpeg(path: &Path) { let img = image::RgbImage::from_fn(100, 80, |x, y| { image::Rgb([(x % 256) as u8, (y % 256) as u8, 128]) }); img.save_with_format(path, image::ImageFormat::Jpeg).unwrap(); } #[test] fn strip_all_metadata_produces_file() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.jpg"); let output = dir.path().join("stripped.jpg"); create_test_jpeg(&input); strip_metadata(&input, &output, &MetadataConfig::StripAll).unwrap(); assert!(output.exists()); assert!(std::fs::metadata(&output).unwrap().len() > 0); } #[test] fn keep_all_metadata_copies_file() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.jpg"); let output = dir.path().join("kept.jpg"); create_test_jpeg(&input); strip_metadata(&input, &output, &MetadataConfig::KeepAll).unwrap(); assert!(output.exists()); } #[test] fn privacy_mode_strips_gps() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.jpg"); let output = dir.path().join("privacy.jpg"); create_test_jpeg(&input); strip_metadata(&input, &output, &MetadataConfig::Privacy).unwrap(); assert!(output.exists()); } fn create_test_png(path: &Path) { let img = image::RgbaImage::from_fn(100, 80, |x, y| { image::Rgba([(x % 256) as u8, (y % 256) as u8, 128, 255]) }); img.save_with_format(path, image::ImageFormat::Png).unwrap(); } #[test] fn strip_png_metadata_produces_valid_png() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.png"); let output = dir.path().join("stripped.png"); create_test_png(&input); strip_metadata(&input, &output, &MetadataConfig::StripAll).unwrap(); assert!(output.exists()); // Output must be a valid PNG that can be opened let img = image::open(&output).unwrap(); assert_eq!(img.width(), 100); assert_eq!(img.height(), 80); } #[test] fn strip_png_removes_text_chunks() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.png"); let output = dir.path().join("stripped.png"); create_test_png(&input); strip_metadata(&input, &output, &MetadataConfig::StripAll).unwrap(); // Read output and verify no tEXt chunks remain let data = std::fs::read(&output).unwrap(); let mut pos = 8; // skip PNG signature while pos + 12 <= data.len() { let chunk_len = u32::from_be_bytes([data[pos], data[pos+1], data[pos+2], data[pos+3]]) as usize; let chunk_type = &data[pos+4..pos+8]; assert_ne!(chunk_type, b"tEXt", "tEXt chunk should be stripped"); assert_ne!(chunk_type, b"iTXt", "iTXt chunk should be stripped"); assert_ne!(chunk_type, b"zTXt", "zTXt chunk should be stripped"); pos += 12 + chunk_len; } } #[test] fn strip_png_output_smaller_or_equal() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.png"); let output = dir.path().join("stripped.png"); create_test_png(&input); let input_size = std::fs::metadata(&input).unwrap().len(); strip_metadata(&input, &output, &MetadataConfig::StripAll).unwrap(); let output_size = std::fs::metadata(&output).unwrap().len(); assert!(output_size <= input_size); } #[test] fn strip_jpeg_removes_app1_exif() { let dir = tempfile::tempdir().unwrap(); let input = dir.path().join("test.jpg"); let output = dir.path().join("stripped.jpg"); create_test_jpeg(&input); strip_metadata(&input, &output, &MetadataConfig::StripAll).unwrap(); // Verify no APP1 (0xFFE1) markers remain let data = std::fs::read(&output).unwrap(); let mut i = 2; // skip SOI while i + 1 < data.len() { if data[i] != 0xFF { break; } let marker = data[i + 1]; if marker == 0xDA { break; } // SOS - rest is image data assert_ne!(marker, 0xE1, "APP1/EXIF marker should be stripped"); if i + 3 < data.len() { let len = ((data[i + 2] as usize) << 8) | (data[i + 3] as usize); i += 2 + len; } else { break; } } }