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"))
}
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:?}");
}
#[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"
);
}
#[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}"
);
}
#[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"
);
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"
);
}
#[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");
}
#[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 [
"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:?}"
);
}
}
#[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);
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:?}");
let tips = of(WantPolicy::AdvertisedTips);
assert!(!has(&tips, "allow-reachable-sha1-in-want"), "{tips:?}");
assert!(!has(&tips, "allow-tip-sha1-in-want"), "{tips:?}");
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
);
assert_eq!(
gunnar_wire::ProtocolVersion::from_git_protocol(Some("version=1")),
V0
);
assert_eq!(
gunnar_wire::ProtocolVersion::from_git_protocol(Some("nonsense")),
V0
);
}
use std::path::{Path, PathBuf};
use gunnar_wire::caps::{CapValue, Capability, Honoured, ADVERTISED};
#[allow(unused_imports)]
use gunnar_pack::index_thin_pack as _witness_ofs_delta_is_resolved_by_gunnar_pack;
const DEPENDENCY_WITNESSES: &[(&str, &str)] = &[("gunnar-pack", "index_thin_pack")];
fn workspace_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(2)
.expect("gunnar-wire lives two levels under the workspace root")
.to_path_buf()
}
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
}
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();
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 } => {
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);
}
}
}
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."
);
}
#[test]
fn the_consumer_check_can_fail_and_a_comment_does_not_satisfy_it() {
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"
);
let trailing = "let sideband = false; // peer.has(\"side-band-64k\")\n";
assert!(!code_only(trailing).contains(r#"peer.has("side-band-64k")"#));
let real = "let atomic = peer.has(\"atomic\"); // the batch flag\n";
assert!(code_only(real).contains(r#"peer.has("atomic")"#));
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"
);
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"
);
assert!(code_only(&text).contains(r#"peer.has("push-options")"#));
}
#[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
}
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)
);
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"
);
}
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"));
}
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
}
#[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));
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."
);
}
}
}
#[test]
fn the_capability_read_scanner_can_fail_and_ignores_comments() {
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:?}"
);
}
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"
);
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"
);
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"
);
}
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
}
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 {
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) => {
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(())
}
#[test]
fn every_serving_policy_is_declared_somewhere() {
let root = workspace_root();
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"
);
}
#[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");
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:?}"
);
}
assert!(
!fields.contains(&"wants".to_string()) && fields.len() < 10,
"the field reader ran past the end of the struct: {fields:?}"
);
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"
);
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"
);
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"
);
}
#[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);
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();
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);
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:?}"
);
}
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
);
}
assert!(
on_wire.iter().any(|c| c.starts_with("symref=HEAD:")),
"the `symref` exception above is excusing something that is not there: {on_wire:?}"
);
}
}