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/answered_path.rs

//! **Which path answered the fetch — and a guard that can tell them apart.**
//!
//! `Selection::answered_from_bitmap` (and the `UploadSummary` field it feeds)
//! exists so that a guard can assert whether a fetch was answered out of the
//! store's reachability index or by the walk beneath it. Until this file, the
//! only assertion anywhere on it was `crates/gunnar-cli/tests/observability.rs`
//! checking that the `git.upload_pack.served` log line carries a `from_index`
//! key *whose value is a boolean* — deliberately not which boolean, because
//! that test cannot know what store its fixture has.
//!
//! A flag that is only ever asserted to be *a bool* is not an instrument. Both
//! constants pass that assertion, and a constant is exactly the failure mode
//! this field was created to catch: the bitmap path declines request shapes it
//! cannot answer exactly, and getting one entry of that list wrong turns the
//! whole feature off **silently** — the walk still answers, and the walk is
//! correct. That happened on 2026-08-04 (`max_blob_bytes` is `Some` by default,
//! the bitmap path declined on it, and four end-to-end cases against stock git
//! went green while measuring the walk) and it is how `--fetch-budget` sat
//! inert on the store the appliance actually runs.
//!
//! So this file asserts the flag in **both directions against the same
//! repository**, which is the only shape that cannot be satisfied by a
//! constant:
//!
//! * the fixture store answers `GitServe::select`, so the index path runs and
//!   the flag must be `true`;
//! * `common::Unindexed` lays `Ok(None)` over that same store — the contract's
//!   own escape hatch, and the permanent state of a backend with no
//!   reachability projection — so the walk answers and the flag must be
//!   `false`;
//! * and the same indexed store, asked for a **filtered** fetch, must also
//!   report `false`, because `reachable::select` declines a filter outright.
//!   That arm is what separates "the flag reports the store" from "the flag
//!   reports the decision this request took".
//!
//! Each arm also asserts that the two paths chose the **same objects**. That is
//! the other half of the instrument: if the flag ever became a proxy for "a
//! different answer came back", it would stop being a statement about the path.
//!
//! # Seen RED
//!
//! Both directions were made to fail before this file was trusted. MEASURED
//! 2026-09-12 on builder, `cargo test -p gunnar-wire --no-fail-fast` in the
//! toolchain container, one break at a time:
//!
//! * `reachable.rs`'s `selection.answered_from_bitmap = true` changed to
//!   `false` — both tests here fail, the first on its index arm ("the index
//!   answered ... and the summary says the walk did"), and **all 167 other
//!   `gunnar-wire` tests stay green**. That is the 2026-08-04 failure exactly:
//!   the fast path reported as off, nothing else able to say so.
//! * `upload_pack.rs`'s `answered_from_bitmap: selection.answered_from_bitmap`
//!   changed to the constant `true` — both tests fail again, this time on the
//!   walk arm (line 131) and the filtered arm (line 182), and the same 167
//!   stay green.
//!
//! Neither constant passes this file, which is the whole property.

mod common;

use common::{Fixture, Unindexed};
use gix_hash::{Kind, ObjectId};
use gunnar_store::git_storage_trait::GitServe;
use gunnar_wire::upload_pack::{Config, UploadPack, UploadSummary};
use gunnar_wire::{ProtocolVersion, Session};

fn write_line(out: &mut Vec<u8>, payload: &str) {
    out.extend_from_slice(format!("{:04x}", payload.len() + 4).as_bytes());
    out.extend_from_slice(payload.as_bytes());
}

/// A v2 `fetch` for `want`, optionally carrying a partial-clone `filter`.
fn fetch_request(want: ObjectId, filter: Option<&str>) -> Vec<u8> {
    let mut request = Vec::new();
    write_line(&mut request, "command=fetch\n");
    write_line(&mut request, "object-format=sha1\n");
    request.extend_from_slice(b"0001");
    write_line(&mut request, &format!("want {want}\n"));
    if let Some(spec) = filter {
        write_line(&mut request, &format!("filter {spec}\n"));
    }
    write_line(&mut request, "done\n");
    request.extend_from_slice(b"0000");
    request
}

/// Serve one v2 fetch out of `store` and hand back the summary and the bytes.
fn serve(store: &dyn GitServe, kind: Kind, request: Vec<u8>) -> (UploadSummary, Vec<u8>) {
    let upload = UploadPack::new(store, kind).with_config(Config::default());
    let mut input = std::io::Cursor::new(request);
    let mut out = Vec::new();
    let summary = upload
        .serve_session(
            ProtocolVersion::V2,
            Session::Connected,
            &mut input,
            &mut out,
        )
        .expect("the fetch must be served");
    (summary, out)
}

/// **The flag says which path answered, and it says two different things about
/// one repository.**
///
/// Not two repositories and not two request shapes: the same fixture, the same
/// `want`, the same objects out — and the only difference is whether
/// `GitServe::select` answers or declines. A constant in either direction
/// fails one of the two arms.
#[test]
fn the_flag_distinguishes_the_index_from_the_walk() {
    let fixture = Fixture::build(Kind::Sha1);
    let request = || fetch_request(fixture.four, None);

    // ── the index answers ───────────────────────────────────────────────────
    //
    // `MemGitServe::select` is a real reachability walk over the in-memory
    // store, so `select_objects`' step 0 answers whole and no traversal runs.
    let (indexed, indexed_bytes) = serve(&fixture.git, fixture.kind, request());
    assert!(
        indexed.answered_from_bitmap,
        "the fixture store answers GitServe::select, so the reachability index answered this \
         fetch — and the summary says the walk did. That is the 2026-08-04 shape: the fast path \
         off, every other test still green. summary={indexed:?}"
    );

    // ── the walk answers ────────────────────────────────────────────────────
    //
    // `Unindexed` is `Ok(None)` laid over the *same* store: the contract's own
    // "cannot answer cheaply, walk it yourself", and the permanent state of a
    // backend whose reachability projection is empty.
    let unindexed = Unindexed(&fixture.git);
    let (walked, walked_bytes) = serve(&unindexed, fixture.kind, request());
    assert!(
        !walked.answered_from_bitmap,
        "GitServe::select declined, so the walk answered this fetch — and the summary claims the \
         reachability index did. A flag that reads `true` on the walk cannot be used to attribute \
         a single measurement. summary={walked:?}"
    );

    // ── and the flag is about the PATH, not about the ANSWER ────────────────
    //
    // Both paths must select the same objects for the same request. If they
    // did not, `answered_from_bitmap` would be standing in for "a different
    // answer came back", which is a different claim and a much weaker one.
    assert_eq!(
        indexed.objects_selected, walked.objects_selected,
        "the two paths selected different object counts for the same want, so the flag is not \
         telling us about the path alone: index={indexed:?} walk={walked:?}"
    );
    assert!(
        indexed.objects_sent > 0 && walked.objects_sent > 0,
        "at least one arm sent no packfile at all, which makes its `false` vacuous: \
         index={indexed:?} walk={walked:?}"
    );
    assert!(
        !indexed_bytes.is_empty() && !walked_bytes.is_empty(),
        "an arm wrote nothing to the client"
    );
}

/// **The same indexed store reports the walk when the REQUEST is one the index
/// declines.**
///
/// `reachable::select` returns `Ok(None)` for any request carrying a filter,
/// before it looks at the store at all. So this arm holds the store constant
/// and varies only the request — which is what proves the flag tracks the
/// decision each fetch took rather than a property of the backend.
#[test]
fn the_filtered_request_on_an_indexed_store_reports_the_walk() {
    let fixture = Fixture::build(Kind::Sha1);

    let (plain, _) = serve(
        &fixture.git,
        fixture.kind,
        fetch_request(fixture.four, None),
    );
    assert!(
        plain.answered_from_bitmap,
        "the unfiltered control did not take the index path, so the contrast below would prove \
         nothing: {plain:?}"
    );

    let (filtered, _) = serve(
        &fixture.git,
        fixture.kind,
        fetch_request(fixture.four, Some("blob:none")),
    );
    assert!(
        !filtered.answered_from_bitmap,
        "a filtered fetch is declined by `reachable::select` before the store is asked, so the \
         walk answered it — and the summary says the index did. The flag is reporting the \
         backend, not this request's decision: {filtered:?}"
    );
}