diff --git a/docs/index.md b/docs/index.md index 3abf41cafd..55c228a44d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1379,6 +1379,10 @@ Free-tier cloud CI services may not provide a suitable multi-core container or V It's unlikely (but not impossible) to see a performance gain from a [job count](#-jobs-count-j-count) _greater than_ the number of available CPU cores. That said, _play around with the job count_--there's no one-size-fits all, and the unique characteristics of your tests will determine the optimal number of jobs; it may even be that fewer is faster! +### Parallel Mode Worker IDs + +Each process launched by parallel mode is assigned a unique id, from 0 for the first process to be launched, to N-1 for the Nth process. This worker id may be accessed in tests via the environment variable `MOCHA_WORKER_ID`. It can be used for example to assign a different database, service port, etc for each test process. + ## Root Hook Plugins > _New in v8.0.0_ diff --git a/lib/nodejs/buffered-worker-pool.js b/lib/nodejs/buffered-worker-pool.js index 9b0d4516e5..fe4abf945e 100644 --- a/lib/nodejs/buffered-worker-pool.js +++ b/lib/nodejs/buffered-worker-pool.js @@ -75,7 +75,23 @@ class BufferedWorkerPool { process.execArgv.join(' ') ); - this.options = {...WORKER_POOL_DEFAULT_OPTS, opts, maxWorkers}; + let counter = 0; + const onCreateWorker = ({forkOpts}) => { + return { + forkOpts: { + ...forkOpts, + // adds an incremental id to all workers, which can be useful to allocate resources for each process + env: {...process.env, MOCHA_WORKER_ID: counter++} + } + }; + }; + + this.options = { + ...WORKER_POOL_DEFAULT_OPTS, + ...opts, + maxWorkers, + onCreateWorker + }; this._pool = workerpool.pool(WORKER_PATH, this.options); } diff --git a/package-lock.json b/package-lock.json index 09fae06f54..71e12256d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "workerpool": "6.1.5", + "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -6385,9 +6385,7 @@ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, - "engines": [ - "node >= 0.8" - ], + "engines": ["node >= 0.8"], "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -9464,9 +9462,7 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true, - "engines": [ - "node >=0.6.0" - ] + "engines": ["node >=0.6.0"] }, "node_modules/fail-on-errors-webpack-plugin": { "version": "3.0.0", @@ -9958,9 +9954,7 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "optional": true, - "os": [ - "darwin" - ], + "os": ["darwin"], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -12956,9 +12950,7 @@ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true, - "engines": [ - "node >= 0.2.0" - ] + "engines": ["node >= 0.2.0"] }, "node_modules/JSONStream": { "version": "1.3.5", @@ -12981,9 +12973,7 @@ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, - "engines": [ - "node >=0.6.0" - ], + "engines": ["node >=0.6.0"], "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -24186,9 +24176,7 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, - "engines": [ - "node >=0.6.0" - ], + "engines": ["node >=0.6.0"], "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -25120,9 +25108,9 @@ } }, "node_modules/workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -45239,9 +45227,9 @@ } }, "workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" }, "wrap-ansi": { "version": "7.0.0", diff --git a/package.json b/package.json index 4f58545031..bf20f911d3 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "workerpool": "6.1.5", + "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" diff --git a/test/integration/fixtures/parallel/testworkerid1.mjs b/test/integration/fixtures/parallel/testworkerid1.mjs new file mode 100644 index 0000000000..2e1f55e6a3 --- /dev/null +++ b/test/integration/fixtures/parallel/testworkerid1.mjs @@ -0,0 +1,7 @@ +import assert from 'assert'; + +describe('test1', () => { + it('should always run on worker with id 0', () => { + assert.ok(process.env.MOCHA_WORKER_ID === '0'); + }); +}); diff --git a/test/integration/fixtures/parallel/testworkerid2.mjs b/test/integration/fixtures/parallel/testworkerid2.mjs new file mode 100644 index 0000000000..c9bf710ca0 --- /dev/null +++ b/test/integration/fixtures/parallel/testworkerid2.mjs @@ -0,0 +1,7 @@ +import assert from 'assert'; + +describe('test2', () => { + it('should always run on worker with id 1', () => { + assert.ok(process.env.MOCHA_WORKER_ID === '1'); + }); +}); diff --git a/test/integration/fixtures/parallel/testworkerid3.mjs b/test/integration/fixtures/parallel/testworkerid3.mjs new file mode 100644 index 0000000000..40a1ab43c5 --- /dev/null +++ b/test/integration/fixtures/parallel/testworkerid3.mjs @@ -0,0 +1,9 @@ +import assert from 'assert'; + +describe('test3', () => { + it('should run on worker with either id 0 or 1', () => { + assert.ok( + process.env.MOCHA_WORKER_ID === '0' || process.env.MOCHA_WORKER_ID === '1' + ); + }); +}); diff --git a/test/integration/parallel.spec.js b/test/integration/parallel.spec.js index b019307414..3cdecfcf18 100644 --- a/test/integration/parallel.spec.js +++ b/test/integration/parallel.spec.js @@ -18,4 +18,16 @@ describe('parallel run', () => { assert.strictEqual(result.stats.failures, 1); assert.strictEqual(result.stats.passes, 2); }); + + it('should correctly set worker ids for each process', async () => { + const result = await runMochaJSONAsync('parallel/testworkerid3.mjs', [ + '--parallel', + '--jobs', + '2', + require.resolve('./fixtures/parallel/testworkerid1.mjs'), + require.resolve('./fixtures/parallel/testworkerid2.mjs') + ]); + assert.strictEqual(result.stats.failures, 0); + assert.strictEqual(result.stats.passes, 3); + }); });