Skip to content

Commit

Permalink
fix avajs#342 set child process debug port to available
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Mar 7, 2016
1 parent a03f826 commit 77d3e86
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 69 deletions.
127 changes: 83 additions & 44 deletions api.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var resolveCwd = require('resolve-cwd');
var uniqueTempDir = require('unique-temp-dir');
var findCacheDir = require('find-cache-dir');
var slash = require('slash');
var getPort = require('get-port');
var AvaError = require('./lib/ava-error');
var fork = require('./lib/fork');
var formatter = require('./lib/enhance-assert').formatter();
Expand Down Expand Up @@ -61,19 +62,44 @@ Api.prototype._reset = function () {
this.base = '';
};

Api.prototype._runFile = function (file) {
Api.prototype._runFile = function (file, onForkStarting) {
var options = objectAssign({}, this.options, {
precompiled: this.precompiler.generateHashForFile(file)
});

return fork(file, options)
.on('teardown', this._handleTeardown)
.on('stats', this._handleStats)
.on('test', this._handleTest)
.on('unhandledRejections', this._handleRejections)
.on('uncaughtException', this._handleExceptions)
.on('stdout', this._handleOutput.bind(this, 'stdout'))
.on('stderr', this._handleOutput.bind(this, 'stderr'));
var execArgv = process.execArgv.slice();
var debugArgIndex = -1;
for (var i = 0; i < execArgv.length; i++) {
if (execArgv[i].indexOf('--debug-brk=') === 0 || execArgv[i].indexOf('--debug=') === 0) {
debugArgIndex = i;
break;
}
}

var execArgvPromise;
if (debugArgIndex === -1) {
execArgvPromise = Promise.resolve(execArgv);
} else {
execArgvPromise = getPort()
.then(function (port) {
execArgv[debugArgIndex] = '--debug-brk=' + port;
return execArgv;
});
}

return execArgvPromise
.then(function (execArgv) {
var result = fork(file, options, execArgv)
.on('teardown', this._handleTeardown)
.on('stats', this._handleStats)
.on('test', this._handleTest)
.on('unhandledRejections', this._handleRejections)
.on('uncaughtException', this._handleExceptions)
.on('stdout', this._handleOutput.bind(this, 'stdout'))
.on('stderr', this._handleOutput.bind(this, 'stderr'));
onForkStarting(result);
return result.promise;
}.bind(this));
};

Api.prototype._handleOutput = function (channel, data) {
Expand Down Expand Up @@ -191,44 +217,57 @@ Api.prototype.run = function (files) {
self.fileCount = files.length;
self.base = path.relative('.', commonPathPrefix(files)) + path.sep;

var tests = files.map(self._runFile);

// receive test count from all files and then run the tests
var statsCount = 0;

return new Promise(function (resolve) {
tests.forEach(function (test) {
function tryRun() {
if (++statsCount === self.fileCount) {
self.emit('ready');

var method = self.options.serial ? 'mapSeries' : 'map';
var options = {
runOnlyExclusive: self.hasExclusive
};

resolve(Promise[method](files, function (file, index) {
return tests[index].run(options).catch(function (err) {
// The test failed catastrophically. Flag it up as an
// exception, then return an empty result. Other tests may
// continue to run.
self._handleExceptions({
exception: err,
file: file
});

return {
stats: {passCount: 0, skipCount: 0, todoCount: 0, failCount: 0},
tests: []
};
// receive test count from all files and then run the tests
var statsCount = 0;

var tests = new Array(files.length);
files.forEach(function (file, index) {
self._runFile(file, function (forkManager) {
tests[index] = forkManager;
forkManager.on('stats', tryRun);
})
.catch(function (error) {
tests[index] = {
run: function () {
return this;
},
promise: Promise.reject(error),
then: function () {
return this.promise.then.apply(this.promise, arguments);
}
};
tryRun();
});
});

function tryRun() {
if (++statsCount === self.fileCount) {
self.emit('ready');

var method = self.options.serial ? 'mapSeries' : 'map';
var options = {
runOnlyExclusive: self.hasExclusive
};

resolve(Promise[method](files, function (file, index) {
return tests[index].run(options).promise.catch(function (err) {
// The test failed catastrophically. Flag it up as an
// exception, then return an empty result. Other tests may
// continue to run.
self._handleExceptions({
exception: err,
file: file
});
}));
}
}

test.on('stats', tryRun);
test.catch(tryRun);
});
return {
stats: {passCount: 0, skipCount: 0, todoCount: 0, failCount: 0},
tests: []
};
});
}));
}
}
});
})
.then(function (results) {
Expand Down
52 changes: 27 additions & 25 deletions lib/fork.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if (env.NODE_PATH) {
.join(path.delimiter);
}

module.exports = function (file, opts) {
module.exports = function (file, opts, execArgv) {
opts = objectAssign({
file: file,
tty: process.stdout.isTTY ? {
Expand All @@ -33,7 +33,8 @@ module.exports = function (file, opts) {
var ps = childProcess.fork(path.join(__dirname, 'test-worker.js'), [JSON.stringify(opts)], {
cwd: path.dirname(file),
silent: true,
env: env
env: env,
execArgv: execArgv
});

var relFile = path.relative('.', file);
Expand Down Expand Up @@ -115,37 +116,38 @@ module.exports = function (file, opts) {
}
});

promise.on = function () {
ps.on.apply(ps, arguments);

return promise;
};

promise.send = function (name, data) {
send(ps, name, data);

return promise;
};

// send 'run' event only when fork is listening for it
var isReady = false;

ps.on('stats', function () {
isReady = true;
});

promise.run = function (options) {
if (isReady) {
send(ps, 'run', options);
return promise;
}
return {
promise: promise,
on: function () {
ps.on.apply(ps, arguments);
return this;
},
send: function (name, data) {
send(ps, name, data);
return this;
},
run: function (options) {
if (isReady) {
send(ps, 'run', options);
return this;
}

ps.on('stats', function () {
send(ps, 'run', options);
});
ps.on('stats', function () {
send(ps, 'run', options);
});

return promise;
return this;
},
then: function () {
// only to simplify test code, in production use .promise
return promise.then.apply(promise, arguments);
}
};

return promise;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"figures": "^1.4.0",
"find-cache-dir": "^0.1.1",
"fn-name": "^2.0.0",
"get-port": "^2.1.0",
"globby": "^4.0.0",
"ignore-by-default": "^1.0.0",
"is-ci": "^1.0.7",
Expand Down

0 comments on commit 77d3e86

Please sign in to comment.