From fdafa67ff16af83677a22bb0ede3461e6253a9b1 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 25 May 2026 03:12:19 +0800 Subject: [PATCH] test: make codex unavailable checks deterministic --- internal/cloud/server.test.mjs | 35 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/internal/cloud/server.test.mjs b/internal/cloud/server.test.mjs index 94294b3f..30121640 100644 --- a/internal/cloud/server.test.mjs +++ b/internal/cloud/server.test.mjs @@ -58,6 +58,14 @@ function assertCodexStdioFeasibilityBlocker(value, label = "codex stdio blocker" assert.equal(CODEX_STDIO_FEASIBILITY_BLOCKERS.has(value), true, `${label}: ${value}`); } +function missingCodexCommandEnv(overrides = {}) { + return { + PATH: "", + HWLAB_CODE_AGENT_CODEX_COMMAND: path.join(os.tmpdir(), `hwlab-${process.pid}-missing-codex`), + ...overrides + }; +} + test("cloud api exposes /health, /health/live, and /live probes", async () => { const originalUrl = process.env.HWLAB_CLOUD_DB_URL; const originalSslMode = process.env.HWLAB_CLOUD_DB_SSL_MODE; @@ -1701,12 +1709,12 @@ test("cloud api /v1 describes Code Agent provider blocker without leaking secret test("cloud api /v1 describes Code Agent egress blocker without leaking API key", async () => { const server = createCloudApiServer({ - env: { + env: missingCodexCommandEnv({ OPENAI_API_KEY: "test-openai-key-material", HWLAB_CODE_AGENT_PROVIDER: "codex-stdio", HWLAB_CODE_AGENT_MODEL: "gpt-test", HWLAB_CODE_AGENT_OPENAI_BASE_URL: "https://api.openai.com/v1/responses" - } + }) }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); @@ -1907,6 +1915,7 @@ test("cloud api health blocks full Code Agent readiness when Codex stdio command test("cloud api /v1/agent/chat refuses provider stub when Codex stdio is unavailable", async () => { let providerCalled = false; const server = createCloudApiServer({ + env: missingCodexCommandEnv(), callCodeAgentProvider: async () => { providerCalled = true; throw new Error("provider stub must not be used"); @@ -3621,10 +3630,9 @@ test("cloud api /v1/agent/chat does not use read-only conversation facts as fall test("cloud api /v1/agent/chat blocks forbidden file paths without leaking values", async () => { const workspace = await mkdtemp(path.join(os.tmpdir(), "hwlab-agent-file-block-")); const server = createCloudApiServer({ - env: { - PATH: process.env.PATH, + env: missingCodexCommandEnv({ HWLAB_CODE_AGENT_WORKSPACE: workspace - } + }) }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); @@ -4084,13 +4092,13 @@ test("cloud api /v1/agent/chat ignores OpenAI fallback and blocks when Codex std const providerPort = providerServer.address().port; const server = createCloudApiServer({ - env: { + env: missingCodexCommandEnv({ OPENAI_API_KEY: "test-openai-key-material", HWLAB_CODE_AGENT_PROVIDER: "openai", HWLAB_CODE_AGENT_ALLOW_TEXT_FALLBACK: "true", HWLAB_CODE_AGENT_MODEL: "gpt-test", HWLAB_CODE_AGENT_OPENAI_BASE_URL: `http://127.0.0.1:${providerPort}/v1/responses` - } + }) }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); @@ -4185,13 +4193,13 @@ test("cloud api /v1/agent/chat does not call delayed provider fallback beyond le test("cloud api /v1/agent/chat skips delayed provider fallback when Codex stdio is unavailable", async () => { let providerCalled = false; const server = createCloudApiServer({ - env: { + env: missingCodexCommandEnv({ OPENAI_API_KEY: "test-openai-key-material", HWLAB_CODE_AGENT_PROVIDER: "openai", HWLAB_CODE_AGENT_ALLOW_TEXT_FALLBACK: "true", HWLAB_CODE_AGENT_MODEL: "gpt-test", HWLAB_CODE_AGENT_OPENAI_BASE_URL: "http://127.0.0.1/provider-fixture" - }, + }), callCodeAgentProvider: async ({ providerPlan }) => { providerCalled = true; await delay(4600); @@ -4250,13 +4258,13 @@ test("cloud api /v1/agent/chat reports Codex stdio blocker instead of provider t const providerPort = providerServer.address().port; const server = createCloudApiServer({ - env: { + env: missingCodexCommandEnv({ OPENAI_API_KEY: "test-openai-key-material", HWLAB_CODE_AGENT_PROVIDER: "openai", HWLAB_CODE_AGENT_ALLOW_TEXT_FALLBACK: "true", HWLAB_CODE_AGENT_MODEL: "gpt-test", HWLAB_CODE_AGENT_OPENAI_BASE_URL: `http://127.0.0.1:${providerPort}/v1/responses` - }, + }), codeAgentTimeoutMs: 50 }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); @@ -4311,13 +4319,13 @@ test("cloud api /v1/agent/chat does not call OpenAI provider 502/503 fallback", const providerPort = providerServer.address().port; const server = createCloudApiServer({ - env: { + env: missingCodexCommandEnv({ OPENAI_API_KEY: "test-openai-key-material", HWLAB_CODE_AGENT_PROVIDER: "openai", HWLAB_CODE_AGENT_ALLOW_TEXT_FALLBACK: "true", HWLAB_CODE_AGENT_MODEL: "gpt-test", HWLAB_CODE_AGENT_OPENAI_BASE_URL: `http://127.0.0.1:${providerPort}/v1/responses` - } + }) }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); @@ -4421,6 +4429,7 @@ function delay(ms) { test("cloud api /v1/agent/chat does not call empty provider text fallback", async () => { let providerCalled = false; const server = createCloudApiServer({ + env: missingCodexCommandEnv(), callCodeAgentProvider: async () => { providerCalled = true; throw new Error("empty provider fallback must not be used");