mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
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.
This commit is contained in:
@@ -446,7 +446,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DSH_COVERAGE_MAX_WORKERS: '6'
|
DSH_COVERAGE_MAX_WORKERS: '6'
|
||||||
DSH_COVERAGE_PARTITIONS: '4'
|
DSH_COVERAGE_PARTITIONS: '4'
|
||||||
DSH_COVERAGE_TEST_TIMEOUT_MS: '30000'
|
DSH_COVERAGE_TEST_TIMEOUT_MS: '90000'
|
||||||
DSH_GATE_CONCURRENCY: '3'
|
DSH_GATE_CONCURRENCY: '3'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
@@ -505,7 +505,7 @@ jobs:
|
|||||||
run: >-
|
run: >-
|
||||||
pnpm exec vitest run
|
pnpm exec vitest run
|
||||||
--no-file-parallelism
|
--no-file-parallelism
|
||||||
--testTimeout 30000
|
--testTimeout 90000
|
||||||
packages/shell/tool-pwsh/tests/loader.spec.ts
|
packages/shell/tool-pwsh/tests/loader.spec.ts
|
||||||
packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts
|
packages/workflow/workflow-worker-thread/tests/workflow-worker-thread.spec.ts
|
||||||
packages/workflow/tool-ralph/tests/integration.spec.ts
|
packages/workflow/tool-ralph/tests/integration.spec.ts
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => {
|
|||||||
expect(result.error).toContain('raced the completion')
|
expect(result.error).toContain('raced the completion')
|
||||||
expect(narration).toEqual(['started'])
|
expect(narration).toEqual(['started'])
|
||||||
await handle.dispose()
|
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 () => {
|
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 } })
|
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)
|
expect(provider.runs[0]!.disposeCalls).toBe(1)
|
||||||
await handle.dispose()
|
await handle.dispose()
|
||||||
await ctx.fiber.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 () => {
|
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({
|
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)
|
expect(provider.runs[0]!.disposed).toBe(true)
|
||||||
const result = await handle.result
|
const result = await handle.result
|
||||||
expect(result.stopReason).toBe('cancelled')
|
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 () => {
|
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 })
|
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.
|
// can finalize its state at run-end without dangling agents.
|
||||||
expect(order.indexOf('run-end')).toBe(order.length - 1)
|
expect(order.indexOf('run-end')).toBe(order.length - 1)
|
||||||
await handle.dispose()
|
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 () => {
|
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 })
|
const { ctx, parent, provider } = await setup({ manual: true })
|
||||||
@@ -1305,7 +1305,7 @@ describe('dsh-workflow-worker-thread', { timeout: 120_000 }, () => {
|
|||||||
await Promise.resolve()
|
await Promise.resolve()
|
||||||
expect(result.stopReason).toBe('error')
|
expect(result.stopReason).toBe('error')
|
||||||
await handle.dispose()
|
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 () => {
|
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 })
|
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)
|
expect(provider.runs[0]!.disposed).toBe(true)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
await handle.dispose()
|
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 () => {
|
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 })
|
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)
|
expect(order.indexOf('run-end')).toBe(order.length - 1)
|
||||||
await handle.dispose()
|
await handle.dispose()
|
||||||
}, 15_000)
|
}, 90_000)
|
||||||
|
|
||||||
it('a dispose ack racing the worker death is dropped, not crashed (post after exit)', async () => {
|
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
|
// 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).
|
// tight explicit bound (see the helper's doc comment).
|
||||||
await waitFor(() => { expect(provider.runs[0]!.disposed).toBe(true) }, 1000)
|
await waitFor(() => { expect(provider.runs[0]!.disposed).toBe(true) }, 1000)
|
||||||
await handle.dispose()
|
await handle.dispose()
|
||||||
}, 15_000)
|
}, 90_000)
|
||||||
|
|
||||||
it('a worker death AFTER a cancel reports cancelled, not error', async () => {
|
it('a worker death AFTER a cancel reports cancelled, not error', async () => {
|
||||||
const { ctx, parent } = await setup({ config: { provider: 'stub', disposeGraceMs: 60_000 } })
|
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.stopReason).toBe('cancelled')
|
||||||
expect(result.error).toContain('stop it')
|
expect(result.error).toContain('stop it')
|
||||||
await handle.dispose()
|
await handle.dispose()
|
||||||
}, process.platform === 'win32' ? 30_000 : 15_000)
|
}, process.platform === 'win32' ? 90_000 : 15_000)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('service API', () => {
|
describe('service API', () => {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ describe('CI workflow', () => {
|
|||||||
))
|
))
|
||||||
const nativeTestCommand = nativeTestCommands.map(step => step.run).join('\n')
|
const nativeTestCommand = nativeTestCommands.map(step => step.run).join('\n')
|
||||||
expect(nativeTestCommand).toContain('--no-file-parallelism')
|
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('tool-pwsh/tests/loader.spec.ts')
|
||||||
expect(nativeTestCommand).toContain('workflow-worker-thread.spec.ts')
|
expect(nativeTestCommand).toContain('workflow-worker-thread.spec.ts')
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ probePromise()
|
|||||||
rm(configPath, { force: true }),
|
rm(configPath, { force: true }),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}, 60_000)
|
}, 90_000)
|
||||||
|
|
||||||
it('runs JavaScript compatibility and nursery rules', async () => {
|
it('runs JavaScript compatibility and nursery rules', async () => {
|
||||||
const suffix = randomUUID()
|
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 }),
|
rm(configPath, { force: true }),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}, 60_000)
|
}, 90_000)
|
||||||
|
|
||||||
it('keeps the complete stylistic contract in Oxlint', async () => {
|
it('keeps the complete stylistic contract in Oxlint', async () => {
|
||||||
const oxlintPath = join(repositoryRoot, '.oxlintrc.json')
|
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 }),
|
rm(configPath, { force: true }),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}, 60_000)
|
}, 90_000)
|
||||||
|
|
||||||
it('accepts an ignored-only staged selection', () => {
|
it('accepts an ignored-only staged selection', () => {
|
||||||
const result = runOxlint([
|
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 })
|
await rm(directory, { recursive: true, force: true })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
60_000,
|
90_000,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user