• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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