1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.SandboxPool = void 0;
|
4 | const os = require("os");
|
5 | const plugin_1 = require("@stryker-mutator/api/plugin");
|
6 | const rxjs_1 = require("rxjs");
|
7 | const operators_1 = require("rxjs/operators");
|
8 | const di_1 = require("./di");
|
9 | const Sandbox_1 = require("./Sandbox");
|
10 | const MAX_CONCURRENT_INITIALIZING_SANDBOXES = 2;
|
11 | let SandboxPool = (() => {
|
12 | class SandboxPool {
|
13 | constructor(log, options, testFramework, initialRunResult, initialFiles, loggingContext, tempDir) {
|
14 | this.log = log;
|
15 | this.options = options;
|
16 | this.testFramework = testFramework;
|
17 | this.initialFiles = initialFiles;
|
18 | this.loggingContext = loggingContext;
|
19 | this.tempDir = tempDir;
|
20 | this.allSandboxes = [];
|
21 | this.runInSandbox = async ([mutant, sandbox]) => {
|
22 | const result = await sandbox.runMutant(mutant);
|
23 | return { result, sandbox };
|
24 | };
|
25 | this.registerSandbox = async (promisedSandbox) => {
|
26 | this.allSandboxes.push(promisedSandbox);
|
27 | return promisedSandbox;
|
28 | };
|
29 | this.isDisposed = false;
|
30 | this.overheadTimeMS = initialRunResult.overheadTimeMS;
|
31 | }
|
32 | runMutants(mutants) {
|
33 | const recycledSandboxes = new rxjs_1.Subject();
|
34 |
|
35 | const sandboxes = this.startSandboxes().pipe(operators_1.merge(recycledSandboxes));
|
36 | return mutants.pipe(operators_1.zip(sandboxes), operators_1.flatMap(this.runInSandbox), operators_1.tap(({ sandbox }) => {
|
37 | recycledSandboxes.next(sandbox);
|
38 | }), operators_1.map(({ result }) => result));
|
39 | }
|
40 | startSandboxes() {
|
41 | const concurrency = this.determineConcurrency();
|
42 | return rxjs_1.range(0, concurrency).pipe(operators_1.flatMap(async (n) => {
|
43 | if (this.isDisposed) {
|
44 | return null;
|
45 | }
|
46 | else {
|
47 | return this.registerSandbox(Sandbox_1.default.create(this.options, n, this.initialFiles, this.testFramework, this.overheadTimeMS, this.loggingContext, this.tempDir));
|
48 | }
|
49 | }, MAX_CONCURRENT_INITIALIZING_SANDBOXES), operators_1.filter((sandboxOrNull) => !!sandboxOrNull), operators_1.map((sandbox) => sandbox));
|
50 | }
|
51 | determineConcurrency() {
|
52 | let numConcurrentRunners = os.cpus().length;
|
53 | if (this.options.transpilers.length) {
|
54 |
|
55 | numConcurrentRunners--;
|
56 | }
|
57 | let numConcurrentRunnersSource = 'CPU count';
|
58 | if (numConcurrentRunners > this.options.maxConcurrentTestRunners && this.options.maxConcurrentTestRunners > 0) {
|
59 | numConcurrentRunners = this.options.maxConcurrentTestRunners;
|
60 | numConcurrentRunnersSource = 'maxConcurrentTestRunners config';
|
61 | }
|
62 | if (numConcurrentRunners <= 0) {
|
63 | numConcurrentRunners = 1;
|
64 | }
|
65 | this.log.info(`Creating ${numConcurrentRunners} test runners (based on ${numConcurrentRunnersSource})`);
|
66 | return numConcurrentRunners;
|
67 | }
|
68 | async dispose() {
|
69 | this.isDisposed = true;
|
70 | const sandboxes = await Promise.all(this.allSandboxes);
|
71 | await Promise.all(sandboxes.map((sandbox) => sandbox.dispose()));
|
72 | }
|
73 | }
|
74 | SandboxPool.inject = plugin_1.tokens(plugin_1.commonTokens.logger, plugin_1.commonTokens.options, di_1.coreTokens.testFramework, di_1.coreTokens.initialRunResult, di_1.coreTokens.transpiledFiles, di_1.coreTokens.loggingContext, di_1.coreTokens.temporaryDirectory);
|
75 | return SandboxPool;
|
76 | })();
|
77 | exports.SandboxPool = SandboxPool;
|
78 |
|
\ | No newline at end of file |