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 let thumb = result.thumbnail_feed.expect("Should generate feed thumbnail for large image"); 75 assert!(thumb.width <= THUMB_SIZE_FEED); 76 assert!(thumb.height <= THUMB_SIZE_FEED); 77} 78 79#[test] 80fn test_thumbnail_full_size() { 81 let processor = ImageProcessor::new(); 82 let data = create_test_png(2000, 1500); 83 let result = processor.process(&data, "image/png").unwrap(); 84 let thumb = result.thumbnail_full.expect("Should generate full thumbnail for large image"); 85 assert!(thumb.width <= THUMB_SIZE_FULL); 86 assert!(thumb.height <= THUMB_SIZE_FULL); 87} 88 89#[test] 90fn test_no_thumbnail_small_image() { 91 let processor = ImageProcessor::new(); 92 let data = create_test_png(100, 100); 93 let result = processor.process(&data, "image/png").unwrap(); 94 assert!(result.thumbnail_feed.is_none(), "Small image should not get feed thumbnail"); 95 assert!(result.thumbnail_full.is_none(), "Small image should not get full thumbnail"); 96} 97 98#[test] 99fn test_webp_conversion() { 100 let processor = ImageProcessor::new().with_output_format(OutputFormat::WebP); 101 let data = create_test_png(300, 300); 102 let result = processor.process(&data, "image/png").unwrap(); 103 assert_eq!(result.original.mime_type, "image/webp"); 104} 105 106#[test] 107fn test_jpeg_output_format() { 108 let processor = ImageProcessor::new().with_output_format(OutputFormat::Jpeg); 109 let data = create_test_png(300, 300); 110 let result = processor.process(&data, "image/png").unwrap(); 111 assert_eq!(result.original.mime_type, "image/jpeg"); 112} 113 114#[test] 115fn test_png_output_format() { 116 let processor = ImageProcessor::new().with_output_format(OutputFormat::Png); 117 let data = create_test_jpeg(300, 300); 118 let result = processor.process(&data, "image/jpeg").unwrap(); 119 assert_eq!(result.original.mime_type, "image/png"); 120} 121 122#[test] 123fn test_max_dimension_enforced() { 124 let processor = ImageProcessor::new().with_max_dimension(1000); 125 let data = create_test_png(2000, 2000); 126 let result = processor.process(&data, "image/png"); 127 assert!(matches!(result, Err(ImageError::TooLarge { .. }))); 128 if let Err(ImageError::TooLarge { width, height, max_dimension }) = result { 129 assert_eq!(width, 2000); 130 assert_eq!(height, 2000); 131 assert_eq!(max_dimension, 1000); 132 } 133} 134 135#[test] 136fn test_file_size_limit() { 137 let processor = ImageProcessor::new().with_max_file_size(100); 138 let data = create_test_png(500, 500); 139 let result = processor.process(&data, "image/png"); 140 assert!(matches!(result, Err(ImageError::FileTooLarge { .. }))); 141 if let Err(ImageError::FileTooLarge { size, max_size }) = result { 142 assert!(size > 100); 143 assert_eq!(max_size, 100); 144 } 145} 146 147#[test] 148fn test_default_max_file_size() { 149 assert_eq!(DEFAULT_MAX_FILE_SIZE, 10 * 1024 * 1024); 150} 151 152#[test] 153fn test_unsupported_format_rejected() { 154 let processor = ImageProcessor::new(); 155 let data = b"this is not an image"; 156 let result = processor.process(data, "application/octet-stream"); 157 assert!(matches!(result, Err(ImageError::UnsupportedFormat(_)))); 158} 159 160#[test] 161fn test_corrupted_image_handling() { 162 let processor = ImageProcessor::new(); 163 let data = b"\x89PNG\r\n\x1a\ncorrupted data here"; 164 let result = processor.process(data, "image/png"); 165 assert!(matches!(result, Err(ImageError::DecodeError(_)))); 166} 167 168#[test] 169fn test_aspect_ratio_preserved_landscape() { 170 let processor = ImageProcessor::new(); 171 let data = create_test_png(1600, 800); 172 let result = processor.process(&data, "image/png").unwrap(); 173 let thumb = result.thumbnail_full.expect("Should have thumbnail"); 174 let original_ratio = 1600.0 / 800.0; 175 let thumb_ratio = thumb.width as f64 / thumb.height as f64; 176 assert!((original_ratio - thumb_ratio).abs() < 0.1, "Aspect ratio should be preserved"); 177} 178 179#[test] 180fn test_aspect_ratio_preserved_portrait() { 181 let processor = ImageProcessor::new(); 182 let data = create_test_png(800, 1600); 183 let result = processor.process(&data, "image/png").unwrap(); 184 let thumb = result.thumbnail_full.expect("Should have thumbnail"); 185 let original_ratio = 800.0 / 1600.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_mime_type_detection_auto() { 192 let processor = ImageProcessor::new(); 193 let data = create_test_png(100, 100); 194 let result = processor.process(&data, "application/octet-stream"); 195 assert!(result.is_ok(), "Should detect PNG format from data"); 196} 197 198#[test] 199fn test_is_supported_mime_type() { 200 assert!(ImageProcessor::is_supported_mime_type("image/jpeg")); 201 assert!(ImageProcessor::is_supported_mime_type("image/jpg")); 202 assert!(ImageProcessor::is_supported_mime_type("image/png")); 203 assert!(ImageProcessor::is_supported_mime_type("image/gif")); 204 assert!(ImageProcessor::is_supported_mime_type("image/webp")); 205 assert!(ImageProcessor::is_supported_mime_type("IMAGE/PNG")); 206 assert!(ImageProcessor::is_supported_mime_type("Image/Jpeg")); 207 assert!(!ImageProcessor::is_supported_mime_type("image/bmp")); 208 assert!(!ImageProcessor::is_supported_mime_type("image/tiff")); 209 assert!(!ImageProcessor::is_supported_mime_type("text/plain")); 210 assert!(!ImageProcessor::is_supported_mime_type("application/json")); 211} 212 213#[test] 214fn test_strip_exif() { 215 let data = create_test_jpeg(100, 100); 216 let result = ImageProcessor::strip_exif(&data); 217 assert!(result.is_ok()); 218 let stripped = result.unwrap(); 219 assert!(!stripped.is_empty()); 220} 221 222#[test] 223fn test_with_thumbnails_disabled() { 224 let processor = ImageProcessor::new().with_thumbnails(false); 225 let data = create_test_png(2000, 2000); 226 let result = processor.process(&data, "image/png").unwrap(); 227 assert!(result.thumbnail_feed.is_none(), "Thumbnails should be disabled"); 228 assert!(result.thumbnail_full.is_none(), "Thumbnails should be disabled"); 229} 230 231#[test] 232fn test_builder_chaining() { 233 let processor = ImageProcessor::new() 234 .with_max_dimension(2048) 235 .with_max_file_size(5 * 1024 * 1024) 236 .with_output_format(OutputFormat::Jpeg) 237 .with_thumbnails(true); 238 let data = create_test_png(500, 500); 239 let result = processor.process(&data, "image/png").unwrap(); 240 assert_eq!(result.original.mime_type, "image/jpeg"); 241} 242 243#[test] 244fn test_processed_image_fields() { 245 let processor = ImageProcessor::new(); 246 let data = create_test_png(500, 500); 247 let result = processor.process(&data, "image/png").unwrap(); 248 assert!(!result.original.data.is_empty()); 249 assert!(!result.original.mime_type.is_empty()); 250 assert!(result.original.width > 0); 251 assert!(result.original.height > 0); 252} 253 254#[test] 255fn test_only_feed_thumbnail_for_medium_images() { 256 let processor = ImageProcessor::new(); 257 let data = create_test_png(500, 500); 258 let result = processor.process(&data, "image/png").unwrap(); 259 assert!(result.thumbnail_feed.is_some(), "Should have feed thumbnail"); 260 assert!(result.thumbnail_full.is_none(), "Should NOT have full thumbnail for 500px image"); 261} 262 263#[test] 264fn test_both_thumbnails_for_large_images() { 265 let processor = ImageProcessor::new(); 266 let data = create_test_png(2000, 2000); 267 let result = processor.process(&data, "image/png").unwrap(); 268 assert!(result.thumbnail_feed.is_some(), "Should have feed thumbnail"); 269 assert!(result.thumbnail_full.is_some(), "Should have full thumbnail for 2000px image"); 270} 271 272#[test] 273fn test_exact_threshold_boundary_feed() { 274 let processor = ImageProcessor::new(); 275 let at_threshold = create_test_png(THUMB_SIZE_FEED, THUMB_SIZE_FEED); 276 let result = processor.process(&at_threshold, "image/png").unwrap(); 277 assert!(result.thumbnail_feed.is_none(), "Exact threshold should not generate thumbnail"); 278 let above_threshold = create_test_png(THUMB_SIZE_FEED + 1, THUMB_SIZE_FEED + 1); 279 let result = processor.process(&above_threshold, "image/png").unwrap(); 280 assert!(result.thumbnail_feed.is_some(), "Above threshold should generate thumbnail"); 281} 282 283#[test] 284fn test_exact_threshold_boundary_full() { 285 let processor = ImageProcessor::new(); 286 let at_threshold = create_test_png(THUMB_SIZE_FULL, THUMB_SIZE_FULL); 287 let result = processor.process(&at_threshold, "image/png").unwrap(); 288 assert!(result.thumbnail_full.is_none(), "Exact threshold should not generate thumbnail"); 289 let above_threshold = create_test_png(THUMB_SIZE_FULL + 1, THUMB_SIZE_FULL + 1); 290 let result = processor.process(&above_threshold, "image/png").unwrap(); 291 assert!(result.thumbnail_full.is_some(), "Above threshold should generate thumbnail"); 292}