crates/gunnar-wire/tests/pack_vocabulary.rs
//! **`gunnar_wire::pack` against the crate it took its words from.**
//!
//! `src/pack.rs` holds the pack-shaped values `upload-pack` and `receive-pack`
//! *report* with. Every one of them used to be `gunnar_pack::…`, and moving
//! them is what took `gix-pack` — plus `gix-diff`, `gix-traverse`,
//! `gix-revwalk`, `gix-commitgraph`, `gix-fs`, `gix-tempfile`, `gix-path`,
//! `gix-chunk`, `gix-zlib` and `gix-features/parallel` — out of the appliance
//! graph, where none of them had ever had a call site.
//!
//! A copy that can drift is worse than no copy (one implementation), so the
//! two are compared here rather than in prose. This is an **integration** test
//! and not a `#[cfg(test)]` block in `src/pack.rs` on purpose:
//! `xtask::engine_seam` reads `crates/*/src` and does not read `#[cfg]`,
//! deliberately — a rule with a "but it is only a test" hatch inside a shipped
//! file is a rule with a hole in it — and it found that very line the first
//! time it ran.
/// The serve-side ceiling and the receive-side ceiling are **one number**.
///
/// An object that could not be received cannot usefully be served, and the
/// figure is attacker-controlled on both ends: it is read out of a pack a peer
/// sent. Two constants that could drift apart would mean a repository that
/// accepts an object it then refuses to hand back.
#[test]
fn the_serve_ceiling_matches_the_receive_ceiling() {
assert_eq!(
gunnar_wire::pack::DEFAULT_ALLOC_LIMIT_BYTES,
gunnar_pack::DEFAULT_ALLOC_LIMIT_BYTES,
"gunnar-wire's serve-side object ceiling has drifted from the receive-side ceiling \
gunnar-pack enforces"
);
assert_eq!(
gunnar_wire::DEFAULT_OBJECT_LIMIT_BYTES,
gunnar_wire::pack::DEFAULT_ALLOC_LIMIT_BYTES,
"`limits` must re-export the one constant rather than restate it"
);
}
/// `PackVersion` reads the same version out of a real pack that gix's indexer
/// does.
///
/// Against **bytes**, not against `gix_pack::data::Version`'s discriminants —
/// which are 0 and 1, not 2 and 3. Asserting on those was the first draft of
/// this test and it went red immediately, which is the whole argument for
/// writing it: `IndexedPack::pack_version` is populated from a number the
/// *engine* read out of a pack header (`PushReceipt::version`), and the two
/// spellings have to agree about which number that is or a receipt reports the
/// wrong format.
#[test]
fn the_local_pack_version_reads_a_real_pack_the_way_gix_does() {
use gunnar_wire::pack::PackVersion;
let pack = gunnar_pack::empty_pack(gix_hash::Kind::Sha1).expect("an empty pack is legal");
let header = u32::from_be_bytes(pack[4..8].try_into().expect("a pack has a 12-byte header"));
let indexed = gunnar_pack::index_pack(
&mut std::io::Cursor::new(&pack),
None,
&gunnar_pack::IndexOptions::new(gix_hash::Kind::Sha1),
None,
)
.expect("gix indexes the pack it just wrote");
assert_eq!(
indexed.pack_version,
gix_pack::data::Version::V2,
"the fixture is a v2 pack, which is what git has written since 2005"
);
assert_eq!(
PackVersion::from_u32(header),
PackVersion::V2,
"the same bytes, read through gunnar's own enum"
);
assert_eq!(
PackVersion::from_u32(header).as_u32(),
header,
"and the number round-trips, so a receipt cannot rename the format"
);
}