test(transcode): a fixture the WebP encoder cannot shrink

The transcode negative path — "the result came out larger, serve the
original and remember that" — had no test because no synthetic image
reaches it. Measured against the real encoder: flat colour goes
4780 → 186 bytes, a diagonal gradient 24852 → 102, and uniform RGBA
noise still loses by ~242 bytes at every size, a margin constant in
absolute terms and so one that never flips. Grayscale does not help
either; WebP's subtract-green transform handles R=G=B.

Two things have to be true at once and only real content does both.
The encoder is the `image` crate's own minimal VP8L writer, not
libwebp, so it wins only where redundancy is extreme enough for any
encoder to find it. And the original has to be near PNG-optimal, which
a screenshot from a real capture tool is: a 2x Retina UI is long
identical runs, flat panels and sharp edges — precisely what PNG's
scanline filters plus zlib were built for.

So the fixture is a real OxiCloud screenshot (emails masked by
overtyping rather than block-filling, which would have added back the
flat redundancy the property depends on; re-verified negative after
masking, 556180 -> 511124 bytes).

`fixture_premise` pins both halves of what tests/api/transcode_cache.hurl
will assume — this one negative, red-image.png positive. Without the
guard a future encoder bump would silently turn the negative half of
that scenario into a second positive test: still passing, no longer
checking what it was written to check.

Worth recording for whenever libwebp replaces this encoder: most of
these screenshots would likely flip to positive, which leaves every
stored negative row a stale verdict. An encoder change has to purge
them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Edouard Vanbelle
2026-08-29 14:55:55 +02:00
parent 9c63f9969a
commit 8fabbfad9e
2 changed files with 59 additions and 0 deletions
@@ -606,6 +606,65 @@ impl ImageTranscodeService {
// ─── CPU-bound transcoding (runs on rayon, never on Tokio) ───────────────────
#[cfg(test)]
mod fixture_premise {
//! Pins the property `tests/api/transcode_cache.hurl` is built on: one
//! fixture WebP shrinks, one it does not.
//!
//! The negative half was hard to come by and the reason is worth
//! recording. Synthetic images do not reproduce it — flat colour goes
//! 4780 → 186 bytes, a gradient 24852 → 102, and even uniform RGBA
//! noise still loses by ~242 bytes at any size, a margin that is
//! constant in absolute terms and so never flips.
//!
//! Two things have to be true at once, and only real content does
//! both. The encoder here is the `image` crate's own minimal VP8L
//! writer, not libwebp — it does none of libwebp's search over
//! predictors, colour transforms and Huffman groups — so it only wins
//! where redundancy is extreme enough that any encoder finds it. And
//! the original has to be near PNG-optimal, which a screenshot from a
//! real capture tool is: a 2× Retina UI is long identical runs, flat
//! panels and sharp edges, exactly what PNG's scanline filters plus
//! zlib were designed around.
//!
//! So the negative verdict this service persists is partly a property
//! of THIS encoder, not of the content. Swapping in libwebp would
//! likely flip most of these to positive and leave the stored negative
//! rows stale — an encoder change has to purge them.
use super::*;
fn webp_len(path: &str) -> (usize, usize) {
let png = std::fs::read(path).expect("fixture present");
let webp =
transcode_image_blocking(&Bytes::from(png.clone()), "image/png", OutputFormat::WebP)
.expect("fixture decodes");
(png.len(), webp.len())
}
/// If this ever fails, the hurl scenario's negative half has silently
/// become a second positive test — it would still pass while checking
/// nothing it was written to check.
#[test]
fn screenshot_fixture_is_a_genuine_negative() {
let (png, webp) = webp_len("tests/fixtures/negative-cache-transcode.png");
assert!(
webp >= png,
"negative-cache-transcode.png no longer defeats the WebP encoder: \
png={png} webp={webp}"
);
}
#[test]
fn flat_colour_fixture_is_a_genuine_positive() {
let (png, webp) = webp_len("tests/fixtures/red-image.png");
assert!(
webp < png,
"red-image.png stopped shrinking: png={png} webp={webp}"
);
}
}
/// Perform actual image transcoding. This is a pure CPU function — safe to call
/// from `rayon::spawn` or `spawn_blocking`.
fn transcode_image_blocking(
Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB