test(cli): distinguish silent hook relay completion (#109339)

This commit is contained in:
Dallin Romney
2026-07-16 13:59:34 -07:00
committed by GitHub
parent 84fb48c3be
commit 5a0fcc2ff9
+16 -5
View File
@@ -16,6 +16,7 @@ const tempDirs = useAutoCleanupTempDirTracker(afterEach);
const activeChildren = new Set<ChildProcessWithoutNullStreams>();
const outputTimeoutMs = 20_000;
const exitAfterOutputTimeoutMs = 5_000;
const exitOnlyTimeoutMs = 45_000;
afterEach(async () => {
nativeHookRelayTesting.clearNativeHookRelaysForTests();
@@ -110,6 +111,7 @@ async function createLingeringPreloadFixture(): Promise<{
async function runHooksCli(params: {
args: string[];
completion: "exit" | "output-then-exit";
label: string;
env?: NodeJS.ProcessEnv;
stdin?: string;
@@ -139,13 +141,16 @@ async function runHooksCli(params: {
}>((resolve, reject) => {
let timedOut = false;
let outputObserved = false;
// Silent relay success has no stream milestone. Give it an exit deadline
// while keeping the tighter post-output deadline for leaked handles.
const initialTimeoutMs = params.completion === "exit" ? exitOnlyTimeoutMs : outputTimeoutMs;
let timer = setTimeout(() => {
timedOut = true;
child.kill("SIGKILL");
}, outputTimeoutMs);
}, initialTimeoutMs);
child.stdout.on("data", (chunk: string) => {
stdout += chunk;
if (outputObserved) {
if (params.completion === "exit" || outputObserved) {
return;
}
outputObserved = true;
@@ -167,9 +172,12 @@ async function runHooksCli(params: {
clearTimeout(timer);
activeChildren.delete(child);
if (timedOut) {
const timeoutMessage = outputObserved
? `${params.label} did not exit within ${exitAfterOutputTimeoutMs}ms after emitting output`
: `${params.label} did not emit output within ${outputTimeoutMs}ms`;
const timeoutMessage =
params.completion === "exit"
? `${params.label} did not exit within ${exitOnlyTimeoutMs}ms`
: outputObserved
? `${params.label} did not exit within ${exitAfterOutputTimeoutMs}ms after emitting output`
: `${params.label} did not emit output within ${outputTimeoutMs}ms`;
reject(new Error(`${timeoutMessage}\nstdout:\n${stdout}\nstderr:\n${stderr}`));
return;
}
@@ -193,6 +201,7 @@ async function runHooksRelay(params: { event: "post_tool_use" | "pre_tool_use";
"--timeout",
"50",
],
completion: params.event === "post_tool_use" ? "exit" : "output-then-exit",
label: `hooks relay ${params.event}`,
env: {
LINGER_MARKER: fixture.markerPath,
@@ -239,6 +248,7 @@ describe("hooks CLI process lifecycle", () => {
"--timeout",
"5000",
],
completion: "exit",
label: "hooks relay explicit state database",
env: {
OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
@@ -260,6 +270,7 @@ describe("hooks CLI process lifecycle", () => {
// bootstraps sequential so low-core shards test lifecycle, not startup contention.
const listResult = await runHooksCli({
args: ["hooks", "list", "--json"],
completion: "output-then-exit",
label: "hooks list",
env: {
LINGER_MARKER: fixture.markerPath,