Files
TREK/server/tests/unit/scripts/pg-probe/baseline.test.ts
T
Maurice 12bf6c0da3 ci(server): fail the Postgres probe on an unmeasured baseline
The probe shipped with scripts/pg-probe-baseline.json at `failing: null`,
and an unmeasured baseline only reported. Every repository statement
Postgres refused, new SQLite-only SQL included, still passed the job;
only the dialect helper cases could fail it, so the ratchet was off until
some later commit seeded the file.

An unmeasured baseline now fails the run outside --update, and the log,
step summary and annotation say which artifact file to commit. The job
stays red until the first measurement lands, so the gate cannot reach dev
holding nothing. A run that called no repository method (an unreadable
tsconfig, a moved repositories directory) fails as well, also under
--update, so a broken plan can neither pass nor seed an empty baseline.
2026-10-08 18:39:34 +02:00

69 lines
3.6 KiB
TypeScript

/**
* The Postgres probe's ratchet (scripts/pg-probe/baseline.ts). The probe
* itself only runs in CI against a Postgres service, so the rules that decide
* whether that job passes are pinned here: a method may not fail more
* statements than its entry, a stale entry fails until it is lowered, an
* unmeasured baseline has nothing to compare (the run fails on it, see
* report.test.ts), and --update never raises or adds.
*/
import { readFileSync } from 'node:fs';
import path from 'node:path';
import { describe, expect, it } from 'vitest';
import { compareWithBaseline, formatBaseline, lowerBaseline, parseBaseline } from '../../../../scripts/pg-probe/baseline';
const now = (entries: Record<string, number>): Map<string, number> => new Map(Object.entries(entries));
describe('pg-probe baseline', () => {
it('PGPROBE-001: parses a measured and an unmeasured baseline', () => {
expect(parseBaseline('{"failing": null}', 'b.json')).toEqual({ failing: null });
expect(parseBaseline('{"failing": {"TagsRepository.listByUser": 2}}', 'b.json')).toEqual({ failing: { 'TagsRepository.listByUser': 2 } });
});
it('PGPROBE-002: refuses a malformed baseline instead of reading it as empty', () => {
expect(() => parseBaseline('nope', 'b.json')).toThrow(/b.json is not valid JSON/);
expect(() => parseBaseline('{}', 'b.json')).toThrow(/"failing" key/);
expect(() => parseBaseline('[]', 'b.json')).toThrow(/"failing" key/);
expect(() => parseBaseline('{"failing": []}', 'b.json')).toThrow(/null or an object/);
expect(() => parseBaseline('{"failing": {"listByUser": 1}}', 'b.json')).toThrow(/not a Class.method key/);
expect(() => parseBaseline('{"failing": {"A.b": 0}}', 'b.json')).toThrow(/expected a positive integer/);
expect(() => parseBaseline('{"failing": {"A.b": 1.5}}', 'b.json')).toThrow(/expected a positive integer/);
});
it('PGPROBE-003: an unmeasured baseline is flagged instead of compared', () => {
expect(compareWithBaseline({ failing: null }, now({ 'A.b': 3 }))).toEqual({ unseeded: true, grown: [], stale: [] });
});
it('PGPROBE-004: a method failing more statements than its entry (or any without one) fails', () => {
const verdict = compareWithBaseline({ failing: { 'A.b': 1 } }, now({ 'A.b': 2, 'C.d': 1, 'E.f': 0 }));
expect(verdict.grown).toEqual([
{ method: 'A.b', allowed: 1, now: 2 },
{ method: 'C.d', allowed: 0, now: 1 },
]);
expect(verdict.stale).toEqual([]);
});
it('PGPROBE-005: an entry above what its method fails now is stale, also when the method is gone', () => {
const verdict = compareWithBaseline({ failing: { 'A.b': 2, 'Gone.away': 1 } }, now({ 'A.b': 1 }));
expect(verdict.grown).toEqual([]);
expect(verdict.stale).toEqual([
{ method: 'A.b', allowed: 2, now: 1 },
{ method: 'Gone.away', allowed: 1, now: 0 },
]);
});
it('PGPROBE-006: --update lowers and drops entries but never raises or adds one', () => {
const lowered = lowerBaseline({ failing: { 'A.b': 2, 'C.d': 1, 'Gone.away': 1 } }, now({ 'A.b': 1, 'C.d': 5, 'New.one': 3 }));
expect(lowered).toEqual({ failing: { 'A.b': 1, 'C.d': 1 } });
});
it('PGPROBE-007: the first --update seeds an unmeasured baseline with what fails, sorted', () => {
expect(lowerBaseline({ failing: null }, now({ 'Z.z': 1, 'A.a': 2, 'M.m': 0 }))).toEqual({ failing: { 'A.a': 2, 'Z.z': 1 } });
});
it('PGPROBE-008: the checked-in baseline parses and formats back to itself', () => {
const file = path.join(__dirname, '../../../../scripts/pg-probe-baseline.json');
const text = readFileSync(file, 'utf8');
expect(formatBaseline(parseBaseline(text, file))).toBe(text.replace(/\r\n/g, '\n'));
});
});