























@@ -1,3 +1,4 @@
1+import { EventEmitter } from "node:events";
12import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
23import { tmpdir } from "node:os";
34import path from "node:path";
@@ -15,6 +16,7 @@ import {
1516runCommand,
1617sampleProcess,
1718sampleWindowsProcessByPort,
19+stopGateway,
1820summarizeProcessSamples,
1921usesBuiltOpenClawEntry,
2022} from "../../scripts/e2e/kitchen-sink-rpc-walk.mjs";
@@ -39,6 +41,36 @@ describe("kitchen-sink RPC isolated state", () => {
3941});
4042});
414344+describe("kitchen-sink RPC gateway teardown", () => {
45+it("releases gateway handles when the process ignores teardown signals", async () => {
46+const child = new EventEmitter() as EventEmitter & {
47+exitCode: number | null;
48+kill: ReturnType<typeof vi.fn>;
49+signalCode: NodeJS.Signals | null;
50+stderr: { destroy: ReturnType<typeof vi.fn> };
51+stdin: { destroy: ReturnType<typeof vi.fn> };
52+stdout: { destroy: ReturnType<typeof vi.fn> };
53+unref: ReturnType<typeof vi.fn>;
54+};
55+child.exitCode = null;
56+child.signalCode = null;
57+child.kill = vi.fn(() => true);
58+child.stderr = { destroy: vi.fn() };
59+child.stdin = { destroy: vi.fn() };
60+child.stdout = { destroy: vi.fn() };
61+child.unref = vi.fn();
62+63+await stopGateway(child, { killGraceMs: 1, teardownGraceMs: 1 });
64+65+expect(child.kill).toHaveBeenNthCalledWith(1, "SIGTERM");
66+expect(child.kill).toHaveBeenNthCalledWith(2, "SIGKILL");
67+expect(child.stdin.destroy).toHaveBeenCalledOnce();
68+expect(child.stdout.destroy).toHaveBeenCalledOnce();
69+expect(child.stderr.destroy).toHaveBeenCalledOnce();
70+expect(child.unref).toHaveBeenCalledOnce();
71+});
72+});
73+4274describe("kitchen-sink RPC command output capture", () => {
4375it("keeps a bounded tail and tracks truncated output", () => {
4476const first = appendBoundedOutput({ text: "", truncatedChars: 0 }, "abcdef", 5);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。