From e9fe41811d5ac60eee92126255093726680c0546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Tue, 9 Jan 2024 16:43:50 +0200 Subject: [PATCH] fix(workspace): support overring `pool` and `poolOptions` on project level (#4765) --- docs/config/index.md | 14 +-- packages/vitest/src/node/workspace.ts | 20 ++++- packages/vitest/src/types/config.ts | 6 +- test/config/test/config-types.test-d.ts | 11 ++- test/workspaces/space-pools/forks.test.ts | 12 +++ test/workspaces/space-pools/isolate.test.ts | 15 ++++ .../space-pools/multi-worker.test.ts | 15 ++++ .../workspaces/space-pools/no-isolate.test.ts | 15 ++++ .../space-pools/single-worker.test.ts | 15 ++++ test/workspaces/space-pools/threads.test.ts | 12 +++ test/workspaces/vitest.workspace.ts | 90 +++++++++++++++++++ 11 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 test/workspaces/space-pools/forks.test.ts create mode 100644 test/workspaces/space-pools/isolate.test.ts create mode 100644 test/workspaces/space-pools/multi-worker.test.ts create mode 100644 test/workspaces/space-pools/no-isolate.test.ts create mode 100644 test/workspaces/space-pools/single-worker.test.ts create mode 100644 test/workspaces/space-pools/threads.test.ts diff --git a/docs/config/index.md b/docs/config/index.md index d579bb06b724..f367eb01e77c 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -655,7 +655,7 @@ Please, be aware of these issues when using this option. Vitest team cannot fix - **Type:** `Record<'threads' | 'forks' | 'vmThreads', {}>` - **Default:** `{}` -#### poolOptions.threads +#### poolOptions.threads Options for `threads` pool. @@ -687,7 +687,7 @@ Maximum number of threads. You can also use `VITEST_MAX_THREADS` environment var Minimum number of threads. You can also use `VITEST_MIN_THREADS` environment variable. -##### poolOptions.threads.singleThread +##### poolOptions.threads.singleThread - **Type:** `boolean` - **Default:** `false` @@ -710,7 +710,7 @@ Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions. -##### poolOptions.threads.isolate +##### poolOptions.threads.isolate - **Type:** `boolean` - **Default:** `true` @@ -728,7 +728,7 @@ Pass additional arguments to `node` in the threads. See [Command-line API | Node Be careful when using, it as some options may crash worker, e.g. --prof, --title. See https://github.com/nodejs/node/issues/41103. ::: -#### poolOptions.forks +#### poolOptions.forks Options for `forks` pool. @@ -760,14 +760,14 @@ Maximum number of forks. Minimum number of forks. -##### poolOptions.forks.isolate +##### poolOptions.forks.isolate - **Type:** `boolean` - **Default:** `true` Isolate environment for each test file. -##### poolOptions.forks.singleFork +##### poolOptions.forks.singleFork - **Type:** `boolean` - **Default:** `false` @@ -792,7 +792,7 @@ Pass additional arguments to `node` process in the child processes. See [Command Be careful when using, it as some options may crash worker, e.g. --prof, --title. See https://github.com/nodejs/node/issues/41103. ::: -#### poolOptions.vmThreads +#### poolOptions.vmThreads Options for `vmThreads` pool. diff --git a/packages/vitest/src/node/workspace.ts b/packages/vitest/src/node/workspace.ts index cb449c11e703..9c41212b25e4 100644 --- a/packages/vitest/src/node/workspace.ts +++ b/packages/vitest/src/node/workspace.ts @@ -319,12 +319,28 @@ export class WorkspaceProject { getSerializableConfig() { const optimizer = this.config.deps?.optimizer + const poolOptions = this.config.poolOptions + + // Resolve from server.config to avoid comparing against default value + const isolate = this.server?.config?.test?.isolate + return deepMerge({ ...this.config, coverage: this.ctx.config.coverage, - pool: this.ctx.config.pool, - poolOptions: this.ctx.config.poolOptions, + poolOptions: { + forks: { + singleFork: poolOptions?.forks?.singleFork ?? this.ctx.config.poolOptions?.forks?.singleFork ?? false, + isolate: poolOptions?.forks?.isolate ?? isolate ?? this.ctx.config.poolOptions?.forks?.isolate ?? true, + }, + threads: { + singleThread: poolOptions?.threads?.singleThread ?? this.ctx.config.poolOptions?.threads?.singleThread ?? false, + isolate: poolOptions?.threads?.isolate ?? isolate ?? this.ctx.config.poolOptions?.threads?.isolate ?? true, + }, + vmThreads: { + singleThread: poolOptions?.vmThreads?.singleThread ?? this.ctx.config.poolOptions?.vmThreads?.singleThread ?? false, + }, + }, reporters: [], deps: { diff --git a/packages/vitest/src/types/config.ts b/packages/vitest/src/types/config.ts index e60a6a3e898f..374e8eb046a3 100644 --- a/packages/vitest/src/types/config.ts +++ b/packages/vitest/src/types/config.ts @@ -817,7 +817,6 @@ export type ProjectConfig = Omit< | 'update' | 'reporters' | 'outputFile' - | 'pool' | 'poolOptions' | 'teardownTimeout' | 'silent' @@ -842,6 +841,11 @@ export type ProjectConfig = Omit< > & { sequencer?: Omit deps?: Omit + poolOptions?: { + threads?: Pick, 'singleThread' | 'isolate'> + vmThreads?: Pick, 'singleThread'> + forks?: Pick, 'singleFork' | 'isolate'> + } } export type RuntimeConfig = Pick< diff --git a/test/config/test/config-types.test-d.ts b/test/config/test/config-types.test-d.ts index 2e3258cfff57..26dd8b4479df 100644 --- a/test/config/test/config-types.test-d.ts +++ b/test/config/test/config-types.test-d.ts @@ -9,11 +9,16 @@ describe('define project helper', () => { expectProjectTestConfig.toHaveProperty('name') expectMainTestConfig.toHaveProperty('name') - expectProjectTestConfig.not.toHaveProperty('pool') - expectMainTestConfig.toHaveProperty('pool') - expectProjectTestConfig.not.toHaveProperty('coverage') expectMainTestConfig.toHaveProperty('coverage') + + expectProjectTestConfig.not.toHaveProperty('reporters') + expectMainTestConfig.toHaveProperty('reporters') + }) + + test('allows expected project fields on a project config', () => { + expectProjectTestConfig.toHaveProperty('pool') + expectProjectTestConfig.toHaveProperty('poolOptions') }) }) diff --git a/test/workspaces/space-pools/forks.test.ts b/test/workspaces/space-pools/forks.test.ts new file mode 100644 index 000000000000..00bdf498a481 --- /dev/null +++ b/test/workspaces/space-pools/forks.test.ts @@ -0,0 +1,12 @@ +import { isMainThread } from 'node:worker_threads' +import { expect, test } from 'vitest' + +test('is run in "node:child_process"', () => { + expect(isChildProcess()).toBe(true) + expect(isMainThread).toBe(true) +}) + +// TODO: Use from "src/utils/base.ts" after #4441 +function isChildProcess(): boolean { + return !!process?.send +} diff --git a/test/workspaces/space-pools/isolate.test.ts b/test/workspaces/space-pools/isolate.test.ts new file mode 100644 index 000000000000..56ded345d3af --- /dev/null +++ b/test/workspaces/space-pools/isolate.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from 'vitest' +import type { UserConfig } from 'vitest/config' + +test('is isolated', () => { + // @ts-expect-error -- internal + const config: NonNullable = globalThis.__vitest_worker__.config + + if (config.pool === 'forks') { + expect(config.poolOptions?.forks?.isolate).toBe(true) + } + else { + expect(config.pool).toBe('threads') + expect(config.poolOptions?.threads?.isolate).toBe(true) + } +}) diff --git a/test/workspaces/space-pools/multi-worker.test.ts b/test/workspaces/space-pools/multi-worker.test.ts new file mode 100644 index 000000000000..7ce5ee9504f4 --- /dev/null +++ b/test/workspaces/space-pools/multi-worker.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from 'vitest' +import type { UserConfig } from 'vitest/config' + +test('is multi worker', () => { + // @ts-expect-error -- internal + const config: NonNullable = globalThis.__vitest_worker__.config + + if (config.pool === 'forks') { + expect(config.poolOptions?.forks?.singleFork).toBe(false) + } + else { + expect(config.pool).toBe('threads') + expect(config.poolOptions?.threads?.singleThread).toBe(false) + } +}) diff --git a/test/workspaces/space-pools/no-isolate.test.ts b/test/workspaces/space-pools/no-isolate.test.ts new file mode 100644 index 000000000000..91b04ee87332 --- /dev/null +++ b/test/workspaces/space-pools/no-isolate.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from 'vitest' +import type { UserConfig } from 'vitest/config' + +test('is not isolated', () => { + // @ts-expect-error -- internal + const config: NonNullable = globalThis.__vitest_worker__.config + + if (config.pool === 'forks') { + expect(config.poolOptions?.forks?.isolate).toBe(false) + } + else { + expect(config.pool).toBe('threads') + expect(config.poolOptions?.threads?.isolate).toBe(false) + } +}) diff --git a/test/workspaces/space-pools/single-worker.test.ts b/test/workspaces/space-pools/single-worker.test.ts new file mode 100644 index 000000000000..fcc056ce814e --- /dev/null +++ b/test/workspaces/space-pools/single-worker.test.ts @@ -0,0 +1,15 @@ +import { expect, test } from 'vitest' +import type { UserConfig } from 'vitest/config' + +test('is single worker', () => { + // @ts-expect-error -- internal + const config: NonNullable = globalThis.__vitest_worker__.config + + if (config.pool === 'forks') { + expect(config.poolOptions?.forks?.singleFork).toBe(true) + } + else { + expect(config.pool).toBe('threads') + expect(config.poolOptions?.threads?.singleThread).toBe(true) + } +}) diff --git a/test/workspaces/space-pools/threads.test.ts b/test/workspaces/space-pools/threads.test.ts new file mode 100644 index 000000000000..115ae5286a82 --- /dev/null +++ b/test/workspaces/space-pools/threads.test.ts @@ -0,0 +1,12 @@ +import { isMainThread } from 'node:worker_threads' +import { expect, test } from 'vitest' + +test('is run in "node:worker_threads"', () => { + expect(isChildProcess()).toBe(false) + expect(isMainThread).toBe(false) +}) + +// TODO: Use from "src/utils/base.ts" after #4441 +function isChildProcess(): boolean { + return !!process?.send +} diff --git a/test/workspaces/vitest.workspace.ts b/test/workspaces/vitest.workspace.ts index e32cad7ff02b..c8481a055402 100644 --- a/test/workspaces/vitest.workspace.ts +++ b/test/workspaces/vitest.workspace.ts @@ -23,6 +23,96 @@ export default defineWorkspace([ }, }, + // Projects testing pool and poolOptions + { + test: { + name: 'Threads pool', + include: [ + './space-pools/threads.test.ts', + './space-pools/multi-worker.test.ts', + './space-pools/isolate.test.ts', + ], + pool: 'threads', + }, + }, + { + test: { + name: 'Single thread pool', + include: [ + './space-pools/threads.test.ts', + './space-pools/single-worker.test.ts', + ], + pool: 'threads', + poolOptions: { threads: { singleThread: true } }, + }, + }, + { + test: { + name: 'Non-isolated thread pool #1', + include: [ + './space-pools/threads.test.ts', + './space-pools/no-isolate.test.ts', + ], + pool: 'threads', + poolOptions: { threads: { isolate: false } }, + }, + }, + { + test: { + name: 'Non-isolated thread pool #2', + include: [ + './space-pools/threads.test.ts', + './space-pools/no-isolate.test.ts', + ], + pool: 'threads', + isolate: false, + }, + }, + { + test: { + name: 'Forks pool', + include: [ + './space-pools/forks.test.ts', + './space-pools/multi-worker.test.ts', + './space-pools/isolate.test.ts', + ], + pool: 'forks', + }, + }, + { + test: { + name: 'Single fork pool', + include: [ + './space-pools/forks.test.ts', + './space-pools/single-worker.test.ts', + ], + pool: 'forks', + poolOptions: { forks: { singleFork: true } }, + }, + }, + { + test: { + name: 'Non-isolated fork pool #1', + include: [ + './space-pools/forks.test.ts', + './space-pools/no-isolate.test.ts', + ], + pool: 'forks', + poolOptions: { forks: { isolate: false } }, + }, + }, + { + test: { + name: 'Non-isolated fork pool #2', + include: [ + './space-pools/forks.test.ts', + './space-pools/no-isolate.test.ts', + ], + pool: 'forks', + isolate: false, + }, + }, + // These two projects run on same environment but still transform // a single file differently due to Vite plugins {