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

//! The advertisement must list every argument the parser accepts.
//!
//! Object-format negotiation matters because getting it wrong is invisible: a v2 client
//! will not send `filter` unless `filter` appears in the advertised `fetch`
//! value, so a server that parses more than it advertises has support that
//! never activates, no error, no failing test, no symptom. Stock `git` 2.53
//! advertises exactly `fetch=shallow wait-for-done`, which is what makes the
//! under-advertising shape so easy to copy.
//!
//! `gunnar_wire::caps` fixes it by construction, with one table generating
//! both. This file asserts the resulting property from outside, plus asserts
//! that the assertion itself can fail.

mod common;

use gix_hash::Kind;
use gunnar_wire::caps::{self, Offered, FETCH_ARGUMENTS, LS_REFS_ARGUMENTS};
use gunnar_wire::upload_pack::{FetchRequest, LsRefsRequest, WantPolicy};
use gunnar_wire::UploadPack;

use common::{Fixture, Response};

fn advertisement(kind: Kind) -> Response {
    let fixture = Fixture::build(kind);
    let upload = UploadPack::new(&fixture.git, fixture.kind);
    Response::parse(&upload.capability_advertisement().expect("advertise"))
}

/// Features named by `table` that do not appear in `advertised`.
fn missing_features(advertised: &str, table: &'static [caps::Argument]) -> Vec<&'static str> {
    caps::features(table)
        .into_iter()
        .filter(|feature| !advertised.split(['=', ' ']).any(|word| word == *feature))
        .collect()
}

#[test]
fn every_gated_fetch_argument_appears_in_the_fetch_capability() {
    let advertised = caps::fetch_capability(Offered::default());
    let missing = missing_features(&advertised, FETCH_ARGUMENTS);
    assert!(
        missing.is_empty(),
        "the parser accepts arguments gated on {missing:?}, but the \
         advertisement is {advertised:?}: that support can never activate"
    );
}

#[test]
fn every_gated_ls_refs_argument_appears_in_the_ls_refs_capability() {
    let advertised = caps::ls_refs_capability();
    let missing = missing_features(&advertised, LS_REFS_ARGUMENTS);
    assert!(missing.is_empty(), "ls-refs under-advertises {missing:?}");
}

/// **The red half.** If the check above cannot fail, it proves nothing, so run
/// it against what stock git advertises, which really is not enough for the
/// arguments gunnar parses.
#[test]
fn the_under_advertising_check_can_fail() {
    let stock_git = "fetch=shallow wait-for-done";
    let missing = missing_features(stock_git, FETCH_ARGUMENTS);
    assert!(
        missing.contains(&"filter") && missing.contains(&"ref-in-want"),
        "the check did not notice that {stock_git:?} omits filter and \
         ref-in-want; it would not notice gunnar omitting them either"
    );
}

/// Advertising is one half; the other is that the parser really does take each
/// argument. A feature list generated from a table nothing reads would pass the
/// tests above and still be fiction.
#[test]
fn the_parser_accepts_every_argument_in_its_own_table() {
    for argument in FETCH_ARGUMENTS {
        let line = match argument.value {
            caps::Value::None => argument.name.to_owned(),
            caps::Value::Required => match argument.name {
                "want" | "have" | "shallow" => {
                    format!("{} {}", argument.name, "0".repeat(40))
                }
                "deepen" | "deepen-since" => format!("{} 1", argument.name),
                "deepen-not" => format!("{} refs/heads/main", argument.name),
                "filter" => format!("{} blob:none", argument.name),
                "want-ref" => format!("{} refs/heads/main", argument.name),
                other => panic!("no sample value for the argument {other:?}"),
            },
        };
        let parsed =
            FetchRequest::parse(&[line.clone().into_bytes()], Kind::Sha1, Offered::default());
        assert!(
            parsed.is_ok(),
            "the table names {:?} but the parser refused {line:?}: {:?}",
            argument.name,
            parsed.err()
        );
    }

    for argument in LS_REFS_ARGUMENTS {
        let line = match argument.value {
            caps::Value::None => argument.name.to_owned(),
            caps::Value::Required => format!("{} refs/heads/", argument.name),
        };
        assert!(
            LsRefsRequest::parse(&[line.clone().into_bytes()]).is_ok(),
            "the table names {:?} but the parser refused {line:?}",
            argument.name
        );
    }
}

#[test]
fn an_argument_outside_the_table_is_refused() {
    let err = FetchRequest::parse(
        &[b"deepen-forever".to_vec()],
        Kind::Sha1,
        Offered::default(),
    )
    .expect_err("an unknown argument must not be accepted quietly");
    assert!(
        matches!(err, gunnar_wire::Error::UnknownArgument { .. }),
        "unexpected error: {err}"
    );
}

/// Declining a feature has to remove it from *both* sides at once.
#[test]
fn declining_filter_removes_it_from_the_advertisement_and_the_parser() {
    let offered = Offered { filter: false };
    let advertised = caps::fetch_capability(offered);
    assert!(
        !advertised.contains("filter"),
        "filter was declined but is still advertised: {advertised}"
    );
    assert!(
        FetchRequest::parse(&[b"filter blob:none".to_vec()], Kind::Sha1, offered).is_err(),
        "filter was declined but the parser still accepts it"
    );
    // And it is genuinely a knob, not a constant that is always off.
    assert!(caps::fetch_capability(Offered::default()).contains("filter"));
}

#[test]
fn the_v2_advertisement_has_the_shape_git_expects() {
    let response = advertisement(Kind::Sha1);
    let lines = response.lines();
    assert_eq!(lines.first().map(String::as_str), Some("version 2"));
    assert!(
        lines.iter().any(|line| line.starts_with("agent=gunnar/")),
        "no gunnar agent line: {lines:?}"
    );
    assert!(
        lines.iter().any(|line| line == "server-option"),
        "{lines:?}"
    );
    assert!(
        lines.iter().any(|line| line == "object-format=sha1"),
        "{lines:?}"
    );
    assert!(
        lines.iter().any(|line| line.starts_with("ls-refs=")),
        "{lines:?}"
    );
    assert!(
        response
            .packets
            .last()
            .map(gunnar_pktline::Packet::is_flush)
            == Some(true),
        "the advertisement is not flush-terminated"
    );
}

/// The session-costing object-format bug, pinned on the type that decides it: the
/// advertisement is the repository's hash kind and nothing else.
#[test]
fn object_format_is_echoed_from_the_repositorys_actual_hash_kind() {
    assert!(advertisement(Kind::Sha256).has_line("object-format=sha256"));
    assert!(!advertisement(Kind::Sha256).has_line("object-format=sha1"));
    assert!(advertisement(Kind::Sha1).has_line("object-format=sha1"));
    assert!(!advertisement(Kind::Sha1).has_line("object-format=sha256"));
}

#[test]
fn a_client_naming_the_wrong_object_format_is_refused() {
    let err = caps::check_object_format(Kind::Sha256, Some("sha1"))
        .expect_err("a sha1 client on a sha256 repository must not be waved through");
    assert!(
        matches!(err, gunnar_wire::Error::ObjectFormatMismatch { .. }),
        "unexpected error: {err}"
    );
    caps::check_object_format(Kind::Sha256, Some("sha256")).expect("the matching pair is fine");
    caps::check_object_format(Kind::Sha256, None).expect("saying nothing is fine");
}

/// The v0 advertisement offers every ACK mode gunnar implements, and no other.
///
/// This guard used to say "no `multi_ack*` at all, gunnar is single-ACK", and
/// it was enforcing a design position that stock git disproved: offered no ACK
/// mode, git 2.53.0 falls back to single-ACK, which **cannot complete a
/// multi-round fetch over stateless-rpc** — `fetch-pack: protocol error: bad
/// band #78`, exit 128, against exit 0 from `git http-backend` on the same
/// repository (MEASURED 2026-08-05). See
/// [`caps::upload_pack_v0_capabilities`] for the mechanism.
///
/// So the rule is unchanged and only its application moved: **advertise what is
/// implemented, and nothing else.** `multi_ack_detailed` and `no-done` are
/// implemented, in `UploadPack::serve_v0_session`, and are asserted present.
/// Plain `multi_ack` is a third mode with its own semantics that nothing here
/// implements, and is asserted absent — by an exact match, because the prefix
/// test this once used would be satisfied by `multi_ack_detailed` and could
/// never fail again.
#[test]
fn the_v0_capabilities_promise_exactly_the_negotiation_gunnar_implements() {
    let caps = caps::upload_pack_v0_capabilities(
        Kind::Sha1,
        "gunnar/test",
        Offered::default(),
        WantPolicy::default(),
    );
    assert!(
        !caps.iter().any(|c| c == "multi_ack"),
        "plain `multi_ack` is not implemented; advertising it would be the same \
         class of lie as under-advertising fetch: {caps:?}"
    );
    for expected in [
        // Without these two, a stateless-rpc client negotiates in single-ACK
        // and a multi-round fetch over smart HTTP dies mid-pack.
        "multi_ack_detailed",
        "no-done",
        "side-band-64k",
        "ofs-delta",
        "shallow",
        "include-tag",
        "filter",
        "object-format=sha1",
    ] {
        assert!(
            caps.iter().any(|c| c == expected),
            "v0 capabilities are missing {expected}: {caps:?}"
        );
    }
}

/// The **other** direction of the same rule, and the one v0 got wrong: a
/// capability gunnar implements and does not advertise is refused by the client
/// before the server ever hears the request, so it fails silently on both ends.
///
/// Each policy is checked against the promise it makes, because a `match` that
/// returned the same slice for every arm would satisfy any single-arm test.
#[test]
fn the_v0_capabilities_promise_exactly_the_want_policy_in_force() {
    let of = |policy| {
        caps::upload_pack_v0_capabilities(Kind::Sha1, "gunnar/test", Offered::default(), policy)
    };
    let has = |caps: &[String], name: &str| caps.iter().any(|c| c == name);

    // The default, and git's `uploadpack.allowReachableSHA1InWant`. Without
    // this line a `blob:none` clone over v0 cannot fetch a blob back.
    let reachable = of(WantPolicy::ReachableFromRefs);
    assert!(
        has(&reachable, "allow-reachable-sha1-in-want"),
        "the default policy serves reachable non-tip wants and says nothing: {reachable:?}"
    );
    assert!(!has(&reachable, "allow-tip-sha1-in-want"), "{reachable:?}");

    // Strictest: promises neither, and must not, or a client sends a want that
    // `check_wants` will refuse.
    let tips = of(WantPolicy::AdvertisedTips);
    assert!(!has(&tips, "allow-reachable-sha1-in-want"), "{tips:?}");
    assert!(!has(&tips, "allow-tip-sha1-in-want"), "{tips:?}");

    // `ALLOW_ANY_SHA1` is both bits set in git, so it prints both.
    let any = of(WantPolicy::Any);
    assert!(has(&any, "allow-reachable-sha1-in-want"), "{any:?}");
    assert!(has(&any, "allow-tip-sha1-in-want"), "{any:?}");
}

#[test]
fn receive_pack_advertises_what_receive_pack_implements() {
    let caps = caps::receive_pack_capabilities(Kind::Sha256, "gunnar/test");
    for expected in [
        "report-status",
        "report-status-v2",
        "delete-refs",
        "side-band-64k",
        "quiet",
        "atomic",
        "ofs-delta",
        "push-options",
        "object-format=sha256",
    ] {
        assert!(
            caps.iter().any(|c| c == expected),
            "receive-pack does not advertise {expected}: {caps:?}"
        );
    }
}

#[test]
fn git_protocol_is_parsed_the_way_ssh_delivers_it() {
    use gunnar_wire::ProtocolVersion::*;
    assert_eq!(gunnar_wire::ProtocolVersion::from_git_protocol(None), V0);
    assert_eq!(
        gunnar_wire::ProtocolVersion::from_git_protocol(Some("version=2")),
        V2
    );
    assert_eq!(
        gunnar_wire::ProtocolVersion::from_git_protocol(Some("version=2:other=1")),
        V2
    );
    // v1 is v0 plus one extra line the client tolerates the absence of.
    assert_eq!(
        gunnar_wire::ProtocolVersion::from_git_protocol(Some("version=1")),
        V0
    );
    assert_eq!(
        gunnar_wire::ProtocolVersion::from_git_protocol(Some("nonsense")),
        V0
    );
}

// ════════════════════════════════════════════════════════════════════════════
// Every advertised capability has a consumer — all three surfaces
// ════════════════════════════════════════════════════════════════════════════
//
// # What was wrong
//
// The module header above says the advertisement is fixed by construction with
// one table generating both halves. That was true of the **v2 arguments** and
// of nothing else. `upload_pack_v0_capabilities` and
// `receive_pack_capabilities` were hand-written `vec![]`s, and the v2
// capability *names* were a fourth hand-written list in `upload_pack.rs`. So
// `"push-options".to_owned()` sat in a `vec![]` that nothing in the tree had to
// agree with — advertised, parsed, and thrown away for the whole of v1, with
// `.len()` in a log line as its only consumer.
//
// An early audit stated that *"advertised but not
// honoured is not something this codebase can express"*. It was expressible in
// three of the four places, and it was expressed.
//
// # What closes it
//
// `caps::ADVERTISED` is now the only thing that decides what goes on the wire,
// for all three surfaces, and every row carries where it is honoured. These
// tests read that claim and check it against the source.

use std::path::{Path, PathBuf};

use gunnar_wire::caps::{CapValue, Capability, Honoured, ADVERTISED};

/// **The compile-time half of a [`Honoured::ByDependency`] citation.**
///
/// A capability discharged by a crate gunnar merely DEPENDS on cannot be checked
/// by reading a file: from a clone, that crate is a registry package under
/// `~/.cargo/registry`, not a path in this tree. It used to be cited as
/// `../edda/crates/gunnar-pack/src/read.rs` and the guard read that path, which
/// meant the guard passed on a machine with an edda checkout beside gunnar and
/// failed everywhere else — for the absence of a sibling, not for anything about
/// gunnar. (Both stopped being true on 2026-09-09: the sibling is a crates.io
/// dependency now, so the path resolved NOWHERE.)
///
/// The `use` below is the check, and it is stronger than the substring search it
/// replaces: if `gunnar_pack::index_thin_pack` is renamed or removed, this file
/// does not COMPILE. The table then only has to agree with it, which
/// `every_advertised_capability_names_code_that_honours_it` asserts in the
/// citation direction — a citation with no witness here is refused.
#[allow(unused_imports)]
use gunnar_pack::index_thin_pack as _witness_ofs_delta_is_resolved_by_gunnar_pack;

/// Every `(crate, item)` pair that has a `use` above. One line per citation.
const DEPENDENCY_WITNESSES: &[(&str, &str)] = &[("gunnar-pack", "index_thin_pack")];

fn workspace_root() -> PathBuf {
    // `crates/gunnar-wire` → `crates` → root.
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .ancestors()
        .nth(2)
        .expect("gunnar-wire lives two levels under the workspace root")
        .to_path_buf()
}

/// `text` with every `//` comment removed, line comments and doc comments
/// alike, leaving string literals intact.
///
/// # Why this exists
///
/// `contains("push-options")` is satisfied by the paragraph *explaining*
/// push-options two lines above the call site. That exact shape — a
/// `contains(…)` a doc comment could satisfy — was found in this tree on
/// 2026-08-05 in a guard written to catch guards like it. So the source a
/// consumer claim is checked against is the code, and only the code.
///
/// Block comments are not stripped: nothing in this workspace uses them, and a
/// stripper that handled a construct nobody writes would be untested code
/// standing between a guard and its subject.
fn code_only(text: &str) -> String {
    let mut out = String::with_capacity(text.len());
    for line in text.lines() {
        let bytes = line.as_bytes();
        let mut in_string = false;
        let mut escaped = false;
        let mut end = bytes.len();
        let mut i = 0;
        while i < bytes.len() {
            let c = bytes[i];
            if escaped {
                escaped = false;
            } else if c == b'\\' && in_string {
                escaped = true;
            } else if c == b'"' {
                in_string = !in_string;
            } else if c == b'/' && !in_string && i + 1 < bytes.len() && bytes[i + 1] == b'/' {
                end = i;
                break;
            }
            i += 1;
        }
        out.push_str(&line[..end]);
        out.push('\n');
    }
    out
}

/// Every capability on every surface, with the surface's name.
fn every_capability() -> Vec<(&'static str, &'static Capability)> {
    ADVERTISED
        .iter()
        .flat_map(|(surface, table)| table.iter().map(move |cap| (*surface, cap)))
        .collect()
}

#[test]
fn every_advertised_capability_names_code_that_honours_it() {
    let root = workspace_root();
    let all = every_capability();

    // Not vacuous: three surfaces really are being walked, and each has rows.
    assert_eq!(
        ADVERTISED.len(),
        3,
        "a surface was added or lost: {ADVERTISED:?}"
    );
    assert!(
        all.len() >= 25,
        "only {} capabilities across all three surfaces, which is fewer than gunnar \
         advertises; this test is looking at the wrong thing",
        all.len()
    );

    let mut checked = 0usize;
    let mut vacuous: Vec<&str> = Vec::new();
    for (surface, cap) in &all {
        match cap.honoured {
            Honoured::ByDependency { krate, item } => {
                // The claim is that a named ITEM exists in a named CRATE, and the
                // COMPILER has already asserted it: `DEPENDENCY_WITNESSES` below
                // carries a `use` of every one, so this file does not build if the
                // item goes. What is left to check here is that the table and the
                // witness list agree — a citation with no witness is a claim
                // nothing verified, and it is the shape this arm was created to
                // stop (`../edda/crates/gunnar-pack/src/read.rs`, a path that
                // resolved only on a machine with a sibling checkout).
                assert!(
                    DEPENDENCY_WITNESSES.contains(&(krate, item)),
                    "{surface} advertises `{}` and says {krate}::{item} honours it, and \
                     nothing in DEPENDENCY_WITNESSES names that pair. Add a `use` for it \
                     there, so the compiler is what checks the citation.",
                    cap.name
                );
                checked += 1;
            }
            Honoured::By { file, code } => {
                let path = root.join(file);
                let text = std::fs::read_to_string(&path).unwrap_or_else(|err| {
                    panic!(
                        "{surface} advertises `{}` and says it is honoured in {file}, which \
                         cannot be read: {err}",
                        cap.name
                    )
                });
                assert!(
                    code_only(&text).contains(code),
                    "{surface} advertises `{}` and claims {file} honours it with `{code}`, \
                     but no LINE OF CODE there contains that (comments are stripped before \
                     looking, so a doc comment mentioning it does not count). Either the \
                     consumer was deleted — in which case the capability must come out of \
                     the table, because advertising it is a wrong answer on the wire — or \
                     the code moved and the table must follow it.",
                    cap.name
                );
                checked += 1;
            }
            Honoured::Vacuously(reason) => {
                assert!(
                    reason.len() > 80,
                    "{surface}'s `{}` is marked vacuously honoured with a {}-character \
                     reason. This variant is the escape hatch from the check above; it has \
                     to carry the argument, not a label.",
                    cap.name,
                    reason.len()
                );
                vacuous.push(cap.name);
            }
        }
    }

    // The escape hatch must not grow quietly. Three today: `agent` (twice over,
    // once per surface — it is one constant) and `quiet` and `server-option`.
    assert!(
        checked >= 20,
        "only {checked} capabilities were checked against real code; the rest took the \
         vacuous exit: {vacuous:?}"
    );
    vacuous.sort_unstable();
    vacuous.dedup();
    assert_eq!(
        vacuous,
        vec!["agent", "quiet", "server-option"],
        "the set of capabilities that honour themselves by doing nothing changed. Each one \
         is a capability gunnar promises on the wire and has no code for; adding to this \
         list is a decision, not a refactor."
    );
}

/// **The red half.** The check above must be able to fail, and must not be
/// satisfiable by a comment.
#[test]
fn the_consumer_check_can_fail_and_a_comment_does_not_satisfy_it() {
    // ── a doc comment is not a consumer ────────────────────────────────────
    let prose = "/// `push-options` is read here and handed to the gate.\n\
                 let x = 1;\n";
    assert!(
        prose.contains(r#"push-options"#),
        "the naive check would pass on this"
    );
    assert!(
        !code_only(prose).contains("push-options"),
        "a doc comment satisfied the consumer check, which is exactly the defect this \
         stripper exists for"
    );

    // ── a trailing comment does not, either ────────────────────────────────
    let trailing = "let sideband = false; // peer.has(\"side-band-64k\")\n";
    assert!(!code_only(trailing).contains(r#"peer.has("side-band-64k")"#));

    // ── but real code does, on the same line as a comment ──────────────────
    let real = "let atomic = peer.has(\"atomic\"); // the batch flag\n";
    assert!(code_only(real).contains(r#"peer.has("atomic")"#));

    // ── a `//` inside a string literal is not a comment ────────────────────
    let url = "let u = \"ssh://git@host\"; let a = peer.has(\"atomic\");\n";
    assert!(
        code_only(url).contains(r#"peer.has("atomic")"#),
        "the stripper cut the line at a `//` inside a string literal and lost real code"
    );

    // ── and the real check really would notice a missing consumer ──────────
    let root = workspace_root();
    let bogus = Capability {
        name: "not-a-real-capability",
        value: CapValue::Bare,
        offered: None,
        honoured: Honoured::By {
            file: "crates/gunnar-wire/src/receive_pack.rs",
            code: r#"peer.has("not-a-real-capability")"#,
        },
        requires: None,
    };
    let Honoured::By { file, code } = bogus.honoured else {
        unreachable!()
    };
    let text = std::fs::read_to_string(root.join(file)).expect("read receive_pack.rs");
    assert!(
        !code_only(&text).contains(code),
        "the check would pass on a capability nothing reads, so it checks nothing"
    );
    // …and it passes on one that IS read, in the same file, so the negative
    // above is not just a file that never matches anything.
    assert!(code_only(&text).contains(r#"peer.has("push-options")"#));
}

/// The bytes on the wire are the table, on every surface.
///
/// Generating from a table proves nothing if a literal is written beside it.
/// Both hand-written `vec![]`s and the fourth list in `upload_pack.rs` are gone,
/// and this is what says so: the advertisement gunnar actually emits carries
/// exactly the table's names, no more and no fewer.
#[test]
fn the_wire_advertisement_carries_exactly_the_table() {
    fn names(lines: &[String]) -> Vec<String> {
        let mut n: Vec<String> = lines
            .iter()
            .map(|l| l.split_once('=').map_or(l.as_str(), |(k, _)| k).to_owned())
            .collect();
        n.sort();
        n
    }
    fn table_names(table: &'static [Capability]) -> Vec<String> {
        let mut n: Vec<String> = table.iter().map(|c| c.name.to_owned()).collect();
        n.sort();
        n
    }

    // `WantPolicy::Any` renders every row, so "no more and no fewer" is
    // asserted against the WHOLE table rather than against a filtered view of
    // it — a filtered comparison would agree with itself if the filter were
    // the bug. That the policy column really withdraws rows is
    // `the_v0_capabilities_promise_exactly_the_want_policy_in_force`.
    let everything = WantPolicy::Any;
    for kind in [Kind::Sha1, Kind::Sha256] {
        assert_eq!(
            names(&caps::receive_pack_capabilities(kind, "gunnar/test")),
            table_names(caps::RECEIVE_PACK)
        );
        assert_eq!(
            names(&caps::upload_pack_v0_capabilities(
                kind,
                "gunnar/test",
                Offered::default(),
                everything,
            )),
            table_names(caps::UPLOAD_PACK_V0)
        );

        // v2 is read back off the WIRE, through the real `UploadPack`, because
        // that is the surface whose list lived in another file.
        let fixture = Fixture::build(kind);
        let upload = UploadPack::new(&fixture.git, fixture.kind);
        let bytes = upload.capability_advertisement().expect("advertise");
        let response = Response::parse(&bytes);
        let on_wire: Vec<String> = response
            .lines()
            .into_iter()
            .map(|l| l.trim().to_owned())
            .filter(|l| l != "version 2" && !l.is_empty())
            .collect();
        let on_wire = names(&on_wire);
        assert_eq!(
            on_wire,
            table_names(caps::UPLOAD_PACK_V2),
            "the v2 advertisement on the wire is not the table"
        );
    }

    // Withdrawing `filter` really removes it from the v0 wire list, so the
    // `Offered` column is not decoration.
    let without = caps::upload_pack_v0_capabilities(
        Kind::Sha1,
        "gunnar/test",
        Offered { filter: false },
        WantPolicy::default(),
    );
    assert!(!without.iter().any(|c| c == "filter"));
    assert!(caps::upload_pack_v0_capabilities(
        Kind::Sha1,
        "gunnar/test",
        Offered::default(),
        WantPolicy::default()
    )
    .iter()
    .any(|c| c == "filter"));
}

// ════════════════════════════════════════════════════════════════════════════
// The other direction: honoured, but named by nothing
// ════════════════════════════════════════════════════════════════════════════
//
// # The class, stated once
//
// `every_advertised_capability_names_code_that_honours_it` walks the table and
// asks whether each row has a consumer. That catches **a row nothing reads**.
// It cannot catch the inverse — *a behaviour the server enforces that no row
// declares* — because there is no row to walk. Nothing to look at, nothing to
// go stale, nothing to fail.
//
// That inverse has produced four wrong answers in this tree in one day:
//
// | | what was enforced | what said so |
// |---|---|---|
// | v0 incremental fetch | `thin-pack` was advertised and only the v2 parser read it | nothing |
// | v0 capability rows | three rows cited the v2 parser, so the guard watched code that could not be wrong | nothing |
// | v0 lazy fetch | `WantPolicy::ReachableFromRefs` on every request | nothing — fixed in `8f4e6e0` |
// | `--shallow-exclude=side` | the exclusion was silently discarded | nothing |
//
// The v0 lazy fetch is the sharpest of them: **not a row nothing reads, but a
// policy no row names.** A stock client refused on its own side, gunnar never
// heard the request, and no log line existed anywhere to notice.
//
// So the two guards below walk the *code* and ask the table about it, rather
// than the other way round.

/// Every `peer.has("…")` / `peer.value("…")` in `text`, in source order.
///
/// The server's capability **readers**. A name here that is not in the
/// corresponding table is a capability gunnar acts on and never offers, which
/// is the inverse drift: a client cannot know to send it, so the branch is
/// dead, and if a non-git client ever did send it the server would honour a
/// promise it never made.
fn capability_reads(text: &str) -> Vec<String> {
    let mut out = Vec::new();
    for opener in [r#"peer.has(""#, r#"peer.value(""#] {
        let mut rest = text;
        while let Some(at) = rest.find(opener) {
            rest = &rest[at + opener.len()..];
            if let Some(end) = rest.find('"') {
                out.push(rest[..end].to_owned());
            }
        }
    }
    out.sort();
    out.dedup();
    out
}

/// **Every capability the server READS is one the server ADVERTISES.**
///
/// Seen red: this test was written against the tree at `c74053c` and failed
/// naming `side-band` — `upload_pack.rs` read `peer.has("side-band-64k") ||
/// peer.has("side-band")` while `UPLOAD_PACK_V0` offered only the 64k form.
/// Nothing in the tree ever sent the plain one, so the branch was dead; had a
/// non-git client sent it, gunnar would have opened a sideband and framed it in
/// 65515-byte packets at a peer that asked for 1000-byte ones. A capability
/// gunnar cannot keep is not a capability gunnar may read.
#[test]
fn every_capability_the_server_reads_is_one_it_advertises() {
    let root = workspace_root();
    let surfaces: [(&str, &str, &[Capability]); 2] = [
        (
            "upload-pack v0",
            "crates/gunnar-wire/src/upload_pack.rs",
            caps::UPLOAD_PACK_V0,
        ),
        (
            "receive-pack",
            "crates/gunnar-wire/src/receive_pack.rs",
            caps::RECEIVE_PACK,
        ),
    ];

    for (surface, file, table) in surfaces {
        let text = std::fs::read_to_string(root.join(file)).expect("read the surface's source");
        let reads = capability_reads(&code_only(&text));
        // Not vacuous: a scanner that found nothing would pass this loop
        // silently, which is the shape of a guard that can never be red.
        assert!(
            reads.len() >= 4,
            "{surface}: only {} capability reads were found in {file} ({reads:?}). The scanner \
             is looking at the wrong thing, and an empty list satisfies every assertion below",
            reads.len()
        );
        for name in &reads {
            assert!(
                table.iter().any(|cap| cap.name == name),
                "{surface} READS the capability `{name}` in {file}, and does not ADVERTISE it. \
                 A client is never told it may send `{name}`, so the branch is dead code at \
                 best; at worst gunnar honours a promise it never made, to a peer that guessed. \
                 Either add the row — with a `Honoured` and, if it depends on a policy, a \
                 `requires` — or stop reading it."
            );
        }
    }
}

/// **The red half.** The scanner must find real names and reject a fabricated
/// one, or the loop above is a walk over an empty list.
#[test]
fn the_capability_read_scanner_can_fail_and_ignores_comments() {
    // It finds what is really there.
    let root = workspace_root();
    let upload = std::fs::read_to_string(root.join("crates/gunnar-wire/src/upload_pack.rs"))
        .expect("read upload_pack.rs");
    let reads = capability_reads(&code_only(&upload));
    for expected in ["ofs-delta", "thin-pack", "side-band-64k", "object-format"] {
        assert!(
            reads.contains(&expected.to_string()),
            "the scanner missed `{expected}`, which upload-pack demonstrably reads: {reads:?}"
        );
    }

    // A name only a comment mentions is not a read, so the guard cannot be
    // satisfied — or tripped — by prose.
    let prose = "// peer.has(\"invented-capability\")\nlet x = 1;\n";
    assert!(
        capability_reads(&code_only(prose)).is_empty(),
        "a commented-out read counted as a read"
    );

    // …and a real one on the same line as a comment IS found, so the stripper
    // is not simply eating everything.
    let real = "let q = peer.has(\"invented-capability\"); // why\n";
    assert_eq!(
        capability_reads(&code_only(real)),
        vec!["invented-capability".to_string()],
        "the scanner cannot see a read at all"
    );

    // And the assertion the loop makes really would reject it.
    assert!(
        !caps::UPLOAD_PACK_V0
            .iter()
            .any(|cap| cap.name == "invented-capability"),
        "the table would accept a capability nothing advertises, so the loop checks nothing"
    );
}

/// The `pub <name>:` fields of the struct that `declaration` opens, read out of
/// `text`.
///
/// Deliberately naive and deliberately anchored: it takes the lines from the
/// declaration to the first `}` at column zero. Nothing in this workspace nests
/// a braced item inside a struct body, and a parser that handled a construct
/// nobody writes would be untested code standing between a guard and its
/// subject — the same argument `code_only` makes about block comments.
fn struct_fields(text: &str, declaration: &str) -> Vec<String> {
    let body = text
        .split_once(declaration)
        .unwrap_or_else(|| panic!("no {declaration:?} in this file"))
        .1;
    let body = body.split_once("\n}").map_or(body, |(head, _)| head);
    let mut out: Vec<String> = Vec::new();
    for line in code_only(body).lines() {
        let line = line.trim();
        let Some(rest) = line.strip_prefix("pub ") else {
            continue;
        };
        let Some((name, _)) = rest.split_once(':') else {
            continue;
        };
        let name = name.trim();
        if !name.is_empty() && name.chars().all(|c| c.is_ascii_lowercase() || c == '_') {
            out.push(name.to_owned());
        }
    }
    out.sort();
    out.dedup();
    out
}

/// Judge one [`caps::Policy`]'s verdict, or say what is wrong with it.
///
/// A function rather than three arms inlined in the loop below, because the
/// loop cannot reach every arm: no field of any `Config` is
/// [`caps::Declared::Invisible`] today, so that arm would be a branch of a
/// guard that has never once executed — a blind third of the check, in a test
/// written to find blind checks. `the_policy_census_can_fail` calls this
/// directly with a fabricated `Policy` and exercises all three.
fn check_verdict(
    root: &Path,
    surface: &str,
    policy: &caps::Policy,
) -> std::result::Result<(), String> {
    let field = policy.field;
    match policy.declared {
        caps::Declared::As(name) => {
            if !ADVERTISED
                .iter()
                .any(|(_, table)| table.iter().any(|cap| cap.name == name))
            {
                return Err(format!(
                    "{surface}'s `{field}` claims a client learns it from the capability \
                     `{name}`, and no surface advertises that. The claim is the whole value of \
                     the entry."
                ));
            }
        }
        caps::Declared::Refuses { seen_by, reason } => {
            if seen_by.is_empty() {
                return Err(format!(
                    "{surface}'s `{field}` says it refuses and names no test that saw the refusal"
                ));
            }
            for citation in seen_by {
                // Rejoined because the constants are written across two source
                // lines and carry the continuation's indentation.
                let citation: String = citation.split_whitespace().collect::<Vec<_>>().join("");
                let Some((file, test)) = citation.split_once("::") else {
                    return Err(format!("{citation:?} is not <file>::<test fn>"));
                };
                let text = std::fs::read_to_string(root.join(file)).map_err(|err| {
                    format!("{surface}'s `{field}` cites {file}, which cannot be read: {err}")
                })?;
                if !code_only(&text).contains(&format!("fn {test}(")) {
                    return Err(format!(
                        "{surface}'s `{field}` says the peer sees the refusal and cites \
                         {file}::{test}, which is not a test there. A citation that does not \
                         resolve is the claim without the evidence."
                    ));
                }
            }
            if reason.len() <= 120 {
                return Err(format!(
                    "{surface}'s `{field}` explains its refusal in {} characters; this arm is a \
                     claim about what a peer sees and has to carry it",
                    reason.len()
                ));
            }
        }
        caps::Declared::RefusesUncovered(reason) => {
            // An ADMISSION, so what it must carry is different from what `Refuses`
            // carries: no citation (there is nothing to cite — that IS the arm), a
            // longer argument than the escape hatch, and the way out named. An
            // admission that does not say how it stops being one becomes furniture.
            if reason.len() <= 200 {
                return Err(format!(
                    "{surface}'s `{field}` admits the refusal is uncovered in {} characters. \
                     This arm has to say what the peer sees AND what would cover it.",
                    reason.len()
                ));
            }
            let joined: String = reason.split_whitespace().collect::<Vec<_>>().join(" ");
            if !joined.contains("THE WAY OUT") {
                return Err(format!(
                    "{surface}'s `{field}` admits it is uncovered and does not name THE WAY \
                     OUT. An admission with no route back is how a gap becomes permanent."
                ));
            }
        }
        caps::Declared::Invisible(reason) => {
            if reason.len() <= 80 {
                return Err(format!(
                    "{surface}'s `{field}` is marked invisible with a {}-character reason; that \
                     is the escape hatch and it has to cost the argument",
                    reason.len()
                ));
            }
        }
    }
    Ok(())
}

/// **Every serving-side policy is declared somewhere — on the wire, or in a
/// refusal a test has watched arrive.**
///
/// This is the guard for the class, rather than for one member of it. The
/// question it makes unanswerable-by-omission is *"gunnar enforces this; how
/// does a client find out?"*, and the three legal answers are the arms of
/// [`caps::Declared`].
///
/// It works by reading the `Config` structs **out of the source** rather than
/// from a list beside them, so a new knob fails this test the moment it is
/// added — which is the only version of this guard that stays true. A
/// hand-written second list of field names is the exact shape (`push-options`
/// in a `vec![]`) that put four wrong answers on the wire.
///
/// Seen red four ways ; 2026-08-05, each naming its own subject:
///
/// * `pub stray_knob: bool` added to `upload_pack::Config` → *"upload-pack
///   enforces `stray_knob` … and nothing in `SERVER_POLICIES` says how a client
///   finds out"*;
/// * an entry left in `SERVER_POLICIES` after its field went → *"`SERVER_POLICIES`
///   classifies `a_removed_knob` for what is on offer, which is not a field of
///   `pub struct Offered {`"*;
/// * `Declared::As("allow-reachable-sha1-in-wants")`, one letter wrong →
///   *"claims a client learns it from the capability
///   `allow-reachable-sha1-in-wants`, and no surface advertises that"*;
/// * a `Declared::Refuses` citation with a typo in the test name → *"cites
///   …`::a_traversal_budget_of_one_refuses_a_clone_rather_than_truncating_itx`,
///   which is not a test there"*.
#[test]
fn every_serving_policy_is_declared_somewhere() {
    let root = workspace_root();

    // Not vacuous: three surfaces, and each really has fields.
    assert_eq!(
        caps::SERVER_POLICIES.len(),
        3,
        "a policy surface was added or lost: {:?}",
        caps::SERVER_POLICIES
    );

    let mut classified = 0usize;
    for surface in caps::SERVER_POLICIES {
        let text = std::fs::read_to_string(root.join(surface.file))
            .unwrap_or_else(|err| panic!("{} cannot be read: {err}", surface.file));
        let in_source = struct_fields(&text, surface.declaration);
        assert!(
            !in_source.is_empty(),
            "{}: `{}` in {} parsed to no fields at all, so every assertion below is about an \
             empty set",
            surface.surface,
            surface.declaration,
            surface.file
        );

        let mut listed: Vec<String> = surface.fields.iter().map(|p| p.field.to_owned()).collect();
        listed.sort();

        for field in &in_source {
            assert!(
                listed.contains(field),
                "{} enforces `{field}` (a field of `{}` in {}) and nothing in \
                 `SERVER_POLICIES` says how a client finds out. That is the shape of the \
                 `WantPolicy` defect: a policy the server applies to every request and no \
                 capability names, so a stock client refuses on its OWN side and the server \
                 never hears the request. Classify it — `Declared::As` if a peer must know \
                 before it asks, `Declared::Refuses` with a test that watched the refusal \
                 arrive, or `Declared::Invisible` with the argument.",
                surface.surface,
                surface.declaration,
                surface.file
            );
        }
        for field in &listed {
            assert!(
                in_source.contains(field),
                "`SERVER_POLICIES` classifies `{field}` for {}, which is not a field of `{}` \
                 in {} ({in_source:?}). A verdict on a knob that no longer exists reads as \
                 coverage and is not.",
                surface.surface,
                surface.declaration,
                surface.file
            );
        }

        for policy in surface.fields {
            if let Err(complaint) = check_verdict(&root, surface.surface, policy) {
                panic!("{complaint}");
            }
            classified += 1;
        }
    }

    assert!(
        classified >= 8,
        "only {classified} policy fields were classified across all surfaces, which is fewer \
         than gunnar has; this test is looking at the wrong structs"
    );
}

/// **The red half.** The field reader has to see real fields and has to notice
/// one that is missing, or the test above is a loop over nothing.
#[test]
fn the_policy_census_can_fail() {
    let root = workspace_root();
    let upload = std::fs::read_to_string(root.join("crates/gunnar-wire/src/upload_pack.rs"))
        .expect("read upload_pack.rs");

    // It reads the real struct.
    let fields = struct_fields(&upload, "pub struct Config {");
    for expected in ["agent", "budget", "limits", "offered", "want_policy"] {
        assert!(
            fields.contains(&expected.to_string()),
            "the field reader missed `{expected}`, which upload-pack's Config demonstrably \
             has: {fields:?}"
        );
    }
    // …and stops at the struct, rather than running on into the file. `Config`
    // is followed by `impl Default` and then by `WantPolicy`, so a reader that
    // did not stop would sweep up half the module.
    assert!(
        !fields.contains(&"wants".to_string()) && fields.len() < 10,
        "the field reader ran past the end of the struct: {fields:?}"
    );

    // A field the census does not classify is genuinely caught.
    let invented = "pub struct Fake {\n    /// doc\n    pub stray_knob: bool,\n}\n";
    assert_eq!(
        struct_fields(invented, "pub struct Fake {"),
        vec!["stray_knob".to_string()],
        "the reader cannot see a new field, so it can never report one"
    );
    assert!(
        !caps::SERVER_POLICIES
            .iter()
            .flat_map(|s| s.fields)
            .any(|p| p.field == "stray_knob"),
        "the census would accept an unclassified field, so it checks nothing"
    );

    // A doc comment naming a field is not a field.
    let commented = "pub struct Fake {\n    // pub ghost_knob: bool,\n    pub real: bool,\n}\n";
    assert_eq!(
        struct_fields(commented, "pub struct Fake {"),
        vec!["real".to_string()],
        "a commented-out field counted as policy"
    );

    // ── all three verdict arms, including the one no real field uses ───────
    //
    // `Declared::Invisible` is not on any `Config` field today, so the census
    // loop never enters that arm. A branch of a guard that has never executed
    // is a guard that has never been tested, so it is exercised here instead of
    // being taken on trust.
    let judge = |declared| {
        check_verdict(
            &root,
            "a fixture",
            &caps::Policy {
                field: "f",
                declared,
            },
        )
    };

    assert!(
        judge(caps::Declared::Invisible("too short to be an argument")).is_err(),
        "a one-line `Invisible` reason was accepted; the escape hatch costs nothing"
    );
    assert!(
        judge(caps::Declared::Invisible(
            "this is a reason long enough to be an argument rather than a label, which is the \
             entire bar the variant sets, and it is set at eighty characters"
        ))
        .is_ok(),
        "a real argument was rejected, so the `Invisible` arm refuses everything and says \
         nothing about length"
    );
    assert!(
        judge(caps::Declared::As("not-a-capability-anyone-advertises")).is_err(),
        "the `As` arm accepted a capability no table carries"
    );
    assert!(
        judge(caps::Declared::As("filter")).is_ok(),
        "the `As` arm rejected a capability gunnar demonstrably advertises, so its failure above \
         was not about the name"
    );
    assert!(
        judge(caps::Declared::Refuses {
            seen_by: &[],
            reason: "x"
        })
        .is_err(),
        "the `Refuses` arm accepted a claim with no test behind it"
    );
}

/// **The v0 WIRE carries exactly the table, plus the one documented exception.**
///
/// `the_wire_advertisement_carries_exactly_the_table` reads the v2
/// advertisement off the wire and the v0 one out of
/// `caps::upload_pack_v0_capabilities`. That asymmetry is the hole: the v0
/// capability string is assembled in `write_ref_advertisement`, which takes the
/// table's list and then **appends to it** —
///
/// ```text
/// extra.push(format!("symref=HEAD:{symref}"));
/// ```
///
/// — so `symref` has always ridden on the v0 wire while being in no table, seen
/// by no `Honoured`, and counted by no guard. It is not a wrong answer: git's
/// client reads it, gunnar computes it from the repository's real `HEAD`, and
/// `the_v0_advertisement_names_heads_branch` covers the value. It is an
/// *unwatched* one, and the next literal appended beside it would be too.
///
/// So this reads the actual first ref line and holds the whole capability set
/// to the table with `symref` named as the single exception. A second
/// off-table literal fails here.
///
/// Seen red both ways ; 2026-08-05: with `extra.push("no-done")` added to
/// `write_ref_advertisement`, this reports *"the v0 wire carries `no-done`,
/// which no row of `UPLOAD_PACK_V0` names"*; with the `symref` exception
/// misspelt so it stops matching, it reports the same sentence about `symref` —
/// which is what says the exception is load bearing rather than decorative.
#[test]
fn the_v0_wire_carries_exactly_the_table_plus_symref() {
    use gunnar_wire::upload_pack::Config;

    for kind in [Kind::Sha1, Kind::Sha256] {
        let fixture = Fixture::build(kind);
        // `WantPolicy::Any` for the same reason the v2 arm uses it: every
        // policy-gated row renders, so "no more and no fewer" is asserted
        // against the whole table rather than against a filtered view that
        // would agree with itself if the filter were the bug.
        let upload = UploadPack::new(&fixture.git, fixture.kind).with_config(Config {
            want_policy: WantPolicy::Any,
            ..Config::default()
        });
        let mut bytes = Vec::new();
        upload
            .write_ref_advertisement(&mut bytes)
            .expect("the v0 advertisement");
        let text = String::from_utf8_lossy(&bytes).into_owned();

        // The capability string is everything after the first NUL, up to the
        // end of that pkt-line.
        let nul = text.find('\0').unwrap_or_else(|| {
            panic!(
                "the v0 advertisement has no NUL, so it carries no capabilities at all: {text:?}"
            )
        });
        let rest = &text[nul + 1..];
        let line = &rest[..rest.find('\n').unwrap_or(rest.len())];
        let on_wire: Vec<&str> = line.split(' ').filter(|c| !c.is_empty()).collect();
        assert!(
            on_wire.len() >= 10,
            "only {} capabilities on the v0 wire ({on_wire:?}); this test is reading the wrong \
             bytes and every assertion below is about a short list",
            on_wire.len()
        );

        for entry in &on_wire {
            let name = entry.split_once('=').map_or(*entry, |(k, _)| k);
            // `symref` is the one capability whose value is a fact about the
            // repository rather than about the server, so it cannot be a
            // static row. It is named here, once, deliberately.
            if name == "symref" {
                continue;
            }
            assert!(
                caps::UPLOAD_PACK_V0.iter().any(|cap| cap.name == name),
                "the v0 wire carries `{name}`, which no row of `UPLOAD_PACK_V0` names. A \
                 capability appended beside the table is a promise with no `Honoured`, no \
                 `requires` and no guard — which is how `push-options` was advertised, parsed \
                 and discarded for a whole release. Wire: {on_wire:?}"
            );
        }
        // …and nothing the table promises went missing on the way out.
        for cap in caps::UPLOAD_PACK_V0 {
            assert!(
                on_wire
                    .iter()
                    .any(|entry| entry.split_once('=').map_or(*entry, |(k, _)| k) == cap.name),
                "`{}` is in `UPLOAD_PACK_V0` and is not on the v0 wire: {on_wire:?}",
                cap.name
            );
        }
        // The exception is real and not a spelling nobody emits.
        assert!(
            on_wire.iter().any(|c| c.starts_with("symref=HEAD:")),
            "the `symref` exception above is excusing something that is not there: {on_wire:?}"
        );
    }
}