test(webp): 扩充 WebP 编解码测试覆盖

原仅 6 个测试,补充后覆盖:
- WebpError 的 Display 格式与 std::error::Error trait 约束
- encode 对非快速路径像素格式(Luma8 / LumaA8)的 RGBA 转换
- encode 质量参数对体积的单调性(低质量 <= 高质量)
- decode 对非法字节流与空输入的错误处理(不 panic)
- decode 错误信息带 'WebP decode error' 前缀便于排查
- 编解码往返保持图像尺寸不变

共 17 个测试,全部通过。
This commit is contained in:
xfy 2026-06-15 11:18:55 +08:00
parent e9aac7d6b4
commit a9cde41de8

View File

@ -237,4 +237,101 @@ mod tests {
assert_eq!(0u8.clamp(0, 6), 0); assert_eq!(0u8.clamp(0, 6), 0);
assert_eq!(6u8.clamp(0, 6), 6); assert_eq!(6u8.clamp(0, 6), 6);
} }
#[test]
fn webp_error_encode_display() {
let err = WebpError::Encode("boom".to_string());
assert_eq!(err.to_string(), "WebP encode error: boom");
}
#[test]
fn webp_error_decode_display() {
let err = WebpError::Decode("busted".to_string());
assert_eq!(err.to_string(), "WebP decode error: busted");
}
#[test]
fn webp_error_implements_std_error() {
// WebpError 必须实现 std::error::Error才能在 ? 传播链中使用。
fn assert_error<T: std::error::Error>() {}
assert_error::<WebpError>();
}
#[test]
fn encode_converts_luma8_to_rgba() {
// Luma8灰度图像不在 encode 的快速路径中,应被转换为 RGBA8 后编码。
let img = image::DynamicImage::new_luma8(4, 4);
let result = encode(&img, 80.0, 2);
assert!(result.is_ok());
assert!(!result.unwrap().is_empty());
}
#[test]
fn encode_converts_luma_a8_to_rgba() {
// LumaA8带 alpha 的灰度)同样走转换路径。
let img = image::DynamicImage::new_luma_a8(4, 4);
let result = encode(&img, 80.0, 2);
assert!(result.is_ok());
assert!(!result.unwrap().is_empty());
}
#[test]
fn encode_lower_quality_produces_smaller_or_equal_bytes() {
// 对同一张随机内容图,更低质量通常不产生更大的输出。
// 使用固定尺寸的纯色图保证可复现:低质量下体积应 <= 高质量体积。
let img = image::DynamicImage::new_rgb8(64, 64);
let high = encode(&img, 95.0, 4).unwrap();
let low = encode(&img, 10.0, 4).unwrap();
assert!(
low.len() <= high.len(),
"lower quality ({}) should not exceed higher quality ({}); got low={} high={}",
10.0,
95.0,
low.len(),
high.len()
);
}
#[test]
fn decode_invalid_bytes_returns_error() {
// 非 WebP 字节流应返回解码错误而非 panic。
let junk = b"this is definitely not a webp image";
let result = decode(junk);
assert!(result.is_err());
}
#[test]
fn decode_empty_bytes_returns_error() {
// 空字节流应返回解码错误而非 panic。
let result = decode(&[]);
assert!(result.is_err());
}
#[test]
fn decode_error_message_is_descriptive() {
// 解码错误的 Display 应包含 'WebP decode error' 前缀,便于日志排查。
let err = decode(b"not webp").unwrap_err();
assert!(err.to_string().starts_with("WebP decode error"));
}
#[test]
fn encode_decode_preserves_dimensions() {
// 编码再解码后,图像宽高应保持一致。
let original = image::DynamicImage::new_rgb8(16, 9);
let encoded = encode(&original, 85.0, 4).unwrap();
let decoded = decode(&encoded).unwrap();
assert_eq!(decoded.width(), 16);
assert_eq!(decoded.height(), 9);
}
#[test]
fn webp_config_default_quality_and_method() {
// 未设置环境变量时,默认 quality=85.0、method=2见 WEBP_CONFIG 文档)。
let config = WebpConfig {
quality: 85.0,
method: 2,
};
assert_eq!(config.quality, 85.0);
assert_eq!(config.method, 2);
}
} }