this repo has no description
1use bspds::image::{ImageProcessor, ImageError, OutputFormat, THUMB_SIZE_FEED, THUMB_SIZE_FULL, DEFAULT_MAX_FILE_SIZE}; 2use image::{DynamicImage, ImageFormat}; 3use std::io::Cursor; 4 5fn create_test_png(width: u32, height: u32) -> Vec<u8> { 6 let img = DynamicImage::new_rgb8(width, height); 7 let mut buf = Vec::new(); 8 img.write_to(&mut Cursor::new(&mut buf), ImageFormat::Png).unwrap(); 9 buf 10} 11 12fn create_test_jpeg(width: u32, height: u32) -> Vec<u8> { 13 let img = DynamicImage::new_rgb8(width, height); 14 let mut buf = Vec::new(); 15 img.write_to(&mut Cursor::new(&mut buf), ImageFormat::Jpeg).unwrap(); 16 buf 17} 18 19fn create_test_gif(width: u32, height: u32) -> Vec<u8> { 20 let img = DynamicImage::new_rgb8(width, height); 21 let mut buf = Vec::new(); 22 img.write_to(&mut Cursor::new(&mut buf), ImageFormat::Gif).unwrap(); 23 buf 24} 25 26fn create_test_webp(width: u32, height: u32) -> Vec<u8> { 27 let img = DynamicImage::new_rgb8(width, height); 28 let mut buf = Vec::new(); 29 img.write_to(&mut Cursor::new(&mut buf), ImageFormat::WebP).unwrap(); 30 buf 31} 32 33#[test] 34fn test_process_png() { 35 let processor = ImageProcessor::new(); 36 let data = create_test_png(500, 500); 37 let result = processor.process(&data, "image/png").unwrap(); 38 assert_eq!(result.original.width, 500); 39 assert_eq!(result.original.height, 500); 40} 41 42#[test] 43fn test_process_jpeg() { 44 let processor = ImageProcessor::new(); 45 let data = create_test_jpeg(400, 300); 46 let result = processor.process(&data, "image/jpeg").unwrap(); 47 assert_eq!(result.original.width, 400); 48 assert_eq!(result.original.height, 300); 49} 50 51#[test] 52fn test_process_gif() { 53 let processor = ImageProcessor::new(); 54 let data = create_test_gif(200, 200); 55 let result = processor.process(&data, "image/gif").unwrap(); 56 assert_eq!(result.original.width, 200); 57 assert_eq!(result.original.height, 200); 58} 59 60#[test] 61fn test_process_webp() { 62 let processor = ImageProcessor::new(); 63 let data = create_test_webp(300, 200); 64 let result = processor.process(&data, "image/webp").unwrap(); 65 assert_eq!(result.original.width, 300); 66 assert_eq!(result.original.height, 200); 67} 68 69#[test] 70fn test_thumbnail_feed_size() { 71 let processor = ImageProcessor::new(); 72 let data = create_test_png(800, 600); 73 let result = processor.process(&data, "image/png").unwrap(); 74 75 let thumb = result.thumbnail_feed.expect("Should generate feed thumbnail for large image"); 76 assert!(thumb.width <= THUMB_SIZE_FEED); 77 assert!(thumb.height <= THUMB_SIZE_FEED); 78} 79 80#[test] 81fn test_thumbnail_full_size() { 82 let processor = ImageProcessor::new(); 83 let data = create_test_png(2000, 1500); 84 let result = processor.process(&data, "image/png").unwrap(); 85 86 let thumb = result.thumbnail_full.expect("Should generate full thumbnail for large image"); 87 assert!(thumb.width <= THUMB_SIZE_FULL); 88 assert!(thumb.height <= THUMB_SIZE_FULL); 89} 90 91#[test] 92fn test_no_thumbnail_small_image() { 93 let processor = ImageProcessor::new(); 94 let data = create_test_png(100, 100); 95 let result = processor.process(&data, "image/png").unwrap(); 96 97 assert!(result.thumbnail_feed.is_none(), "Small image should not get feed thumbnail"); 98 assert!(result.thumbnail_full.is_none(), "Small image should not get full thumbnail"); 99} 100 101#[test] 102fn test_webp_conversion() { 103 let processor = ImageProcessor::new().with_output_format(OutputFormat::WebP); 104 let data = create_test_png(300, 300); 105 let result = processor.process(&data, "image/png").unwrap(); 106 107 assert_eq!(result.original.mime_type, "image/webp"); 108} 109 110#[test] 111fn test_jpeg_output_format() { 112 let processor = ImageProcessor::new().with_output_format(OutputFormat::Jpeg); 113 let data = create_test_png(300, 300); 114 let result = processor.process(&data, "image/png").unwrap(); 115 116 assert_eq!(result.original.mime_type, "image/jpeg"); 117} 118 119#[test] 120fn test_png_output_format() { 121 let processor = ImageProcessor::new().with_output_format(OutputFormat::Png); 122 let data = create_test_jpeg(300, 300); 123 let result = processor.process(&data, "image/jpeg").unwrap(); 124 125 assert_eq!(result.original.mime_type, "image/png"); 126} 127 128#[test] 129fn test_max_dimension_enforced() { 130 let processor = ImageProcessor::new().with_max_dimension(1000); 131 let data = create_test_png(2000, 2000); 132 let result = processor.process(&data, "image/png"); 133 134 assert!(matches!(result, Err(ImageError::TooLarge { .. }))); 135 if let Err(ImageError::TooLarge { width, height, max_dimension }) = result { 136 assert_eq!(width, 2000); 137 assert_eq!(height, 2000); 138 assert_eq!(max_dimension, 1000); 139 } 140} 141 142#[test] 143fn test_file_size_limit() { 144 let processor = ImageProcessor::new().with_max_file_size(100); 145 let data = create_test_png(500, 500); 146 let result = processor.process(&data, "image/png"); 147 148 assert!(matches!(result, Err(ImageError::FileTooLarge { .. }))); 149 if let Err(ImageError::FileTooLarge { size, max_size }) = result { 150 assert!(size > 100); 151 assert_eq!(max_size, 100); 152 } 153} 154 155#[test] 156fn test_default_max_file_size() { 157 assert_eq!(DEFAULT_MAX_FILE_SIZE, 10 * 1024 * 1024); 158} 159 160#[test] 161fn test_unsupported_format_rejected() { 162 let processor = ImageProcessor::new(); 163 let data = b"this is not an image"; 164 let result = processor.process(data, "application/octet-stream"); 165 166 assert!(matches!(result, Err(ImageError::UnsupportedFormat(_)))); 167} 168 169#[test] 170fn test_corrupted_image_handling() { 171 let processor = ImageProcessor::new(); 172 let data = b"\x89PNG\r\n\x1a\ncorrupted data here"; 173 let result = processor.process(data, "image/png"); 174 175 assert!(matches!(result, Err(ImageError::DecodeError(_)))); 176} 177 178#[test] 179fn test_aspect_ratio_preserved_landscape() { 180 let processor = ImageProcessor::new(); 181 let data = create_test_png(1600, 800); 182 let result = processor.process(&data, "image/png").unwrap(); 183 184 let thumb = result.thumbnail_full.expect("Should have thumbnail"); 185 let original_ratio = 1600.0 / 800.0; 186 let thumb_ratio = thumb.width as f64 / thumb.height as f64; 187 assert!((original_ratio - thumb_ratio).abs() < 0.1, "Aspect ratio should be preserved"); 188} 189 190#[test] 191fn test_aspect_ratio_preserved_portrait() { 192 let processor = ImageProcessor::new(); 193 let data = create_test_png(800, 1600); 194 let result = processor.process(&data, "image/png").unwrap(); 195 196 let thumb = result.thumbnail_full.expect("Should have thumbnail"); 197 let original_ratio = 800.0 / 1600.0; 198 let thumb_ratio = thumb.width as f64 / thumb.height as f64; 199 assert!((original_ratio - thumb_ratio).abs() < 0.1, "Aspect ratio should be preserved"); 200} 201 202#[test] 203fn test_mime_type_detection_auto() { 204 let processor = ImageProcessor::new(); 205 let data = create_test_png(100, 100); 206 let result = processor.process(&data, "application/octet-stream"); 207 208 assert!(result.is_ok(), "Should detect PNG format from data"); 209} 210 211#[test] 212fn test_is_supported_mime_type() { 213 assert!(ImageProcessor::is_supported_mime_type("image/jpeg")); 214 assert!(ImageProcessor::is_supported_mime_type("image/jpg")); 215 assert!(ImageProcessor::is_supported_mime_type("image/png")); 216 assert!(ImageProcessor::is_supported_mime_type("image/gif")); 217 assert!(ImageProcessor::is_supported_mime_type("image/webp")); 218 assert!(ImageProcessor::is_supported_mime_type("IMAGE/PNG")); 219 assert!(ImageProcessor::is_supported_mime_type("Image/Jpeg")); 220 221 assert!(!ImageProcessor::is_supported_mime_type("image/bmp")); 222 assert!(!ImageProcessor::is_supported_mime_type("image/tiff")); 223 assert!(!ImageProcessor::is_supported_mime_type("text/plain")); 224 assert!(!ImageProcessor::is_supported_mime_type("application/json")); 225} 226 227#[test] 228fn test_strip_exif() { 229 let data = create_test_jpeg(100, 100); 230 let result = ImageProcessor::strip_exif(&data); 231 assert!(result.is_ok()); 232 let stripped = result.unwrap(); 233 assert!(!stripped.is_empty()); 234} 235 236#[test] 237fn test_with_thumbnails_disabled() { 238 let processor = ImageProcessor::new().with_thumbnails(false); 239 let data = create_test_png(2000, 2000); 240 let result = processor.process(&data, "image/png").unwrap(); 241 242 assert!(result.thumbnail_feed.is_none(), "Thumbnails should be disabled"); 243 assert!(result.thumbnail_full.is_none(), "Thumbnails should be disabled"); 244} 245 246#[test] 247fn test_builder_chaining() { 248 let processor = ImageProcessor::new() 249 .with_max_dimension(2048) 250 .with_max_file_size(5 * 1024 * 1024) 251 .with_output_format(OutputFormat::Jpeg) 252 .with_thumbnails(true); 253 254 let data = create_test_png(500, 500); 255 let result = processor.process(&data, "image/png").unwrap(); 256 assert_eq!(result.original.mime_type, "image/jpeg"); 257} 258 259#[test] 260fn test_processed_image_fields() { 261 let processor = ImageProcessor::new(); 262 let data = create_test_png(500, 500); 263 let result = processor.process(&data, "image/png").unwrap(); 264 265 assert!(!result.original.data.is_empty()); 266 assert!(!result.original.mime_type.is_empty()); 267 assert!(result.original.width > 0); 268 assert!(result.original.height > 0); 269} 270 271#[test] 272fn test_only_feed_thumbnail_for_medium_images() { 273 let processor = ImageProcessor::new(); 274 let data = create_test_png(500, 500); 275 let result = processor.process(&data, "image/png").unwrap(); 276 277 assert!(result.thumbnail_feed.is_some(), "Should have feed thumbnail"); 278 assert!(result.thumbnail_full.is_none(), "Should NOT have full thumbnail for 500px image"); 279} 280 281#[test] 282fn test_both_thumbnails_for_large_images() { 283 let processor = ImageProcessor::new(); 284 let data = create_test_png(2000, 2000); 285 let result = processor.process(&data, "image/png").unwrap(); 286 287 assert!(result.thumbnail_feed.is_some(), "Should have feed thumbnail"); 288 assert!(result.thumbnail_full.is_some(), "Should have full thumbnail for 2000px image"); 289} 290 291#[test] 292fn test_exact_threshold_boundary_feed() { 293 let processor = ImageProcessor::new(); 294 295 let at_threshold = create_test_png(THUMB_SIZE_FEED, THUMB_SIZE_FEED); 296 let result = processor.process(&at_threshold, "image/png").unwrap(); 297 assert!(result.thumbnail_feed.is_none(), "Exact threshold should not generate thumbnail"); 298 299 let above_threshold = create_test_png(THUMB_SIZE_FEED + 1, THUMB_SIZE_FEED + 1); 300 let result = processor.process(&above_threshold, "image/png").unwrap(); 301 assert!(result.thumbnail_feed.is_some(), "Above threshold should generate thumbnail"); 302} 303 304#[test] 305fn test_exact_threshold_boundary_full() { 306 let processor = ImageProcessor::new(); 307 308 let at_threshold = create_test_png(THUMB_SIZE_FULL, THUMB_SIZE_FULL); 309 let result = processor.process(&at_threshold, "image/png").unwrap(); 310 assert!(result.thumbnail_full.is_none(), "Exact threshold should not generate thumbnail"); 311 312 let above_threshold = create_test_png(THUMB_SIZE_FULL + 1, THUMB_SIZE_FULL + 1); 313 let result = processor.process(&above_threshold, "image/png").unwrap(); 314 assert!(result.thumbnail_full.is_some(), "Above threshold should generate thumbnail"); 315}