Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions xtask/src/gates/kind_isolation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,18 @@ const BATTERY_MARKER: &str = "testkit";
/// A per-crate battery file matches this, under the crate's own `tests/`.
const CONFORMANCE_MARKER: &str = "conformance";

/// THE PUBLISHED CONFORMANCE SUITE'S INVOCATION. A plugin runs busbar's published suite (OWNER
/// 2026-10-03: plugins test themselves against busbar's published suite) by invoking
/// `busbar_plugin_loader::conformance_suite!` in its `tests/conformance.rs`, and the macro expands
/// to the suite's `#[test]` entries (`crates/plugin-loader/src/conformance/mod.rs`). The file
/// itself spells no `#[test]`, so a counter that reads only attributes scored a running battery as
/// one with no entry.
const PUBLISHED_SUITE_MACRO: &str = "conformance_suite!";

/// The key an invocation of [`PUBLISHED_SUITE_MACRO`] names its subject with. An invocation that
/// names no `door:` expands to no entry against any subject, so it is not counted.
const PUBLISHED_SUITE_SUBJECT: &str = "door:";

// ------------------------------------------------------------------------------------------------
// the vocabulary bans
// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -4020,9 +4032,68 @@ fn live_battery_entries(text: &str) -> (usize, usize) {
live += 1;
}
}
live += published_suite_invocations(&lines);
(live, ignored)
}

/// How many invocations of the published suite ([`PUBLISHED_SUITE_MACRO`]) a battery file makes
/// that name a subject — each one is the suite's entries run against that subject.
///
/// Read off the BLANKED lines, so the macro's name in prose or in a string is not an invocation.
/// The invocation runs from the macro's name to the delimiter that closes the one it opened, and it
/// counts only if that span names [`PUBLISHED_SUITE_SUBJECT`]: `conformance_suite! {}` expands to
/// nothing and stays a file with no entry. A file that DEFINES its own `macro_rules!
/// conformance_suite` is not invoking the published suite, whatever its invocation looks like, so
/// none of its invocations count.
fn published_suite_invocations(lines: &[String]) -> usize {
let shadowed = lines.iter().any(|l| {
l.contains("macro_rules!") && l.contains(PUBLISHED_SUITE_MACRO.trim_end_matches('!'))
});
if shadowed {
return 0;
}
let mut count = 0usize;
for (i, l) in lines.iter().enumerate() {
let Some(at) = l.find(PUBLISHED_SUITE_MACRO) else {
continue;
};
// The macro's name must be a path's last segment, not the tail of a longer identifier.
let before = l[..at].chars().next_back();
if before.is_some_and(|c| c.is_ascii_alphanumeric() || c == '_') {
continue;
}
let mut span = String::new();
let mut depth = 0i32;
let mut opened = false;
'walk: for (j, line) in lines[i..].iter().enumerate() {
let text = if j == 0 {
&line[at + PUBLISHED_SUITE_MACRO.len()..]
} else {
line.as_str()
};
for ch in text.chars() {
match ch {
'{' | '(' | '[' => {
depth += 1;
opened = true;
}
'}' | ')' | ']' => depth -= 1,
_ => {}
}
span.push(ch);
if opened && depth <= 0 {
break 'walk;
}
}
span.push('\n');
}
if span.contains(PUBLISHED_SUITE_SUBJECT) {
count += 1;
}
}
count
}

/// The `<…>` immediately after `impl`, skipped as a BALANCED group: `impl<S: CellStore>` and
/// `impl<'a, T: Into<Vec<u8>>>` both end at the `>` that closes the one this opened, not at the
/// first `>` in the line.
Expand Down Expand Up @@ -9686,6 +9757,81 @@ impl Gate for KindIsolationGate {
&["battery-ignored", "busbar-store-ignored"],
));

// THE PUBLISHED SUITE IS A BATTERY. A plugin's `tests/conformance.rs` that invokes
// `busbar_plugin_loader::conformance_suite!` over its door runs the suite's entries — the
// macro expands to them — and spells no `#[test]` of its own. It is a live battery, and the
// row must not call it ignored.
let mut ov = manifest_plant(
"crates/busbar-store-suite",
"busbar-store-suite",
&["busbar-contract"],
);
ov.set(
"crates/busbar-store-suite/src/lib.rs",
"pub struct P;\nimpl Store for P {}\n",
);
ov.set(
"crates/busbar-store-suite/tests/conformance.rs",
"busbar_plugin_loader::conformance_suite! {\n door: busbar_store_suite::door,\n \
cdylib: \"store_suite_door\",\n inputs: include_str!(\"conformance.json\"),\n}\n",
);
report.push(prove_rows_green(
cx,
subject,
"a battery that invokes the published suite over its door is a live battery",
&[ROW_TESTKIT],
ov,
));

// AN INVOCATION THAT EXPANDS TO NOTHING IS NOT A BATTERY. The same file with the subject
// taken out names the published macro and runs no entry against anything.
let mut ov = manifest_plant(
"crates/busbar-store-emptysuite",
"busbar-store-emptysuite",
&["busbar-contract"],
);
ov.set(
"crates/busbar-store-emptysuite/src/lib.rs",
"pub struct P;\nimpl Store for P {}\n",
);
ov.set(
"crates/busbar-store-emptysuite/tests/conformance.rs",
"busbar_plugin_loader::conformance_suite! {}\n",
);
report.push(prove_rows_red(
cx,
subject,
"a published-suite invocation that names no subject is a file with no entry",
&[ROW_TESTKIT],
ov,
&["battery-ignored", "busbar-store-emptysuite"],
));

// A LOCAL MACRO BY THE SAME NAME IS NOT THE PUBLISHED SUITE. A file that defines its own
// `conformance_suite` to expand to nothing, then invokes it with a subject, runs nothing.
let mut ov = manifest_plant(
"crates/busbar-store-shadowsuite",
"busbar-store-shadowsuite",
&["busbar-contract"],
);
ov.set(
"crates/busbar-store-shadowsuite/src/lib.rs",
"pub struct P;\nimpl Store for P {}\n",
);
ov.set(
"crates/busbar-store-shadowsuite/tests/conformance.rs",
"macro_rules! conformance_suite {\n ($($t:tt)*) => {};\n}\n\
conformance_suite! {\n door: busbar_store_shadowsuite::door,\n}\n",
);
report.push(prove_rows_red(
cx,
subject,
"a file-local conformance_suite macro is not the published suite",
&[ROW_TESTKIT],
ov,
&["battery-ignored", "busbar-store-shadowsuite"],
));

// A BATTERY WITH NO SUBJECT. The same crate, with a live battery and no implementor of its
// kind's trait anywhere in shipped source: the file compiles, the battery passes, and it is
// evidence about nothing this crate ships.
Expand Down
Loading