Skip to content

Commit 266a8c9

Browse files
committed
--wip-- [skip ci]
1 parent 949baad commit 266a8c9

File tree

4 files changed

+843
-0
lines changed

4 files changed

+843
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
'use strict';
2+
3+
function _exit() {
4+
const data = _interopRequireDefault(require('exit'));
5+
6+
_exit = function _exit() {
7+
return data;
8+
};
9+
10+
return data;
11+
}
12+
13+
function _throat() {
14+
const data = _interopRequireDefault(require('throat'));
15+
16+
_throat = function _throat() {
17+
return data;
18+
};
19+
20+
return data;
21+
}
22+
23+
function _jestWorker() {
24+
const data = _interopRequireDefault(require('jest-worker'));
25+
26+
_jestWorker = function _jestWorker() {
27+
return data;
28+
};
29+
30+
return data;
31+
}
32+
33+
var _runTest = _interopRequireDefault(require('./runTest'));
34+
35+
var _testWorker = require('./testWorker');
36+
37+
function _interopRequireDefault(obj) {
38+
return obj && obj.__esModule ? obj : {default: obj};
39+
}
40+
41+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
42+
try {
43+
var info = gen[key](arg);
44+
var value = info.value;
45+
} catch (error) {
46+
reject(error);
47+
return;
48+
}
49+
if (info.done) {
50+
resolve(value);
51+
} else {
52+
Promise.resolve(value).then(_next, _throw);
53+
}
54+
}
55+
56+
function _asyncToGenerator(fn) {
57+
return function() {
58+
var self = this,
59+
args = arguments;
60+
return new Promise(function(resolve, reject) {
61+
var gen = fn.apply(self, args);
62+
function _next(value) {
63+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
64+
}
65+
function _throw(err) {
66+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
67+
}
68+
_next(undefined);
69+
});
70+
};
71+
}
72+
73+
const TEST_WORKER_PATH = require.resolve('./testWorker');
74+
75+
class TestRunner {
76+
constructor(globalConfig, context) {
77+
this._globalConfig = globalConfig;
78+
this._context = context || {};
79+
}
80+
81+
runTests(tests, watcher, onStart, onResult, onFailure, options) {
82+
var _this = this;
83+
84+
return _asyncToGenerator(function*() {
85+
return yield options.serial
86+
? _this._createInBandTestRun(
87+
tests,
88+
watcher,
89+
onStart,
90+
onResult,
91+
onFailure
92+
)
93+
: _this._createParallelTestRun(
94+
tests,
95+
watcher,
96+
onStart,
97+
onResult,
98+
onFailure
99+
);
100+
})();
101+
}
102+
103+
_createInBandTestRun(tests, watcher, onStart, onResult, onFailure) {
104+
var _this2 = this;
105+
106+
return _asyncToGenerator(function*() {
107+
process.env.JEST_WORKER_ID = '1';
108+
const mutex = (0, _throat().default)(1);
109+
return tests.reduce(
110+
(promise, test) =>
111+
mutex(() =>
112+
promise
113+
.then(
114+
/*#__PURE__*/
115+
_asyncToGenerator(function*() {
116+
if (watcher.isInterrupted()) {
117+
throw new CancelRun();
118+
}
119+
120+
yield onStart(test);
121+
return (0,
122+
_runTest.default)(test.path, _this2._globalConfig, test.context.config, test.context.resolver, _this2._context);
123+
})
124+
)
125+
.then(result => onResult(test, result))
126+
.catch(err => onFailure(test, err))
127+
),
128+
Promise.resolve()
129+
);
130+
})();
131+
}
132+
133+
_createParallelTestRun(tests, watcher, onStart, onResult, onFailure) {
134+
var _this3 = this;
135+
136+
return _asyncToGenerator(function*() {
137+
const worker = new (_jestWorker()).default(TEST_WORKER_PATH, {
138+
exposedMethods: ['worker'],
139+
forkOptions: {
140+
stdio: 'pipe'
141+
},
142+
maxRetries: 3,
143+
numWorkers: _this3._globalConfig.maxWorkers
144+
});
145+
if (worker.getStdout()) worker.getStdout().pipe(process.stdout);
146+
if (worker.getStderr()) worker.getStderr().pipe(process.stderr);
147+
const mutex = (0, _throat().default)(_this3._globalConfig.maxWorkers); // Send test suites to workers continuously instead of all at once to track
148+
// the start time of individual tests.
149+
150+
const runTestInWorker = test =>
151+
mutex(
152+
/*#__PURE__*/
153+
_asyncToGenerator(function*() {
154+
if (watcher.isInterrupted()) {
155+
return Promise.reject();
156+
}
157+
158+
yield onStart(test);
159+
return worker.worker({
160+
config: test.context.config,
161+
context: _this3._context,
162+
globalConfig: _this3._globalConfig,
163+
path: test.path,
164+
serializableModuleMap: watcher.isWatchMode()
165+
? test.context.moduleMap.toJSON()
166+
: null
167+
});
168+
})
169+
);
170+
171+
const onError =
172+
/*#__PURE__*/
173+
(function() {
174+
var _ref3 = _asyncToGenerator(function*(err, test) {
175+
yield onFailure(test, err);
176+
177+
if (err.type === 'ProcessTerminatedError') {
178+
console.error(
179+
'A worker process has quit unexpectedly! ' +
180+
'Most likely this is an initialization error.'
181+
);
182+
(0, _exit().default)(1);
183+
}
184+
});
185+
186+
return function onError(_x, _x2) {
187+
return _ref3.apply(this, arguments);
188+
};
189+
})();
190+
191+
const onInterrupt = new Promise((_, reject) => {
192+
watcher.on('change', state => {
193+
if (state.interrupted) {
194+
reject(new CancelRun());
195+
}
196+
});
197+
});
198+
const runAllTests = Promise.all(
199+
tests.map(test =>
200+
runTestInWorker(test)
201+
.then(testResult => onResult(test, testResult))
202+
.catch(error => onError(error, test))
203+
)
204+
);
205+
206+
const cleanup = () => worker.end();
207+
208+
return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup);
209+
})();
210+
}
211+
}
212+
213+
class CancelRun extends Error {
214+
constructor(message) {
215+
super(message);
216+
this.name = 'CancelRun';
217+
}
218+
}
219+
220+
module.exports = TestRunner;

0 commit comments

Comments
 (0)