Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/__tests__/acp-test-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {describe, expect, it} from "vitest";
import {createObjectDump} from "./acp-test-utils";
import {createTestFixture, createObjectDump} from "./acp-test-utils";

describe("createObjectDump anonymizer", () => {
it("anonymizes both direct keys and dotted paths", () => {
Expand Down Expand Up @@ -33,3 +33,16 @@ describe("createObjectDump anonymizer", () => {
expect(parsed.items[1].secret).toBe("second-item");
});
});


describe("native fixture cleanup", () => {
let previous: ReturnType<typeof createTestFixture>;
it("owns a running app-server for the current test", async () => {
previous = createTestFixture();
await previous.getCodexAcpAgent().initialize({protocolVersion: 1});
expect(previous.getCodexAcpAgent()["getExitCode"]()).toBeNull();
});
it("does not leave the preceding test app-server alive", () => {
expect(previous.getCodexAcpAgent()["getExitCode"]()).not.toBeNull();
});
});
23 changes: 22 additions & 1 deletion src/__tests__/acp-test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import fs from "node:fs";
import os from "node:os";
import {AgentMode} from "../AgentMode";
import {DEFAULT_COLLABORATION_MODE} from "../CollaborationModeConfig";
import {expect, vi} from "vitest";
import {afterEach, expect, vi} from "vitest";
import type {Model, ReasoningEffortOption} from "../app-server/v2";
import {CodexSubagentEventRouter} from "../subagents/CodexSubagentEventRouter";
import {CodexEventHandler} from "../CodexEventHandler";
Expand Down Expand Up @@ -189,6 +189,13 @@ export function createBaseTestFixture(config: ConnectionConfig): TestFixture {
* Creates a test fixture with a real Codex connection.
* Use for integration tests that need to interact with the actual Codex binary.
*/
const nativeFixtureCleanup = new Set<() => Promise<void>>();
afterEach(async () => {
const pending = [...nativeFixtureCleanup];
nativeFixtureCleanup.clear();
await Promise.all(pending.map(cleanup => cleanup()));
});

export function createTestFixture(): TestFixture {
const pathToCodex = path.resolve(process.cwd(), "node_modules", ".bin", process.platform === 'win32' ? "codex.cmd" : "codex");
if (!fs.existsSync(pathToCodex)) {
Expand All @@ -200,6 +207,20 @@ export function createTestFixture(): TestFixture {
...process.env,
CODEX_HOME: codexHome,
});
// Real fixtures previously accumulated app-servers until the worker exited,
// starving later initialize requests and making unrelated commands time out.
nativeFixtureCleanup.add(async () => {
if (codexConnection.process.exitCode !== null || codexConnection.process.signalCode !== null) return;
const exited = new Promise<void>(resolve => codexConnection.process.once("exit", () => resolve()));
const deadline = setTimeout(() => codexConnection.process.kill("SIGKILL"), 2000);
try {
codexConnection.process.stdin.end();
await exited;
} finally {
clearTimeout(deadline);
codexConnection.connection.dispose();
}
});
codexConnection.process.on("exit", () => {
removeDirectoryWithRetry(codexHome);
});
Expand Down