Skip to content

Commit 00b20d6

Browse files
committed
test(miner-governor): close remaining branch-coverage gaps in chokepoint tests
Measured coverage showed chokepoint.js at 84.44% branch despite every stage's fail-closed catch block already being exercised -- every existing error test threw a genuine TypeError (a real Error instance) via a null-cast input, so error instanceof Error was always true and the String(error) fallback arm never ran. Add a throwingProxy helper that throws a plain string instead, exercising that arm for all five calculator stages. Also covers the rateLimitRandomFn conditional-spread branch and the self-plagiarism similarity ?? null fallback (via a whitespace-only fingerprint, which denies with no computed similarity). chokepoint.js now measures 100/100/100 (lines/branch/funcs), up from 84.44% branch. No production code changes -- test-only.
1 parent b0b2d69 commit 00b20d6

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

packages/gittensory-engine/test/chokepoint.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,84 @@ test("the repo-side live opt-in alone (no global env opt-in) is sufficient to re
200200
assert.equal(decision.mode, "live");
201201
assert.equal(decision.allowed, true);
202202
});
203+
204+
/** Throws a non-`Error` value (a plain string) the instant any property is read -- distinct from the existing
205+
* `null as unknown as X` fail-closed tests above, which all throw a genuine `TypeError` (a real `Error`
206+
* instance) and so only ever exercise the `error instanceof Error` arm of each catch block's message
207+
* formatting. This exercises the `String(error)` fallback arm for a thrown non-Error value. */
208+
function throwingProxy(message: string): never {
209+
return new Proxy(
210+
{},
211+
{
212+
get(): never {
213+
throw message;
214+
},
215+
},
216+
) as never;
217+
}
218+
219+
test("fail-closed: a rate-limit calculator throwing a non-Error value still formats a reason via String(error)", () => {
220+
const decision = evaluateGovernorChokepoint(baseInput({ rateLimitBuckets: throwingProxy("boom: not an Error") }));
221+
assert.equal(decision.allowed, false);
222+
assert.equal(decision.stage, "internal_error");
223+
assert.match(decision.reason, /rate_limit_calculator_error: boom: not an Error/);
224+
});
225+
226+
test("fail-closed: a budget-cap calculator throwing a non-Error value still formats a reason via String(error)", () => {
227+
const decision = evaluateGovernorChokepoint(baseInput({ capUsage: throwingProxy("boom: not an Error") }));
228+
assert.equal(decision.allowed, false);
229+
assert.equal(decision.stage, "internal_error");
230+
assert.match(decision.reason, /budget_cap_calculator_error: boom: not an Error/);
231+
});
232+
233+
test("fail-closed: a non-convergence calculator throwing a non-Error value still formats a reason via String(error)", () => {
234+
const decision = evaluateGovernorChokepoint(baseInput({ convergenceInput: throwingProxy("boom: not an Error") }));
235+
assert.equal(decision.allowed, false);
236+
assert.equal(decision.stage, "internal_error");
237+
assert.match(decision.reason, /non_convergence_calculator_error: boom: not an Error/);
238+
});
239+
240+
test("fail-closed: a reputation-throttle calculator throwing a non-Error value still formats a reason via String(error)", () => {
241+
const decision = evaluateGovernorChokepoint(baseInput({ reputationHistory: throwingProxy("boom: not an Error") }));
242+
assert.equal(decision.allowed, false);
243+
assert.equal(decision.stage, "internal_error");
244+
assert.match(decision.reason, /reputation_throttle_calculator_error: boom: not an Error/);
245+
});
246+
247+
test("fail-closed: a self-plagiarism calculator throwing a non-Error value still formats a reason via String(error)", () => {
248+
const decision = evaluateGovernorChokepoint(baseInput({ selfPlagiarismCandidate: throwingProxy("boom: not an Error") }));
249+
assert.equal(decision.allowed, false);
250+
assert.equal(decision.stage, "internal_error");
251+
assert.match(decision.reason, /self_plagiarism_calculator_error: boom: not an Error/);
252+
});
253+
254+
test("rate limit: a caller-supplied randomFn is threaded through to the calculator (not just the default)", () => {
255+
let called = false;
256+
const decision = evaluateGovernorChokepoint(
257+
baseInput({
258+
rateLimitRandomFn: () => {
259+
called = true;
260+
return 0.25;
261+
},
262+
}),
263+
);
264+
assert.equal(decision.allowed, true, "a custom randomFn on an otherwise-clear bucket must not itself deny");
265+
// The rate-limit calculator only actually invokes randomFn when a bucket is over-limit and jittering a
266+
// retry delay; on a clear bucket it is threaded through but never called -- asserting `false` here would be
267+
// wrong. What this test verifies is the conditional-spread branch (the field IS present) compiles and runs
268+
// end-to-end without the calculator rejecting an unexpected extra field.
269+
assert.equal(called, false, "documents that a clear bucket never needs to call randomFn");
270+
});
271+
272+
test("self-plagiarism: a whitespace-only candidate fingerprint denies via missing_candidate_fingerprint, with similarity omitted -> null", () => {
273+
const decision = evaluateGovernorChokepoint(
274+
baseInput({
275+
selfPlagiarismCandidate: { repoFullName: "acme/widgets", fingerprint: " ", submittedAt: "2026-07-11T12:00:00Z" },
276+
selfPlagiarismRecentSubmissions: [],
277+
}),
278+
);
279+
assert.equal(decision.allowed, false);
280+
assert.equal(decision.stage, "self_plagiarism");
281+
assert.equal(decision.detail.selfPlagiarism?.similarity, undefined, "no similarity was ever computed for this deny reason");
282+
assert.equal(decision.ledgerEvent.payload?.similarity, null, "the ?? null fallback must surface explicitly, not as an omitted key");
283+
});

0 commit comments

Comments
 (0)