From 84692044af90811536380a8be16c00d0e99624c0 Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Wed, 26 Aug 2026 17:17:47 +0800 Subject: [PATCH] test: raise the contended Windows spawn budgets to 90s The per-case 15-30s budgets on the Windows native and coverage lanes fire before oxlint, workflow-worker-thread, and other subprocess-spawning cases finish under the loaded self-hosted pool; the failures rotate across cases as load shifts, so per-case widening only moved the flake. Raise the lane defaults (DSH_COVERAGE_TEST_TIMEOUT_MS and the native --testTimeout) to 90s, align the oxlint and workflow-worker-thread case budgets, and keep the built-bin SPAWN_TIMEOUT_MS at 60s under a 90s outer budget. --- .github/workflows/ci.yml | 4 ++-- .../tests/workflow-worker-thread.spec.ts | 18 +++++++++--------- scripts/ci-workflow.spec.ts | 2 +- scripts/oxlint-contract.spec.ts | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d9b3e5925..45d345b9a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -446,7 +446,7 @@ jobs: env: DSH_COVERAGE_MAX_WORKERS: '6' DSH_COVERAGE_PARTITIONS: '4' - DSH_COVERAGE_TEST_TIMEOUT_MS: '30000' + DSH_COVERAGE_TEST_TIMEOUT_MS: '90000' DSH_GATE_CONCURRENCY: '3' steps: - uses: actions/checkout@v6 @@ -505,7 +505,7 @@ jobs: run: >- pnpm exec vitest run --no-file-parallelism - --testTimeout 30000 + --testTimeout 90000 packages/shell/tool-pwsh/tests/loader.spec.ts packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts packages/workflow/tool-ralph/tests/integration.spec.ts diff --git a/packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts b/packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts index acd2702dab..7ed206e934 100644 --- a/packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts +++ b/packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts @@ -787,7 +787,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { expect(result.error).toContain('raced the completion') expect(narration).toEqual(['started']) await handle.dispose() - }, 15_000) + }, 90_000) it('cancel() force-settles a script parked on a promise no hook owns, and TERMINATES its worker', async () => { const { ctx, parent } = await setup({ config: { provider: 'stub', disposeGraceMs: 50 } }) @@ -1027,7 +1027,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { expect(provider.runs[0]!.disposeCalls).toBe(1) await handle.dispose() await ctx.fiber.dispose() - }, 15_000) + }, 90_000) it('dispose() on a wedged worker host-drives child disposal inside the grace: it returns with the children DISPOSED, not with their teardown still in flight', async () => { const { ctx, parent, provider } = await setup({ @@ -1062,7 +1062,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { expect(provider.runs[0]!.disposed).toBe(true) const result = await handle.result expect(result.stopReason).toBe('cancelled') - }, 15_000) + }, 90_000) it('a live child disposed by the dispose() drive is disposed ONCE, and the worker\'s late dispose RPC still gets its ack (the script settles, not the grace)', async () => { const { ctx, parent, provider } = await setup({ manual: true }) @@ -1127,7 +1127,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { // can finalize its state at run-end without dangling agents. expect(order.indexOf('run-end')).toBe(order.length - 1) await handle.dispose() - }, 15_000) + }, 90_000) it('graceful cancellation keeps pairing worker-authored: exactly one agent-end per start, nothing synthesized on top', async () => { const { ctx, parent, provider } = await setup({ manual: true }) @@ -1305,7 +1305,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { await Promise.resolve() expect(result.stopReason).toBe('error') await handle.dispose() - }, 15_000) + }, 90_000) it('an uncaught exception inside the worker surfaces as an error result and reaps the in-flight child', async () => { const { ctx, parent, provider } = await setup({ manual: true }) @@ -1331,7 +1331,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { expect(provider.runs[0]!.disposed).toBe(true) }, 1000) await handle.dispose() - }, 15_000) + }, 90_000) it('a worker death pairs every stranded start: the synthesized cancelled agent-end precedes the error workflow/end', async () => { const { ctx, parent, provider } = await setup({ manual: true }) @@ -1366,7 +1366,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { ]) expect(order.indexOf('run-end')).toBe(order.length - 1) await handle.dispose() - }, 15_000) + }, 90_000) it('a dispose ack racing the worker death is dropped, not crashed (post after exit)', async () => { // Slow child disposal: the ack resolves only AFTER the worker died, so @@ -1395,7 +1395,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { // tight explicit bound (see the helper's doc comment). await waitFor(() => { expect(provider.runs[0]!.disposed).toBe(true) }, 1000) await handle.dispose() - }, 15_000) + }, 90_000) it('a worker death AFTER a cancel reports cancelled, not error', async () => { const { ctx, parent } = await setup({ config: { provider: 'stub', disposeGraceMs: 60_000 } }) @@ -1421,7 +1421,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => { expect(result.stopReason).toBe('cancelled') expect(result.error).toContain('stop it') await handle.dispose() - }, process.platform === 'win32' ? 30_000 : 15_000) + }, process.platform === 'win32' ? 90_000 : 15_000) }) describe('service API', () => { diff --git a/scripts/ci-workflow.spec.ts b/scripts/ci-workflow.spec.ts index 7c0b762bdc..f9c8269903 100644 --- a/scripts/ci-workflow.spec.ts +++ b/scripts/ci-workflow.spec.ts @@ -134,7 +134,7 @@ describe('CI workflow', () => { )) const nativeTestCommand = nativeTestCommands.map(step => step.run).join('\n') expect(nativeTestCommand).toContain('--no-file-parallelism') - expect(nativeTestCommand).toContain('--testTimeout 30000') + expect(nativeTestCommand).toContain('--testTimeout 90000') expect(nativeTestCommand).toContain('tool-pwsh/tests/loader.spec.ts') expect(nativeTestCommand).toContain('workflow-worker-thread.spec.ts') diff --git a/scripts/oxlint-contract.spec.ts b/scripts/oxlint-contract.spec.ts index 24fbbd4af0..1141067ad2 100644 --- a/scripts/oxlint-contract.spec.ts +++ b/scripts/oxlint-contract.spec.ts @@ -105,7 +105,7 @@ probePromise() rm(configPath, { force: true }), ]) } - }, 60_000) + }, 90_000) it('runs JavaScript compatibility and nursery rules', async () => { const suffix = randomUUID() @@ -152,7 +152,7 @@ export const longProbe = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + rm(configPath, { force: true }), ]) } - }, 60_000) + }, 90_000) it('keeps the complete stylistic contract in Oxlint', async () => { const oxlintPath = join(repositoryRoot, '.oxlintrc.json') @@ -252,7 +252,7 @@ export const longProbe = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + rm(configPath, { force: true }), ]) } - }, 60_000) + }, 90_000) it('accepts an ignored-only staged selection', () => { const result = runOxlint([ @@ -371,6 +371,6 @@ export const longProbe = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + await rm(directory, { recursive: true, force: true }) } }, - 60_000, + 90_000, ) })