Release Minimize Tools 0.1.0
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
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 = `<case><noise a="1">discard</noise><payload><message>BOOM</message><also>discard</also></payload></case>`;
|
||||
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:
|
||||
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:include href="https://invalid/x.xsl"/></xsl:stylesheet>',
|
||||
},
|
||||
unusedRegex,
|
||||
),
|
||||
).toThrow(/include/u);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user