mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-14 06:06:08 +00:00
test: remove more avoidable waits (#105816)
This commit is contained in:
committed by
GitHub
parent
f1a64741b5
commit
a63aec8bf8
@@ -22,17 +22,30 @@ function isProcessRunning(pid: number): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForFile(pathToCheck: string, timeoutMs: number): Promise<void> {
|
||||
async function waitForPidFile(pathToCheck: string, timeoutMs: number): Promise<number> {
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
while (Date.now() < deadline) {
|
||||
try {
|
||||
await readFile(pathToCheck, "utf8");
|
||||
return;
|
||||
} catch {
|
||||
await sleep(25);
|
||||
}
|
||||
const value = (await readFile(pathToCheck, "utf8")).trim();
|
||||
const pid = Number(value);
|
||||
if (/^[1-9]\d*$/u.test(value) && Number.isSafeInteger(pid)) {
|
||||
return pid;
|
||||
}
|
||||
} catch {}
|
||||
await sleep(25);
|
||||
}
|
||||
throw new Error(`Timed out waiting for ${pathToCheck}`);
|
||||
throw new Error(`Timed out waiting for a PID in ${pathToCheck}`);
|
||||
}
|
||||
|
||||
async function waitForProcessExit(pid: number, timeoutMs: number): Promise<void> {
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
while (Date.now() < deadline) {
|
||||
if (!isProcessRunning(pid)) {
|
||||
return;
|
||||
}
|
||||
await sleep(25);
|
||||
}
|
||||
throw new Error(`Timed out waiting for process ${pid} to exit`);
|
||||
}
|
||||
|
||||
describe("Matrix QA CLI runtime", () => {
|
||||
@@ -235,15 +248,9 @@ describe("Matrix QA CLI runtime", () => {
|
||||
env: process.env,
|
||||
timeoutMs: 250,
|
||||
}),
|
||||
).rejects.toThrow(/stdout:\nwaiting for verification/);
|
||||
await expect(
|
||||
runMatrixQaOpenClawCli({
|
||||
args: ["matrix", "verify", "self"],
|
||||
cwd: root,
|
||||
env: process.env,
|
||||
timeoutMs: 250,
|
||||
}),
|
||||
).rejects.toThrow(/stderr:\nmatrix sdk still syncing/);
|
||||
).rejects.toThrow(
|
||||
/stderr:\nmatrix sdk still syncing[\s\S]*stdout:\nwaiting for verification/u,
|
||||
);
|
||||
} finally {
|
||||
await rm(root, { force: true, recursive: true });
|
||||
}
|
||||
@@ -312,12 +319,12 @@ describe("Matrix QA CLI runtime", () => {
|
||||
env: process.env,
|
||||
timeoutMs: 500,
|
||||
});
|
||||
await sleep(850);
|
||||
childPid = await waitForPidFile(pidPath, 2_000);
|
||||
await waitForProcessExit(childPid, 2_000);
|
||||
|
||||
await expect(session.wait()).rejects.toThrow(/timed out after 500ms/u);
|
||||
await expect(session.wait()).rejects.toThrow(/late wait timeout marker/u);
|
||||
|
||||
childPid = Number(await readFile(pidPath, "utf8"));
|
||||
expect(isProcessRunning(childPid)).toBe(false);
|
||||
} finally {
|
||||
if (childPid && isProcessRunning(childPid)) {
|
||||
@@ -409,12 +416,11 @@ describe("Matrix QA CLI runtime", () => {
|
||||
env: process.env,
|
||||
timeoutMs: 500,
|
||||
});
|
||||
await waitForFile(grandchildPidPath, 2_000);
|
||||
grandchildPid = await waitForPidFile(grandchildPidPath, 2_000);
|
||||
|
||||
await expect(run).rejects.toThrow(/timed out after 500ms/u);
|
||||
|
||||
childPid = Number(await readFile(childPidPath, "utf8"));
|
||||
grandchildPid = Number(await readFile(grandchildPidPath, "utf8"));
|
||||
childPid = await waitForPidFile(childPidPath, 2_000);
|
||||
expect(isProcessRunning(childPid)).toBe(false);
|
||||
expect(isProcessRunning(grandchildPid)).toBe(false);
|
||||
} finally {
|
||||
@@ -460,14 +466,17 @@ describe("Matrix QA CLI runtime", () => {
|
||||
env: process.env,
|
||||
timeoutMs: 10_000,
|
||||
});
|
||||
await waitForFile(grandchildPidPath, 2_000);
|
||||
await sleep(300);
|
||||
childPid = await waitForPidFile(childPidPath, 2_000);
|
||||
grandchildPid = await waitForPidFile(grandchildPidPath, 2_000);
|
||||
|
||||
const sessionExit = session.wait().catch(() => undefined);
|
||||
session.kill();
|
||||
await sleep(500);
|
||||
|
||||
childPid = Number(await readFile(childPidPath, "utf8"));
|
||||
grandchildPid = Number(await readFile(grandchildPidPath, "utf8"));
|
||||
await Promise.all([
|
||||
waitForProcessExit(childPid, 2_000),
|
||||
waitForProcessExit(grandchildPid, 2_000),
|
||||
]);
|
||||
await sessionExit;
|
||||
expect(isProcessRunning(childPid)).toBe(false);
|
||||
expect(isProcessRunning(grandchildPid)).toBe(false);
|
||||
} finally {
|
||||
|
||||
@@ -17,6 +17,7 @@ describe("telegram transport cache eviction over real sockets", () => {
|
||||
let sendMessageCalls = 0;
|
||||
let slowMode = false;
|
||||
let slowRequestReceived: () => void = () => {};
|
||||
let releaseSlowResponse: (() => void) | undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
server = createServer((req, res) => {
|
||||
@@ -34,7 +35,9 @@ describe("telegram transport cache eviction over real sockets", () => {
|
||||
sendMessageCalls += 1;
|
||||
if (slowMode) {
|
||||
slowRequestReceived();
|
||||
setTimeout(() => respond({ message_id: sendMessageCalls, chat: { id: 123 } }), 800);
|
||||
releaseSlowResponse = () => {
|
||||
respond({ message_id: sendMessageCalls, chat: { id: 123 } });
|
||||
};
|
||||
return;
|
||||
}
|
||||
respond({ message_id: sendMessageCalls, chat: { id: 123 } });
|
||||
@@ -114,12 +117,24 @@ describe("telegram transport cache eviction over real sockets", () => {
|
||||
await inFlight;
|
||||
slowMode = false;
|
||||
|
||||
// New cache key -> evicts acct-0 while its send holds the lease.
|
||||
const evictor = await sendMessageTelegram("123", "evictor", { cfg, accountId: "acct-64" });
|
||||
expect(evictor.messageId).toBeTruthy();
|
||||
// Deferred close: the evicted transport must NOT be closed mid-request.
|
||||
expect(sockets.closed).toBe(0);
|
||||
|
||||
const releaseResponse = releaseSlowResponse;
|
||||
if (!releaseResponse) {
|
||||
throw new Error("slow Telegram response was not captured");
|
||||
}
|
||||
try {
|
||||
// New cache key -> evicts acct-0 while its send holds the lease.
|
||||
const evictor = await sendMessageTelegram("123", "evictor", {
|
||||
cfg,
|
||||
accountId: "acct-64",
|
||||
});
|
||||
expect(evictor.messageId).toBeTruthy();
|
||||
// Deferred close: the evicted transport must NOT be closed mid-request.
|
||||
expect(sockets.closed).toBe(0);
|
||||
} finally {
|
||||
releaseSlowResponse = undefined;
|
||||
releaseResponse();
|
||||
await slowSend.catch(() => undefined);
|
||||
}
|
||||
const slow = await slowSend;
|
||||
expect(slow.messageId).toBeTruthy();
|
||||
// Lease released -> the retired acct-0 transport closes its real socket.
|
||||
|
||||
@@ -208,6 +208,43 @@ async function waitForExit(child: ChildProcess): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
async function waitForStderr(
|
||||
child: ChildProcess,
|
||||
expected: string,
|
||||
timeoutMs: number,
|
||||
): Promise<string> {
|
||||
const stderr = child.stderr;
|
||||
if (!stderr) {
|
||||
throw new Error("child stderr is not piped");
|
||||
}
|
||||
stderr.setEncoding("utf8");
|
||||
let output = "";
|
||||
return await new Promise<string>((resolve, reject) => {
|
||||
const cleanup = () => {
|
||||
clearTimeout(timeout);
|
||||
stderr.off("data", onData);
|
||||
child.off("exit", onExit);
|
||||
};
|
||||
const onData = (chunk: string) => {
|
||||
output += chunk;
|
||||
if (output.includes(expected)) {
|
||||
cleanup();
|
||||
resolve(output);
|
||||
}
|
||||
};
|
||||
const onExit = () => {
|
||||
cleanup();
|
||||
reject(new Error(`child exited before writing ${JSON.stringify(expected)}: ${output}`));
|
||||
};
|
||||
const timeout = setTimeout(() => {
|
||||
cleanup();
|
||||
reject(new Error(`timed out waiting for ${JSON.stringify(expected)}: ${output}`));
|
||||
}, timeoutMs);
|
||||
stderr.on("data", onData);
|
||||
child.once("exit", onExit);
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
for (const child of children.splice(0)) {
|
||||
child.kill("SIGKILL");
|
||||
@@ -759,7 +796,7 @@ describe("pr-gates-lock helper", () => {
|
||||
const second = spawnGateLockHolder(repoDir, secondStatus, {
|
||||
OPENCLAW_HEAVY_CHECK_LOCK_POLL_MS: "50",
|
||||
});
|
||||
await new Promise((resolve) => setTimeout(resolve, 400));
|
||||
await waitForStderr(second, "queued behind the local heavy-check lock", 5_000);
|
||||
expect(existsSync(secondStatus)).toBe(false);
|
||||
|
||||
first.kill("SIGTERM");
|
||||
|
||||
Reference in New Issue
Block a user