From b1759c180777e0c6490d0be43e6196d379b2bfb8 Mon Sep 17 00:00:00 2001 From: faizan-oai <269039902+faizan-oai@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:41:10 -0700 Subject: [PATCH] test: preserve Windows CI timeouts in isolated tests --- .../scripts/run-windows-ci-tests.mjs | 23 +++++++---- sdk/typescript/tests-ts/skeleton.test.ts | 41 ++++++++++++++++++- .../tests-ts/support/test-subprocess.ts | 3 +- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/sdk/typescript/scripts/run-windows-ci-tests.mjs b/sdk/typescript/scripts/run-windows-ci-tests.mjs index 83b792e81..6fc1fea6e 100644 --- a/sdk/typescript/scripts/run-windows-ci-tests.mjs +++ b/sdk/typescript/scripts/run-windows-ci-tests.mjs @@ -2,6 +2,9 @@ import { spawn } from "node:child_process"; import { readdir } from "node:fs/promises"; import { fileURLToPath } from "node:url"; +// Native Windows credential and document checks can exceed 30 seconds. +// The workflow still bounds each complete shard to ten minutes. +const testTimeoutMs = "120000"; const testsDirectory = new URL("../tests-ts/", import.meta.url); const packageDirectory = fileURLToPath(new URL("../", import.meta.url)); const tests = (await readdir(testsDirectory)) @@ -71,13 +74,19 @@ const results = await Promise.all( ": " + paths.join(" "), ); - // Native Windows credential and document checks can exceed 30 seconds. - // The workflow still bounds each complete shard to ten minutes. - const child = spawn("bun", ["test", "--timeout", "120000", ...paths], { - cwd: packageDirectory, - stdio: "inherit", - windowsHide: true, - }); + const child = spawn( + "bun", + ["test", "--timeout", testTimeoutMs, ...paths], + { + cwd: packageDirectory, + env: { + ...process.env, + CODEX_SECURITY_TEST_TIMEOUT_MS: testTimeoutMs, + }, + stdio: "inherit", + windowsHide: true, + }, + ); child.once("error", reject); child.once("close", (code) => { resolve(code ?? 1); diff --git a/sdk/typescript/tests-ts/skeleton.test.ts b/sdk/typescript/tests-ts/skeleton.test.ts index d6020a41f..721023b0b 100644 --- a/sdk/typescript/tests-ts/skeleton.test.ts +++ b/sdk/typescript/tests-ts/skeleton.test.ts @@ -1,4 +1,7 @@ -import { readFile } from "node:fs/promises"; +import { spawnSync } from "node:child_process"; +import { mkdtemp, readFile, realpath, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; import { describe, expect, test } from "bun:test"; import { parse } from "smol-toml"; import { @@ -114,6 +117,42 @@ describe("TypeScript package skeleton", () => { expect(ciWorkflow).not.toContain("--timeout 60000"); }); + test("preserves the configured timeout in isolated test subprocesses", async () => { + const directory = await realpath( + await mkdtemp(join(tmpdir(), "codex-security-test-timeout-")), + ); + const fixture = join(directory, "isolated.test.ts"); + const helper = new URL("./support/test-subprocess.ts", import.meta.url) + .href; + await writeFile( + fixture, + `import { test } from "bun:test"; +import { runTestInSubprocess } from ${JSON.stringify(helper)}; +test("isolated timeout", async () => { + if (runTestInSubprocess(import.meta.path, "isolated timeout")) return; + await Bun.sleep(1_000); +}); +`, + ); + + try { + const result = spawnSync( + process.execPath, + ["test", "--timeout", "30000", fixture], + { + encoding: "utf8", + env: { ...process.env, CODEX_SECURITY_TEST_TIMEOUT_MS: "100" }, + timeout: 30_000, + windowsHide: true, + }, + ); + expect(result.status, result.stderr || result.error?.message).toBe(1); + expect(result.stderr).toContain("this test timed out after 100ms"); + } finally { + await rm(directory, { recursive: true, force: true }); + } + }); + test("builds packages without a preinstalled package manager and provides a production audit", async () => { const packageJson = JSON.parse( await readFile(new URL("../package.json", import.meta.url), "utf8"), diff --git a/sdk/typescript/tests-ts/support/test-subprocess.ts b/sdk/typescript/tests-ts/support/test-subprocess.ts index dfe4588f5..c840aa5ee 100644 --- a/sdk/typescript/tests-ts/support/test-subprocess.ts +++ b/sdk/typescript/tests-ts/support/test-subprocess.ts @@ -5,11 +5,12 @@ import { expect } from "bun:test"; export function runTestInSubprocess(file: string, name: string): boolean { const identity = `${file}::${name}`; if (process.env["CODEX_SECURITY_ISOLATED_TEST"] === identity) return false; + const timeout = process.env["CODEX_SECURITY_TEST_TIMEOUT_MS"] ?? "30000"; const pattern = `${name.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}$`; const result = spawnSync( process.execPath, - ["test", "--timeout", "30000", "--test-name-pattern", pattern, file], + ["test", "--timeout", timeout, "--test-name-pattern", pattern, file], { cwd: fileURLToPath(new URL("../../", import.meta.url)), encoding: "utf8",