Skip to content

Commit a04b6ce

Browse files
authored
test: stabilize load-sensitive test families that break gates under parallel load (#100420)
* test: stabilize process-heavy fixtures under load * test: stabilize channel mocks under load
1 parent 4b9c51c commit a04b6ce

6 files changed

Lines changed: 161 additions & 104 deletions

extensions/matrix/src/approval-reactions.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ import {
1010
} from "./approval-reactions.js";
1111
import { setMatrixRuntime } from "./runtime.js";
1212

13+
function createRuntimeLogger(overrides: { warn?: ReturnType<typeof vi.fn> } = {}) {
14+
// Runtime state survives no-isolate workers, so expose every logger method later files may call.
15+
return {
16+
debug: vi.fn(),
17+
info: vi.fn(),
18+
warn: overrides.warn ?? vi.fn(),
19+
error: vi.fn(),
20+
};
21+
}
22+
1323
afterEach(() => {
1424
clearMatrixApprovalReactionTargetsForTest();
1525
vi.restoreAllMocks();
@@ -124,7 +134,7 @@ describe("matrix approval reactions", () => {
124134
}));
125135
setMatrixRuntime({
126136
state: { openKeyedStore },
127-
logging: { getChildLogger: () => ({ warn: vi.fn() }) },
137+
logging: { getChildLogger: () => createRuntimeLogger() },
128138
} as never);
129139

130140
registerMatrixApprovalReactionTarget({
@@ -165,7 +175,7 @@ describe("matrix approval reactions", () => {
165175
throw new Error("sqlite unavailable");
166176
}),
167177
},
168-
logging: { getChildLogger: () => ({ warn }) },
178+
logging: { getChildLogger: () => createRuntimeLogger({ warn }) },
169179
} as never);
170180

171181
registerMatrixApprovalReactionTarget({

extensions/whatsapp/src/monitor-inbox.captures-media-path-image-messages.test-support.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import {
88
getSock,
99
installWebMonitorInboxUnitTestHooks,
1010
mockLoadConfig,
11-
settleInboundWork,
12-
waitForMessageCalls,
1311
} from "./monitor-inbox.test-harness.js";
1412
let monitorWebInbox: typeof import("./inbound.js").monitorWebInbox;
1513
const inboundLoggerInfoMock = vi.hoisted(() => vi.fn());
@@ -37,23 +35,45 @@ describe("web monitor inbox", () => {
3735
monitorWebInbox = getMonitorWebInbox();
3836
});
3937

40-
async function openMonitor(onMessage = vi.fn()) {
38+
async function openMonitor(
39+
onMessage = vi.fn(),
40+
extraOptions: Partial<Parameters<typeof monitorWebInbox>[0]> = {},
41+
) {
4142
return await monitorWebInbox({
4243
cfg: mockLoadConfig() as never,
4344
verbose: false,
4445
accountId: DEFAULT_ACCOUNT_ID,
4546
authDir: getAuthDir(),
4647
onMessage,
48+
...extraOptions,
4749
});
4850
}
4951

5052
async function runSingleUpsertAndCapture(upsert: unknown) {
5153
const onMessage = vi.fn();
52-
const listener = await openMonitor(onMessage);
54+
let armed = false;
55+
let observedPendingWork = false;
56+
let resolvePendingWorkDrained!: () => void;
57+
const pendingWorkDrained = new Promise<void>((resolve) => {
58+
resolvePendingWorkDrained = resolve;
59+
});
60+
const listener = await openMonitor(onMessage, {
61+
onPendingWorkChanged: (pendingWorkCount) => {
62+
if (!armed) {
63+
return;
64+
}
65+
if (pendingWorkCount > 0) {
66+
observedPendingWork = true;
67+
} else if (observedPendingWork) {
68+
resolvePendingWorkDrained();
69+
}
70+
},
71+
});
5372
const sock = getSock();
73+
// The monitor owns async media and delivery work; wait for its drain signal instead of polling.
74+
armed = true;
5475
sock.ev.emit("messages.upsert", upsert);
55-
await waitForMessageCalls(onMessage, 1);
56-
await settleInboundWork();
76+
await pendingWorkDrained;
5777
return { onMessage, listener, sock };
5878
}
5979

test/scripts/kitchen-sink-plugin-assertions.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { describe, expect, it } from "vitest";
1616
const ASSERTIONS_SCRIPT = "scripts/e2e/lib/kitchen-sink-plugin/assertions.mjs";
1717
const BASH_BIN = process.platform === "win32" ? "bash" : "/bin/bash";
1818
const SWEEP_SCRIPT = "scripts/e2e/lib/kitchen-sink-plugin/sweep.sh";
19+
// The shim waits for an explicit log-ready marker; this only bounds a broken fixture process.
20+
const FIXTURE_READY_WAIT_ATTEMPTS = process.env.CI ? 2_000 : 1_000;
1921
const REQUIRED_FULL_DIAGNOSTIC_CANARIES = [
2022
"agent tool result middleware must be a function",
2123
"trusted tool policy registration requires id, description, and evaluate()",
@@ -843,6 +845,7 @@ exit "$status"
843845
const fixtureDir = path.join(scratchRoot, "clawhub-fixture");
844846
const nodeShim = path.join(fakeBin, "node");
845847
const sleepShim = path.join(fakeBin, "sleep");
848+
const fixtureReadyPath = path.join(parent, "fixture-log-ready");
846849
try {
847850
mkdirSync(fakeBin, { recursive: true });
848851
mkdirSync(fixtureDir, { recursive: true });
@@ -853,6 +856,7 @@ exit "$status"
853856
"printf 'DO_NOT_DUMP_CLAWHUB_PREFIX\\n'",
854857
"head -c 2048 /dev/zero | tr '\\0' x",
855858
"printf '\\nFIXTURE_TAIL_MARKER\\n'",
859+
': >"$FIXTURE_READY_PATH"',
856860
"/bin/sleep 30",
857861
"",
858862
].join("\n"),
@@ -862,8 +866,8 @@ exit "$status"
862866
sleepShim,
863867
[
864868
"#!/usr/bin/env bash",
865-
"for _ in $(seq 1 50); do",
866-
' grep -q "FIXTURE_TAIL_MARKER" "$FIXTURE_DIR/clawhub-fixture.log" && exit 0',
869+
'for _ in $(seq 1 "$FIXTURE_READY_WAIT_ATTEMPTS"); do',
870+
' [[ -f "$FIXTURE_READY_PATH" ]] && exit 0',
867871
" /bin/sleep 0.01",
868872
"done",
869873
"exit 1",
@@ -891,6 +895,8 @@ exit "$status"
891895
{
892896
FAKE_BIN: fakeBin,
893897
FIXTURE_DIR: fixtureDir,
898+
FIXTURE_READY_PATH: fixtureReadyPath,
899+
FIXTURE_READY_WAIT_ATTEMPTS: String(FIXTURE_READY_WAIT_ATTEMPTS),
894900
SCRATCH_ROOT: scratchRoot,
895901
},
896902
);

test/scripts/run-vitest.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import {
3131
} from "../../scripts/run-vitest.mjs";
3232

3333
const posixIt = process.platform === "win32" ? it.skip : it;
34+
// These bounds only guard broken fixtures; readiness and exit are asserted via process signals.
35+
const LOAD_SENSITIVE_PROCESS_TIMEOUT_MS = process.env.CI ? 30_000 : 15_000;
3436

3537
describe("scripts/run-vitest", () => {
3638
it("adds --no-maglev to vitest child processes by default", () => {
@@ -659,8 +661,10 @@ describe("scripts/run-vitest", () => {
659661
let descendantPid = 0;
660662

661663
try {
662-
await waitFor(() => fs.existsSync(childPidPath), 10_000);
663-
await waitFor(() => fs.existsSync(descendantPidPath), 10_000);
664+
await waitFor(
665+
() => fs.existsSync(childPidPath) && fs.existsSync(descendantPidPath),
666+
LOAD_SENSITIVE_PROCESS_TIMEOUT_MS,
667+
);
664668
childPid = Number(fs.readFileSync(childPidPath, "utf8"));
665669
descendantPid = Number(fs.readFileSync(descendantPidPath, "utf8"));
666670
expect(Number.isInteger(childPid)).toBe(true);
@@ -670,11 +674,11 @@ describe("scripts/run-vitest", () => {
670674

671675
expect(runner.pid).toBeGreaterThan(0);
672676
process.kill(runner.pid!, "SIGTERM");
673-
const result = await waitForClose(runner);
677+
const result = await waitForClose(runner, LOAD_SENSITIVE_PROCESS_TIMEOUT_MS);
674678

675679
expect(result).toEqual({ code: null, signal: "SIGTERM" });
676-
await waitFor(() => !isProcessAlive(childPid), 5_000);
677-
await waitFor(() => !isProcessAlive(descendantPid), 5_000);
680+
await waitFor(() => !isProcessAlive(childPid), LOAD_SENSITIVE_PROCESS_TIMEOUT_MS);
681+
await waitFor(() => !isProcessAlive(descendantPid), LOAD_SENSITIVE_PROCESS_TIMEOUT_MS);
678682
} finally {
679683
if (runner.pid && isProcessAlive(runner.pid)) {
680684
process.kill(runner.pid, "SIGKILL");

0 commit comments

Comments
 (0)