crates/gunnar-pack/tests/deflate_backend.rs
//! P-007's safety net: the zlib backend is `zlib-rs`, and swapping to it did
//! not trade compression quality for speed.
//!
//! The workspace selects `flate2`'s `zlib-rs` backend because it is ~1.9× faster
//! than the default `miniz_oxide` at effectively the same ratio, and is already
//! linked into this tree through `gix-zlib`. Two things could silently undo
//! that, and neither would fail any other test in the suite:
//!
//! * **the feature comes off**: someone drops `features = ["zlib-rs"]` from
//! the workspace `flate2` line, or a new crate pulls flate2 in a way that
//! re-selects the C backend. Everything still works, just at half speed.
//! * **the win was never free**. A backend that compresses *worse* would
//! look faster on a benchmark while putting more bytes on every wire.
//!
//! So this file pins the one observable that separates the backends: the bytes
//! they produce. [`MINIZ_OXIDE_PACK_ID`] is the trailer of the pack below as
//! written by `miniz_oxide`, captured on 2026-08-03 by temporarily restoring
//! flate2's default features. If the backend ever reverts, the pack is
//! byte-identical to that one again and `backend_is_not_miniz_oxide` goes red.
//! It was seen red exactly that way before being committed.
//!
//! The constant is deliberately a *negative* pin. Pinning the zlib-rs output
//! instead would turn every zlib-rs patch release into a spurious failure,
//! which is how a guard gets deleted rather than fixed.
mod common;
use common::MemObjects;
use gix_hash::Kind;
use gunnar_pack::{write_pack_to_vec, WriteOptions};
/// The trailer of [`fixture_pack`] when `flate2` uses its default `miniz_oxide`
/// backend. MEASURED 2026-08-03 on oden; see the module docs for how.
const MINIZ_OXIDE_PACK_ID: &str =
"bcda49c25e95816fd06a95aa1efb77299c14bac44837c4d1dce823364dedbad0";
/// Total size of [`fixture_pack`] at level 6, MEASURED 2026-08-03 on oden:
/// miniz_oxide **172_282** bytes, zlib-rs **172_308** bytes, i.e. **0.015%
/// apart**, which is P-007's "free win" claim reduced to two integers.
///
/// The band below is ±3%. Level 1 produces 280_823 bytes for this fixture
/// (+63%), so a silent level or backend-quality regression lands far outside it
/// while a zlib-rs patch release does not. `the_quality_band_can_fail` asserts
/// that gap rather than trusting this paragraph.
const EXPECTED_PACK_BYTES: usize = 172_308;
const BAND: f64 = 0.03;
/// Deterministic, source-code-shaped content: a fixed vocabulary assembled by a
/// seeded LCG, so every machine and every run builds the identical corpus.
///
/// Random *bytes* would be the wrong fixture. Incompressible input makes every
/// backend look alike and would hide precisely what this file is guarding.
fn fixture_blobs() -> Vec<Vec<u8>> {
const WORDS: &[&str] = &[
"let", "mut", "fn", "pub", "struct", "impl", "match", "self", "Result", "Ok", "Err",
"writer", "hasher", "pack", "object", "deflate", "trailer", "bytes", "kind", "options",
"gix_hash", "flate2", "compress", "scratch", "chunk", "return", "if", "else", "for",
"while",
];
let mut state: u64 = 0x9E37_79B9_7F4A_7C15;
let mut next = move || {
state = state
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
(state >> 33) as usize
};
(0..48)
.map(|_| {
let mut blob = String::with_capacity(16 * 1024);
while blob.len() < 16 * 1024 {
let indent = " ".repeat(next() % 4);
blob.push_str(&indent);
for _ in 0..(4 + next() % 10) {
blob.push_str(WORDS[next() % WORDS.len()]);
blob.push(' ');
}
blob.push_str(";\n");
}
blob.into_bytes()
})
.collect()
}
/// The pack both constants above describe. SHA-256 so the fixture is
/// independent of which SHA-1 hasher `checksum.rs` picks; this file is about
/// the *compressor*, and mixing the two concerns would make a red ambiguous.
fn fixture_pack() -> (Vec<u8>, gunnar_pack::WriteOutcome) {
let mut store = MemObjects::new(Kind::Sha256);
let ids: Vec<_> = fixture_blobs()
.into_iter()
.map(|blob| store.insert_blob(blob))
.collect();
write_pack_to_vec(&ids, &store, &WriteOptions::new(Kind::Sha256)).expect("writing the fixture")
}
/// The backend is not `miniz_oxide`.
///
/// Two different zlib implementations do not produce the same deflate stream
/// for a 750 KiB corpus, so an equal pack id means the same backend produced
/// it. This is the assertion that catches the feature quietly falling off the
/// `flate2` line.
#[test]
fn backend_is_not_miniz_oxide() {
let (_, outcome) = fixture_pack();
assert_ne!(
outcome.pack_id.to_string(),
MINIZ_OXIDE_PACK_ID,
"flate2 is compressing exactly like miniz_oxide again — the `zlib-rs` \
feature has come off the workspace `flate2` dependency (P-007), and \
deflate is running at about half speed"
);
}
/// The swap did not cost compression quality.
///
/// P-007's whole claim is a free win: same bytes out, twice as fast. A backend
/// that got faster by compressing less would pass every correctness test in the
/// suite and quietly widen every clone.
#[test]
fn compression_quality_did_not_regress() {
let (pack, outcome) = fixture_pack();
assert_eq!(pack.len() as u64, outcome.bytes_written);
let low = (EXPECTED_PACK_BYTES as f64 * (1.0 - BAND)) as usize;
let high = (EXPECTED_PACK_BYTES as f64 * (1.0 + BAND)) as usize;
assert!(
(low..=high).contains(&pack.len()),
"the fixture pack is {} bytes, outside the {low}..={high} band around the \
measured {EXPECTED_PACK_BYTES}. Either the compression level moved or the \
backend is compressing worse — P-007 was supposed to be free.",
pack.len()
);
}
/// **The red for the band.** Level 1 is the cheapest way to make the writer
/// "faster" while spending more bytes, and it must land outside the band the
/// test above accepts. Without this, a band wide enough to be quiet would also
/// be wide enough to be useless.
#[test]
fn the_quality_band_can_fail() {
let mut store = MemObjects::new(Kind::Sha256);
let ids: Vec<_> = fixture_blobs()
.into_iter()
.map(|blob| store.insert_blob(blob))
.collect();
let (fast, _) = write_pack_to_vec(
&ids,
&store,
&WriteOptions::new(Kind::Sha256).compression_level(1),
)
.expect("writing at level 1");
let high = (EXPECTED_PACK_BYTES as f64 * (1.0 + BAND)) as usize;
assert!(
fast.len() > high,
"a level-1 pack is {} bytes, inside the band `compression_quality_did_not_regress` \
accepts ({high} max) — that test cannot detect a quality regression and must be \
retuned, not trusted",
fast.len()
);
}
/// Stock `git`, with its own zlib rather than ours, inflates every entry of
/// what this backend produced.
///
/// `zlib-rs` emits a different bit stream from `miniz_oxide`; that is expected
/// and legal, but "legal" has to be checked against an implementation that has
/// no shared code with the one under test. `--strict` makes `index-pack` verify
/// each object's id against its inflated content, so this fails if the
/// compressor ever produces something that merely round-trips through itself.
#[test]
fn stock_git_inflates_what_this_backend_wrote() {
// A hard failure, not a skip (`S-026`). "The real interop coverage lives in
// `gunnar-wire`" was the old justification for returning early here, and it
// is not one: on an image without `git` this test reported a pass having
// inflated nothing, and so did every suite in `gunnar-wire`.
let git = git_binary().expect("this test requires `git` on PATH");
let dir = tempfile::tempdir().expect("tempdir");
let (pack, outcome) = fixture_pack();
let path = dir.path().join("in.pack");
std::fs::write(&path, &pack).expect("writing the pack");
let out = std::process::Command::new(git)
.args(["index-pack", "--strict", "--object-format=sha256", "-v"])
.arg(&path)
.output()
.expect("running git index-pack");
assert!(
out.status.success(),
"stock git rejected a pack this backend wrote: {}",
String::from_utf8_lossy(&out.stderr)
);
assert!(
dir.path().join("in.idx").exists(),
"git index-pack reported success but wrote no index — check output, not exit code"
);
assert_eq!(outcome.num_objects, 48);
}
fn git_binary() -> Option<&'static str> {
std::process::Command::new("git")
.arg("--version")
.output()
.ok()
.filter(|out| out.status.success())
.map(|_| "git")
}