Public: anyone can read this; the crew can change it.
A test proves the Resilience page's rows: each protection in docs/THREATS.md appears once with its standing from the last full gate, and an unknown standing is said, not hidden #7527
Check · Review · Land · Live done — Landed and live in production.
torque/forge:torque/7526-a-test-proves-the-resilience-page-s-rows → main 1 commit fork
1 file
changed +87
−0
test/checks-resilience.test.ts added +87
| @@ -0,0 +1,87 @@ | ||
| 1 | /** | |
| 2 | * readResilience, the rows the Resilience page and the terminal draw: every | |
| 3 | * protection in docs/THREATS.md once, in the document's order, with its | |
| 4 | * standing from the last full gate — unknown said ("untested", "no test yet"), | |
| 5 | * never dropped. | |
| 6 | */ | |
| 7 | import { afterAll, beforeAll, expect, test } from "bun:test"; | |
| 8 | import { readFileSync } from "node:fs"; | |
| 9 | import { mkdtemp, rm } from "node:fs/promises"; | |
| 10 | import { tmpdir } from "node:os"; | |
| 11 | import { join } from "node:path"; | |
| 12 | import { keepGate } from "../src/checks/gate_last.ts"; | |
| 13 | import { readResilience, type Row } from "../src/checks/resilience.ts"; | |
| 14 | ||
| 15 | const DOC = readFileSync(join(import.meta.dir, "..", "docs", "THREATS.md"), "utf8"); | |
| 16 | const UNKNOWN = new Set(["untested", "no test yet"]); | |
| 17 | ||
| 18 | // Counted from the document without its parser: one protection per `Test:` | |
| 19 | // line, one per table row naming a call. | |
| 20 | const TESTS = DOC.split("\n").filter((l) => /^\s*Test: /.test(l)).length; | |
| 21 | const CALLS = DOC.split("\n").filter((l) => l.startsWith("| ") && l.includes("→")).length; | |
| 22 | ||
| 23 | let dataDir: string; | |
| 24 | ||
| 25 | beforeAll(async () => { | |
| 26 | dataDir = await mkdtemp(join(tmpdir(), "forge-checks-resilience-")); | |
| 27 | }); | |
| 28 | ||
| 29 | afterAll(async () => { | |
| 30 | await rm(dataDir, { recursive: true, force: true }); | |
| 31 | }); | |
| 32 | ||
| 33 | /** Each row's text starts somewhere in the document, after the row before it. */ | |
| 34 | function inDocOrder(rows: readonly Row[]): void { | |
| 35 | const flat = DOC.replace(/\s+/g, " "); | |
| 36 | let at = 0; | |
| 37 | for (const { p } of rows) { | |
| 38 | const found = flat.indexOf(p.text.slice(0, 40), at); | |
| 39 | expect(found, p.text).toBeGreaterThanOrEqual(at); | |
| 40 | at = found + 1; | |
| 41 | } | |
| 42 | } | |
| 43 | ||
| 44 | function once(rows: readonly Row[]): void { | |
| 45 | const keys = rows.map(({ p }) => `${p.adversary}\n${p.text}`); | |
| 46 | expect(new Set(keys).size).toBe(keys.length); | |
| 47 | } | |
| 48 | ||
| 49 | test("with no gate yet, every protection is listed once, in order, with an unknown standing", () => { | |
| 50 | const rows = readResilience(dataDir); | |
| 51 | expect(TESTS + CALLS).toBeGreaterThan(0); | |
| 52 | expect(rows.length).toBe(TESTS + CALLS); | |
| 53 | once(rows); | |
| 54 | inDocOrder(rows); | |
| 55 | for (const r of rows) { | |
| 56 | expect(UNKNOWN.has(r.s), r.p.text).toBe(true); | |
| 57 | expect(r.s).toBe(r.p.test === undefined ? "no test yet" : "untested"); | |
| 58 | } | |
| 59 | }); | |
| 60 | ||
| 61 | test("after a full gate with one protection green and one red, those read so and the rest stay unknown", () => { | |
| 62 | const before = readResilience(dataDir); | |
| 63 | const cited = [...new Set(before.flatMap(({ p }) => (p.test ? [p.test] : [])))]; | |
| 64 | const [green, red] = cited; | |
| 65 | if (green === undefined || red === undefined) throw new Error("THREATS.md cites fewer than two tests"); | |
| 66 | keepGate(dataDir, [ | |
| 67 | `${green}:`, | |
| 68 | "(pass) holds", | |
| 69 | `${red}:`, | |
| 70 | "(pass) one holds", | |
| 71 | "(fail) one does not", | |
| 72 | ]); | |
| 73 | ||
| 74 | const rows = readResilience(dataDir); | |
| 75 | expect(rows.length).toBe(before.length); | |
| 76 | once(rows); | |
| 77 | inDocOrder(rows); | |
| 78 | expect(rows.map(({ p }) => p)).toEqual(before.map(({ p }) => p)); | |
| 79 | for (const r of rows) { | |
| 80 | if (r.p.test === green) expect(r.s).toBe("green"); | |
| 81 | else if (r.p.test === red) expect(r.s).toBe("red"); | |
| 82 | else expect(UNKNOWN.has(r.s), r.p.text).toBe(true); | |
| 83 | } | |
| 84 | expect(rows.some((r) => r.s === "green")).toBe(true); | |
| 85 | expect(rows.some((r) => r.s === "red")).toBe(true); | |
| 86 | expect(rows.filter((r) => r.p.test === undefined).every((r) => r.s === "no test yet")).toBe(true); | |
| 87 | }); |
new above
offline