Stryker

IsolatedTestRunnerAdapter.js - Stryker report

Summary

File
Mutation score
# Killed
# Survived
# Timeout
# No coverage
# Errors
Total detected
Total undetected
Total mutants
IsolatedTestRunnerAdapter.js
61%
38/62 38 18 0 6 0 38 24 62

Code

"use strict";
var __extends = 0(1this && this.__extends) || function (d, b) 2{
    for (var p in b) if (34b.hasOwnProperty(p)) d[p] = b[p];
    function __() 5{ this.constructor = d; }
    d.prototype = 678b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var test_runner_1 = require('stryker-api/test_runner');
var child_process_1 = require('child_process');
var _ = require('lodash');
var log4js = require('log4js');
var events_1 = require('events');
var objectUtils_1 = require('../utils/objectUtils');
var log = log4js.getLogger('IsolatedTestRunnerAdapter');
var MAX_WAIT_FOR_DISPOSE = 2000;
/**
 * Runs the given test runner in a child process and forwards reports about test results
 * Also implements timeout-mechanisme (on timeout, restart the child runner and report timeout)
 */
var TestRunnerChildProcessAdapter = (function (_super) 9{
    __extends(TestRunnerChildProcessAdapter, _super);
    function TestRunnerChildProcessAdapter(realTestRunnerName, options) 10{
        _super.call(this);
        this.realTestRunnerName = realTestRunnerName;
        this.options = options;
        this.startWorker();
    }
    TestRunnerChildProcessAdapter.prototype.startWorker = function () 11{
        // Remove --debug-brk from process arguments. 
        // When debugging, it will try to reuse the same debug port, which will be taken by the main process.
        var execArgv = _.clone(process.execArgv);
        _.remove(execArgv, function (arg) 12{ return 13arg.substr(0, 11) === '--debug-brk'; });
        this.workerProcess = child_process_1.fork(14__dirname + "/IsolatedTestRunnerAdapterWorker", [], { silent: true, execArgv: execArgv });
        this.sendStartCommand();
        this.listenToWorkerProcess();
    };
    TestRunnerChildProcessAdapter.prototype.listenToWorkerProcess = function () 15{
        var _this = this;
        if (1617this.workerProcess.stdout) 18{
            var traceEnabled_1 = log.isTraceEnabled();
            this.workerProcess.stdout.on('data', function (data) 19{
                if (2021traceEnabled_1) 22{
                    log.trace(data.toString());
                }
            });
        }
        if (2324this.workerProcess.stderr) 25{
            this.workerProcess.stderr.on('data', function (data) 26{
                log.error(data.toString());
            });
        }
        this.workerProcess.on('message', function (message) 27{
            _this.clearCurrentTimer();
            switch (message.kind) {
                case 'result':
                    if (2829!_this.isDisposing) 30{
                        _this.runPromiseFulfillmentCallback(message.result);
                    }
                    break;
                case 'initDone':
                    _this.initPromiseFulfillmentCallback();
                    break;
                case 'disposeDone':
                    _this.disposePromiseFulfillmentCallback();
                    break;
                default:
                    _this.logReceivedMessageWarning(message);
                    break;
            }
        });
    };
    TestRunnerChildProcessAdapter.prototype.logReceivedMessageWarning = function (message) 31{
        log.error(32"Retrieved unrecognized message from child process: " + JSON.stringify(message));
    };
    TestRunnerChildProcessAdapter.prototype.init = function () 33{
        var _this = this;
        this.initPromise = new Promise(function (resolve) 34{ return _this.initPromiseFulfillmentCallback = resolve; });
        this.sendInitCommand();
        return this.initPromise;
    };
    TestRunnerChildProcessAdapter.prototype.run = function (options) 35{
        var _this = this;
        this.clearCurrentTimer();
        if (3637options.timeout) 38{
            this.markNoResultTimeout(options.timeout);
        }
        this.runPromise = new Promise(function (resolve) 39{
            _this.runPromiseFulfillmentCallback = resolve;
            _this.sendRunCommand(options);
            _this.currentRunStartedTimestamp = new Date();
        });
        return this.runPromise;
    };
    TestRunnerChildProcessAdapter.prototype.dispose = function () 40{
        var _this = this;
        if (4142this.isDisposing) 43{
            return this.disposingPromise;
        }
        else 44{
            this.isDisposing = true;
            this.disposingPromise = new Promise(function (resolve) 45{ return _this.disposePromiseFulfillmentCallback = resolve; })
                .then(function () 46{
                clearTimeout(timer_1);
                _this.workerProcess.kill();
                _this.isDisposing = false;
            });
            this.clearCurrentTimer();
            this.sendDisposeCommand();
            var timer_1 = setTimeout(this.disposePromiseFulfillmentCallback, MAX_WAIT_FOR_DISPOSE);
            return this.disposingPromise;
        }
    };
    TestRunnerChildProcessAdapter.prototype.sendRunCommand = function (options) 47{
        this.send({
            kind: 'run',
            runOptions: options
        });
    };
    TestRunnerChildProcessAdapter.prototype.send = function (message) 48{
        // Serialize message before sending to preserve all javascript, including regexes and functions
        // See https://github.com/stryker-mutator/stryker/issues/143
        this.workerProcess.send(objectUtils_1.serialize(message));
    };
    TestRunnerChildProcessAdapter.prototype.sendStartCommand = function () 49{
        this.send({
            kind: 'start',
            runnerName: this.realTestRunnerName,
            runnerOptions: this.options
        });
    };
    TestRunnerChildProcessAdapter.prototype.sendInitCommand = function () 50{
        this.send({ kind: 'init' });
    };
    TestRunnerChildProcessAdapter.prototype.sendDisposeCommand = function () 51{
        this.send({ kind: 'dispose' });
    };
    TestRunnerChildProcessAdapter.prototype.clearCurrentTimer = function () 52{
        if (5354this.currentTimeoutTimer) 55{
            clearTimeout(this.currentTimeoutTimer);
        }
    };
    TestRunnerChildProcessAdapter.prototype.markNoResultTimeout = function (timeoutMs) 56{
        var _this = this;
        this.currentTimeoutTimer = setTimeout(function () 57{
            _this.handleTimeout();
        }, timeoutMs);
    };
    TestRunnerChildProcessAdapter.prototype.handleTimeout = function () 58{
        var _this = this;
        this.dispose()
            .then(function () 59{ return _this.startWorker(); })
            .then(function () 60{ return _this.init(); })
            .then(function () 61{ return _this.runPromiseFulfillmentCallback({ status: test_runner_1.RunStatus.Timeout, tests: [] }); });
    };
    return TestRunnerChildProcessAdapter;
}(events_1.EventEmitter));
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = TestRunnerChildProcessAdapter;
//# sourceMappingURL=IsolatedTestRunnerAdapter.js.map