|
| 1 | +import type { ChildProcess } from 'node:child_process' |
| 2 | +import { fileURLToPath } from 'node:url' |
| 3 | +import { afterEach, describe, expect, it, vi } from 'vitest' |
| 4 | + |
| 5 | +import { ForkPool } from '../../src/dev/pool' |
| 6 | + |
| 7 | +const devEntry = fileURLToPath(new URL('../fixtures/fork-pool-entry.mjs', import.meta.url)) |
| 8 | + |
| 9 | +const pools: ForkPool[] = [] |
| 10 | + |
| 11 | +function createPool(poolSize?: number) { |
| 12 | + globalThis.__nuxt_cli__ = { ...globalThis.__nuxt_cli__, devEntry } as typeof globalThis.__nuxt_cli__ |
| 13 | + const pool = new ForkPool({ rawArgs: [], poolSize, listenOverrides: {} }) |
| 14 | + pools.push(pool) |
| 15 | + return pool |
| 16 | +} |
| 17 | + |
| 18 | +async function waitForReady(pool: ForkPool, count: number) { |
| 19 | + await vi.waitFor(() => { |
| 20 | + expect(pool.getStats().ready).toBe(count) |
| 21 | + }, { timeout: 20_000, interval: 25 }) |
| 22 | +} |
| 23 | + |
| 24 | +afterEach(async () => { |
| 25 | + for (const pool of pools.splice(0)) { |
| 26 | + await (pool as unknown as { killAll: (signal: number) => void }).killAll(0) |
| 27 | + } |
| 28 | +}) |
| 29 | + |
| 30 | +describe('forkPool', () => { |
| 31 | + it('should kill every fork on shutdown', { timeout: 30_000 }, async () => { |
| 32 | + const pool = createPool(3) |
| 33 | + pool.startWarming() |
| 34 | + await waitForReady(pool, 3) |
| 35 | + |
| 36 | + const processes = (pool as unknown as { pool: Array<{ process: ChildProcess }> }).pool.map(f => f.process) |
| 37 | + ;(pool as unknown as { killAll: (signal: number) => void }).killAll(0) |
| 38 | + |
| 39 | + await vi.waitFor(() => { |
| 40 | + for (const child of processes) { |
| 41 | + expect(child.killed).toBe(true) |
| 42 | + } |
| 43 | + }, { timeout: 10_000, interval: 25 }) |
| 44 | + expect(pool.getStats().total).toBe(0) |
| 45 | + }) |
| 46 | +}) |
0 commit comments