fix(test): fail secret proof signal exits

This commit is contained in:
Vincent Koc
2026-06-07 02:06:21 +02:00
parent b6cbb4b861
commit ba46d00589
2 changed files with 76 additions and 7 deletions

View File

@@ -20,16 +20,30 @@ const MANUAL_EXEC_TOKEN = "proof-manual-exec-token";
const PLUGIN_EXEC_TOKEN = "proof-plugin-exec-token";
const OPENAI_PROFILE = "openai:secretref-proof";
const OPENAI_LIVE_PROOF_MODEL = "openai/gpt-5.5";
const COMMAND_TIMEOUT_MS = readPositiveInt(process.env.OPENCLAW_SECRET_PROOF_COMMAND_MS, 120000);
const READY_TIMEOUT_MS = readPositiveInt(process.env.OPENCLAW_SECRET_PROOF_READY_MS, 120000);
const RPC_TIMEOUT_MS = readPositiveInt(process.env.OPENCLAW_SECRET_PROOF_RPC_MS, 15000);
const COMMAND_TIMEOUT_MS = readPositiveInt(
process.env.OPENCLAW_SECRET_PROOF_COMMAND_MS,
120000,
"OPENCLAW_SECRET_PROOF_COMMAND_MS",
);
const READY_TIMEOUT_MS = readPositiveInt(
process.env.OPENCLAW_SECRET_PROOF_READY_MS,
120000,
"OPENCLAW_SECRET_PROOF_READY_MS",
);
const RPC_TIMEOUT_MS = readPositiveInt(
process.env.OPENCLAW_SECRET_PROOF_RPC_MS,
15000,
"OPENCLAW_SECRET_PROOF_RPC_MS",
);
const TEARDOWN_GRACE_MS = readPositiveInt(
process.env.OPENCLAW_SECRET_PROOF_TEARDOWN_GRACE_MS,
5000,
"OPENCLAW_SECRET_PROOF_TEARDOWN_GRACE_MS",
);
const OUTPUT_CAPTURE_LIMIT_BYTES = readPositiveInt(
process.env.OPENCLAW_SECRET_PROOF_OUTPUT_BYTES,
4 * 1024 * 1024,
"OPENCLAW_SECRET_PROOF_OUTPUT_BYTES",
);
const RESULTS_PATH =
process.env.OPENCLAW_SECRET_PROOF_RESULTS_PATH?.trim() ||
@@ -42,13 +56,19 @@ function requireFullMatrix() {
return process.env.OPENCLAW_SECRET_PROOF_FULL === "1";
}
function readPositiveInt(raw, fallback) {
function readPositiveInt(raw, fallback, label) {
const text = String(raw ?? "").trim();
if (!/^\d+$/u.test(text)) {
if (!text) {
return fallback;
}
if (!/^\d+$/u.test(text)) {
throw new Error(`${label} must be a positive integer. Got: ${JSON.stringify(text)}`);
}
const parsed = Number(text);
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback;
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
throw new Error(`${label} must be a positive integer. Got: ${JSON.stringify(text)}`);
}
return parsed;
}
function remainingDeadlineMs(started, timeoutMs) {
@@ -303,7 +323,7 @@ function runCommand(command, args, options = {}) {
}
abortSignal?.removeEventListener("abort", abort);
removeParentSignalHandlers();
const result = { code: code ?? 0, signal, stdout: stdout.text(), stderr: stderr.text() };
const result = { code, signal, stdout: stdout.text(), stderr: stderr.text() };
if (aborted) {
reject(new Error(scrub(`command aborted: ${command} ${args.join(" ")}`)));
return;
@@ -313,6 +333,18 @@ function runCommand(command, args, options = {}) {
reject(new Error(scrub(`command timed out: ${command} ${args.join(" ")}`)));
return;
}
if (result.signal && options.allowFailure !== true) {
reject(
new Error(
scrub(
`command terminated by signal (${result.signal}): ${command} ${args.join(" ")}\n${
result.stderr || result.stdout
}`,
),
),
);
return;
}
if (result.code !== 0 && options.allowFailure !== true) {
reject(
new Error(

View File

@@ -237,6 +237,43 @@ describe("secret provider integration proof harness", () => {
}
});
it.runIf(process.platform !== "win32")(
"fails mandatory commands that exit by signal",
async () => {
const proof = await import(
`${pathToFileURL(proofScriptPath).href}?case=signal-${Date.now()}`
);
await expect(
proof.runCommand(process.execPath, [
"--input-type=module",
"--eval",
"process.kill(process.pid, 'SIGTERM');",
]),
).rejects.toThrow("command terminated by signal (SIGTERM)");
},
);
it.each([
["OPENCLAW_SECRET_PROOF_COMMAND_MS", "150ms"],
["OPENCLAW_SECRET_PROOF_READY_MS", "0"],
["OPENCLAW_SECRET_PROOF_OUTPUT_BYTES", "4mb"],
])("rejects malformed proof env limit %s=%s", async (name, value) => {
const previous = process.env[name];
process.env[name] = value;
try {
await expect(
import(`${pathToFileURL(proofScriptPath).href}?case=env-${name}-${Date.now()}`),
).rejects.toThrow(`${name} must be a positive integer`);
} finally {
if (previous === undefined) {
delete process.env[name];
} else {
process.env[name] = previous;
}
}
});
it("fails when proof temp cleanup cannot remove the root", async () => {
const proof = await import(`${pathToFileURL(proofScriptPath).href}?case=cleanup-${Date.now()}`);
const rmSync = vi.spyOn(fs, "rmSync").mockImplementation(() => {