import { describe, expect, it } from "vitest"; import { minimizeInput } from "../../src/minimize/engine"; import { createPredicate, type RegexEvaluator, } from "../../src/minimize/predicates"; const unusedRegex: RegexEvaluator = async () => ({ matched: false, elapsedMs: 0, timedOut: false, }); describe("minimization engine", () => { it("removes XML structure while preserving a literal marker", async () => { const input = `discardBOOMdiscard`; const predicate = createPredicate( { kind: "contains", needle: "BOOM" }, unusedRegex, ); const result = await minimizeInput( input, { structure: "xml", maxTests: 300, maxSeconds: 5 }, predicate, new AbortController().signal, ); expect(result.minimized).toContain("BOOM"); expect(result.minimized.length).toBeLessThan(input.length); expect( new DOMParser() .parseFromString(result.minimized, "application/xml") .querySelector("parsererror"), ).toBeNull(); expect(result.steps.length).toBeGreaterThan(0); }); it("keeps the original JSON Schema failure signature", async () => { const input = JSON.stringify({ request: { id: 0, label: "noise" }, unrelated: [1, 2, 3], }); const predicate = createPredicate( { kind: "json-schema-fails", preserveFailureSignature: true, schema: JSON.stringify({ type: "object", required: ["request"], properties: { request: { type: "object", required: ["id"], properties: { id: { type: "integer", minimum: 1 } }, }, }, }), }, unusedRegex, ); const result = await minimizeInput( input, { structure: "json", maxTests: 500, maxSeconds: 5 }, predicate, new AbortController().signal, ); expect(JSON.parse(result.minimized)).toEqual({ request: { id: 0 } }); }); it("minimizes malformed syntax and reports budget exhaustion", async () => { const predicate = createPredicate({ kind: "invalid-json" }, unusedRegex); const result = await minimizeInput( '{"large": [1,2,}', { structure: "json", maxTests: 1, maxSeconds: 5 }, predicate, new AbortController().signal, ); expect(result.exhausted).toBe(true); expect(result.tests).toBe(1); }); it("rejects a baseline that does not reproduce and honours cancellation", async () => { await expect( minimizeInput( "safe", { structure: "text", maxTests: 20, maxSeconds: 2 }, createPredicate({ kind: "contains", needle: "BOOM" }, unusedRegex), new AbortController().signal, ), ).rejects.toThrow(/does not satisfy/u); const controller = new AbortController(); controller.abort(); await expect( minimizeInput( "BOOM", { structure: "text", maxTests: 20, maxSeconds: 2 }, createPredicate({ kind: "contains", needle: "BOOM" }, unusedRegex), controller.signal, ), ).rejects.toMatchObject({ name: "AbortError" }); }); it("uses isolated regex outcomes and fails closed on unsafe schemas/XSLT", async () => { const slow = createPredicate( { kind: "regex-slow", pattern: "a+", flags: "u", thresholdMs: 20 }, async () => ({ matched: false, elapsedMs: 20, timedOut: false }), ); expect(await slow("aaaa", new AbortController().signal)).toBe(true); expect(() => createPredicate( { kind: "json-schema-fails", schema: '{"$ref":"https://invalid/schema.json"}', }, unusedRegex, ), ).toThrow(/unsupported.*\$ref/iu); expect(() => createPredicate( { kind: "xslt-throws", stylesheet: '', }, unusedRegex, ), ).toThrow(/include/u); }); });