Skip to content

Commit 0ddf722

Browse files
authored
feat: process timeout to log names of stuck test files (#3031)
1 parent c7f0c86 commit 0ddf722

File tree

5 files changed

+24
-5
lines changed

5 files changed

+24
-5
lines changed

packages/vitest/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
"std-env": "^3.3.1",
138138
"strip-literal": "^1.0.0",
139139
"tinybench": "^2.3.1",
140-
"tinypool": "^0.3.1",
140+
"tinypool": "^0.4.0",
141141
"tinyspy": "^1.0.2",
142142
"vite": "^3.0.0 || ^4.0.0",
143143
"vite-node": "workspace:*",

packages/vitest/src/node/core.ts

+1
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ export class Vitest {
597597
setTimeout(() => {
598598
this.report('onProcessTimeout').then(() => {
599599
console.warn(`close timed out after ${this.config.teardownTimeout}ms`)
600+
this.state.getProcessTimeoutCauses().forEach(cause => console.warn(cause))
600601
process.exit()
601602
})
602603
}, this.config.teardownTimeout).unref()

packages/vitest/src/node/pools/threads.ts

+9
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export function createThreadsPool(ctx: Vitest, { execArgv, env }: PoolProcessOpt
5454

5555
env,
5656
execArgv,
57+
58+
terminateTimeout: ctx.config.teardownTimeout,
5759
}
5860

5961
if (ctx.config.isolate) {
@@ -87,6 +89,13 @@ export function createThreadsPool(ctx: Vitest, { execArgv, env }: PoolProcessOpt
8789
try {
8890
await pool.run(data, { transferList: [workerPort], name })
8991
}
92+
catch (error) {
93+
// Worker got stuck and won't terminate - this may cause process to hang
94+
if (error instanceof Error && /Failed to terminate worker/.test(error.message))
95+
ctx.state.addProcessTimeoutCause(`Failed to terminate worker while running ${files.join(', ')}.`)
96+
else
97+
throw error
98+
}
9099
finally {
91100
port.close()
92101
workerPort.close()

packages/vitest/src/node/state.ts

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export class StateManager {
2222
idMap = new Map<string, Task>()
2323
taskFileMap = new WeakMap<Task, File>()
2424
errorsSet = new Set<unknown>()
25+
processTimeoutCauses = new Set<string>()
2526

2627
catchError(err: unknown, type: string): void {
2728
if (isAggregateError(err))
@@ -39,6 +40,14 @@ export class StateManager {
3940
return Array.from(this.errorsSet.values())
4041
}
4142

43+
addProcessTimeoutCause(cause: string) {
44+
this.processTimeoutCauses.add(cause)
45+
}
46+
47+
getProcessTimeoutCauses() {
48+
return Array.from(this.processTimeoutCauses.values())
49+
}
50+
4251
getPaths() {
4352
return Array.from(this.pathsSet)
4453
}

pnpm-lock.yaml

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)