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