Files
oh-my-pi/packages/coding-agent/test/eval/process-entry-import.test.ts
T
Larry Gordon 959ad3451f fix(test): gave CLI-spawning tests explicit timeouts
Four tests spawn the full CLI entry graph (or compile a standalone binary)
and declared no timeout, so they inherited Bun's 5s default. Spawning
`src/cli.ts` costs ~900ms warm on a fast machine and ~3.1s cold, so the
budget is spent almost entirely on transpile. When CI runs the native
bucket with OMP_TEST_CONCURRENCY=4, a cold spawn on a contended runner
crosses 5s and the test fails with `timed out after 5000ms` plus a
trailing `killed 1 dangling process` - the subprocess was still alive when
the timeout fired.

Reproduced locally by oversubscribing the box (48 concurrent runs of the
same chunk): 48/48 failed with the identical signature, while 4-way
concurrency - what CI actually configures - passed every time. Only the
subprocess tests starve; the pure-unit tests in the same files pass.

Timeouts are sized to the work, matching existing subprocess tests
(read-cli-mcp-resource 30_000, acp-stdout-hygiene 60_000): 30s for CLI
spawns, 60s for the `bun build --compile` case. After the change, 64
concurrent runs of all three files produce zero timeouts.

`profile-cli.test.ts` gets the timeout on both spawn tests. Only the first
was observed failing, because it warms the transpile cache for its
sibling - that ordering is incidental and would flake if it changed.

These are drift and wiring assertions, not latency assertions, so a
generous ceiling costs nothing on a healthy run.
2026-07-30 11:27:10 -07:00

142 lines
5.2 KiB
TypeScript

import { expect, it } from "bun:test";
import * as fs from "node:fs";
import * as path from "node:path";
import { TempDir } from "@oh-my-pi/pi-utils";
it("imports the CLI entry graph without loading dotenv before profile bootstrap", async () => {
using tempDir = TempDir.createSync("@omp-js-process-import-");
await Bun.write(path.join(tempDir.path(), ".env"), "OMP_PROCESS_ENTRY_ENV_PROBE=loaded-too-early\n");
const env = Object.fromEntries(
Object.entries(process.env).filter((entry): entry is [string, string] => typeof entry[1] === "string"),
);
delete env.OMP_PROCESS_ENTRY_ENV_PROBE;
env.HOME = tempDir.path();
const fixture = path.resolve(import.meta.dir, "../fixtures/js-process-entry-import.ts");
const proc = Bun.spawn([process.execPath, fixture], {
env,
stdout: "pipe",
stderr: "pipe",
});
const [exitCode, stdout, stderr] = await Promise.all([
proc.exited,
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
]);
expect(exitCode).toBe(0);
expect(stdout).toBe("");
expect(stderr).toBe("");
});
async function pingComputerWorker(
entry: string,
id: string,
argv: string[] = ["__omp_worker_computer"],
): Promise<unknown> {
const worker = new Worker(entry, {
type: "module",
argv,
});
const response = Promise.withResolvers<unknown>();
worker.addEventListener("message", event => response.resolve(event.data));
worker.addEventListener("error", event => response.reject(event.error ?? new Error(event.message)));
worker.postMessage({ type: "ping", id });
try {
return await response.promise;
} finally {
worker.terminate();
}
}
it("starts ordinary CLI paths without loading the native computer addon", async () => {
const cliPath = path.resolve(import.meta.dir, "../../src/cli.ts");
for (const args of [
["--no-addons", cliPath, "--version"],
[cliPath, "--help"],
]) {
const proc = Bun.spawn([process.execPath, ...args], {
stdout: "pipe",
stderr: "pipe",
});
const [exitCode, stderr] = await Promise.all([proc.exited, new Response(proc.stderr).text()]);
expect(exitCode, `${args.at(-1)}: ${stderr}`).toBe(0);
}
// Two cold CLI spawns (`--version`, `--help`) per run; the assertion is the exit
// code, not the wall time.
}, 30_000);
it("dispatches the computer worker through the CLI host selector in a child process", async () => {
const fixture = path.resolve(import.meta.dir, "../fixtures/computer-worker-cli-selector.ts");
const proc = Bun.spawn([process.execPath, "--no-addons", fixture], {
stdout: "pipe",
stderr: "pipe",
});
const [exitCode, stdout, stderr] = await Promise.all([
proc.exited,
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
]);
expect(exitCode, stderr).toBe(0);
expect(stdout).toBe('{"type":"pong","id":"computer-cli-selector"}\n');
});
it("loads the computer worker module directly outside a declared CLI host", async () => {
const entry = new URL("../../src/tools/computer/worker-entry.ts", import.meta.url).href;
const response = await pingComputerWorker(entry, "computer-direct-module", []);
expect(response).toEqual({ type: "pong", id: "computer-direct-module" });
});
it("dispatches the computer worker from a single npm-style host bundle", async () => {
const packageDir = path.resolve(import.meta.dir, "../..");
const outDir = fs.mkdtempSync(path.join(packageDir, ".computer-worker-bundle-"));
try {
const output = await Bun.build({
entrypoints: [path.join(packageDir, "test/fixtures/computer-worker-bundled-host.ts")],
outdir: outDir,
naming: "cli.js",
target: "bun",
external: ["@oh-my-pi/pi-natives"],
define: { "process.env.PI_BUNDLED": JSON.stringify("true") },
throw: false,
});
expect(output.logs).toEqual([]);
expect(output.outputs.map(file => path.basename(file.path))).toEqual(["cli.js"]);
const response = await pingComputerWorker(output.outputs[0]!.path, "computer-npm-bundle");
expect(response).toEqual({ type: "pong", id: "computer-npm-bundle" });
} finally {
fs.rmSync(outDir, { recursive: true, force: true });
}
});
it("keeps non-computer selectors isolated in a compiled single-entry worker host", async () => {
using tempDir = TempDir.createSync("@omp-compiled-worker-selector-");
const packageDir = path.resolve(import.meta.dir, "../..");
const outfile = path.join(tempDir.path(), process.platform === "win32" ? "worker-host.exe" : "worker-host");
const build = Bun.spawn(
[
process.execPath,
"build",
"--compile",
"--target=bun",
`--outfile=${outfile}`,
path.join(packageDir, "test/fixtures/compiled-worker-selector-host.ts"),
],
{ cwd: packageDir, stdout: "pipe", stderr: "pipe" },
);
const [buildExitCode, buildStderr] = await Promise.all([build.exited, new Response(build.stderr).text()]);
expect(buildExitCode, buildStderr).toBe(0);
const proc = Bun.spawn([outfile], {
cwd: packageDir,
stdout: "pipe",
stderr: "pipe",
});
const [exitCode, stdout, stderr] = await Promise.all([
proc.exited,
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
]);
expect(exitCode, stderr).toBe(0);
expect(stdout).toBe('{"ok":true,"kind":"pong"}\n');
// Compiles a standalone binary with `bun build --compile` before running it, so
// this needs the same headroom as the other compile-backed tests.
}, 60_000);