Comparing version 0.35.0 to 0.35.1
@@ -6,2 +6,13 @@ # Change Log | ||
## [0.35.1](https://github.com/stryker-mutator/stryker/compare/stryker@0.35.0...stryker@0.35.1) (2019-02-12) | ||
### Bug Fixes | ||
* **mutants:** Prevent memory leak when transpiling mutants ([#1376](https://github.com/stryker-mutator/stryker/issues/1376)) ([45c2852](https://github.com/stryker-mutator/stryker/commit/45c2852)), closes [#920](https://github.com/stryker-mutator/stryker/issues/920) | ||
# [0.35.0](https://github.com/stryker-mutator/stryker/compare/stryker@0.34.0...stryker@0.35.0) (2019-02-08) | ||
@@ -8,0 +19,0 @@ |
{ | ||
"name": "stryker", | ||
"version": "0.35.0", | ||
"version": "0.35.1", | ||
"description": "The extendable JavaScript mutation testing framework", | ||
@@ -63,5 +63,5 @@ "main": "src/Stryker.js", | ||
"inquirer": "~6.2.0", | ||
"istanbul-lib-instrument": "~3.0.0", | ||
"istanbul-lib-instrument": "~3.1.0", | ||
"lodash": "~4.17.4", | ||
"log4js": "~3.0.0", | ||
"log4js": "~4.0.2", | ||
"mkdirp": "~0.5.1", | ||
@@ -73,10 +73,10 @@ "prettier": "~1.16.1", | ||
"source-map": "~0.6.1", | ||
"surrial": "^0.2.0", | ||
"surrial": "~1.0.0", | ||
"tree-kill": "~1.2.0", | ||
"tslib": "~1.9.3", | ||
"typed-inject": "^0.2.0", | ||
"typed-rest-client": "~1.0.7" | ||
"typed-inject": "~1.0.0", | ||
"typed-rest-client": "~1.1.2" | ||
}, | ||
"devDependencies": { | ||
"@stryker-mutator/test-helpers": "^0.1.0", | ||
"@stryker-mutator/test-helpers": "^0.1.1", | ||
"@types/get-port": "~4.0.0", | ||
@@ -88,3 +88,4 @@ "@types/inquirer": "~0.0.42", | ||
"@types/progress": "~2.0.1", | ||
"stryker-api": "^0.24.0" | ||
"flatted": "^2.0.0", | ||
"stryker-api": "^0.24.1" | ||
}, | ||
@@ -94,3 +95,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "2065d438debacc4c44a96f616bf13ad4912d6483" | ||
"gitHead": "1882514c285e1bc582e4394375c0ac64717b2f8b" | ||
} |
@@ -7,8 +7,11 @@ export declare const cliOptions = "cliOptions"; | ||
export declare const initialRunResult = "initialRunResult"; | ||
export declare const mutantTranspiler = "mutantTranspiler"; | ||
export declare const transpiledFiles = "transpiledFiles"; | ||
export declare const mutantTranspileScheduler = "mutantTranspileScheduler"; | ||
export declare const sandboxPool = "sandboxPool"; | ||
export declare const testFramework = "testFramework"; | ||
export declare const timer = "timer"; | ||
export declare const timeOverheadMS = "timeOverheadMS"; | ||
export declare const loggingContext = "loggingContext"; | ||
export declare const transpiler = "transpiler"; | ||
export declare const sandboxIndex = "sandboxIndex"; | ||
export declare const reporter = "reporter"; | ||
@@ -15,0 +18,0 @@ export declare const pluginKind = "pluginKind"; |
@@ -9,8 +9,11 @@ "use strict"; | ||
exports.initialRunResult = 'initialRunResult'; | ||
exports.mutantTranspiler = 'mutantTranspiler'; | ||
exports.transpiledFiles = 'transpiledFiles'; | ||
exports.mutantTranspileScheduler = 'mutantTranspileScheduler'; | ||
exports.sandboxPool = 'sandboxPool'; | ||
exports.testFramework = 'testFramework'; | ||
exports.timer = 'timer'; | ||
exports.timeOverheadMS = 'timeOverheadMS'; | ||
exports.loggingContext = 'loggingContext'; | ||
exports.transpiler = 'transpiler'; | ||
exports.sandboxIndex = 'sandboxIndex'; | ||
exports.reporter = 'reporter'; | ||
@@ -17,0 +20,0 @@ exports.pluginKind = 'pluginKind'; |
@@ -5,19 +5,13 @@ import { MutantResult } from 'stryker-api/report'; | ||
import StrictReporter from '../reporters/StrictReporter'; | ||
import MutantTranspiler from '../transpiler/MutantTranspiler'; | ||
import { Logger } from 'stryker-api/logging'; | ||
import InputFileCollection from '../input/InputFileCollection'; | ||
import { MutantTranspileScheduler } from '../transpiler/MutantTranspileScheduler'; | ||
export declare class MutationTestExecutor { | ||
private readonly log; | ||
private readonly input; | ||
private readonly reporter; | ||
private readonly mutantTranspiler; | ||
private readonly mutantTranspileScheduler; | ||
private readonly sandboxPool; | ||
static inject: ["logger", "inputFiles", "reporter", "mutantTranspiler", "sandboxPool"]; | ||
constructor(log: Logger, input: InputFileCollection, reporter: StrictReporter, mutantTranspiler: MutantTranspiler, sandboxPool: SandboxPool); | ||
static inject: ["reporter", "mutantTranspileScheduler", "sandboxPool"]; | ||
constructor(reporter: StrictReporter, mutantTranspileScheduler: MutantTranspileScheduler, sandboxPool: SandboxPool); | ||
run(allMutants: ReadonlyArray<TestableMutant>): Promise<MutantResult[]>; | ||
private runInsideSandboxes; | ||
private readonly earlyResult; | ||
private readonly runInSandbox; | ||
private readonly collectMutantResult; | ||
private readonly reportResult; | ||
private readonly reportAll; | ||
} | ||
//# sourceMappingURL=MutationTestExecutor.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
var rxjs_1 = require("rxjs"); | ||
var operators_1 = require("rxjs/operators"); | ||
var report_1 = require("stryker-api/report"); | ||
var test_runner_1 = require("stryker-api/test_runner"); | ||
var plugin_1 = require("stryker-api/plugin"); | ||
var di_1 = require("../di"); | ||
var MutationTestExecutor = /** @class */ (function () { | ||
function MutationTestExecutor(log, input, reporter, mutantTranspiler, sandboxPool) { | ||
function MutationTestExecutor(reporter, mutantTranspileScheduler, sandboxPool) { | ||
var _this = this; | ||
this.log = log; | ||
this.input = input; | ||
this.reporter = reporter; | ||
this.mutantTranspiler = mutantTranspiler; | ||
this.mutantTranspileScheduler = mutantTranspileScheduler; | ||
this.sandboxPool = sandboxPool; | ||
this.earlyResult = function (_a) { | ||
var transpiledMutant = _a[0], sandbox = _a[1]; | ||
if (transpiledMutant.transpileResult.error) { | ||
if (_this.log.isDebugEnabled()) { | ||
_this.log.debug("Transpile error occurred: \"" + transpiledMutant.transpileResult.error + "\" during transpiling of mutant " + transpiledMutant.mutant.toString()); | ||
} | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.TranspileError, []); | ||
return [transpiledMutant, sandbox, result]; | ||
} | ||
else if (!transpiledMutant.mutant.selectedTests.length) { | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.NoCoverage, []); | ||
return [transpiledMutant, sandbox, result]; | ||
} | ||
else if (!transpiledMutant.changedAnyTranspiledFiles) { | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.Survived, []); | ||
return [transpiledMutant, sandbox, result]; | ||
} | ||
else { | ||
// No early result possible, need to run in the sandbox later | ||
return [transpiledMutant, sandbox, null]; | ||
} | ||
this.reportResult = function (mutantResult) { | ||
_this.reporter.onMutantTested(mutantResult); | ||
}; | ||
this.runInSandbox = function (_a) { | ||
var transpiledMutant = _a[0], sandbox = _a[1], earlyResult = _a[2]; | ||
if (earlyResult) { | ||
return Promise.resolve({ sandbox: sandbox, result: earlyResult }); | ||
} | ||
else { | ||
return sandbox.runMutant(transpiledMutant) | ||
.then(function (runResult) { return ({ sandbox: sandbox, result: _this.collectMutantResult(transpiledMutant.mutant, runResult) }); }); | ||
} | ||
this.reportAll = function (mutantResults) { | ||
_this.reporter.onAllMutantsTested(mutantResults); | ||
}; | ||
this.collectMutantResult = function (mutant, runResult) { | ||
var status = mutantState(runResult); | ||
var testNames = runResult.tests | ||
.filter(function (t) { return t.status !== test_runner_1.TestStatus.Skipped; }) | ||
.map(function (t) { return t.name; }); | ||
if (_this.log.isDebugEnabled() && status === report_1.MutantStatus.RuntimeError) { | ||
var error = runResult.errorMessages ? runResult.errorMessages.toString() : '(undefined)'; | ||
_this.log.debug('A runtime error occurred: %s during execution of mutant: %s', error, mutant.toString()); | ||
} | ||
return mutant.result(status, testNames); | ||
}; | ||
} | ||
MutationTestExecutor.prototype.run = function (allMutants) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var transpiledFiles, result; | ||
var results; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.mutantTranspiler.initialize(this.input.files)]; | ||
case 0: return [4 /*yield*/, this.sandboxPool.runMutants(this.mutantTranspileScheduler.scheduleTranspileMutants(allMutants)).pipe(operators_1.tap(this.reportResult), | ||
// Signal the mutant transpiler that there is another slot open for transpiling | ||
operators_1.tap(this.mutantTranspileScheduler.scheduleNext), operators_1.toArray(), operators_1.tap(this.reportAll)).toPromise()]; | ||
case 1: | ||
transpiledFiles = _a.sent(); | ||
return [4 /*yield*/, this.runInsideSandboxes(this.sandboxPool.streamSandboxes(transpiledFiles), this.mutantTranspiler.transpileMutants(allMutants))]; | ||
results = _a.sent(); | ||
// TODO: Let typed inject dispose of sandbox pool | ||
return [4 /*yield*/, this.sandboxPool.disposeAll()]; | ||
case 2: | ||
result = _a.sent(); | ||
return [4 /*yield*/, this.sandboxPool.disposeAll()]; | ||
// TODO: Let typed inject dispose of sandbox pool | ||
_a.sent(); | ||
return [4 /*yield*/, this.mutantTranspileScheduler.dispose()]; | ||
case 3: | ||
_a.sent(); | ||
this.mutantTranspiler.dispose(); | ||
return [2 /*return*/, result]; | ||
return [2 /*return*/, results]; | ||
} | ||
@@ -82,54 +43,6 @@ }); | ||
}; | ||
MutationTestExecutor.prototype.runInsideSandboxes = function (sandboxes, transpiledMutants) { | ||
var recycleObserver; | ||
var recycled = new rxjs_1.Observable(function (observer) { | ||
recycleObserver = observer; | ||
}); | ||
function recycle(sandbox) { | ||
return recycleObserver.next(sandbox.sandbox); | ||
} | ||
function completeRecycle() { | ||
if (recycleObserver) { | ||
recycleObserver.complete(); | ||
} | ||
} | ||
return rxjs_1.zip(transpiledMutants, rxjs_1.merge(recycled, sandboxes), createTuple) | ||
.pipe(operators_1.map(this.earlyResult), operators_1.flatMap(this.runInSandbox), operators_1.tap(recycle), operators_1.map(function (_a) { | ||
var result = _a.result; | ||
return result; | ||
}), operators_1.tap(reportResult(this.reporter)), operators_1.toArray(), operators_1.tap(completeRecycle), operators_1.tap(reportAll(this.reporter))) | ||
.toPromise(Promise); | ||
}; | ||
MutationTestExecutor.inject = plugin_1.tokens(plugin_1.commonTokens.logger, di_1.coreTokens.inputFiles, di_1.coreTokens.reporter, di_1.coreTokens.mutantTranspiler, di_1.coreTokens.sandboxPool); | ||
MutationTestExecutor.inject = plugin_1.tokens(di_1.coreTokens.reporter, di_1.coreTokens.mutantTranspileScheduler, di_1.coreTokens.sandboxPool); | ||
return MutationTestExecutor; | ||
}()); | ||
exports.MutationTestExecutor = MutationTestExecutor; | ||
function createTuple(a, b) { | ||
return [a, b]; | ||
} | ||
function mutantState(runResult) { | ||
switch (runResult.status) { | ||
case test_runner_1.RunStatus.Timeout: | ||
return report_1.MutantStatus.TimedOut; | ||
case test_runner_1.RunStatus.Error: | ||
return report_1.MutantStatus.RuntimeError; | ||
case test_runner_1.RunStatus.Complete: | ||
if (runResult.tests.some(function (t) { return t.status === test_runner_1.TestStatus.Failed; })) { | ||
return report_1.MutantStatus.Killed; | ||
} | ||
else { | ||
return report_1.MutantStatus.Survived; | ||
} | ||
} | ||
} | ||
function reportResult(reporter) { | ||
return function (mutantResult) { | ||
reporter.onMutantTested(mutantResult); | ||
}; | ||
} | ||
function reportAll(reporter) { | ||
return function (mutantResults) { | ||
reporter.onAllMutantsTested(mutantResults); | ||
}; | ||
} | ||
//# sourceMappingURL=MutationTestExecutor.js.map |
@@ -7,5 +7,7 @@ import { StrykerOptions } from 'stryker-api/core'; | ||
import LoggingClientContext from './logging/LoggingClientContext'; | ||
import { MutantResult } from 'stryker-api/report'; | ||
export default class Sandbox { | ||
private readonly options; | ||
private readonly index; | ||
private readonly files; | ||
private readonly testFramework; | ||
@@ -17,3 +19,2 @@ private readonly timeOverheadMS; | ||
private fileMap; | ||
private readonly files; | ||
private readonly workingDirectory; | ||
@@ -25,3 +26,6 @@ private constructor(); | ||
dispose(): Promise<void>; | ||
runMutant(transpiledMutant: TranspiledMutant): Promise<RunResult>; | ||
runMutant(transpiledMutant: TranspiledMutant): Promise<MutantResult>; | ||
private readonly retrieveEarlyResult; | ||
private collectMutantResult; | ||
private determineMutantState; | ||
private reset; | ||
@@ -28,0 +32,0 @@ private writeFileInSandbox; |
@@ -7,2 +7,3 @@ "use strict"; | ||
var mkdirp = require("mkdirp"); | ||
var test_runner_1 = require("stryker-api/test_runner"); | ||
var objectUtils_1 = require("./utils/objectUtils"); | ||
@@ -13,6 +14,9 @@ var ResilientTestRunnerFactory_1 = require("./test-runner/ResilientTestRunnerFactory"); | ||
var TestableMutant_1 = require("./TestableMutant"); | ||
var report_1 = require("stryker-api/report"); | ||
var Sandbox = /** @class */ (function () { | ||
function Sandbox(options, index, files, testFramework, timeOverheadMS, loggingContext) { | ||
var _this = this; | ||
this.options = options; | ||
this.index = index; | ||
this.files = files; | ||
this.testFramework = testFramework; | ||
@@ -22,5 +26,25 @@ this.timeOverheadMS = timeOverheadMS; | ||
this.log = log4js_1.getLogger(Sandbox.name); | ||
this.retrieveEarlyResult = function (transpiledMutant) { | ||
if (transpiledMutant.transpileResult.error) { | ||
if (_this.log.isDebugEnabled()) { | ||
_this.log.debug("Transpile error occurred: \"" + transpiledMutant.transpileResult.error + "\" during transpiling of mutant " + transpiledMutant.mutant.toString()); | ||
} | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.TranspileError, []); | ||
return result; | ||
} | ||
else if (!transpiledMutant.mutant.selectedTests.length) { | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.NoCoverage, []); | ||
return result; | ||
} | ||
else if (!transpiledMutant.changedAnyTranspiledFiles) { | ||
var result = transpiledMutant.mutant.result(report_1.MutantStatus.Survived, []); | ||
return result; | ||
} | ||
else { | ||
// No early result possible, need to run in the sandbox later | ||
return null; | ||
} | ||
}; | ||
this.workingDirectory = TempFolder_1.TempFolder.instance().createRandomFolder('sandbox'); | ||
this.log.debug('Creating a sandbox for files in %s', this.workingDirectory); | ||
this.files = files.slice(); // Create a copy | ||
} | ||
@@ -54,3 +78,3 @@ Sandbox.prototype.initialize = function () { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var mutantFiles, runResult; | ||
var earlyResult, mutantFiles, runResult; | ||
var _this = this; | ||
@@ -60,2 +84,6 @@ return tslib_1.__generator(this, function (_a) { | ||
case 0: | ||
earlyResult = this.retrieveEarlyResult(transpiledMutant); | ||
if (!earlyResult) return [3 /*break*/, 1]; | ||
return [2 /*return*/, earlyResult]; | ||
case 1: | ||
mutantFiles = transpiledMutant.transpileResult.outputFiles; | ||
@@ -66,11 +94,11 @@ if (transpiledMutant.mutant.testSelectionResult === TestableMutant_1.TestSelectionResult.Failed) { | ||
return [4 /*yield*/, Promise.all(mutantFiles.map(function (mutatedFile) { return _this.writeFileInSandbox(mutatedFile); }))]; | ||
case 1: | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, this.run(this.calculateTimeout(transpiledMutant.mutant), this.getFilterTestsHooks(transpiledMutant.mutant), this.fileMap[transpiledMutant.mutant.fileName])]; | ||
case 2: | ||
case 3: | ||
runResult = _a.sent(); | ||
return [4 /*yield*/, this.reset(mutantFiles)]; | ||
case 3: | ||
case 4: | ||
_a.sent(); | ||
return [2 /*return*/, runResult]; | ||
return [2 /*return*/, this.collectMutantResult(transpiledMutant.mutant, runResult)]; | ||
} | ||
@@ -80,2 +108,28 @@ }); | ||
}; | ||
Sandbox.prototype.collectMutantResult = function (mutant, runResult) { | ||
var status = this.determineMutantState(runResult); | ||
var testNames = runResult.tests | ||
.filter(function (t) { return t.status !== test_runner_1.TestStatus.Skipped; }) | ||
.map(function (t) { return t.name; }); | ||
if (this.log.isDebugEnabled() && status === report_1.MutantStatus.RuntimeError) { | ||
var error = runResult.errorMessages ? runResult.errorMessages.toString() : '(undefined)'; | ||
this.log.debug('A runtime error occurred: %s during execution of mutant: %s', error, mutant.toString()); | ||
} | ||
return mutant.result(status, testNames); | ||
}; | ||
Sandbox.prototype.determineMutantState = function (runResult) { | ||
switch (runResult.status) { | ||
case test_runner_1.RunStatus.Timeout: | ||
return report_1.MutantStatus.TimedOut; | ||
case test_runner_1.RunStatus.Error: | ||
return report_1.MutantStatus.RuntimeError; | ||
case test_runner_1.RunStatus.Complete: | ||
if (runResult.tests.some(function (t) { return t.status === test_runner_1.TestStatus.Failed; })) { | ||
return report_1.MutantStatus.Killed; | ||
} | ||
else { | ||
return report_1.MutantStatus.Survived; | ||
} | ||
} | ||
}; | ||
Sandbox.prototype.reset = function (mutatedFiles) { | ||
@@ -146,3 +200,3 @@ var _this = this; | ||
fileNames = Object.keys(this.fileMap).map(function (sourceFileName) { return _this.fileMap[sourceFileName]; }); | ||
this.log.debug("Creating test runner %s using settings {port: %s}", this.index); | ||
this.log.debug("Creating test runner %s", this.index); | ||
this.testRunner = ResilientTestRunnerFactory_1.default.create(this.options, fileNames, this.workingDirectory, this.loggingContext); | ||
@@ -149,0 +203,0 @@ return [4 /*yield*/, this.testRunner.init()]; |
import { Observable } from 'rxjs'; | ||
import { File, StrykerOptions } from 'stryker-api/core'; | ||
import { TestFramework } from 'stryker-api/test_framework'; | ||
import Sandbox from './Sandbox'; | ||
import LoggingClientContext from './logging/LoggingClientContext'; | ||
import { InitialTestRunResult } from './process/InitialTestExecutor'; | ||
import { Logger } from 'stryker-api/logging'; | ||
import TranspiledMutant from './TranspiledMutant'; | ||
import { MutantResult } from 'stryker-api/report'; | ||
export declare class SandboxPool { | ||
@@ -12,11 +13,15 @@ private readonly log; | ||
private readonly testFramework; | ||
private readonly initialFiles; | ||
private readonly loggingContext; | ||
private readonly sandboxes; | ||
private readonly allSandboxes; | ||
private readonly overheadTimeMS; | ||
static inject: ["logger", "options", "testFramework", "initialRunResult", "loggingContext"]; | ||
constructor(log: Logger, options: StrykerOptions, testFramework: TestFramework | null, initialRunResult: InitialTestRunResult, loggingContext: LoggingClientContext); | ||
streamSandboxes(initialFiles: ReadonlyArray<File>): Observable<Sandbox>; | ||
private registerSandbox; | ||
static inject: ["logger", "options", "testFramework", "initialRunResult", "transpiledFiles", "loggingContext"]; | ||
constructor(log: Logger, options: StrykerOptions, testFramework: TestFramework | null, initialRunResult: InitialTestRunResult, initialFiles: ReadonlyArray<File>, loggingContext: LoggingClientContext); | ||
runMutants(mutants: Observable<TranspiledMutant>): Observable<MutantResult>; | ||
private readonly runInSandbox; | ||
private startSandboxes; | ||
private determineConcurrency; | ||
private readonly registerSandbox; | ||
disposeAll(): Promise<void[]>; | ||
} | ||
//# sourceMappingURL=SandboxPool.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tslib_1 = require("tslib"); | ||
var os = require("os"); | ||
@@ -9,13 +10,54 @@ var rxjs_1 = require("rxjs"); | ||
var di_1 = require("./di"); | ||
var MAX_CONCURRENT_INITIALIZING_SANDBOXES = 2; | ||
var SandboxPool = /** @class */ (function () { | ||
function SandboxPool(log, options, testFramework, initialRunResult, loggingContext) { | ||
function SandboxPool(log, options, testFramework, initialRunResult, initialFiles, loggingContext) { | ||
var _this = this; | ||
this.log = log; | ||
this.options = options; | ||
this.testFramework = testFramework; | ||
this.initialFiles = initialFiles; | ||
this.loggingContext = loggingContext; | ||
this.sandboxes = []; | ||
this.allSandboxes = []; | ||
this.runInSandbox = function (_a) { | ||
var mutant = _a[0], sandbox = _a[1]; | ||
return tslib_1.__awaiter(_this, void 0, void 0, function () { | ||
var result; | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, sandbox.runMutant(mutant)]; | ||
case 1: | ||
result = _b.sent(); | ||
return [2 /*return*/, { result: result, sandbox: sandbox }]; | ||
} | ||
}); | ||
}); | ||
}; | ||
this.registerSandbox = function (promisedSandbox) { return tslib_1.__awaiter(_this, void 0, void 0, function () { | ||
return tslib_1.__generator(this, function (_a) { | ||
this.allSandboxes.push(promisedSandbox); | ||
return [2 /*return*/, promisedSandbox]; | ||
}); | ||
}); }; | ||
this.overheadTimeMS = initialRunResult.overheadTimeMS; | ||
} | ||
SandboxPool.prototype.streamSandboxes = function (initialFiles) { | ||
SandboxPool.prototype.runMutants = function (mutants) { | ||
var recycledSandboxes = new rxjs_1.Subject(); | ||
// Make sure sandboxes get recycled | ||
var sandboxes = this.startSandboxes().pipe(operators_1.merge(recycledSandboxes)); | ||
return mutants.pipe(operators_1.zip(sandboxes), operators_1.flatMap(this.runInSandbox), operators_1.tap(function (_a) { | ||
var sandbox = _a.sandbox; | ||
recycledSandboxes.next(sandbox); | ||
}), operators_1.map(function (_a) { | ||
var result = _a.result; | ||
return result; | ||
})); | ||
}; | ||
SandboxPool.prototype.startSandboxes = function () { | ||
var _this = this; | ||
var concurrency = this.determineConcurrency(); | ||
return rxjs_1.range(0, concurrency).pipe(operators_1.flatMap(function (n) { | ||
return _this.registerSandbox(Sandbox_1.default.create(_this.options, n, _this.initialFiles, _this.testFramework, _this.overheadTimeMS, _this.loggingContext)); | ||
}, MAX_CONCURRENT_INITIALIZING_SANDBOXES)); | ||
}; | ||
SandboxPool.prototype.determineConcurrency = function () { | ||
var numConcurrentRunners = os.cpus().length; | ||
@@ -35,14 +77,18 @@ if (this.options.transpilers.length) { | ||
this.log.info("Creating " + numConcurrentRunners + " test runners (based on " + numConcurrentRunnersSource + ")"); | ||
var sandboxes = rxjs_1.range(0, numConcurrentRunners) | ||
.pipe(operators_1.flatMap(function (n) { return _this.registerSandbox(Sandbox_1.default.create(_this.options, n, initialFiles, _this.testFramework, _this.overheadTimeMS, _this.loggingContext)); })); | ||
return sandboxes; | ||
return numConcurrentRunners; | ||
}; | ||
SandboxPool.prototype.registerSandbox = function (promisedSandbox) { | ||
this.sandboxes.push(promisedSandbox); | ||
return promisedSandbox; | ||
}; | ||
SandboxPool.prototype.disposeAll = function () { | ||
return Promise.all(this.sandboxes.map(function (promisedSandbox) { return promisedSandbox.then(function (sandbox) { return sandbox.dispose(); }); })); | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var sandboxes; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, Promise.all(this.allSandboxes)]; | ||
case 1: | ||
sandboxes = _a.sent(); | ||
return [2 /*return*/, Promise.all(sandboxes.map(function (sandbox) { return sandbox.dispose(); }))]; | ||
} | ||
}); | ||
}); | ||
}; | ||
SandboxPool.inject = plugin_1.tokens(plugin_1.commonTokens.logger, plugin_1.commonTokens.options, di_1.coreTokens.testFramework, di_1.coreTokens.initialRunResult, di_1.coreTokens.loggingContext); | ||
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); | ||
return SandboxPool; | ||
@@ -49,0 +95,0 @@ }()); |
@@ -16,4 +16,5 @@ "use strict"; | ||
var plugin_1 = require("stryker-api/plugin"); | ||
var MutantTranspiler_1 = require("./transpiler/MutantTranspiler"); | ||
var MutantTranspileScheduler_1 = require("./transpiler/MutantTranspileScheduler"); | ||
var SandboxPool_1 = require("./SandboxPool"); | ||
var transpiler_1 = require("./transpiler"); | ||
var Stryker = /** @class */ (function () { | ||
@@ -56,3 +57,3 @@ /** | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var loggingContext, inputFiles, inputFileInjector, initialTestRunProcess, initialRunResult, mutator, mutationTestProcessInjector, testableMutants, mutationTestExecutor, mutantResults; | ||
var loggingContext, inputFiles, inputFileInjector, initialTestRunProcess, initialRunResult, mutator, transpilerProvider, transpiler, transpiledFiles, mutationTestProcessInjector, testableMutants, mutationTestExecutor, mutantResults; | ||
return tslib_1.__generator(this, function (_a) { | ||
@@ -67,3 +68,3 @@ switch (_a.label) { | ||
inputFiles = _a.sent(); | ||
if (!inputFiles.files.length) return [3 /*break*/, 11]; | ||
if (!inputFiles.files.length) return [3 /*break*/, 12]; | ||
TempFolder_1.TempFolder.instance().initialize(); | ||
@@ -82,5 +83,13 @@ inputFileInjector = this.injector | ||
mutator = inputFileInjector.injectClass(MutatorFacade_1.MutatorFacade); | ||
mutationTestProcessInjector = inputFileInjector | ||
transpilerProvider = inputFileInjector | ||
.provideValue(di_1.coreTokens.initialRunResult, initialRunResult) | ||
.provideClass(di_1.coreTokens.mutantTranspiler, MutantTranspiler_1.default) | ||
.provideValue(plugin_1.commonTokens.produceSourceMaps, false) | ||
.provideFactory(di_1.coreTokens.transpiler, transpiler_1.transpilerFactory); | ||
transpiler = transpilerProvider.resolve(di_1.coreTokens.transpiler); | ||
return [4 /*yield*/, transpiler.transpile(inputFiles.files)]; | ||
case 4: | ||
transpiledFiles = _a.sent(); | ||
mutationTestProcessInjector = transpilerProvider | ||
.provideValue(di_1.coreTokens.transpiledFiles, transpiledFiles) | ||
.provideClass(di_1.coreTokens.mutantTranspileScheduler, MutantTranspileScheduler_1.MutantTranspileScheduler) | ||
.provideClass(di_1.coreTokens.sandboxPool, SandboxPool_1.SandboxPool); | ||
@@ -90,27 +99,27 @@ return [4 /*yield*/, mutationTestProcessInjector | ||
.matchWithMutants(mutator.mutate(inputFiles.filesToMutate))]; | ||
case 4: | ||
case 5: | ||
testableMutants = _a.sent(); | ||
if (!(initialRunResult.runResult.tests.length && testableMutants.length)) return [3 /*break*/, 10]; | ||
if (!(initialRunResult.runResult.tests.length && testableMutants.length)) return [3 /*break*/, 11]; | ||
mutationTestExecutor = mutationTestProcessInjector.injectClass(MutationTestExecutor_1.MutationTestExecutor); | ||
return [4 /*yield*/, mutationTestExecutor.run(testableMutants)]; | ||
case 5: | ||
case 6: | ||
mutantResults = _a.sent(); | ||
this.reportScore(mutantResults); | ||
return [4 /*yield*/, this.wrapUpReporter()]; | ||
case 6: | ||
case 7: | ||
_a.sent(); | ||
return [4 /*yield*/, TempFolder_1.TempFolder.instance().clean()]; | ||
case 7: | ||
case 8: | ||
_a.sent(); | ||
return [4 /*yield*/, this.logDone()]; | ||
case 8: | ||
case 9: | ||
_a.sent(); | ||
return [4 /*yield*/, LogConfigurator_1.default.shutdown()]; | ||
case 9: | ||
case 10: | ||
_a.sent(); | ||
return [2 /*return*/, mutantResults]; | ||
case 10: | ||
case 11: | ||
this.logRemark(); | ||
_a.label = 11; | ||
case 11: return [2 /*return*/, Promise.resolve([])]; | ||
_a.label = 12; | ||
case 12: return [2 /*return*/, Promise.resolve([])]; | ||
} | ||
@@ -120,15 +129,2 @@ }); | ||
}; | ||
// private mutate(input: InputFileCollection, initialTestRunResult: InitialTestRunResult): TestableMutant[] { | ||
// const mutator = this.injector.injectClass(MutatorFacade); | ||
// const mutants = mutator.mutate(input.filesToMutate); | ||
// const mutantRunResultMatcher = new MutantTestMatcher( | ||
// mutants, | ||
// input.filesToMutate, | ||
// initialTestRunResult.runResult, | ||
// initialTestRunResult.sourceMapper, | ||
// initialTestRunResult.coverageMaps, | ||
// this.config, | ||
// this.reporter); | ||
// return mutantRunResultMatcher.matchWithMutants(); | ||
// } | ||
Stryker.prototype.wrapUpReporter = function () { | ||
@@ -135,0 +131,0 @@ var maybePromise = this.reporter.wrapUp(); |
@@ -13,4 +13,4 @@ import { TimeoutExpired } from './objectUtils'; | ||
readonly isCompleted: boolean; | ||
resolve(result: T | PromiseLike<T>): void; | ||
reject(reason: any): void; | ||
resolve: (result: T | PromiseLike<T>) => void; | ||
reject: (reason: any) => void; | ||
} | ||
@@ -17,0 +17,0 @@ /** |
@@ -12,2 +12,10 @@ "use strict"; | ||
this._isCompleted = false; | ||
this.resolve = function (result) { | ||
_this._isCompleted = true; | ||
_this.resolveFn(result); | ||
}; | ||
this.reject = function (reason) { | ||
_this._isCompleted = true; | ||
_this.rejectFn(reason); | ||
}; | ||
this._promise = new Promise(function (resolve, reject) { | ||
@@ -32,10 +40,2 @@ _this.resolveFn = resolve; | ||
}); | ||
Task.prototype.resolve = function (result) { | ||
this._isCompleted = true; | ||
this.resolveFn(result); | ||
}; | ||
Task.prototype.reject = function (reason) { | ||
this._isCompleted = true; | ||
this.rejectFn(reason); | ||
}; | ||
return Task; | ||
@@ -42,0 +42,0 @@ }()); |
457744
217
8048
9
+ Addedasync@2.6.4(transitive)
+ Addeddate-format@2.1.0(transitive)
+ Addedflatted@2.0.2(transitive)
+ Addedfs-extra@7.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedistanbul-lib-instrument@3.1.2(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedlog4js@4.0.2(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedstreamroller@1.0.6(transitive)
+ Addedsurrial@1.0.0(transitive)
+ Addedtyped-inject@1.0.0(transitive)
+ Addedtyped-rest-client@1.1.2(transitive)
+ Addeduniversalify@0.1.2(transitive)
- Removedassertion-error@1.1.0(transitive)
- Removedcall-bind@1.0.8(transitive)
- Removedcall-bind-apply-helpers@1.0.1(transitive)
- Removedcall-bound@1.0.3(transitive)
- Removedchai@4.5.0(transitive)
- Removedcheck-error@1.0.3(transitive)
- Removedcircular-json@0.5.9(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddate-format@1.2.0(transitive)
- Removeddeep-eql@4.1.4(transitive)
- Removeddeep-equal@1.1.2(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removeddunder-proto@1.0.1(transitive)
- Removedes-define-property@1.0.1(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-object-atoms@1.1.1(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedfunctions-have-names@1.2.3(transitive)
- Removedget-func-name@2.0.2(transitive)
- Removedget-intrinsic@1.2.7(transitive)
- Removedget-proto@1.0.1(transitive)
- Removedgopd@1.2.0(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-symbols@1.1.0(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedis-arguments@1.2.0(transitive)
- Removedis-date-object@1.1.0(transitive)
- Removedis-regex@1.2.1(transitive)
- Removedisarray@1.0.0(transitive)
- Removedistanbul-lib-instrument@3.0.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedlog4js@3.0.6(transitive)
- Removedloupe@2.3.7(transitive)
- Removedmath-intrinsics@1.1.0(transitive)
- Removednock@9.6.1(transitive)
- Removedobject-inspect@1.13.3(transitive)
- Removedobject-is@1.1.6(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedpathval@1.1.1(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedpropagate@1.0.0(transitive)
- Removedqs@6.14.0(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedregexp.prototype.flags@1.5.4(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedsemver@5.7.2(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedset-function-name@2.0.2(transitive)
- Removedside-channel@1.1.0(transitive)
- Removedside-channel-list@1.0.0(transitive)
- Removedside-channel-map@1.0.1(transitive)
- Removedside-channel-weakmap@1.0.2(transitive)
- Removedstreamroller@0.7.0(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedsurrial@0.2.0(transitive)
- Removedtype-detect@4.1.0(transitive)
- Removedtyped-inject@0.2.1(transitive)
- Removedtyped-rest-client@1.0.11(transitive)
- Removedutil-deprecate@1.0.2(transitive)
Updatedlog4js@~4.0.2
Updatedsurrial@~1.0.0
Updatedtyped-inject@~1.0.0
Updatedtyped-rest-client@~1.1.2