Skip to content

Commit f854f51

Browse files
committed
move max worker defaults into buffered-worker-pool
- add some missing coverage in `test/node-unit/worker.spec.js` - remove a noisy debug in `lib/nodejs/worker.js`
1 parent 155841a commit f854f51

File tree

6 files changed

+53
-37
lines changed

6 files changed

+53
-37
lines changed

lib/cli/run.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ const {ONE_AND_DONES, ONE_AND_DONE_ARGS} = require('./one-and-dones');
2525
const debug = require('debug')('mocha:cli:run');
2626
const defaults = require('../mocharc');
2727
const {types, aliases} = require('./run-option-metadata');
28-
const coreCount = require('os').cpus().length;
2928

3029
/**
3130
* Logical option groups
@@ -157,8 +156,7 @@ exports.builder = yargs =>
157156
'Number of concurrent jobs for --parallel; use 1 to run in serial',
158157
defaultDescription: '(number of CPU cores - 1)',
159158
requiresArg: true,
160-
group: GROUPS.RULES,
161-
default: Math.max(2, coreCount - 1)
159+
group: GROUPS.RULES
162160
},
163161
'list-interfaces': {
164162
conflicts: Array.from(ONE_AND_DONE_ARGS),

lib/mocha.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,12 @@ function Mocha(options) {
197197
*/
198198
this.isWorker = Boolean(options.isWorker);
199199

200-
if (options.parallel) {
201-
if (options.jobs > 1) {
202-
debug('attempting to enable parallel mode');
203-
this.parallelMode(true);
204-
} else {
205-
debug('parallel mode requested, but job count < 2');
206-
}
200+
if (
201+
options.parallel &&
202+
(typeof options.jobs === 'undefined' || options.jobs > 1)
203+
) {
204+
debug('attempting to enable parallel mode');
205+
this.parallelMode(true);
207206
}
208207
}
209208

lib/nodejs/buffered-worker-pool.js

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const serializeJavascript = require('serialize-javascript');
1111
const workerpool = require('workerpool');
1212
const {deserialize} = require('./serializer');
1313
const debug = require('debug')('mocha:parallel:buffered-worker-pool');
14-
const {cpus} = require('os');
1514
const {createInvalidArgumentTypeError} = require('../errors');
1615

1716
const WORKER_PATH = require.resolve('./worker.js');
@@ -25,20 +24,6 @@ const WORKER_PATH = require.resolve('./worker.js');
2524
*/
2625
let optionsCache = new WeakMap();
2726

28-
/**
29-
* Count of CPU cores
30-
*/
31-
const CPU_COUNT = cpus().length;
32-
33-
/**
34-
* Default max number of workers.
35-
*
36-
* We are already using one core for the main process, so assume only _n - 1_ are left.
37-
*
38-
* This is a reasonable default, but YMMV.
39-
*/
40-
const DEFAULT_MAX_WORKERS = CPU_COUNT - 1;
41-
4227
/**
4328
* These options are passed into the [workerpool](https://npm.im/workerpool) module.
4429
* @type {Partial<WorkerPoolOptions>}
@@ -49,29 +34,38 @@ const WORKER_POOL_DEFAULT_OPTS = {
4934
// ensure the same flags sent to `node` for this `mocha` invocation are passed
5035
// along to children
5136
forkOpts: {execArgv: process.execArgv},
52-
maxWorkers: DEFAULT_MAX_WORKERS
37+
maxWorkers: workerpool.cpus - 1
5338
};
5439

5540
/**
5641
* A wrapper around a third-party worker pool implementation.
5742
* @private
5843
*/
5944
class BufferedWorkerPool {
45+
/**
46+
* Creates an underlying worker pool instance; determines max worker count
47+
* @param {Partial<WorkerPoolOptions>} [opts] - Options
48+
*/
6049
constructor(opts = {}) {
61-
const maxWorkers = Math.max(1, opts.maxWorkers || 0);
50+
const maxWorkers = Math.max(
51+
1,
52+
typeof opts.maxWorkers === 'undefined'
53+
? WORKER_POOL_DEFAULT_OPTS.maxWorkers
54+
: opts.maxWorkers
55+
);
6256

63-
if (maxWorkers < 2) {
64-
/* istanbul ignore next */
57+
/* istanbul ignore next */
58+
if (workerpool.cpus < 2) {
59+
// TODO: decide whether we should warn
6560
debug(
66-
'not enough CPU cores available (%d) to run multiple jobs; avoid --parallel on this machine',
67-
CPU_COUNT
61+
'not enough CPU cores available to run multiple jobs; avoid --parallel on this machine'
6862
);
69-
} else if (maxWorkers >= CPU_COUNT) {
70-
/* istanbul ignore next */
63+
} else if (maxWorkers >= workerpool.cpus) {
64+
// TODO: decide whether we should warn
7165
debug(
7266
'%d concurrent job(s) requested, but only %d core(s) available',
7367
maxWorkers,
74-
CPU_COUNT
68+
workerpool.cpus
7569
);
7670
}
7771
/* istanbul ignore next */

lib/nodejs/worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ async function run(filepath, serializedOptions = '{}') {
9090
);
9191
}
9292

93-
debug('run(): deserialized options to %O', argv);
9493
const opts = Object.assign({ui: 'bdd'}, argv, {
9594
// workers only use the `Buffered` reporter.
9695
reporter: BUFFERED_REPORTER_PATH,
@@ -117,6 +116,7 @@ async function run(filepath, serializedOptions = '{}') {
117116

118117
return new Promise((resolve, reject) => {
119118
let debugInterval;
119+
/* istanbul ignore next */
120120
if (isDebugEnabled) {
121121
debugInterval = setInterval(() => {
122122
debug('run(): still running %s...', filepath);

test/node-unit/buffered-worker-pool.spec.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ describe('class BufferedWorkerPool', function() {
3030
require.resolve('../../lib/nodejs/buffered-worker-pool'),
3131
{
3232
workerpool: {
33-
pool: sandbox.stub().returns(pool)
33+
pool: sandbox.stub().returns(pool),
34+
cpus: 8
3435
},
3536
'../../lib/nodejs/serializer': serializer,
3637
'serialize-javascript': serializeJavascript

test/node-unit/worker.spec.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('worker', function() {
7676
});
7777

7878
describe('function', function() {
79-
describe('run', function() {
79+
describe('run()', function() {
8080
describe('when called without arguments', function() {
8181
it('should reject', async function() {
8282
return expect(worker.run, 'to be rejected with error satisfying', {
@@ -85,6 +85,30 @@ describe('worker', function() {
8585
});
8686
});
8787

88+
describe('when passed a non-string `options` value', function() {
89+
it('should reject', async function() {
90+
return expect(
91+
() => worker.run('foo.js', 42),
92+
'to be rejected with error satisfying',
93+
{
94+
code: 'ERR_MOCHA_INVALID_ARG_TYPE'
95+
}
96+
);
97+
});
98+
});
99+
100+
describe('when passed an invalid string `options` value', function() {
101+
it('should reject', async function() {
102+
return expect(
103+
() => worker.run('foo.js', 'tomfoolery'),
104+
'to be rejected with error satisfying',
105+
{
106+
code: 'ERR_MOCHA_INVALID_ARG_VALUE'
107+
}
108+
);
109+
});
110+
});
111+
88112
describe('when called with empty "filepath" argument', function() {
89113
it('should reject', async function() {
90114
return expect(

0 commit comments

Comments
 (0)