UNPKG

toofast

Version:

The Node.js performance testing tool with unit-test-like API.

118 lines (117 loc) 4.31 kB
import cluster from 'cluster'; import childProcess from 'child_process'; import { bootstrapRunner, createRunMeasure, runTest, setCurrentNode, TestSuiteNode, } from './runner-api.js'; import { getErrorMessage } from './utils.js'; import { createNodeLogger } from './createNodeLogger.js'; import { resolveConfig } from './resolveConfig.js'; import path from 'path'; export default async function start() { if (cluster.isWorker) { startWorker(); return; } const config = resolveConfig(); // Restart process and enable TypeScript support if ((config.setupFiles.some(isTypeScriptFile) || config.testFiles.some(isTypeScriptFile)) && !process.execArgv.includes('--experimental-strip-types')) { const [, filePath, ...args] = process.argv; childProcess .fork(filePath, args, { execArgv: [...process.execArgv, '--experimental-strip-types', '--no-warnings=ExperimentalWarning'], }) .once('close', exitCode => process.exit(exitCode)); return; } const testPatterns = config.testRegExps.map(re => re.source); const logger = createNodeLogger(); for (const testFile of config.testFiles) { let nodeLocation = []; const nextTest = () => { return new Promise(resolve => { const worker = cluster.fork(); worker.on('message', (message) => { if (message.type === 'workerReady') { worker.send({ type: 'runTest', setupFiles: config.setupFiles, testFile, nodeLocation, testPatterns, testOptions: config.testOptions, }); return; } logger(message); if (message.type === 'fatalError') { process.exit(1); } if (message.type === 'testStart') { nodeLocation = message.nodeLocation; } if (message.type === 'testEnd') { resolve(nextTest()); } if (message.type === 'testSuiteEnd') { resolve(); } }); worker.on('error', error => { logger({ type: 'fatalError', errorMessage: getErrorMessage(error) }); process.exit(1); }); worker.on('exit', resolve); }); }; await nextTest(); } process.exit(0); } function startWorker() { process.once('message', async (message) => { if (message.type !== 'runTest') { return; } const { setupFiles, testFile, nodeLocation, testPatterns } = message; const testRegExps = testPatterns.map(pattern => RegExp(pattern, 'i')); const testSuiteNode = new TestSuiteNode(message.testOptions); setCurrentNode(testSuiteNode); const isSuccessful = await bootstrapRunner({ setupFiles, testFile, evalFile, sendMessage, }); if (!isSuccessful) { cluster.worker.kill(); return; } const runMeasure = createRunMeasure({ sendMessage, getMemoryUsed() { return typeof process !== 'undefined' ? process.memoryUsage().heapUsed : 0; }, }); await runTest({ startNode: testSuiteNode, nodeLocation, isSkipped(testNode) { return testRegExps.length !== 0 && !testRegExps.some(re => re.test(testNode.absoluteName)); }, setCurrentNode, runMeasure, sendMessage, }); cluster.worker.kill(); }); sendMessage({ type: 'workerReady' }); } function evalFile(file) { return import(file); } function sendMessage(message) { process.send(message); } function isTypeScriptFile(file) { const ext = path.extname(file); return ext === '.ts' || ext === '.mts' || ext === '.tsx' || ext === '.mtsx'; }