Files
reverse-engineering-anything/tests/evaluation/providerRequiredCases.test.ts
T
morlutoandCursor Agent 77b09314ff test(ci): require provider checks and reduce test startup (#8145)
* test(ci): require provider coverage and reuse test sessions

* fix(ci): prepare the runtime before Python producer tests

The fast Python job ran the suite on a fresh checkout, so analysis-efficiency
checks failed without compiled process modules. Install locked dependencies
and prepare the runtime before the suite.

* fix(ci): keep provider test reports inside the checkout

The provider-report reader accepted an arbitrary path from argv. Resolve the
path and reject anything outside the checkout before reading it. The packet
and signal workflows write those reports under .cache.

* fix(ci): require a test module in each named Python bridge family

Discovery still runs every bridge test. The mitmproxy, native, and pwndbg
families must each keep a test module, so deleting one cannot pass through
the others.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-10-30 19:34:19 +08:00

216 lines
6.6 KiB
TypeScript

import { execFileSync } from "node:child_process";
import {
mkdirSync,
mkdtempSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { expect, it } from "vitest";
import { parse } from "yaml";
import { z } from "zod";
const script = fileURLToPath(
new URL("../../scripts/ci/require-provider-tests.mjs", import.meta.url),
);
const cleanupCases = [
"capture",
"tool",
"limiter",
"kernel",
"field-tool",
"field-limiter",
"field-kernel",
].map(
(item) =>
`retains failed ${item} descriptors and retries them before further acquisition and shutdown`,
);
const commonLimits = [
"enforces both address-space limits before any producer allocation",
"preserves lower inherited file/CPU limits in the real launch",
];
const testFile = (path: string, names: string[]) => ({
name: resolve(path),
assertionResults: names.map((fullName) => ({ fullName, status: "passed" })),
});
const report = (lane: "packet" | "signal") => ({
success: true,
testResults:
lane === "packet"
? [
testFile("tests/boundary/captures/resourceLimits.test.ts", [
...commonLimits,
"reports a real kernel file-limit termination with its effective ceiling",
]),
testFile(
"tests/boundary/captures/captureDescriptorCleanup.test.ts",
cleanupCases,
),
]
: [
testFile(
"tests/boundary/signals/resourceLimits.test.ts",
commonLimits,
),
testFile(
"tests/boundary/signals/recordingDescriptorCleanup.test.ts",
cleanupCases,
),
],
});
const run = (lane: string, value: unknown) => {
mkdirSync(join(process.cwd(), ".cache"), { recursive: true });
const directory = mkdtempSync(
join(process.cwd(), ".cache", "rea-required-cases-"),
);
try {
const path = join(directory, "report.json");
writeFileSync(path, JSON.stringify(value));
return execFileSync(process.execPath, [script, lane, path], {
cwd: process.cwd(),
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
} finally {
rmSync(directory, { recursive: true, force: true });
}
};
const outsideReportFailure = (reportPath: string) => {
try {
execFileSync(process.execPath, [script, "packet", reportPath], {
cwd: process.cwd(),
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
return undefined;
} catch (error) {
return error;
}
};
it.each(["packet", "signal"] as const)(
"requires the %s resource and descriptor cases without banning unrelated skips",
(lane) => {
const result = report(lane);
result.testResults.push({
name: resolve("tests/unrelated.test.ts"),
assertionResults: [{ fullName: "host-specific", status: "pending" }],
});
expect(run(lane, result)).toContain("cases passed");
for (const resultIndex of [0, 1]) {
const skipped = report(lane);
skipped.testResults[resultIndex]!.assertionResults[0]!.status = "pending";
expect(() => run(lane, skipped)).toThrow(
"Required provider test did not pass",
);
const failed = report(lane);
failed.testResults[resultIndex]!.assertionResults[0]!.status = "failed";
expect(() => run(lane, failed)).toThrow(
"Required provider test did not pass",
);
const removed = report(lane);
removed.testResults[resultIndex]!.assertionResults.shift();
expect(() => run(lane, removed)).toThrow(
"Required provider test did not pass",
);
const duplicate = report(lane);
duplicate.testResults[resultIndex]!.assertionResults.push(
duplicate.testResults[resultIndex]!.assertionResults[0]!,
);
expect(() => run(lane, duplicate)).toThrow(
"Required provider test did not pass",
);
}
const missingFile = report(lane);
missingFile.testResults.pop();
expect(() => run(lane, missingFile)).toThrow(
"Expected exactly one provider test result",
);
expect(() => run(lane, { success: true, testResults: [] })).toThrow();
expect(() => run(lane, { success: false, testResults: [] })).toThrow();
},
);
it.each([
["parent", resolve(process.cwd(), "..", "rea-provider-report.json")],
["sibling prefix", `${resolve(process.cwd())}-outside/report.json`],
["absolute outside", resolve(tmpdir(), "rea-provider-report.json")],
] as const)(
"rejects a %s report path outside the checkout",
(_label, reportPath) => {
const failure = z
.object({ status: z.literal(1), stderr: z.string() })
.parse(outsideReportFailure(reportPath));
const encoded = failure.stderr.match(
/\{"code":"report_path_outside_checkout"\}/u,
)?.[0];
expect(JSON.parse(encoded ?? "")).toEqual({
code: "report_path_outside_checkout",
});
},
);
it("rejects unknown lanes and missing or malformed reports", () => {
expect(() => run("other", report("packet"))).toThrow(
"Expected provider test lane",
);
expect(() => run("packet", null)).toThrow(
"missing a successful test inventory",
);
expect(() =>
execFileSync(process.execPath, [script, "packet", "/missing/report.json"], {
stdio: "pipe",
}),
).toThrow();
});
it.each([
[
"real-packet-capture.yml",
"tshark",
"packet",
"tests/boundary/captures/resourceLimits.test.ts",
"tests/boundary/captures/captureDescriptorCleanup.test.ts",
],
[
"real-signal-recording.yml",
"sigrok",
"signal",
"tests/boundary/signals/resourceLimits.test.ts",
"tests/boundary/signals/recordingDescriptorCleanup.test.ts",
],
] as const)(
"keeps required case validation in %s",
(workflow, job, lane, limits, cleanup) => {
const file = new URL(
`../../.github/workflows/${workflow}`,
import.meta.url,
);
const parsed = z
.object({
jobs: z.record(
z.string(),
z.object({
steps: z.array(z.object({ run: z.string().optional() })),
}),
),
})
.parse(parse(readFileSync(file, "utf8")));
const step = parsed.jobs[job]?.steps.find((item) =>
item.run?.includes("scripts/ci/require-provider-tests.mjs"),
);
expect(step?.run).toContain('rm -f "$report"');
expect(step?.run).toContain("node scripts/run-exact-tests.mjs run");
expect(step?.run).toContain("--reporter=json");
expect(step?.run).toContain('--outputFile.json="$report"');
expect(step?.run).toContain(limits);
expect(step?.run).toContain(cleanup);
expect(step?.run).toContain(
`node scripts/ci/require-provider-tests.mjs ${lane} "$report"`,
);
},
);