#[cfg(test)]
mod image_tests {
use crate::XlsxError;
use crate::Image;
#[test]
fn test_images() {
let image_test_data = vec![
("black_150.jpg", 64, 64, 150.0, 150.0, "jpeg"),
("black_300.jpg", 64, 64, 300.0, 300.0, "jpeg"),
("black_300.png", 64, 64, 299.9994, 299.9994, "png"),
("black_300e.png", 64, 64, 299.9994, 299.9994, "png"),
("black_40000x45000.gif", 40_000, 45_000, 96.0, 96.0, "gif"),
("black_72.jpg", 64, 64, 72.0, 72.0, "jpeg"),
("black_72.png", 64, 64, 72.009, 72.009, "png"),
("black_72e.png", 64, 64, 72.009, 72.009, "png"),
("black_96.jpg", 64, 64, 96.0, 96.0, "jpeg"),
("black_96.png", 64, 64, 96.012, 96.012, "png"),
("blue.jpg", 23, 23, 96.0, 96.0, "jpeg"),
("blue.png", 23, 23, 96.0, 96.0, "png"),
("grey.jpg", 99, 69, 96.0, 96.0, "jpeg"),
("grey.png", 99, 69, 96.0, 96.0, "png"),
("happy.jpg", 423, 563, 96.0, 96.0, "jpeg"),
("issue32.png", 115, 115, 96.0, 96.0, "png"),
("logo.gif", 200, 80, 96.0, 96.0, "gif"),
("logo.jpg", 200, 80, 96.0, 96.0, "jpeg"),
("logo.png", 200, 80, 96.0, 96.0, "png"),
("mylogo.png", 215, 36, 95.9866, 95.9866, "png"),
("red.bmp", 32, 32, 96.0, 96.0, "bmp"),
("red.gif", 32, 32, 96.0, 96.0, "gif"),
("red.jpg", 32, 32, 96.0, 96.0, "jpeg"),
("red.png", 32, 32, 96.0, 96.0, "png"),
("red2.png", 32, 32, 96.0, 96.0, "png"),
("red_208.png", 208, 49, 96.0, 96.0, "png"),
("red_64x20.png", 64, 20, 96.0, 96.0, "png"),
("red_readonly.png", 32, 32, 96.0, 96.0, "png"),
("red_topdown_20x12.bmp", 20, 12, 96.0, 96.0, "bmp"),
("red_topdown_32x32.bmp", 32, 32, 96.0, 96.0, "bmp"),
("train.jpg", 640, 480, 96.0, 96.0, "jpeg"),
("watermark.png", 1778, 1003, 329.9968, 329.9968, "png"),
("yellow.jpg", 72, 72, 96.0, 96.0, "jpeg"),
("yellow.png", 72, 72, 96.0, 96.0, "png"),
("zero_dpi.jpg", 11, 16, 96.0, 96.0, "jpeg"),
(
"black_150.png",
64,
64,
150.01239999999999,
150.01239999999999,
"png",
),
(
"black_150e.png",
64,
64,
150.01239999999999,
150.01239999999999,
"png",
),
];
for test_data in image_test_data {
let (filename, width, height, width_dpi, height_dpi, image_type) = test_data;
let filename = format!("tests/input/images/{filename}");
let image = Image::new(&filename).unwrap();
assert_eq!(width as f64, image.width());
assert_eq!(height as f64, image.height());
assert_eq!(width_dpi, image.width_dpi());
assert_eq!(height_dpi, image.height_dpi());
assert_eq!(image_type, image.image_type.extension());
}
}
#[test]
fn unknown_file_format() {
let filename = "tests/input/images/unknown.img".to_string();
let image = Image::new(filename);
assert!(matches!(image, Err(XlsxError::UnknownImageType)));
}
#[test]
fn invalid_file_format() {
let filename = "tests/input/images/no_dimensions.png".to_string();
let image = Image::new(filename);
assert!(matches!(image, Err(XlsxError::ImageDimensionError)));
}
#[test]
fn truncated_image_data() {
let cases: Vec<Vec<u8>> = vec![
vec![], vec![0x42, 0x4D, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], vec![0u8; 25], vec![0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A], ];
for data in cases {
let image = Image::new_from_buffer(&data);
assert!(matches!(image, Err(XlsxError::UnknownImageType)));
}
}
#[test]
fn truncated_image_loop_data() {
let mut png_short_marker = Vec::new();
png_short_marker.extend_from_slice(&[0x89]);
png_short_marker.extend_from_slice(b"PNG\r\n\x1a\n");
png_short_marker.extend_from_slice(&13u32.to_be_bytes());
png_short_marker.extend_from_slice(b"IHDR");
png_short_marker.extend_from_slice(&[0; 17]); png_short_marker.push(0);
let mut png_short_ihdr = Vec::new();
png_short_ihdr.extend_from_slice(&[0x89]);
png_short_ihdr.extend_from_slice(b"PNG\r\n\x1a\n");
png_short_ihdr.extend_from_slice(&2u32.to_be_bytes());
png_short_ihdr.extend_from_slice(b"aaaa");
png_short_ihdr.extend_from_slice(&[0; 10]);
png_short_ihdr.extend_from_slice(b"IHDR");
let mut png_short_phys = Vec::new();
png_short_phys.extend_from_slice(&[0x89]);
png_short_phys.extend_from_slice(b"PNG\r\n\x1a\n");
png_short_phys.extend_from_slice(&2u32.to_be_bytes());
png_short_phys.extend_from_slice(b"aaaa");
png_short_phys.extend_from_slice(&[0; 6]); png_short_phys.extend_from_slice(&9u32.to_be_bytes());
png_short_phys.extend_from_slice(b"pHYs");
let mut jpg_short_sof = Vec::new();
jpg_short_sof.extend_from_slice(&[0xFF, 0xD8]); jpg_short_sof.extend_from_slice(&[0xFF, 0xE0, 0x00, 0x14]); jpg_short_sof.extend_from_slice(&[0; 18]); jpg_short_sof.extend_from_slice(&[0xFF, 0xC0, 0x00, 0x11]); jpg_short_sof.push(8);
let mut jpg_short_marker = Vec::new();
jpg_short_marker.extend_from_slice(&[0xFF, 0xD8]); jpg_short_marker.extend_from_slice(&[0xFF, 0xE0, 0x00, 0x15]); jpg_short_marker.extend_from_slice(&[0; 19]); jpg_short_marker.push(0xFF);
let mut jpg_short_app0 = Vec::new();
jpg_short_app0.extend_from_slice(&[0xFF, 0xD8]); jpg_short_app0.extend_from_slice(&[0xFF, 0xFE, 0x00, 0x14]); jpg_short_app0.extend_from_slice(&[0; 18]); jpg_short_app0.extend_from_slice(&[0xFF, 0xE0, 0x00, 0x14]); jpg_short_app0.extend_from_slice(&[0; 5]);
let mut png_overflow = Vec::new();
png_overflow.extend_from_slice(&[0x89]);
png_overflow.extend_from_slice(b"PNG\r\n\x1a\n");
png_overflow.extend_from_slice(&u32::MAX.to_be_bytes());
png_overflow.extend_from_slice(b"aaaa");
png_overflow.extend_from_slice(&[0; 10]);
let cases = vec![
png_short_marker,
png_short_ihdr,
png_short_phys,
jpg_short_sof,
jpg_short_marker,
jpg_short_app0,
png_overflow,
];
for data in cases {
let image = Image::new_from_buffer(&data);
assert!(matches!(image, Err(XlsxError::ImageDimensionError)));
}
}
#[test]
fn bmp_negative_height() {
fn tmp_bmp(height: i32) -> Vec<u8> {
let mut data = vec![0u8; 26];
let width: i32 = 100;
data[0] = b'B';
data[1] = b'M';
data[18..22].copy_from_slice(&width.to_le_bytes());
data[22..26].copy_from_slice(&height.to_le_bytes());
data
}
for height in [50, -50] {
let image = Image::new_from_buffer(&tmp_bmp(height)).unwrap();
assert_eq!(100.0, image.width());
assert_eq!(50.0, image.height());
}
let image = Image::new_from_buffer(&tmp_bmp(i32::MIN));
assert!(matches!(image, Err(XlsxError::ImageDimensionError)));
}
}