-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
worker.js
99 lines (84 loc) · 2.66 KB
/
worker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
'use strict';
const {createInvalidArgumentTypeError} = require('./errors');
const workerpool = require('workerpool');
const Mocha = require('./mocha');
const {handleRequires, validatePlugin} = require('./cli/run-helpers');
const debug = require('debug')(`mocha:worker:${process.pid}`);
const {serialize} = require('./serializer');
const BUFFERED_REPORTER_PATH = require.resolve('./reporters/buffered');
if (workerpool.isMainThread) {
throw new Error(
'This script is intended to be run as a worker (by the `workerpool` package).'
);
}
/**
* Initializes some stuff on the first call to {@link run}.
*
* Handles `--require` and `--ui`. Does _not_ handle `--reporter`,
* as only the `Buffered` reporter is used.
*
* **This function only runs once**; it overwrites itself with a no-op
* before returning.
*
* @param {Options} argv - Command-line options
*/
let bootstrap = argv => {
handleRequires(argv.require);
validatePlugin(argv, 'ui', Mocha.interfaces);
process.on('beforeExit', () => {
/* istanbul ignore next */
debug('exiting');
});
debug('bootstrapped');
bootstrap = () => {};
};
/**
* Runs a single test file in a worker thread.
* @param {string} filepath - Filepath of test file
* @param {Options} [argv] - Parsed command-line options object
* @returns {Promise<{failures: number, events: BufferedEvent[]}>} - Test
* failure count and list of events.
*/
async function run(filepath, argv = {ui: 'bdd'}) {
if (!filepath) {
throw createInvalidArgumentTypeError(
'Expected a non-empty "filepath" argument',
'file',
'string'
);
}
debug('running test file %s', filepath);
const opts = Object.assign(argv, {
// workers only use the `Buffered` reporter.
reporter: BUFFERED_REPORTER_PATH,
// if this was true, it would cause infinite recursion.
parallel: false
});
bootstrap(opts);
const mocha = new Mocha(opts).addFile(filepath);
try {
await mocha.loadFilesAsync();
} catch (err) {
debug('could not load file %s: %s', filepath, err);
throw err;
}
return new Promise((resolve, reject) => {
mocha.run(result => {
// Runner adds these; if we don't remove them, we'll get a leak.
process.removeAllListeners('uncaughtException');
debug('completed run with %d test failures', result.failures);
try {
resolve(serialize(result));
} catch (err) {
// TODO: figure out exactly what the sad path looks like here.
// rejection should only happen if an error is "unrecoverable"
reject(err);
}
});
});
}
// this registers the `run` function.
workerpool.worker({run});
debug('running');
// for testing
exports.run = run;