|
| 1 | +import { readFileSync } from "node:fs"; |
| 2 | +import { join } from "node:path"; |
| 3 | +import { describe, expect, test } from "bun:test"; |
| 4 | +import { |
| 5 | + COUNTED_OP_TOLERANCE, |
| 6 | + GIT_FANOUT_TOLERANCE, |
| 7 | + type BaselineFile, |
| 8 | + type CensusMeasurement, |
| 9 | + type PerfMeasurement, |
| 10 | + gateSessionStoreBaseline, |
| 11 | + gateSessionStoreBaselineJson, |
| 12 | +} from "./check-session-store-perf-baseline.js"; |
| 13 | + |
| 14 | +const repoRoot = join(import.meta.dir, ".."); |
| 15 | +const baselinePath = join( |
| 16 | + repoRoot, |
| 17 | + "scripts", |
| 18 | + "results", |
| 19 | + "session-store-perf-baseline.json", |
| 20 | +); |
| 21 | +const baselineRaw = readFileSync(baselinePath, "utf8"); |
| 22 | +const ci = readFileSync( |
| 23 | + join(repoRoot, ".github", "workflows", "ci.yml"), |
| 24 | + "utf8", |
| 25 | +); |
| 26 | + |
| 27 | +function parsedBaseline(): { |
| 28 | + baseline: BaselineFile; |
| 29 | + perf: PerfMeasurement; |
| 30 | + census: CensusMeasurement; |
| 31 | +} { |
| 32 | + const failures = gateSessionStoreBaselineJson( |
| 33 | + baselineRaw, |
| 34 | + JSON.stringify(JSON.parse(baselineRaw).contextStorePerf), |
| 35 | + JSON.stringify(JSON.parse(baselineRaw).turnPersistenceCensus), |
| 36 | + ); |
| 37 | + expect(failures).toEqual([]); |
| 38 | + const baseline = JSON.parse(baselineRaw) as BaselineFile; |
| 39 | + return { |
| 40 | + baseline, |
| 41 | + perf: baseline.contextStorePerf, |
| 42 | + census: baseline.turnPersistenceCensus, |
| 43 | + }; |
| 44 | +} |
| 45 | + |
| 46 | +describe("session-store perf baseline", () => { |
| 47 | + test("checked-in snapshot matches the gate, ignoring wall time", () => { |
| 48 | + expect(COUNTED_OP_TOLERANCE).toBe(0); |
| 49 | + expect(GIT_FANOUT_TOLERANCE).toBe(64); |
| 50 | + const { baseline, perf, census } = parsedBaseline(); |
| 51 | + const noisy = { |
| 52 | + ...perf, |
| 53 | + wallMs: 1, |
| 54 | + perTurn: { wallMs: 99, fsOps: 0 }, |
| 55 | + }; |
| 56 | + expect(gateSessionStoreBaseline(baseline, noisy, census)).toEqual([]); |
| 57 | + }); |
| 58 | + |
| 59 | + test("a per-turn access outside .git fails; git fanout within slack passes", () => { |
| 60 | + const { baseline, perf, census } = parsedBaseline(); |
| 61 | + const extraAccess: PerfMeasurement = { |
| 62 | + ...perf, |
| 63 | + fsOps: { ...perf.fsOps, access: (perf.fsOps.access ?? 0) + 1 }, |
| 64 | + }; |
| 65 | + expect(gateSessionStoreBaseline(baseline, extraAccess, census)).not.toEqual( |
| 66 | + [], |
| 67 | + ); |
| 68 | + |
| 69 | + const fanout = GIT_FANOUT_TOLERANCE; |
| 70 | + const within: PerfMeasurement = { |
| 71 | + ...perf, |
| 72 | + fsOps: { |
| 73 | + ...perf.fsOps, |
| 74 | + mkdir: (perf.fsOps.mkdir ?? 0) + fanout, |
| 75 | + writeFile: (perf.fsOps.writeFile ?? 0) + fanout, |
| 76 | + }, |
| 77 | + gitPathFsOpsByName: { |
| 78 | + ...perf.gitPathFsOpsByName, |
| 79 | + mkdir: (perf.gitPathFsOpsByName.mkdir ?? 0) + fanout, |
| 80 | + writeFile: (perf.gitPathFsOpsByName.writeFile ?? 0) + fanout, |
| 81 | + }, |
| 82 | + }; |
| 83 | + expect(gateSessionStoreBaseline(baseline, within, census)).toEqual([]); |
| 84 | + |
| 85 | + const past: PerfMeasurement = { |
| 86 | + ...perf, |
| 87 | + fsOps: { |
| 88 | + ...perf.fsOps, |
| 89 | + mkdir: (perf.fsOps.mkdir ?? 0) + fanout + 1, |
| 90 | + }, |
| 91 | + gitPathFsOpsByName: { |
| 92 | + ...perf.gitPathFsOpsByName, |
| 93 | + mkdir: (perf.gitPathFsOpsByName.mkdir ?? 0) + fanout + 1, |
| 94 | + }, |
| 95 | + }; |
| 96 | + const failures = gateSessionStoreBaseline(baseline, past, census); |
| 97 | + expect(failures.some((line) => line.includes(".git mkdir"))).toBe(true); |
| 98 | + }); |
| 99 | + |
| 100 | + test("CI runs both scripts and states the fs.promises-only blind spot", () => { |
| 101 | + expect(ci).toContain("bun scripts/context-store-perf.ts 200 --json"); |
| 102 | + expect(ci).toContain( |
| 103 | + "bun scripts/turn-persistence-census.ts 200 --flow=coalesced --json", |
| 104 | + ); |
| 105 | + expect(ci).toContain( |
| 106 | + "both patch fs.promises only, so synchronous fs is invisible", |
| 107 | + ); |
| 108 | + expect(ci).not.toContain("synchronous fs is counted"); |
| 109 | + expect(ci).not.toContain("every filesystem"); |
| 110 | + }); |
| 111 | +}); |
0 commit comments