mirror of
https://github.com/block/buzz.git
synced 2026-11-01 23:11:58 +00:00
test(scripts): require the ratchet child to run to completion
The child-process guard proved the gate *started* reporting, not that it
finished. Status 1 plus the report heading was accepted as a completed
policy decision, so a child that printed the heading -- or the whole
report -- and then crashed still read as the gate having decided.
The eval script now writes a fixed sentinel to stdout after the awaited
`runFileSizeCheck` returns, and the harness requires it on both the
exit-0 and exit-1 paths. The two questions are separated: the sentinel
proves normal completion, and only then does the exit status carry the
policy result.
Proven against the case the old guard missed. Injecting a throw after the
full violation report is emitted but before the gate returns:
old guard (heading only) 9 passing / 0 failing <- crash read as a pass
new guard (sentinel) 7 passing / 2 failing <- "did not run to
completion ... crashed
rather than gated"
A throw injected immediately after the heading also fails with the same
assertion rather than being misattributed to a missing violation line.
This is the same defect the PR closes, one level up: a check that cannot
distinguish the outcome it reports from a failure to reach it.
Signed-off-by: ss-dev-01 <11939edb7df583f855dbef923f2358f1184538f88ca452e19e7e35e42ad6d796@buzz.block.builderlab.xyz>
Co-authored-by: Bradley Axen <baxen@squareup.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>
This commit is contained in:
@@ -152,6 +152,8 @@ test("every script root governs .mjs alongside .ts and .tsx", () => {
|
||||
// Runs the real desktop rule table against a throwaway repository in a child
|
||||
// process. A child keeps `process.exitCode` and `console.error` out of this
|
||||
// test's own process, where a leaked exit code would mark the whole file failed.
|
||||
const COMPLETION_SENTINEL = "__file_size_gate_completed__";
|
||||
|
||||
function runDesktopGate({ fixtureRoot, baseRef }) {
|
||||
const result = spawnSync(
|
||||
process.execPath,
|
||||
@@ -166,6 +168,9 @@ function runDesktopGate({ fixtureRoot, baseRef }) {
|
||||
rules,
|
||||
label: "Desktop",
|
||||
});
|
||||
// Printed only if the awaited call returned normally. On stdout so it
|
||||
// cannot be confused with any part of the violation report.
|
||||
process.stdout.write(${JSON.stringify(COMPLETION_SENTINEL)});
|
||||
`,
|
||||
],
|
||||
{
|
||||
@@ -181,15 +186,20 @@ function runDesktopGate({ fixtureRoot, baseRef }) {
|
||||
},
|
||||
);
|
||||
// Node exits 1 for an uncaught exception too, so status alone cannot tell a
|
||||
// ratchet violation from a crash. The runner's only output is its violation
|
||||
// report, so a failing status must carry that report to count as a real
|
||||
// violation; anything else is the harness breaking, not the gate deciding.
|
||||
// ratchet violation from a crash. Split the two questions: the sentinel proves
|
||||
// the gate ran to completion, and only then does the exit status mean a policy
|
||||
// decision. Asserting on the report heading alone would accept a child that
|
||||
// started printing violations and then crashed part-way through.
|
||||
assert.ok(
|
||||
result.stdout.includes(COMPLETION_SENTINEL),
|
||||
`the ratchet child did not run to completion (exit ${result.status}, signal ${result.signal}), so it crashed rather than gated:\n${result.stderr}`,
|
||||
);
|
||||
const failed = result.status === 1;
|
||||
if (failed) {
|
||||
assert.match(
|
||||
result.stderr,
|
||||
/file size ratchet failed \(base /,
|
||||
`the ratchet child exited 1 without reporting a violation, so it crashed rather than gated:\n${result.stderr}`,
|
||||
`the ratchet child exited 1 without reporting a violation:\n${result.stderr}`,
|
||||
);
|
||||
} else {
|
||||
assert.equal(
|
||||
|
||||
Reference in New Issue
Block a user