Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

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"
    );
}