1'use strict'; 2const common = require('../common'); 3const tmpdir = require('../common/tmpdir'); 4const fixtures = require('../common/fixtures'); 5const { describe, it, test } = require('node:test'); 6const assert = require('node:assert'); 7const path = require('node:path'); 8const fs = require('node:fs/promises'); 9const os = require('node:os'); 10const timers = require('node:timers/promises'); 11 12tmpdir.refresh(); 13 14describe('Concurrency option (boolean) = true', { concurrency: true }, () => { 15 let isFirstTestOver = false; 16 it('should start the first test', () => new Promise((resolve) => { 17 setImmediate(() => { isFirstTestOver = true; resolve(); }); 18 })); 19 it('should start before the previous test ends', () => { 20 // Should work even on single core CPUs 21 assert.strictEqual(isFirstTestOver, false); 22 }); 23}); 24 25describe( 26 'Concurrency option (boolean) = false', 27 { concurrency: false }, 28 () => { 29 let isFirstTestOver = false; 30 it('should start the first test', () => new Promise((resolve) => { 31 setImmediate(() => { isFirstTestOver = true; resolve(); }); 32 })); 33 it('should start after the previous test ends', () => { 34 assert.strictEqual(isFirstTestOver, true); 35 }); 36 } 37); 38 39// Despite the docs saying so at some point, setting concurrency to true should 40// not limit concurrency to the number of available CPU cores. 41describe('concurrency: true implies Infinity', { concurrency: true }, () => { 42 // The factor 5 is intentionally chosen to be higher than the default libuv 43 // thread pool size. 44 const nTests = 5 * os.availableParallelism(); 45 let nStarted = 0; 46 for (let i = 0; i < nTests; i++) { 47 it(`should run test ${i} concurrently`, async () => { 48 assert.strictEqual(nStarted++, i); 49 await timers.setImmediate(); 50 assert.strictEqual(nStarted, nTests); 51 }); 52 } 53}); 54 55{ 56 // Make sure tests run in order when root concurrency is 1 (default) 57 const tree = []; 58 const expectedTestTree = common.mustCall(() => { 59 assert.deepStrictEqual(tree, [ 60 'suite 1', 'nested', 'suite 2', 61 '1', '2', 'nested 1', 'nested 2', 62 'test', 'test 1', 'test 2', 63 ]); 64 }); 65 66 describe('suite 1', () => { 67 tree.push('suite 1'); 68 it('1', () => tree.push('1')); 69 it('2', () => tree.push('2')); 70 71 describe('nested', () => { 72 tree.push('nested'); 73 it('nested 1', () => tree.push('nested 1')); 74 it('nested 2', () => tree.push('nested 2')); 75 }); 76 }); 77 78 test('test', async (t) => { 79 tree.push('test'); 80 await t.test('test1', () => tree.push('test 1')); 81 await t.test('test 2', () => tree.push('test 2')); 82 }); 83 84 describe('suite 2', () => { 85 tree.push('suite 2'); 86 it('should run after other suites', expectedTestTree); 87 }); 88} 89 90test('--test multiple files', { skip: os.availableParallelism() < 3 }, async () => { 91 await fs.writeFile(path.resolve(tmpdir.path, 'test-runner-concurrency'), ''); 92 const { code, stderr } = await common.spawnPromisified(process.execPath, [ 93 '--test', 94 fixtures.path('test-runner', 'concurrency', 'a.mjs'), 95 fixtures.path('test-runner', 'concurrency', 'b.mjs'), 96 ]); 97 assert.strictEqual(stderr, ''); 98 assert.strictEqual(code, 0); 99}); 100