Files
buzz/scripts/flake-check.test.mjs
Matt Toohey b1f76ef4d2 ci: cache the Tauri apt .debs and fit a cold Windows Rust run in its cap (#8679)
## Summary

Fixes the two CI workflow defects that turned `main` red most often in
the 21–28 Oct 2026 audit:

- **Desktop Tauri:** the lane now caches its apt `.deb`s. It no longer
re-downloads 62 MB from a slow Ubuntu mirror on every run.
- **Windows Rust:** the lane drops a duplicate `cargo check` and gets a
60 min cap, so a cold run can save its cache.

It also updates #8613's `scripts/flake-check.test.mjs`, which breaks
once the Tauri package list moves into an env var. There are no product
code or test-behaviour changes.

This is one of seven PRs split out of the `flakey-tests` branch
(siblings below).

### Related issue

None found. #8613 touched both workflows after the audit, but not these
steps. No open PR changes how the Tauri packages are fetched, the
Windows timeout, or its Check (workspace) step:

- #8422, #8321 and #8373 only add packages to the list, and would now
add them to `TAURI_APT_PACKAGES`.
- #8414 adds two mesh-llm Tauri steps to the Windows job. If it lands,
they must fit the cold budget below.

### CI failures fixed

| Lane / test | Failing runs | Cause | Change |
|---|---|---|---|
| Desktop Tauri, "Install Tauri dependencies (Linux)"
(`_ci-desktop.yml`) | 62 jobs in 51 run attempts, 22–27 Oct. On main:
39821769576, 39822883395, 39827234118, 40333705511, 40342468627,
40348069929, 40353619362, 40368315739, 40373404267, 40374519539,
40556742929 | All 3 `ci-apt-retry.sh` attempts hit their 420 s limit
while `azure.archive.ubuntu.com` served the 62 MB at 20–65 KB/s. The
25.5 MB `libwebkit2gtk-4.1-0` alone takes a whole attempt, and each
attempt loses its partial download. | The package list moves to a
job-level `TAURI_APT_PACKAGES`. A new "Resolve Tauri apt archives" step
builds the cache key from `apt-get install --print-uris -o
Acquire::ForceHash=SHA256` (name, size and SHA256 per file).
`actions/cache/restore` uses that key. The install step copies only the
restored files whose SHA256 matches the signed index, because apt 2.8.3
reuses any same-size cached `.deb` without hashing it. A best-effort
rebuild keeps exactly the listed files. `actions/cache/save` runs only
on core-lane pushes after a successful rebuild; PR runs never save. |
| Windows Rust (`_ci-rust.yml`) | All on main: 39796569342 (job
119885795086), 39821769576 (119975358772), 39827234118 (119994286695),
39865872891 (120128351939), 40402556064 (121852634685) | Every test
passed. Cold steps take 41.3–43.5 min, so the 45 min cap cancelled the
`Swatinem/rust-cache` post-run save 1.6–3.7 min in. No cache was
written, and the next push was cold again. | Delete "Check (workspace)".
The clippy step before it covers the same `--workspace --all-targets`
set with `-D warnings`, which saves 2.0–2.8 min. Raise `timeout-minutes`
from 45 to 60, with the measured breakdown in a comment: 39–41 min of
steps, a ~4.5 min save and ~15 min of margin. |
| `scripts/flake-check.test.mjs` "repeat invocations mirror the lanes
they stand in for" | None in CI yet: it fails only with this change
applied | #8613 added this test after `flakey-tests` branched. It checks
that the advisory `flake-tauri` lane installs the same packages as the
Desktop Tauri core lane, by regex-matching the inline `apt-get install
-y --no-install-recommends \` list in `_ci-desktop.yml`. That list now
lives in `TAURI_APT_PACKAGES`, so the regex matched nothing and the test
failed with "Desktop Tauri apt packages". | Read `TAURI_APT_PACKAGES`
from `_ci-desktop.yml` and compare package names (12 on each side) with
`_ci-flake.yml`'s list. Renaming one package in `_ci-flake.yml` still
fails the test. Giving the `flake-tauri` lane the same read-only `.deb`
restore is a follow-up. |

Local evidence is from the original `flakey-tests` commit (9aa768a3b):

- The apt steps ran verbatim in Ubuntu 24.04 containers with apt 2.8.3,
with the cache restore and the save step's `if:` emulated.
- On a miss, the install fetches everything ("Need to get 254 MB"). On
an exact hit with the network down, it fetches nothing ("Need to get 0
B/254 MB").
- On a fallback with one `.deb` missing and one corrupted at the same
size, the hash check rejects the corrupt file, and apt re-fetches only
the corrupt and missing files.
- The key was identical in all four simulated jobs.
- The Windows numbers come from the jobs API for the five runs above.

On this branch, the split session ran the `scripts/` node tests:
`ci-selection`, `ci-required-gates`, `ci-apt-retry` and `flake-check` on
macOS gave 84 pass, 0 fail and 8 skipped (Linux-only). Before the
`flake-check.test.mjs` fix, that test failed 1 case. The same session
ran actionlint 1.7.12 with shellcheck, which was clean, and the
rust-cache contract scripts, which passed.

### Verification

This branch was pushed without further local re-verification, by the
user's choice: local test runs were overloading the machine and failing
for that reason. **Hosted CI is the check.** It was pushed with `git
push --no-verify` over SSH. The pre-push hook runs tests, and the HTTPS
token lacks the `workflow` scope.

Only hosted CI can show:

- The runner's real package list (about 62 MB) and the same key in all
three Tauri lanes.
- The `actions/cache` round trip. The first PR run misses, because
`main` has no key yet. After merge, the first push to `main` saves it.
- A cold Windows run saving its cache within the new cap. The next
toolchain bump or cache eviction will show it.

Remaining risk: after Ubuntu updates a large package, runs fetch it from
the mirror until a push to `main` saves a new key.

### Readiness

CI-only change. AGENTS.md's readiness steps (agent review, then human
confirmation) are still outstanding, so `buzz-review-completed` is not
set.

### Merge order

Independent of the other six. It merges cleanly onto `main`, and with
every sibling, in any order.

### Sibling PRs

Split from `flakey-tests` (one PR per area): #8676 (PostgreSQL lease +
lane), #8677 (relay E2E helper + Windows shell), #8678 (mobile), #8680
(desktop product races), #8681 (desktop E2E state gates), #8682 (desktop
E2E composer + row actions).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Matt Toohey <contact@matttoohey.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:00:00 +11:00

1431 lines
51 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import assert from "node:assert/strict";
import { execFileSync, spawnSync } from "node:child_process";
import {
copyFileSync,
mkdirSync,
mkdtempSync,
readFileSync,
realpathSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
import {
chooseRust,
classify,
cratePackage,
dartDefine,
hunkRanges,
ITERATIONS,
infraTest,
listPlaywright,
MAX_PLAYWRIGHT_JOURNEYS,
nodeTestArgs,
parseDartReport,
parseJunit,
playwrightRepetitions,
playwrightShards,
runners,
rustFeatureGraphs,
rustGroups,
rustImporters,
rustIncludedTests,
rustIncludes,
rustModulePath,
rustModules,
rustTarget,
rustTargetRoot,
rustTests,
rustWorkspaces,
selectRust,
selectTests,
testBodies,
testCalls,
} from "./flake-check.mjs";
const read = (path) => readFileSync(new URL(path, import.meta.url), "utf8");
const root = fileURLToPath(new URL("../", import.meta.url));
const git = (args, env = {}) =>
execFileSync("git", ["-c", "core.hooksPath=/dev/null", ...args], {
cwd: root,
encoding: "utf8",
env: { ...process.env, ...env },
});
// `select` over a synthetic head tree: HEAD's tree with a comment appended to
// each given file, so only those files differ and no test body changes. The
// outputs are keyed per runner as the workflow reads them. The selector
// writes its summary and outputs to $GITHUB_STEP_SUMMARY and $GITHUB_OUTPUT
// when they are set (as under Actions, where this suite also runs) and to
// stdout otherwise, so the child gets one contract or the other by `github`,
// never whichever the parent happens to have.
function selectAppending(files, { github = false } = {}) {
const dir = mkdtempSync(join(tmpdir(), "flake-select-"));
try {
const env = { GIT_INDEX_FILE: join(dir, "index") };
git(["read-tree", "HEAD"], env);
for (const file of files) {
const blob = execFileSync("git", ["hash-object", "-w", "--stdin"], {
cwd: root,
encoding: "utf8",
input: `${git(["show", `HEAD:${file}`])}// flake-check probe\n`,
}).trim();
git(["update-index", "--cacheinfo", `100644,${blob},${file}`], env);
}
const tree = git(["write-tree"], env).trim();
const { GITHUB_STEP_SUMMARY, GITHUB_OUTPUT, ...inherited } = process.env;
const routed = {
GITHUB_STEP_SUMMARY: join(dir, "summary.md"),
GITHUB_OUTPUT: join(dir, "output.txt"),
};
const result = spawnSync(
process.execPath,
[join(root, "scripts/flake-check.mjs"), "select", "HEAD", tree],
{
cwd: root,
encoding: "utf8",
env: github ? { ...inherited, ...routed } : inherited,
},
);
assert.equal(result.status, 0, result.stderr);
const summary = github
? readFileSync(routed.GITHUB_STEP_SUMMARY, "utf8")
: result.stdout;
const output = github
? readFileSync(routed.GITHUB_OUTPUT, "utf8")
: result.stdout;
const outputs = Object.fromEntries(
[...output.matchAll(/^(\w+)=(.*)$/gm)].map(([, key, value]) => [
key,
value.split(" ").filter(Boolean),
]),
);
return { summary, outputs, stdout: result.stdout };
} finally {
rmSync(dir, { recursive: true, force: true });
}
}
// A hunk writing new-side lines start..end; by default it removed nothing.
const hunk = (start, end, removed = { start: start + 1, end: start }) => ({
start,
end,
removed,
});
// A -U0 diff of (old start, old count, new start, new count) hunks.
const diff = (...hunks) =>
hunks.map(([o, oc, n, nc]) => `@@ -${o},${oc} +${n},${nc} @@`).join("\n");
test("classification follows each runner's test file layout", () => {
for (const [file, runner] of [
["crates/buzz-core/src/filter.rs", "rust"],
["crates/buzz-test-client/tests/e2e_relay.rs", "rust"],
["desktop/src-tauri/src/lib.rs", "tauri"],
["desktop/src-tauri/tests/rodio_mixer_diagnostic.rs", "tauri"],
["desktop/src-tauri/crates/buzz-terminal/src/lib.rs", "tauri"],
["desktop/src-tauri/crates/buzz-terminal/tests/latency.rs", "tauri"],
["desktop/src/features/channels/lib/channelDescription.test.mjs", "node"],
["desktop/src/shared/ui/thing.jsdom-test.mjs", "node"],
["desktop/scripts/demo-build-config.test.mjs", "node"],
["desktop/tests/e2e/channels.spec.ts", "playwright"],
["mobile/test/features/invites/invite_join_provider_test.dart", "dart"],
])
assert.equal(classify(file), runner, file);
for (const file of [
"crates/buzz-core/Cargo.toml",
"crates/buzz-feature-flags/tests/fixtures/relay-feature-selection/src/main.rs",
"desktop/src-tauri/build.rs",
"desktop/src-tauri/tests/fixtures/x.rs",
"desktop/src-tauri/crates/buzz-terminal/Cargo.toml",
"desktop/src/features/channels/lib/channelDescription.ts",
"desktop/tests/e2e/helpers/animations.ts",
"desktop/tests/e2e/typing-latency.perf.ts",
"desktop/tests/e2e/fixtures/x.spec.ts",
"mobile/lib/main.dart",
"mobile/test/helpers.dart",
"scripts/flake-check.test.mjs",
"web/src/x.test.mjs",
// Selections are shell-split downstream; refuse unusual names.
"desktop/tests/e2e/odd name.spec.ts",
"crates/buzz-core/src/$(id).rs",
])
assert.equal(classify(file), undefined, file);
// Each Rust runner names the cargo workspace its lane repeats.
assert.deepEqual(Object.keys(rustWorkspaces), ["rust", "tauri"]);
assert.ok(runners.includes("tauri"));
});
test("-U0 hunks map to new-side ranges, with deletions attached to the preceding line and their old-side lines kept", () => {
const text = [
"diff --git a/x.spec.ts b/x.spec.ts",
"--- a/x.spec.ts",
"+++ b/x.spec.ts",
"@@ -1 +1 @@",
'-import { test } from "@playwright/test";',
'+import { expect, test } from "@playwright/test";',
"@@ -12,0 +13,3 @@ test('a', async () => {",
"+ const x = 1;",
"+ const y = 2;",
"+ expect(x).toBe(y - 1);",
"@@ -30,2 +33,0 @@ test('b', async () => {",
"- removed();",
"- alsoRemoved();",
"@@ -1,3 +0,0 @@",
"-gone",
"",
].join("\n");
assert.deepEqual(hunkRanges(text), [
{ start: 1, end: 1, removed: { start: 1, end: 1 } },
{ start: 13, end: 15, removed: { start: 12, end: 11 } },
{ start: 33, end: 33, removed: { start: 30, end: 31 } },
{ start: 0, end: 0, removed: { start: 1, end: 3 } },
]);
assert.deepEqual(hunkRanges(""), []);
});
test("Playwright test calls span the declaration; groups, hooks and configuration are outside", () => {
const spec = [
'import { expect, test } from "@playwright/test";',
"test.use({ viewport: { width: 800, height: 600 } });",
"const seed = 1;",
'test.describe("suite", () => {',
" test.beforeEach(async ({ page }) => {",
' await page.goto("/");',
" });",
' test("journey", async ({ page }) => {',
' test.skip(seed === 2, "not here");',
' await expect(page.getByText("Go")).toBeVisible();',
" });",
' for (const mode of ["mouse", "keyboard"]) {',
' test.fixme(mode + " later", async () => {',
" await Promise.resolve();",
" });",
" }",
"});",
'test.describe.configure({ mode: "serial" });',
'test.fail("known broken", async () => {',
" await Promise.resolve();",
"});",
"",
].join("\n");
const calls = testCalls(spec, "x.spec.ts");
assert.deepEqual(calls, [
{ start: 8, end: 11 },
{ start: 13, end: 15 },
{ start: 19, end: 21 },
]);
// Playwright lists a looped declaration once per iteration, at one line.
assert.deepEqual(testBodies(calls, [13, 13, 8]), [
{ start: 8, end: 11, line: 8 },
{ start: 13, end: 15, line: 13 },
]);
// A listed line outside every call (a hook) has no body.
assert.deepEqual(testBodies(calls, [5]), []);
});
const rustSource = [
"//! Module docs mentioning #[test] in prose.",
"use std::fmt;",
"",
"pub fn code_under_test(input: &str) -> String {",
" let brace = '{';",
' let raw = r"\\";',
' format!("{brace}{raw}{input}")',
"}",
"",
"#[cfg(test)]",
"mod tests {",
" use super::*;",
"",
" fn helper() -> &'static str {",
' "}"',
" }",
"",
" /// Docs for the first test.",
" #[test]",
" fn plain() {",
' assert_eq!(code_under_test("x"), "{\\\\x");',
" }",
"",
' #[tokio::test(flavor = "multi_thread")]',
' #[ignore = "requires Postgres }"]',
" async fn needs_infra() {",
" /* a block comment with a } brace",
" and #[test] inside */",
" helper();",
" }",
"",
" #[ignore]",
" #[test]",
" pub(crate) fn also_ignored() {}",
"",
" mod postgres_tests {",
" #[sqlx::test]",
" async fn in_nested_module(pool: Pool) -> Result<(), E> {",
" Ok(())",
" }",
" }",
"}",
"",
].join("\n");
test("Rust test functions span their attribute block to the closing brace, through strings, chars and comments, named by their inline module path", () => {
assert.deepEqual(rustTests(rustSource), [
{ name: "tests::plain", start: 19, end: 22, ignored: false },
{ name: "tests::needs_infra", start: 24, end: 30, ignored: true },
{ name: "tests::also_ignored", start: 32, end: 34, ignored: true },
{
name: "tests::postgres_tests::in_nested_module",
start: 37,
end: 40,
ignored: false,
},
]);
assert.deepEqual(rustTests("fn main() {}\n"), []);
});
test("same-named Rust tests in different modules are distinct, and a hunk selects only its own", () => {
const source = [
"mod alpha {",
" #[test]",
" fn same() {}",
"}",
"pub(crate) mod beta {",
" mod tests {",
" #[test]",
" fn same() { let _ = 1; }",
" }",
"}",
"",
].join("\n");
assert.deepEqual(
rustTests(source).map((test) => test.name),
["alpha::same", "beta::tests::same"],
);
assert.deepEqual(
selectRust(diff([8, 1, 8, 1]), source, { previous: source }),
{
lines: [7],
names: ["beta::tests::same"],
},
);
// The file's path predicts the rest of the name; cargo's layout rules.
for (const [file, modules] of [
["crates/buzz-relay/src/lib.rs", []],
["crates/buzz-relay/src/main.rs", []],
["crates/buzz-relay/src/api/mod.rs", ["api"]],
["crates/buzz-relay/src/handlers/auth.rs", ["handlers", "auth"]],
["crates/buzz-test-client/src/bin/mention.rs", []],
["crates/buzz-test-client/tests/e2e_relay.rs", []],
["crates/x/tests/suite/main.rs", []],
["crates/x/tests/suite/helpers.rs", ["helpers"]],
["desktop/src-tauri/src/app_state.rs", ["app_state"]],
["desktop/src-tauri/tests/rodio_mixer_diagnostic.rs", []],
[
"desktop/src-tauri/crates/buzz-terminal/src/grid/cell.rs",
["grid", "cell"],
],
])
assert.deepEqual(rustModulePath(file), modules, file);
// Listed candidates: the predicted name wins; without it every suffix
// match is kept rather than nothing.
const candidates = [
{ binary: "buzz-relay", name: "api::relay_members::tests::same" },
{ binary: "buzz-relay", name: "handlers::auth::tests::same" },
{ binary: "buzz-relay", name: "handlers::auth::tests::other" },
{
binary: "buzz-relay::bin/buzz-relay",
name: "handlers::auth::tests::same",
},
];
assert.deepEqual(
chooseRust(
[{ path: "tests::same", exact: "handlers::auth::tests::same" }],
candidates,
),
{ chosen: [candidates[1], candidates[3]], unlisted: [] },
);
// An entry no candidate stands for is kept apart, not dropped.
const gated = { path: "tests::gated", exact: "handlers::auth::tests::gated" };
assert.deepEqual(
chooseRust(
[
{ path: "tests::same", exact: "elsewhere::tests::same" },
{ path: "tests::other", exact: "handlers::auth::tests::other" },
gated,
],
candidates,
),
{
chosen: [candidates[0], candidates[1], candidates[3], candidates[2]],
unlisted: [gated],
},
);
});
test("Rust files build only the targets they can be part of, merged per package one whole flag each", () => {
for (const [file, flags] of [
["crates/buzz-relay/src/api/mod.rs", [["--lib"], ["--bins"]]],
["crates/buzz-admin/src/main.rs", [["--bins"]]],
["crates/buzz-test-client/tests/e2e_relay.rs", [["--test", "e2e_relay"]]],
["crates/buzz-agent/tests/common/mod.rs", []],
["desktop/src-tauri/src/lib.rs", [["--lib"], ["--bins"]]],
[
"desktop/src-tauri/tests/rodio_mixer_diagnostic.rs",
[["--test", "rodio_mixer_diagnostic"]],
],
[
"desktop/src-tauri/crates/buzz-terminal/tests/latency.rs",
[["--test", "latency"]],
],
])
assert.deepEqual(rustTarget(file), flags, file);
// Two integration tests keep two `--test` flags: `--test codec connection`
// would make nextest filter on a test named "connection" and repeat nothing.
const args = (...entries) =>
[...rustGroups(entries).groups.values()].map((group) => group.args);
assert.deepEqual(
args(
"crates/buzz-audio-client/tests/codec.rs::roundtrip",
"crates/buzz-audio-client/tests/connection.rs::connects",
),
[["-p", "buzz-audio-client", "--test", "codec", "--test", "connection"]],
);
assert.deepEqual(
args(
"crates/buzz-audio-client/src/wire.rs::tests::frame",
"crates/buzz-audio-client/src/jitter.rs::tests::order",
"crates/buzz-audio-client/tests/codec.rs::roundtrip",
),
[["-p", "buzz-audio-client", "--lib", "--bins", "--test", "codec"]],
);
// A custom-path file builds every target of its package; packages stay apart.
assert.deepEqual(
args(
"crates/buzz-agent/tests/regressions.rs::replay",
"crates/buzz-agent/tests/common/mod.rs::helper",
"crates/buzz-admin/src/main.rs::tests::parses",
),
[
["-p", "buzz-agent"],
["-p", "buzz-admin", "--bins"],
],
);
// The Tauri workspace's packages are addressed by its manifest, and never
// mixed into a root-workspace invocation.
const tauri = rustGroups([
"desktop/src-tauri/tests/rodio_mixer_diagnostic.rs::single_queue_serializes_sources",
"desktop/src-tauri/crates/buzz-terminal/tests/latency.rs::g3_renderer_acquire_stays_within_frame_budget",
]);
assert.equal(tauri.runner, "tauri");
assert.equal(rustWorkspaces[tauri.runner], "desktop/src-tauri/Cargo.toml");
assert.deepEqual(
[...tauri.groups.values()].map((group) => group.args),
[
["-p", "buzz-desktop", "--test", "rodio_mixer_diagnostic"],
["-p", "buzz-terminal", "--test", "latency"],
],
);
assert.equal(
rustGroups(["crates/buzz-core/src/filter.rs::tests::a"]).runner,
"rust",
);
assert.throws(
() =>
rustGroups([
"crates/buzz-core/src/filter.rs::tests::a",
"desktop/src-tauri/src/lib.rs::tests::b",
]),
/span workspaces/,
);
assert.throws(
() => rustGroups(["desktop/src/x.rs::tests::a"]),
/rust entry must be/,
);
// Packages the regular lanes test under a feature list in those graphs, in
// order; the rest in their default graph alone. The desktop crate's
// mesh-llm graph builds only its lib, and only for a selection reaching it.
const graphs = (entries) =>
[...rustGroups(entries).groups.values()][0].graphs.map(({ args }) =>
args.join(" "),
);
assert.deepEqual(
[
"crates/buzz-feature-flags/src/launchdarkly.rs::tests::a",
"crates/buzz-push-gateway/src/lib.rs::tests::b",
"crates/buzz-core/src/filter.rs::tests::c",
"desktop/src-tauri/src/lib.rs::tests::d",
"desktop/src-tauri/tests/rodio_mixer_diagnostic.rs::e",
].map((entry) => graphs([entry])),
[
["-p buzz-feature-flags --lib --bins --features launchdarkly"],
[
"-p buzz-push-gateway --lib --bins",
"-p buzz-push-gateway --lib --bins --features personal-dev-app-attest",
],
["-p buzz-core --lib --bins"],
[
"-p buzz-desktop --lib --bins",
"-p buzz-desktop --lib --features mesh-llm",
],
["-p buzz-desktop --test rodio_mixer_diagnostic"],
],
);
// Postgres-backed tests are excluded by name and binary, as the postgres-ci
// default-filter selects them.
assert.ok(infraTest("buzz_db", "event_store::postgres_tests::insert"));
assert.ok(infraTest("postgres_relay", "admits"));
assert.ok(infraTest("buzz_media", "tests::external_infra_s3::upload"));
assert.ok(!infraTest("buzz_db", "tests::postgres_free"));
});
test("a helper under tests/ selects the integration binaries that include it", () => {
const helper = "crates/x/tests/common/mod.rs";
const includes = (target, ...lines) =>
rustIncludes(target, `${lines.join("\n")}\n`, helper);
// `mod common;` in a crate root, in any form; not in a comment or string.
assert.ok(
includes("crates/x/tests/a.rs", "mod common;", "#[test] fn t() {}"),
);
assert.ok(includes("crates/x/tests/a.rs", "pub(crate) mod common ;"));
assert.ok(!includes("crates/x/tests/a.rs", "// uses mod common; elsewhere"));
assert.ok(!includes("crates/x/tests/a.rs", 'const S: &str = "mod common;";'));
assert.ok(!includes("crates/x/tests/a.rs", "mod commonplace;", "mod other;"));
// `#[path]` reaching the file itself or its directory's mod.rs.
assert.ok(
includes("crates/x/tests/a.rs", '#[path = "common/mod.rs"]', "mod shared;"),
);
assert.ok(
includes(
"crates/x/tests/a.rs",
'#[path="../tests/common/mod.rs"] mod shared;',
),
);
assert.ok(
!includes("crates/x/tests/a.rs", '#[path = "other/mod.rs"]', "mod shared;"),
);
assert.ok(
rustIncludes(
"crates/x/tests/a.rs",
'#[path = "common/mod.rs"] mod shared;\n',
"crates/x/tests/common/util.rs",
),
);
// A tests/<dir>/main.rs target owns every file under its directory.
assert.ok(
rustIncludes(
"crates/x/tests/suite/main.rs",
"",
"crates/x/tests/suite/util.rs",
),
);
assert.ok(!rustIncludes("crates/x/tests/suite/main.rs", "", helper));
assert.ok(
rustIncludes(
"crates/x/tests/suite/main.rs",
'#[path = "../common/mod.rs"]\nmod common;\n',
helper,
),
);
// The real importers of buzz-agent's shared harness: the files declaring
// `mod common;`, not the suites that do not.
assert.deepEqual(rustImporters("crates/buzz-agent/tests/common/mod.rs"), {
importers: [
"crates/buzz-agent/tests/anthropic_continuation.rs",
"crates/buzz-agent/tests/fake_llm.rs",
"crates/buzz-agent/tests/permission_boundary.rs",
"crates/buzz-agent/tests/regressions.rs",
],
scanned: true,
});
for (const importer of rustImporters("crates/buzz-agent/tests/common/mod.rs")
.importers)
assert.match(read(`../${importer}`), /^mod common;$/m, importer);
assert.doesNotMatch(
read("../crates/buzz-agent/tests/golden_transcripts.rs"),
/^mod common;$/m,
);
// A binary's root is tests/<stem>.rs or tests/<dir>/main.rs; anything else
// under tests/ is a module of one.
for (const file of ["crates/x/tests/a.rs", "crates/x/tests/suite/main.rs"])
assert.ok(rustTargetRoot(file), file);
for (const file of [
"crates/x/tests/common/mod.rs",
"crates/x/tests/suite/util.rs",
"crates/x/src/lib.rs",
"crates/x/src/main.rs",
])
assert.ok(!rustTargetRoot(file), file);
// File modules resolve by cargo's conventions against the real tree: a
// root's `mod common;` is tests/common/mod.rs, a non-root's `mod launch;`
// is <stem>/launch.rs, a `#[path]` names its file, and a declaration in a
// comment or one no file backs is left out.
assert.deepEqual(
rustModules(
"crates/buzz-agent/tests/fake_llm.rs",
"mod common;\n// mod missing;\nmod nowhere;\n",
),
[{ name: "common", file: "crates/buzz-agent/tests/common/mod.rs" }],
);
assert.deepEqual(rustModules("crates/buzz-acp/src/acp.rs", "mod launch;\n"), [
{ name: "launch", file: "crates/buzz-acp/src/acp/launch.rs" },
]);
const wrapper = "crates/buzz-acp/tests/pool_lifecycle_state.rs";
assert.deepEqual(rustModules(wrapper, read(`../${wrapper}`)), [
{ name: "pool_lifecycle", file: "crates/buzz-acp/src/pool_lifecycle.rs" },
]);
// The wrapper's tests are the included module's, under its module name:
// the names nextest lists for the pool_lifecycle_state binary.
const included = rustTests(read("../crates/buzz-acp/src/pool_lifecycle.rs"));
assert.ok(included.length > 0);
assert.deepEqual(
rustIncludedTests(wrapper, read(`../${wrapper}`)).map((test) => test.name),
included.map((test) => `pool_lifecycle::${test.name}`),
);
assert.deepEqual(
rustIncludedTests("crates/buzz-agent/tests/fake_llm.rs", "mod common;\n"),
[],
);
});
test("select, through its entry point, repeats a changed Tauri test and the binaries including a changed helper", () => {
// Reviewer probes on #8613: before, both produced an empty selection and
// every repeat lane skipped.
const tauri = selectAppending([
"desktop/src-tauri/tests/rodio_mixer_diagnostic.rs",
]);
assert.match(
tauri.summary,
/\| desktop\/src-tauri\/tests\/rodio_mixer_diagnostic\.rs \| tauri \| whole file \(shared code changed\): 3 test\(s\) \|/,
);
assert.deepEqual(tauri.outputs.rust, []);
assert.deepEqual(
tauri.outputs.tauri,
rustTests(read("../desktop/src-tauri/tests/rodio_mixer_diagnostic.rs")).map(
(test) =>
`desktop/src-tauri/tests/rodio_mixer_diagnostic.rs::${test.name}`,
),
);
assert.equal(tauri.outputs.tauri.length, 3);
// Under Actions, where the Desktop JS lane runs this suite, the selector
// routes the summary and outputs to $GITHUB_STEP_SUMMARY and
// $GITHUB_OUTPUT: the same selection arrives there, and nothing on stdout.
const routed = selectAppending(
["desktop/src-tauri/tests/rodio_mixer_diagnostic.rs"],
{ github: true },
);
assert.equal(routed.stdout, "");
assert.match(
routed.summary,
/\| desktop\/src-tauri\/tests\/rodio_mixer_diagnostic\.rs \| tauri \| whole file \(shared code changed\): 3 test\(s\) \|/,
);
assert.deepEqual(routed.outputs, tauri.outputs);
const helper = selectAppending(["crates/buzz-agent/tests/common/mod.rs"]);
assert.match(
helper.summary,
/\| crates\/buzz-agent\/tests\/common\/mod\.rs \| rust \| helper for: anthropic_continuation, fake_llm, permission_boundary, regressions: \d+ test\(s\) \|/,
);
const binaries = new Set(
helper.outputs.rust.map((entry) => entry.split("::")[0]),
);
assert.deepEqual([...binaries].sort(), [
"crates/buzz-agent/tests/anthropic_continuation.rs",
"crates/buzz-agent/tests/fake_llm.rs",
"crates/buzz-agent/tests/permission_boundary.rs",
"crates/buzz-agent/tests/regressions.rs",
]);
assert.ok(helper.outputs.rust.length > 0);
// Changed together, the helper and an importer select each test once.
const both = selectAppending([
"crates/buzz-agent/tests/common/mod.rs",
"crates/buzz-agent/tests/fake_llm.rs",
]);
assert.deepEqual(both.outputs.rust, [...new Set(both.outputs.rust)]);
assert.deepEqual(both.outputs.rust.length, helper.outputs.rust.length);
// A tests/<stem>.rs root with no test of its own is a binary, not a
// helper: buzz-acp's pool_lifecycle_state compiles src/pool_lifecycle.rs
// in by `#[path]`, and a change to it repeats that binary's tests, not its
// siblings' (before, the selection was git_bootstrap, run_task and
// stdio_contract, and pool_lifecycle_state was not repeated at all).
const wrapper = "crates/buzz-acp/tests/pool_lifecycle_state.rs";
assert.deepEqual(rustTests(read(`../${wrapper}`)), []);
const included = rustTests(read("../crates/buzz-acp/src/pool_lifecycle.rs"));
const wrapped = selectAppending([wrapper]);
assert.match(
wrapped.summary,
new RegExp(
`\\| crates/buzz-acp/tests/pool_lifecycle_state\\.rs \\| rust \\| whole file \\(shared code changed\\): ${included.length} test\\(s\\) \\|`,
),
);
assert.deepEqual(
wrapped.outputs.rust,
included.map((test) => `${wrapper}::pool_lifecycle::${test.name}`),
);
const { groups } = rustGroups(wrapped.outputs.rust);
assert.deepEqual(groups.get("buzz-acp").args, [
"-p",
"buzz-acp",
"--test",
"pool_lifecycle_state",
]);
assert.deepEqual(
groups.get("buzz-acp").tests.map(({ exact }) => exact),
included.map((test) => `pool_lifecycle::${test.name}`),
);
// A src/** file without test functions still selects nothing: the regular
// lanes run what depends on it.
const source = selectAppending(["crates/buzz-core/src/lib.rs"]);
assert.match(
source.summary,
/\| crates\/buzz-core\/src\/lib\.rs \| rust \| no test functions \|/,
);
assert.deepEqual(source.outputs.rust, []);
});
test("Rust selection: a hunk inside a test selects it, elsewhere selects every runnable test; ignored tests never run", () => {
const select = (text, options) =>
selectRust(text, rustSource, { previous: rustSource, ...options });
assert.deepEqual(select(diff([21, 1, 21, 1])), {
lines: [19],
names: ["tests::plain"],
});
// Inside an ignored test: owned, so not shared code, but nothing to run.
assert.deepEqual(select(diff([28, 0, 29, 1])), { lines: [24], names: [] });
// The code under test, a helper, or a deleted helper (attached to line 13)
// can change every test.
const whole = (reason) => ({
whole: true,
reason,
names: ["tests::plain", "tests::postgres_tests::in_nested_module"],
});
assert.deepEqual(select(diff([4, 0, 5, 1])), whole("shared code changed"));
assert.deepEqual(
select(diff([21, 1, 21, 1], [14, 0, 15, 1])),
whole("shared code changed"),
);
assert.deepEqual(select(diff([14, 3, 13, 0])), whole("shared code removed"));
assert.deepEqual(
select(diff([21, 1, 21, 1]), { added: true, previous: "" }),
whole("new file"),
);
// Tests of the file modules an integration-test root declares ride along
// with a whole selection, not with a hunk inside one of the root's own
// tests; a root with no test of its own selects only them, and one with no
// tests at all is not a test file.
const included = [
{ name: "m::a", ignored: false },
{ name: "m::b", ignored: true },
];
assert.deepEqual(select(diff([4, 0, 5, 1]), { included }), {
...whole("shared code changed"),
names: [...whole().names, "m::a"],
});
assert.deepEqual(select(diff([21, 1, 21, 1]), { included }), {
lines: [19],
names: ["tests::plain"],
});
assert.deepEqual(selectRust(diff([1, 1, 1, 1]), "mod m;\n", { included }), {
whole: true,
reason: "shared code changed",
names: ["m::a"],
});
assert.deepEqual(
selectRust(diff([0, 0, 1, 1]), "mod m;\n", { added: true, included }),
{ whole: true, reason: "new file", names: ["m::a"] },
);
assert.equal(selectRust(diff([1, 1, 1, 1]), "fn main() {}\n"), undefined);
assert.equal(cratePackage("crates/buzz-core/src/filter.rs"), "buzz-core");
});
test("hunks inside tests select those tests; shared code, new or unlisted files select the whole file", () => {
const bodies = [
{ start: 10, end: 22, line: 10 },
{ start: 25, end: 37, line: 25 },
{ start: 38, end: 52, line: 40 },
];
// The old file had the same tests, with a hook between the last two.
const previous = [
{ start: 10, end: 22 },
{ start: 25, end: 37 },
{ start: 41, end: 55 },
];
const select = (ranges, options) =>
selectTests(ranges, bodies, { previous, ...options });
// Edit inside one test, including its first and last lines.
assert.deepEqual(select([hunk(12, 14)]), { lines: [10] });
assert.deepEqual(select([hunk(10, 10)]), { lines: [10] });
assert.deepEqual(select([hunk(22, 22)]), { lines: [10] });
// A hunk across two adjacent bodies selects both, by their listed lines.
assert.deepEqual(select([hunk(36, 39)]), { lines: [25, 40] });
// A hunk that also covers the gap between tests, or lines after the last
// test, touches shared code.
for (const range of [hunk(22, 25), hunk(52, 53), hunk(400, 405)])
assert.deepEqual(select([range]), {
whole: true,
reason: "shared code changed",
});
// Several hunks accumulate distinct tests in file order.
assert.deepEqual(select([hunk(41, 41), hunk(11, 11), hunk(12, 12)]), {
lines: [10, 40],
});
// Replacing lines inside a test, or deleting some of them (attached to the
// preceding line), selects that test when the old lines were its own.
assert.deepEqual(select([hunk(30, 31, { start: 30, end: 32 })]), {
lines: [25],
});
assert.deepEqual(select([hunk(30, 30, { start: 31, end: 32 })]), {
lines: [25],
});
// Deleting the hook that followed the second test attaches to that test's
// closing line, but the removed lines were never a test's.
assert.deepEqual(select([hunk(37, 37, { start: 38, end: 40 })]), {
whole: true,
reason: "shared code removed",
});
// Deletion at the top of the file (line 0) and edits before the first test
// fall back to the whole file.
assert.deepEqual(select([hunk(0, 0, { start: 1, end: 1 })]), {
whole: true,
reason: "shared code removed",
});
assert.deepEqual(select([hunk(12, 12), hunk(3, 3)]), {
whole: true,
reason: "shared code changed",
});
assert.deepEqual(select([hunk(12, 12)], { added: true }), {
whole: true,
reason: "new file",
});
assert.deepEqual(selectTests([hunk(12, 12)], []), {
whole: true,
reason: "no tests listed",
});
// Without old-side calls, every removal is shared code.
assert.deepEqual(
selectTests([hunk(30, 30, { start: 31, end: 32 })], bodies),
{ whole: true, reason: "shared code removed" },
);
});
test("Playwright lists smoke journeys per spec once each; integration-only specs list none", () => {
const smoke = "desktop/tests/e2e/channel-sort.spec.ts";
const looped = "desktop/tests/e2e/claude-effort-picker.spec.ts";
const integration = "desktop/tests/e2e/agents.spec.ts";
// Alone, an integration spec makes Playwright exit 1 with "No tests found".
assert.deepEqual(listPlaywright([integration]), new Map([[integration, []]]));
const listed = listPlaywright([smoke, looped, integration]);
assert.deepEqual(listed.get(integration), []);
const lines = listed.get(smoke);
assert.ok(lines.length > 0, "a smoke spec must list its journeys");
assert.equal(
testBodies(testCalls(read(`../${smoke}`), smoke), lines).length,
lines.length,
"every listed journey must be owned by a test call",
);
// A looped declaration is listed once per iteration at the same line.
const loopedLines = listed.get(looped);
assert.deepEqual(loopedLines, [...new Set(loopedLines)]);
assert.ok(
/^\s*for \(const .+\) \{\n\s+test\(/m.test(read(`../${looped}`)),
"the looped spec must still declare a test inside a loop",
);
});
test("Playwright repetitions get one shard per five journeys, at most ten, and a selection past ~19 minutes per shard skips", () => {
assert.deepEqual(
[0, 1, 5, 6, 18, 40, 41, 50, 51, 200].map(playwrightShards),
[1, 1, 1, 2, 4, 8, 9, 10, 10, 10],
);
// 250 journey-runs per shard at ~4.5 s each, over ten shards.
assert.equal(MAX_PLAYWRIGHT_JOURNEYS, 250);
assert.equal(ITERATIONS, 10);
});
test("nextest's JUnit classname is the binary id its list reports", () => {
// Captured from cargo-nextest 0.9.136 on one buzz-core test: `cargo nextest
// list -p buzz-core --lib -E 'test(=kind::tests::no_duplicate_kind_values)'
// --message-format json` (trimmed to the matching testcase) and the
// target/nextest/flake/junit.xml of `cargo nextest run --profile flake` with
// the same arguments. repeatRust keys expectations as `<binary-id> <name>`
// from the list and reads statuses as `<classname> <name>` from the report,
// so the two must agree.
const list = {
"rust-suites": {
"buzz-core": {
"package-name": "buzz-core",
"binary-id": "buzz-core",
"binary-name": "buzz_core",
kind: "lib",
status: "listed",
testcases: {
"kind::tests::no_duplicate_kind_values": {
kind: "test",
ignored: false,
"filter-match": { status: "matches" },
},
},
},
},
};
const junit = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<testsuites name="nextest-run" tests="1" failures="0" errors="0" uuid="01abf963-07b0-46d9-8f00-e212969d85a8" timestamp="2026-10-27T00:32:44.093+11:00" time="0.042">',
' <testsuite name="buzz-core" tests="1" disabled="0" errors="0" failures="0">',
' <testcase name="kind::tests::no_duplicate_kind_values" classname="buzz-core" timestamp="2026-10-27T00:32:44.094+11:00" time="0.040">',
" </testcase>",
" </testsuite>",
"</testsuites>",
"",
].join("\n");
const expected = Object.entries(list["rust-suites"]).flatMap(
([binary, suite]) =>
Object.keys(suite.testcases).map((name) => `${binary} ${name}`),
);
assert.deepEqual(
parseJunit(junit),
new Map(expected.map((test) => [test, "passed"])),
);
});
test("reports give per-test statuses per iteration", () => {
assert.deepEqual(
parseJunit(
[
'<?xml version="1.0" encoding="UTF-8"?>',
'<testsuites name="nextest-run">',
'<testsuite name="buzz-core" tests="3">',
'<testcase name="filter::tests::a" classname="buzz-core" time="0.1"/>',
'<testcase name="filter::tests::b &lt;x&gt;" classname="buzz-core" time="0.1">',
'<failure type="test failure">assertion `left == right` failed</failure>',
"</testcase>",
'<testcase name="filter::tests::c" classname="buzz-core"><skipped/></testcase>',
"</testsuite>",
'<testsuite name="buzz-core::e2e" tests="1">',
'<testcase name="d" classname="buzz-core::e2e" time="0.1"><error/></testcase>',
"</testsuite>",
"</testsuites>",
].join("\n"),
),
new Map([
["buzz-core filter::tests::a", "passed"],
["buzz-core filter::tests::b <x>", "failed"],
["buzz-core filter::tests::c", "skipped"],
["buzz-core::e2e d", "failed"],
]),
);
const event = (value) => JSON.stringify(value);
assert.deepEqual(
parseDartReport(
[
event({ type: "start", protocolVersion: "0.1.1" }),
event({ type: "suite", suite: { id: 7, path: "/m/test/a_test.dart" } }),
event({
type: "testStart",
test: { id: 1, name: "loading /m/test/a_test.dart", url: null },
}),
event({
type: "testDone",
testID: 1,
result: "success",
hidden: true,
skipped: false,
}),
event({
type: "testStart",
test: {
id: 2,
name: "group renders",
suiteID: 7,
url: "package:flutter_test/src/widget_tester.dart",
},
}),
event({
type: "testStart",
test: {
id: 3,
name: "group fails",
url: "file:///m/test/a_test.dart",
},
}),
event({
type: "testStart",
test: { id: 4, name: "later", url: "file:///m/test/b_test.dart" },
}),
"not json",
event({
type: "testDone",
testID: 2,
result: "success",
hidden: false,
skipped: false,
}),
event({
type: "testDone",
testID: 3,
result: "error",
hidden: false,
skipped: false,
}),
event({
type: "testDone",
testID: 4,
result: "success",
hidden: false,
skipped: true,
}),
event({ type: "done", success: false }),
].join("\n"),
"/m/",
),
new Map([
["test/a_test.dart › group renders", "passed"],
["test/a_test.dart › group fails", "failed"],
["test/b_test.dart › later", "skipped"],
]),
);
// Playwright lists a --repeat-each journey once per repetition, in order.
const spec = (title, line, status) => ({
title,
file: "channels.spec.ts",
line,
tests: [{ status }],
});
assert.deepEqual(
playwrightRepetitions({
suites: [
{
specs: [spec("a", 10, "expected"), spec("a", 10, "unexpected")],
suites: [
{ specs: [spec("b", 30, "skipped"), spec("a", 10, "expected")] },
],
},
],
}),
new Map([
["channels.spec.ts:10 › a", ["passed", "failed", "passed"]],
["channels.spec.ts:30 › b", ["skipped"]],
]),
);
});
test("repeat invocations mirror the lanes they stand in for", () => {
// node:test flags come from desktop/package.json "test"; the Flutter define
// from the mobile test shards; nextest's flake profile must keep retries off.
const script = JSON.parse(read("../desktop/package.json")).scripts.test;
for (const file of ["x.test.mjs", "x.jsdom-test.mjs"])
assert.ok(script.includes(`node ${nodeTestArgs(file).join(" ")} "`), file);
assert.ok(
read("../.github/workflows/_ci-clients.yml").includes(
`scripts/mobile-test-shard.sh \${{ matrix.shard }} 3 ${dartDefine}`,
),
);
// nextest reads its config from the workspace root, so each Rust workspace
// carries the flake profile.
for (const config of [
"../.config/nextest.toml",
"../desktop/src-tauri/.config/nextest.toml",
])
assert.match(
read(config),
/^\[profile\.flake\]\n(?:#.*\n)*retries = 0\nfail-fast = false\n\n\[profile\.flake\.junit\]\npath = "junit\.xml"\n/m,
config,
);
// The infrastructure exclusion mirrors the postgres-ci default-filter.
for (const predicate of [
"test(/postgres_tests::/)",
"binary(/^postgres_/)",
"test(/(^|::)external_infra[^:]*::/)",
])
assert.ok(read("../.config/nextest.toml").includes(predicate), predicate);
// Feature graphs mirror the Justfile recipes the regular lanes run: every
// package test-unit runs under a feature, in each graph it runs there, and
// the desktop crate's default and lib-only mesh-llm lanes.
const justfile = read("../Justfile");
const graphs = {};
for (const [, crate, features] of justfile.matchAll(
/^ +cargo nextest run -p ([\w-]+)(?: --features ([\w,-]+))?$/gm,
)) {
graphs[crate] ??= [];
graphs[crate].push({ features: features?.split(",") ?? [] });
}
assert.ok(
justfile.includes(
"\ndesktop-tauri-test: _ensure-sidecar-stubs\n cd desktop/src-tauri && cargo test --workspace\n",
),
);
assert.ok(
justfile.includes(
"\ndesktop-tauri-test-mesh: _ensure-sidecar-stubs\n cargo test --manifest-path {{desktop_tauri_manifest}} --features mesh-llm --lib\n",
),
);
graphs["buzz-desktop"] = [
{ features: [] },
{ features: ["mesh-llm"], lib: true },
];
assert.deepEqual(
rustFeatureGraphs,
Object.fromEntries(
Object.entries(graphs).filter(([, list]) =>
list.some(({ features }) => features.length),
),
),
);
const flake = read("../.github/workflows/_ci-flake.yml");
for (const runner of ["rust", "tauri", "node", "dart"])
assert.ok(
flake.includes(`flake-check.mjs ${runner} --iterations=10 $SELECTED`),
runner,
);
// The Tauri lane builds what the Desktop Tauri core lane does: the same
// workspace cache, system packages and sidecar stubs. The core lane lists
// its packages in TAURI_APT_PACKAGES, which its .deb cache key hashes.
const desktop = read("../.github/workflows/_ci-desktop.yml");
const desktopPackages = /^ {6}TAURI_APT_PACKAGES: >-\n((?: {8}\S+\n)+)/m
.exec(desktop)?.[1]
.split(/\s+/)
.filter(Boolean);
const flakePackages =
/apt-get install -y --no-install-recommends \\\n((?: {12}\S+(?: \\)?\n)+)/
.exec(flake)?.[1]
.split(/[\s\\]+/)
.filter(Boolean);
assert.ok(desktopPackages?.length, "Desktop Tauri apt packages");
assert.deepEqual(flakePackages, desktopPackages);
assert.match(
flake,
/flake-tauri:\n(?: {4}.*\n)*? {6}- uses: Swatinem\/rust-cache@\w+\n {8}with:\n {10}workspaces: desktop\/src-tauri\n {10}shared-key: desktop-core\n {10}save-if: false\n/,
);
assert.match(desktop, /- lane: core\n {12}cache: desktop-core\n/);
assert.ok(flake.includes("run: just _ensure-sidecar-stubs"));
assert.ok(read("../Justfile").includes("\n_ensure-sidecar-stubs:\n"));
assert.ok(flake.includes("--repeat-each=10 --retries=0"));
// The lanes are advisory: ci.yml calls the workflow on pull requests only,
// and no required gate depends on it.
const ci = read("../.github/workflows/ci.yml");
assert.match(
ci,
/^ {2}flake-check:\n(?: {4}.*\n)*? {4}if: github\.event_name == 'pull_request'\n(?: {4}.*\n)*? {4}uses: \.\/\.github\/workflows\/_ci-flake\.yml\n/m,
);
assert.doesNotMatch(ci, /needs: \[[^\]]*flake/);
});
// The repeat, through its entry point, in a scratch tree holding the script
// and the packages its entries name, with a fake `cargo` on PATH listing
// `tests` ({pkg, binary, binaryName, name, feature?, ignored?, failsWith?}; a
// feature test only under that feature) and passing every test a run selects
// but one failing in the graph enabling its `failsWith` feature.
function repeatWithFakeCargo(runner, entries, tests) {
const dir = realpathSync(mkdtempSync(join(tmpdir(), "flake-repeat-")));
try {
mkdirSync(join(dir, "scripts"));
copyFileSync(
join(root, "scripts/flake-check.mjs"),
join(dir, "scripts/flake-check.mjs"),
);
for (const [crateDir, name] of [
["crates/buzz-feature-flags", "buzz-feature-flags"],
["crates/buzz-push-gateway", "buzz-push-gateway"],
["desktop/src-tauri", "buzz-desktop"],
]) {
mkdirSync(join(dir, crateDir, "src"), { recursive: true });
writeFileSync(
join(dir, crateDir, "Cargo.toml"),
`[package]\nname = "${name}"\n`,
);
writeFileSync(join(dir, crateDir, "src/lib.rs"), "");
}
mkdirSync(join(dir, "bin"));
writeFileSync(
join(dir, "fake-cargo.mjs"),
`import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
const args = process.argv.slice(2);
appendFileSync(process.env.FAKE_CARGO_LOG, JSON.stringify(args) + "\\n");
const value = (flag) => args[args.indexOf(flag) + 1];
const features = args.includes("--features") ? value("--features").split(",") : [];
const tests = JSON.parse(process.env.FAKE_CARGO_TESTS).filter(
(test) => test.pkg === value("-p") && (!test.feature || features.includes(test.feature)),
);
if (args[1] === "list") {
const suites = {};
for (const test of tests) {
suites[test.binary] ??= { "binary-name": test.binaryName, testcases: {} };
suites[test.binary].testcases[test.name] = {
ignored: Boolean(test.ignored),
"filter-match": test.ignored ? { status: "mismatch", reason: "ignored" } : { status: "matches" },
};
}
process.stdout.write(JSON.stringify({ "rust-suites": suites }));
} else {
const junit = join(
args.includes("--manifest-path") ? dirname(value("--manifest-path")) : ".",
"target/nextest/flake/junit.xml",
);
mkdirSync(dirname(junit), { recursive: true });
const cases = [...value("-E").matchAll(/binary_id\\(=([^)]+)\\) & test\\(=([^)]+)\\)/g)];
const fails = ([, binary, name]) =>
tests.some((test) => test.binary === binary && test.name === name && features.includes(test.failsWith));
writeFileSync(junit, "<testsuites>" + cases.map((match) => '<testcase name="' + match[2] + '" classname="' + match[1] + '">' + (fails(match) ? "<failure/>" : "") + "</testcase>").join("") + "</testsuites>");
if (cases.some(fails)) process.exitCode = 100;
}
`,
);
writeFileSync(
join(dir, "bin/cargo"),
`#!/bin/sh\nexec "${process.execPath}" "${join(dir, "fake-cargo.mjs")}" "$@"\n`,
{ mode: 0o755 },
);
const { GITHUB_STEP_SUMMARY, GITHUB_OUTPUT, ...inherited } = process.env;
const log = join(dir, "cargo.log");
const summary = join(dir, "summary.md");
writeFileSync(summary, "");
const result = spawnSync(
process.execPath,
[
join(dir, "scripts/flake-check.mjs"),
runner,
"--iterations=2",
...entries,
],
{
cwd: dir,
encoding: "utf8",
env: {
...inherited,
PATH: `${join(dir, "bin")}:${process.env.PATH}`,
GITHUB_STEP_SUMMARY: summary,
FAKE_CARGO_LOG: log,
FAKE_CARGO_TESTS: JSON.stringify(tests),
},
},
);
assert.equal(result.signal, null, result.stderr);
return {
status: result.status,
summary: readFileSync(summary, "utf8"),
calls: readFileSync(log, "utf8")
.trim()
.split("\n")
.map((line) => JSON.parse(line)),
};
} finally {
rmSync(dir, { recursive: true, force: true });
}
}
test("feature-gated Rust tests repeat in every graph the regular lanes test them in, and unlisted ones fail the lane", () => {
// Reviewer probes on #8613: the repeat listed only the default graph, so a
// selected `#[cfg(feature = …)]` test was dropped and the lane passed as
// "nothing to repeat"; then it repeated each test in the first graph listing
// it alone, so a changed `#[cfg(feature = …)]` arm inside a test the default
// graph lists too was never compiled, and the lane passed.
const features = (call) =>
call.includes("--features") ? call[call.indexOf("--features") + 1] : "";
const targets = (call) =>
call.filter((arg) => arg === "--lib" || arg === "--bins").join(" ");
const flags = {
pkg: "buzz-feature-flags",
binary: "buzz-feature-flags",
binaryName: "buzz_feature_flags",
};
const root = repeatWithFakeCargo(
"rust",
[
"crates/buzz-feature-flags/src/lib.rs::tests::plain",
"crates/buzz-feature-flags/src/launchdarkly.rs::tests::null_events",
],
[
{ ...flags, name: "tests::plain" },
{
...flags,
name: "launchdarkly::tests::null_events",
feature: "launchdarkly",
},
],
);
assert.equal(root.status, 0, root.summary);
// buzz-feature-flags is only tested with LaunchDarkly, so it is listed and
// run in that graph alone.
assert.deepEqual(
root.calls.map((call) => [call[1], features(call)]),
[
["list", "launchdarkly"],
["run", "launchdarkly"],
["run", "launchdarkly"],
],
);
assert.match(
root.summary,
/## Flake check \(Rust\): 0 of 2 iterations failed/,
);
assert.match(
root.summary,
/\| buzz-feature-flags launchdarkly::tests::null_events \[launchdarkly\] \| ✅ \| ✅ \| 0\/2 \|/,
);
assert.match(
root.summary,
/\| buzz-feature-flags tests::plain \[launchdarkly\] \| ✅ \| ✅ \| 0\/2 \|/,
);
// buzz-push-gateway is tested without and with personal-dev-app-attest, and
// config.rs's attestation_environment_is_explicit_and_build_gated asserts
// differently in each: it repeats in both graphs, and a change breaking only
// the feature's arm fails the lane on that graph's row while the default
// graph's row passes.
const gateway = {
pkg: "buzz-push-gateway",
binary: "buzz-push-gateway",
binaryName: "buzz_push_gateway",
};
const gated = repeatWithFakeCargo(
"rust",
[
"crates/buzz-push-gateway/src/config.rs::tests::attestation_environment_is_explicit_and_build_gated",
],
[
{
...gateway,
name: "config::tests::attestation_environment_is_explicit_and_build_gated",
failsWith: "personal-dev-app-attest",
},
],
);
assert.equal(gated.status, 1, gated.summary);
assert.deepEqual(
gated.calls.map((call) => [call[1], features(call)]),
[
["list", ""],
["list", "personal-dev-app-attest"],
["run", ""],
["run", "personal-dev-app-attest"],
["run", ""],
["run", "personal-dev-app-attest"],
],
);
assert.match(
gated.summary,
/## Flake check \(Rust\): 2 of 2 iterations failed/,
);
assert.match(
gated.summary,
/\| buzz-push-gateway config::tests::attestation_environment_is_explicit_and_build_gated \| ✅ \| ✅ \| 0\/2 \|/,
);
assert.match(
gated.summary,
/\| buzz-push-gateway config::tests::attestation_environment_is_explicit_and_build_gated \[personal-dev-app-attest\] \| ❌ \| ❌ \| 2\/2 \|/,
);
// The desktop crate's lib is tested in its default graph and under
// mesh-llm, which builds the lib alone: a lib test repeats in both, a mesh
// test in the mesh graph, and one no graph lists fails the lane by name
// while the rest still repeat. An ignored test is excluded, not unlisted.
const desktop = {
pkg: "buzz-desktop",
binary: "buzz-desktop",
binaryName: "buzz_lib",
};
const tauriTests = [
{ ...desktop, name: "tests::plain" },
{ ...desktop, name: "tests::skipped", ignored: true },
{
...desktop,
name: "managed_agents::relay_mesh::tests::mesh_only",
feature: "mesh-llm",
},
{
...desktop,
binary: "buzz-desktop::rodio_mixer_diagnostic",
binaryName: "rodio_mixer_diagnostic",
name: "mixes",
},
];
const tauri = repeatWithFakeCargo(
"tauri",
[
"desktop/src-tauri/src/lib.rs::tests::plain",
"desktop/src-tauri/src/lib.rs::tests::skipped",
"desktop/src-tauri/src/managed_agents/relay_mesh.rs::tests::mesh_only",
"desktop/src-tauri/src/lib.rs::tests::macos_only",
],
tauriTests,
);
assert.equal(tauri.status, 1, tauri.summary);
assert.deepEqual(
tauri.calls.map((call) => [call[1], features(call), targets(call)]),
[
["list", "", "--lib --bins"],
["list", "mesh-llm", "--lib"],
["run", "", "--lib --bins"],
["run", "mesh-llm", "--lib"],
["run", "", "--lib --bins"],
["run", "mesh-llm", "--lib"],
],
);
assert.match(
tauri.summary,
/## Flake check \(Desktop Tauri\): 1 selected test\(s\) not listed\n[^#]*- `desktop\/src-tauri\/src\/lib\.rs::tests::macos_only`\n/,
);
assert.doesNotMatch(tauri.summary, /skipped`/);
assert.match(
tauri.summary,
/## Flake check \(Desktop Tauri\): 0 of 2 iterations failed/,
);
for (const row of [
"managed_agents::relay_mesh::tests::mesh_only [mesh-llm]",
"tests::plain",
"tests::plain [mesh-llm]",
])
assert.ok(
tauri.summary.includes(`| buzz-desktop ${row} | ✅ | ✅ | 0/2 |`),
row,
);
assert.doesNotMatch(tauri.summary, /mesh_only \|/);
// An integration test selection never reaches the lib-only mesh graph.
const integration = repeatWithFakeCargo(
"tauri",
["desktop/src-tauri/tests/rodio_mixer_diagnostic.rs::mixes"],
tauriTests,
);
assert.equal(integration.status, 0, integration.summary);
assert.deepEqual(
integration.calls.map((call) => [call[1], features(call)]),
[
["list", ""],
["run", ""],
["run", ""],
],
);
assert.ok(
integration.summary.includes(
"| buzz-desktop::rodio_mixer_diagnostic mixes | ✅ | ✅ | 0/2 |",
),
);
// A selection of only ignored tests is excluded, and passes as such; one
// of only unlisted tests fails without running anything.
const ignored = repeatWithFakeCargo(
"tauri",
["desktop/src-tauri/src/lib.rs::tests::skipped"],
tauriTests,
);
assert.equal(ignored.status, 0, ignored.summary);
assert.match(
ignored.summary,
/## Flake check \(Desktop Tauri\): nothing to repeat/,
);
const unlisted = repeatWithFakeCargo(
"tauri",
["desktop/src-tauri/src/lib.rs::tests::macos_only"],
tauriTests,
);
assert.equal(unlisted.status, 1, unlisted.summary);
assert.deepEqual(
unlisted.calls.map((call) => call[1]),
["list", "list"],
);
assert.doesNotMatch(unlisted.summary, /nothing to repeat/);
});