refactor(test): consolidate benchmark child teardown coverage (#158654)

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Vincent Koc 2026-09-26 14:50:23 +08:00 • committed by GitHub
parent 8f22acdd74
commit 618217c542
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 60 deletions

View file

@ -8,7 +8,6 @@ import path from "node:path";
import { performance } from "node:perf_hooks";
import { beforeAll, describe, expect, it, vi } from "vitest";
import { testing } from "../../scripts/bench-gateway-restart.ts";
import { stopChild } from "../../scripts/lib/gateway-bench-child.ts";
import * as gatewayBenchProbes from "../../scripts/lib/gateway-bench-probes.ts";
import { parseProcessRssKb, requestProbeStatus } from "../../scripts/lib/gateway-bench-probes.ts";
import {
@ -27,7 +26,6 @@ import {
closeOpenClawStateDatabaseForTest,
openOpenClawStateDatabase,
} from "../../src/state/openclaw-state-db.js";
import { registerStopChildBehaviorTests } from "./bench-gateway-child-test-support.js";
type RestartSampleFixture = Parameters<typeof testing.summarizeCase>[1][number];
type ProbeFixture = RestartSampleFixture["initialHealthz"];
@ -469,11 +467,6 @@ node 1234 user 12u IPv4 0t0 TCP localhost:1234
expect(testing.resolveRestartDeadlineFailure(true)).toBe("restart_child_exited");
});
registerStopChildBehaviorTests({
stopChild,
queuedExitCode: 0,
});
it("marks clean and signaled pre-teardown child exits as benchmark failures", () => {
expect(
testing.resolveSampleExitFailure({

View file

@ -8,7 +8,6 @@ import { performance } from "node:perf_hooks";
import { collectConfiguredModelRefs } from "@openclaw/model-catalog-core/configured-model-refs";
import { afterEach, beforeAll, describe, expect, it } from "vitest";
import { testing } from "../../scripts/bench-gateway-startup.ts";
import { stopChild } from "../../scripts/lib/gateway-bench-child.ts";
import {
classifyGatewayReadyLog,
collectOutputLines,
@ -21,7 +20,6 @@ import { isPidAlive } from "../../src/shared/pid-alive.js";
import { waitForPidToExit } from "../../src/test-utils/process-tree.js";
import { runNodeScript } from "../helpers/run-node-script.js";
import { createTempDirTracker, useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";
import { registerStopChildBehaviorTests } from "./bench-gateway-child-test-support.js";
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
@ -659,11 +657,6 @@ server.listen(port, "127.0.0.1", () => {
]);
});
registerStopChildBehaviorTests({
stopChild,
queuedExitCode: 7,
});
it("collects Count-suffixed startup trace metrics", () => {
const startupTrace: Record<string, number> = {};

View file

@ -1,48 +1,35 @@
// Gateway benchmark child test support simulates child process behavior for script tests.
import type { ChildProcess } from "node:child_process";
import { EventEmitter } from "node:events";
import { expect, it, vi } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { stopChild } from "../../scripts/lib/gateway-bench-child.ts";
type StopChildResult = {
exitedBeforeTeardown: boolean;
exitCode: number | null;
signal: string | null;
};
describe("gateway benchmark child teardown", () => {
it.each([0, 7])(
"classifies queued child exit %i before sending teardown signals",
async (exitCode) => {
const child = new EventEmitter() as EventEmitter & {
exitCode: number | null;
kill: ReturnType<typeof vi.fn>;
signalCode: NodeJS.Signals | null;
};
child.exitCode = null;
child.signalCode = null;
child.kill = vi.fn(() => true);
type StopChild<TChild> = (
child: TChild,
options?: {
killGraceMs?: number;
teardownGraceMs?: number;
},
) => Promise<StopChildResult>;
const stopped = stopChild(child as unknown as ChildProcess);
queueMicrotask(() => {
child.exitCode = exitCode;
child.emit("exit", exitCode, null);
});
export function registerStopChildBehaviorTests<TChild>(params: {
stopChild: StopChild<TChild>;
queuedExitCode: number;
}) {
it("classifies queued child exits before sending teardown signals", async () => {
const child = new EventEmitter() as EventEmitter & {
exitCode: number | null;
kill: ReturnType<typeof vi.fn>;
signalCode: NodeJS.Signals | null;
};
child.exitCode = null;
child.signalCode = null;
child.kill = vi.fn(() => true);
const stopped = params.stopChild(child as unknown as TChild);
queueMicrotask(() => {
child.exitCode = params.queuedExitCode;
child.emit("exit", params.queuedExitCode, null);
});
await expect(stopped).resolves.toEqual({
exitedBeforeTeardown: true,
exitCode: params.queuedExitCode,
signal: null,
});
expect(child.kill).not.toHaveBeenCalled();
});
await expect(stopped).resolves.toEqual({
exitedBeforeTeardown: true,
exitCode,
signal: null,
});
expect(child.kill).not.toHaveBeenCalled();
},
);
it("classifies failed teardown signaling as a pre-teardown child exit", async () => {
const child = new EventEmitter() as EventEmitter & {
@ -60,7 +47,7 @@ export function registerStopChildBehaviorTests<TChild>(params: {
return false;
});
await expect(params.stopChild(child as unknown as TChild)).resolves.toEqual({
await expect(stopChild(child as unknown as ChildProcess)).resolves.toEqual({
exitedBeforeTeardown: true,
exitCode: 8,
signal: null,
@ -89,7 +76,7 @@ export function registerStopChildBehaviorTests<TChild>(params: {
child.unref = vi.fn();
await expect(
params.stopChild(child as unknown as TChild, {
stopChild(child as unknown as ChildProcess, {
killGraceMs: 1,
teardownGraceMs: 1,
}),
@ -142,7 +129,7 @@ export function registerStopChildBehaviorTests<TChild>(params: {
return true;
});
try {
const stopped = params.stopChild(child as unknown as TChild, {
const stopped = stopChild(child as unknown as ChildProcess, {
killGraceMs: 50,
teardownGraceMs: 1,
});
@ -212,7 +199,7 @@ export function registerStopChildBehaviorTests<TChild>(params: {
});
try {
await expect(
params.stopChild(child as unknown as TChild, {
stopChild(child as unknown as ChildProcess, {
killGraceMs: 50,
teardownGraceMs: 1,
}),
@ -233,4 +220,4 @@ export function registerStopChildBehaviorTests<TChild>(params: {
}
},
);
}
});