From 734748d4f4fef7436def57f7a7ae3350bba9a091 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 25 Apr 2026 01:29:11 -0700 Subject: [PATCH] fix(test): cap native worker pools for serial Vitest --- scripts/run-vitest.mjs | 32 +++++++++++++++++++++++- scripts/test-projects.test-support.mjs | 6 ++++- test/scripts/run-vitest.test.ts | 34 ++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/scripts/run-vitest.mjs b/scripts/run-vitest.mjs index bc3645cc3c0..6dc435f8895 100644 --- a/scripts/run-vitest.mjs +++ b/scripts/run-vitest.mjs @@ -40,12 +40,42 @@ export function resolveVitestNoOutputTimeoutMs(env = process.env) { export function resolveVitestSpawnParams(env = process.env, platform = process.platform) { return { - env, + env: resolveVitestSpawnEnv(env), detached: shouldUseDetachedVitestProcessGroup(platform), stdio: ["inherit", "pipe", "pipe"], }; } +export function resolveVitestSpawnEnv(env = process.env) { + if (!shouldApplyNativeWorkerBudget(env)) { + return env; + } + + const nativeWorkerCount = String(resolveNativeWorkerCount(env)); + return { + ...env, + RAYON_NUM_THREADS: env.RAYON_NUM_THREADS?.trim() || nativeWorkerCount, + TOKIO_WORKER_THREADS: env.TOKIO_WORKER_THREADS?.trim() || nativeWorkerCount, + }; +} + +function shouldApplyNativeWorkerBudget(env) { + if (env.RAYON_NUM_THREADS?.trim() && env.TOKIO_WORKER_THREADS?.trim()) { + return false; + } + return ( + env.OPENCLAW_TEST_PROJECTS_SERIAL === "1" || resolveExplicitVitestWorkerBudget(env) !== null + ); +} + +function resolveNativeWorkerCount(env) { + return Math.min(resolveExplicitVitestWorkerBudget(env) ?? 1, 4); +} + +function resolveExplicitVitestWorkerBudget(env) { + return parsePositiveInt(env.OPENCLAW_VITEST_MAX_WORKERS ?? env.OPENCLAW_TEST_WORKERS); +} + export function shouldSuppressVitestStderrLine(line) { return SUPPRESSED_VITEST_STDERR_PATTERNS.some((pattern) => line.includes(pattern)); } diff --git a/scripts/test-projects.test-support.mjs b/scripts/test-projects.test-support.mjs index e8baedd4d3a..8647dec29a6 100644 --- a/scripts/test-projects.test-support.mjs +++ b/scripts/test-projects.test-support.mjs @@ -230,7 +230,11 @@ const TOOLING_SOURCE_TEST_TARGETS = new Map([ ["scripts/lib/vitest-local-scheduling.mjs", ["test/scripts/vitest-local-scheduling.test.ts"]], [ "scripts/run-vitest.mjs", - ["test/scripts/test-projects.test.ts", "test/scripts/vitest-local-scheduling.test.ts"], + [ + "test/scripts/run-vitest.test.ts", + "test/scripts/test-projects.test.ts", + "test/scripts/vitest-local-scheduling.test.ts", + ], ], ["scripts/run-oxlint.mjs", ["test/scripts/run-oxlint.test.ts"]], ["scripts/test-extension-batch.mjs", ["test/scripts/test-extension.test.ts"]], diff --git a/test/scripts/run-vitest.test.ts b/test/scripts/run-vitest.test.ts index 028f34dbfee..1088ffcc05d 100644 --- a/test/scripts/run-vitest.test.ts +++ b/test/scripts/run-vitest.test.ts @@ -58,6 +58,40 @@ describe("scripts/run-vitest", () => { }); }); + it("caps native Rust worker pools for serial Vitest runs", () => { + expect( + resolveVitestSpawnParams( + { + OPENCLAW_TEST_PROJECTS_SERIAL: "1", + PATH: "/usr/bin", + }, + "darwin", + ).env, + ).toMatchObject({ + OPENCLAW_TEST_PROJECTS_SERIAL: "1", + RAYON_NUM_THREADS: "1", + TOKIO_WORKER_THREADS: "1", + }); + }); + + it("keeps explicit native Rust worker pool settings", () => { + expect( + resolveVitestSpawnParams( + { + OPENCLAW_VITEST_MAX_WORKERS: "2", + PATH: "/usr/bin", + RAYON_NUM_THREADS: "8", + TOKIO_WORKER_THREADS: "6", + }, + "darwin", + ).env, + ).toMatchObject({ + OPENCLAW_VITEST_MAX_WORKERS: "2", + RAYON_NUM_THREADS: "8", + TOKIO_WORKER_THREADS: "6", + }); + }); + it("suppresses rolldown plugin timing noise while keeping other stderr intact", () => { expect( shouldSuppressVitestStderrLine(