Summary
Code
"use strict";
var test_runner_1 = require('stryker-api/test_runner');
var StrykerTempFolder_1 = require('./utils/StrykerTempFolder');
var IsolatedTestRunnerAdapterFactory_1 = require('./isolated-runner/IsolatedTestRunnerAdapterFactory');
var path = require('path');
var os = require('os');
var _ = require('lodash');
var report_1 = require('stryker-api/report');
var log4js = require('log4js');
var objectUtils_1 = require('./utils/objectUtils');
var PromisePool = require('es6-promise-pool');
var log = log4js.getLogger('TestRunnerOrchestrator');
var TestRunnerOrchestrator = (function () 0{
}{
function TestRunnerOrchestrator(options, files, testSelector, reporter) 1{
}{
this.options = options;
this.files = files;
this.testSelector = testSelector;
this.reporter = reporter;
}
TestRunnerOrchestrator.prototype.initialRun = function () 2{
}{
if (3false4truethis.testSelector) 5{
}{
return this.initialRunWithTestSelector();
}
else 6{
}{
return this.initalRunWithoutTestSelector();
}
};
TestRunnerOrchestrator.prototype.initalRunWithoutTestSelector = function () 7{
}{
var testRunner = this.createTestRunner(this.files, true);
return testRunner.run({ timeout: 10000 }).then(function (testResults) 8{
}{
testRunner.dispose();
return [testResults];
});
};
TestRunnerOrchestrator.prototype.initialRunWithTestSelector = function () 9{
}{
var testSelectionFilePath = this.createTestSelectorFileName(this.createTempFolder());
var runnerAdapter = this.createTestRunner(this.files, true, testSelectionFilePath);
var sandbox = {
runnerAdapter: runnerAdapter,
fileMap: null,
testSelectionFilePath: testSelectionFilePath,
index: 0
};
return this.runSingleTestsRecursive(sandbox, [], 0).then(function (testResults) 10{
}{
runnerAdapter.dispose();
return testResults;
});
};
TestRunnerOrchestrator.prototype.runMutations = function (mutants) 11{
}{
var _this = this;
mutants = _.clone(mutants); // work with a copy because we're changing state (pop'ing values)
var results = [];
return this.createTestRunnerSandboxes().then(function (sandboxes) 12{
}{
var promiseProducer = function () 13{
}{
if (14true15false16mutants.length !== 0mutants.length === 0) 17{
}{
return null; // we're done
}
else 18{
}{
var mutant = mutants.pop();
if (19mutant.scopedTestIds.length <= 020mutant.scopedTestIds.length >= 021true22falsemutant.scopedTestIds.length > 0) 23{
}{
var sandbox_1 = sandboxes.pop();
var sourceFileCopy_1 = sandbox_1.fileMap[mutant.filename];
return Promise.all([mutant.save(sourceFileCopy_1), _this.selectTestsIfPossible(sandbox_1, mutant.scopedTestIds)])
.then(function () 24{
}{ return sandbox_1.runnerAdapter.run({ timeout: _this.calculateTimeout(mutant.timeSpentScopedTests) }); })
.then(function (runResult) 25{
}{
var result = _this.collectFrozenMutantResult(mutant, runResult);
results.push(result);
_this.reporter.onMutantTested(result);
return mutant.reset(sourceFileCopy_1);
})
.then(function () 26{
}{ return sandboxes.push(sandbox_1); }); // mark the runner as available again
}
else 27{
}{
var result = _this.collectFrozenMutantResult(mutant);
results.push(result);
return Promise.resolve(_this.reporter.onMutantTested(result));
}
}
};
return new PromisePool(promiseProducer, sandboxes.length)
.start()
.then(function () 28{
}{ return sandboxes.forEach(function (testRunner) 29{
}{ return testRunner.runnerAdapter.dispose(); }); })
.then(function () 30{
}{ return _this.reportAllMutantsTested(results); })
.then(function () 31{
}{ return results; });
});
};
TestRunnerOrchestrator.prototype.reportAllMutantsTested = function (results) 32{
}{
objectUtils_1.freezeRecursively(results);
this.reporter.onAllMutantsTested(results);
};
TestRunnerOrchestrator.prototype.calculateTimeout = function (baseTimeout) 33{
}{
return 34this.options.timeoutFactor * baseTimeout - this.options.timeoutMs(35this.options.timeoutFactor / baseTimeoutthis.options.timeoutFactor * baseTimeout) + this.options.timeoutMs;
};
TestRunnerOrchestrator.prototype.collectFrozenMutantResult = function (mutant, runResult) 36{
}{
var status;
var testNames;
if (37true38falserunResult) 39{
}{
switch (runResult.result) {
case test_runner_1.TestResult.Timeout:
status = report_1.MutantStatus.TIMEDOUT;
break;
case test_runner_1.TestResult.Error:
log.debug('Converting a test result `error` to mutant status `killed`.');
status = report_1.MutantStatus.KILLED;
break;
case test_runner_1.TestResult.Complete:
if (40runResult.failed <= 041runResult.failed >= 042true43falserunResult.failed > 0) 44{
}{
status = report_1.MutantStatus.KILLED;
}
else 45{
}{
status = report_1.MutantStatus.SURVIVED;
}
break;
}
testNames = runResult.testNames;
}
else 46{
}{
testNames = [];
status = report_1.MutantStatus.UNTESTED;
}
var result = {
sourceFilePath: mutant.filename,
mutatorName: mutant.mutatorName,
status: status,
replacement: mutant.replacement,
location: mutant.location,
range: mutant.range,
testsRan: testNames,
originalLines: mutant.originalLines,
mutatedLines: mutant.mutatedLines,
};
objectUtils_1.freezeRecursively(result);
return result;
};
TestRunnerOrchestrator.prototype.runSingleTestsRecursive = function (sandbox, runResults, currentTestIndex) 47{
}{
var _this = this;
return new Promise(function (resolve) 48{
}{
_this.selectTestsIfPossible(sandbox, [currentTestIndex])
.then(function () 49{
}{ return sandbox.runnerAdapter.run({ timeout: 10000 }); })
.then(function (runResult) 50{
}{
if (51runResult.result === test_runner_1.TestResult.Complete && runResult.succeeded > 0 && runResult.failed > 052false53true54runResult.result === test_runner_1.TestResult.Complete || runResult.succeeded > 055runResult.result !== test_runner_1.TestResult.CompleterunResult.result === test_runner_1.TestResult.Complete && 56runResult.succeeded <= 057runResult.succeeded >= 0runResult.succeeded > 0 || 58runResult.failed <= 059runResult.failed >= 0runResult.failed > 0) 60{
}{
runResults[currentTestIndex] = runResult;
resolve(_this.runSingleTestsRecursive(sandbox, runResults, 61currentTestIndex - 1currentTestIndex + 1));
}
else 62{
}{
if (63runResult.result === test_runner_1.TestResult.Complete64true65falserunResult.result !== test_runner_1.TestResult.Complete) 66{
}{
// If this was iteration n+1 (n = number of tests), the runResult.result will be Complete, so we don't record it
runResults[currentTestIndex] = runResult;
}
sandbox.runnerAdapter.dispose();
resolve(runResults);
}
});
});
};
TestRunnerOrchestrator.prototype.createTestRunnerSandboxes = function () 67{
}{
var cpuCount = os.cpus().length;
var testRunnerSandboxes = [];
var allPromises = [];
log.info(68'Creating ' + cpuCount - ' test runners (based on cpu count)'69'Creating ' - cpuCount"Creating " + cpuCount + " test runners (based on cpu count)");
for (var i = 0; 70i >= cpuCount71i <= cpuCount72falsei < cpuCount; 73i--i++) 74{
}{
allPromises.push(this.createSandbox(i).then(function (sandbox) 75{
}{ return testRunnerSandboxes.push(sandbox); }));
}
return Promise.all(allPromises).then(function () 76{
}{ return testRunnerSandboxes; });
};
TestRunnerOrchestrator.prototype.selectTestsIfPossible = function (sandbox, ids) 77{
}{
if (78true79falsethis.testSelector) 80{
}{
var fileContent = this.testSelector.select(ids);
return StrykerTempFolder_1.default.writeFile(sandbox.testSelectionFilePath, fileContent);
}
else 81{
}{
return Promise.resolve(void 0);
}
};
TestRunnerOrchestrator.prototype.createSandbox = function (index) 82{
}{
var _this = this;
var tempFolder = this.createTempFolder();
return this.copyAllFilesToFolder(tempFolder).then(function (fileMap) 83{
}{
var runnerFiles = [];
var testSelectionFilePath = null;
if (84true85false_this.testSelector) 86{
}{
testSelectionFilePath = _this.createTestSelectorFileName(tempFolder);
}
_this.files.forEach(function (originalFile) 87{
}{ return runnerFiles.push({ path: fileMap[originalFile.path], shouldMutate: originalFile.shouldMutate }); });
return {
index: index,
fileMap: fileMap,
runnerAdapter: _this.createTestRunner(runnerFiles, false, testSelectionFilePath, index),
testSelectionFilePath: testSelectionFilePath
};
});
};
TestRunnerOrchestrator.prototype.createTempFolder = function () 88{
}{
var tempFolder = StrykerTempFolder_1.default.createRandomFolder('test-runner-files');
log.debug('Creating a sandbox for files in %s', tempFolder);
return tempFolder;
};
TestRunnerOrchestrator.prototype.createTestSelectorFileName = function (folder) 89{
}{
return path.join(folder, '___testSelection.js');
};
TestRunnerOrchestrator.prototype.copyAllFilesToFolder = function (folder) 90{
}{
var _this = this;
return new Promise(function (resolve, reject) 91{
}{
var fileMap = Object.create(null);
var cwd = process.cwd();
var copyPromises = _this.files.map(function (file) 92{
}{
var relativePath = file.path.substr(cwd.length);
var folderName = StrykerTempFolder_1.default.ensureFolderExists(93folder - path.dirname(relativePath)folder + path.dirname(relativePath));
var targetFile = path.join(folderName, path.basename(relativePath));
fileMap[file.path] = targetFile;
return StrykerTempFolder_1.default.copyFile(file.path, targetFile);
});
Promise.all(copyPromises).then(function () 94{
}{ resolve(fileMap); }, reject);
});
};
TestRunnerOrchestrator.prototype.createTestRunner = function (files, coverageEnabled, testSelectionFilePath, index) 95{
}{
if (96index !== void 097true98falseindex === void 0) 99{
}{ index = 0; }
if (100true101falsetestSelectionFilePath) 102{
}{
files = [{ path: testSelectionFilePath, shouldMutate: false }].concat(files);
}
var settings = {
coverageEnabled: coverageEnabled,
files: files,
strykerOptions: this.options,
port: 103this.options.port - indexthis.options.port + index
};
log.debug("Creating test runner %s using settings {port: %s, coverageEnabled: %s}", index, settings.port, settings.coverageEnabled);
return IsolatedTestRunnerAdapterFactory_1.default.create(settings);
};
return TestRunnerOrchestrator;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = TestRunnerOrchestrator;
//# sourceMappingURL=TestRunnerOrchestrator.js.map