-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
pool.ts
114 lines (98 loc) · 3.17 KB
/
pool.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { pathToFileURL } from 'node:url'
import mm from 'micromatch'
import { resolve } from 'pathe'
import { distDir, rootDir } from '../constants'
import type { VitestPool } from '../types'
import type { Vitest } from './core'
import { createChildProcessPool } from './pools/child'
import { createThreadsPool } from './pools/threads'
export type RunWithFiles = (files: string[], invalidates?: string[]) => Promise<void>
export interface ProcessPool {
runTests: RunWithFiles
close: () => Promise<void>
}
export interface PoolProcessOptions {
execArgv: string[]
env: Record<string, string>
}
const loaderPath = pathToFileURL(resolve(distDir, './loader.js')).href
const suppressLoaderWarningsPath = resolve(rootDir, './suppress-warnings.cjs')
export function createPool(ctx: Vitest): ProcessPool {
const pools: Record<VitestPool, ProcessPool | null> = {
child_process: null,
threads: null,
}
function getDefaultPoolName() {
if (ctx.config.threads)
return 'threads'
return 'child_process'
}
function getPoolName(file: string) {
for (const [glob, pool] of ctx.config.poolMatchGlobs || []) {
if (mm.isMatch(file, glob, { cwd: ctx.server.config.root }))
return pool
}
return getDefaultPoolName()
}
async function runTests(files: string[], invalidate?: string[]) {
const conditions = ctx.server.config.resolve.conditions?.flatMap(c => ['--conditions', c]) || []
// Instead of passing whole process.execArgv to the workers, pick allowed options.
// Some options may crash worker, e.g. --prof, --title. nodejs/node#41103
const execArgv = process.execArgv.filter(execArg =>
execArg.startsWith('--cpu-prof') || execArg.startsWith('--heap-prof'),
)
const options: PoolProcessOptions = {
execArgv: ctx.config.deps.registerNodeLoader
? [
...execArgv,
'--require',
suppressLoaderWarningsPath,
'--experimental-loader',
loaderPath,
]
: [
...execArgv,
...conditions,
],
env: {
TEST: 'true',
VITEST: 'true',
NODE_ENV: ctx.config.mode || 'test',
VITEST_MODE: ctx.config.watch ? 'WATCH' : 'RUN',
...process.env,
...ctx.config.env,
},
}
const filesByPool = {
child_process: [] as string[],
threads: [] as string[],
browser: [] as string[],
}
if (!ctx.config.poolMatchGlobs) {
const name = getDefaultPoolName()
filesByPool[name] = files
}
else {
for (const file of files) {
const pool = getPoolName(file)
filesByPool[pool].push(file)
}
}
await Promise.all(Object.entries(filesByPool).map(([pool, files]) => {
if (!files.length)
return null
if (pool === 'threads') {
pools.threads ??= createThreadsPool(ctx, options)
return pools.threads.runTests(files, invalidate)
}
pools.child_process ??= createChildProcessPool(ctx, options)
return pools.child_process.runTests(files, invalidate)
}))
}
return {
runTests,
async close() {
await Promise.all(Object.values(pools).map(p => p?.close()))
},
}
}