Skip to content

Commit

Permalink
Support for wtfnode
Browse files Browse the repository at this point in the history
  • Loading branch information
johanblumenberg committed Jun 9, 2019
1 parent d48474e commit f160a66
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 2 deletions.
45 changes: 44 additions & 1 deletion bin/_mocha
Expand Up @@ -7,9 +7,12 @@
* Module dependencies.
*/

const wtfnode = require('wtfnode');

const program = require('commander');
const path = require('path');
const fs = require('fs');
const ms = require('ms');
const minimatch = require('minimatch');
const resolve = path.resolve;
const exists = fs.existsSync;
Expand All @@ -31,6 +34,18 @@ const setInterval = global.setInterval;
const clearTimeout = global.clearTimeout;
const clearInterval = global.clearInterval;

function calcLeakTimeout() {
if (program.leakTimeout) {
if (typeof program.leakTimeout === 'string') {
return ms(program.leakTimeout);
} else {
return program.leakTimeout;
}
} else {
return 60000;
}
}

/**
* Exits Mocha when tests + code under test has finished execution (default)
* @param {number} code - Exit code; typically # of failures
Expand All @@ -39,6 +54,30 @@ const exitLater = code => {
process.on('exit', () => {
process.exit(Math.min(code, 255));
});

let timeout = Date.now() + calcLeakTimeout();
let timer = setInterval(() => {
if (Date.now() > timeout) {
clearInterval(timer);

console.error(
'Process did not terminate, dumping remaining handles and exiting'
);
wtfnode.dump();

process.removeAllListeners('exit');
process.exit(-1);
} else {
let activeHandles = process
._getActiveHandles()
.filter(h => typeof h.fd !== 'number' || h.fd > 2); // Filter out stdio handles

// Allow this timer to be running
if (activeHandles.length <= 1) {
clearInterval(timer);
}
}
}, 10);
};

/**
Expand Down Expand Up @@ -258,7 +297,11 @@ program
'--cleanup-after <timeout>',
'Always run after hooks even if the process is killed'
)
.option('--repeat <n>', 'Repeat all tests n times');
.option('--repeat <n>', 'Repeat all tests n times')
.option(
'--leak-timeout <ms>',
'Kill process forcefully if not terminated after the last test has completed'
);

program._name = 'mocha';

Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -470,7 +470,8 @@
"he": "1.1.1",
"minimatch": "3.0.4",
"mkdirp": "0.5.1",
"supports-color": "5.4.0"
"supports-color": "5.4.0",
"wtfnode": "^0.8.0"
},
"devDependencies": {
"@mocha/docdash": "^1.0.1",
Expand Down
12 changes: 12 additions & 0 deletions test/integration/fixtures/hang-after-completion.fixture.js
@@ -0,0 +1,12 @@
'use strict';

describe('hanging test', function () {
this.timeout(3000);

it('should complete with a hanging timer', function() {
console.log('it()');
setTimeout(function () {
console.log('timer expired');
}, 300);
});
});
54 changes: 54 additions & 0 deletions test/integration/options.spec.js
Expand Up @@ -779,6 +779,60 @@ describe('options', function() {
});
});
});

describe('--leak-timeout', function() {
function run(fixture, args, fn) {
helpers.runMocha(fixture, ['--reporter', 'dot'].concat(args), function(
err,
res
) {
if (err) {
fn(err);
} else {
fn(null, res.code, res.output);
}
});
}

it('should give the program time to complete', function(done) {
run(
'hang-after-completion.fixture.js',
['--leak-timeout', '500'],
function(err, code, output) {
if (err) {
done(err);
} else {
assert.equal(code, 0);
assert(/it\(\)\n/.test(output));
assert(/timer expired\n/.test(output));
assert(!/Process did not terminate\n/.test(output));
done();
}
}
);
});

it('should forcefully kill the program', function(done) {
run(
'hang-after-completion.fixture.js',
['--leak-timeout', '100'],
function(err, code, output) {
if (err) {
done(err);
} else {
assert.equal(code, 255);
assert(/it\(\)\n/.test(output));
assert(!/timer expired\n/.test(output));
assert(/Process did not terminate/.test(output));
assert(
/fixtures\/hang-after-completion\.fixture\.js:8\n/.test(output)
);
done();
}
}
);
});
});
});

function onlyConsoleOutput() {
Expand Down

0 comments on commit f160a66

Please sign in to comment.