diff --git a/test/README.md b/test/README.md index e73d278653b99b..a5a0c0a90830c0 100644 --- a/test/README.md +++ b/test/README.md @@ -416,6 +416,12 @@ The realpath of the 'tmp' directory. Name of the temp directory used by tests. +### childShouldNotThrowAndAbort() + +This test makes sure that when using `--abort-on-uncaught-exception` and when +throwing an error from within a domain that has an error handler setup, +the process _does not_ abort. + ### WPT A port of parts of diff --git a/test/common.js b/test/common.js index 6fe2d4520f6a08..85f1b9f3c92e99 100644 --- a/test/common.js +++ b/test/common.js @@ -253,6 +253,28 @@ exports.childShouldThrowAndAbort = function() { }); }; + +// This function makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +exports.childShouldNotThrowAndAbort = () => { + let testCmd = ''; + if (!exports.isWindows) { + testCmd += 'ulimit -c 0 && '; + } + + testCmd += `${process.argv[0]} --abort-on-uncaught-exception`; + testCmd += ` ${process.argv[1]} child`; + + const child = child_process.exec(testCmd); + child.on('exit', (code, signal) => { + const errorMsg = `Test should have exited with exit code 0 but instead + exited with ${code} and signal ${signal}`; + assert.strictEqual(code, 0, errorMsg); + }); +}; + exports.ddCommand = function(filename, kilobytes) { if (exports.isWindows) { const p = path.resolve(exports.fixturesDir, 'create-file.js'); diff --git a/test/parallel/test-domain-abort-on-uncaught-0.js b/test/parallel/test-domain-abort-on-uncaught-0.js new file mode 100644 index 00000000000000..b8bed202dd7d4c --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-0.js @@ -0,0 +1,26 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const nextTick = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => {})); + + d.run(() => { + process.nextTick(() => { + throw new Error('exceptional!'); + }); + }); +}; + + +if (process.argv[2] === 'child') { + nextTick(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-1.js b/test/parallel/test-domain-abort-on-uncaught-1.js new file mode 100644 index 00000000000000..e904a4b1286635 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-1.js @@ -0,0 +1,26 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => {})); + + d.run(function() { + setTimeout(function() { + throw new Error('exceptional!'); + }, 33); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-10.js b/test/parallel/test-domain-abort-on-uncaught-10.js new file mode 100644 index 00000000000000..a8a1aa29be461d --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-10.js @@ -0,0 +1,29 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + d2.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + setImmediate(function() { + throw new Error('boom!'); + }); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-11.js b/test/parallel/test-domain-abort-on-uncaught-11.js new file mode 100644 index 00000000000000..1894c0f59468b1 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-11.js @@ -0,0 +1,29 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + d2.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + process.nextTick(function() { + throw new Error('boom!'); + }); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-12.js b/test/parallel/test-domain-abort-on-uncaught-12.js new file mode 100644 index 00000000000000..047f9b12047a72 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-12.js @@ -0,0 +1,31 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + d2.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + const fs = require('fs'); + fs.exists('/non/existing/file', function onExists(exists) { + throw new Error('boom!'); + }); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-2.js b/test/parallel/test-domain-abort-on-uncaught-2.js new file mode 100644 index 00000000000000..b9227fbfa1caae --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-2.js @@ -0,0 +1,25 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => {})); + + d.run(function() { + setImmediate(function() { + throw new Error('boom!'); + }); + }); +}; + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-3.js b/test/parallel/test-domain-abort-on-uncaught-3.js new file mode 100644 index 00000000000000..cf99f117a8ca91 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-3.js @@ -0,0 +1,28 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => { })); + + d.run(function() { + setTimeout(function() { + process.nextTick(function() { + throw new Error('exceptional!'); + }); + }, 33); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-4.js b/test/parallel/test-domain-abort-on-uncaught-4.js new file mode 100644 index 00000000000000..25009fd363d62f --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-4.js @@ -0,0 +1,24 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => { })); + + d.run(function() { + throw new Error('exceptional!'); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-5.js b/test/parallel/test-domain-abort-on-uncaught-5.js new file mode 100644 index 00000000000000..58065e85ce1d05 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-5.js @@ -0,0 +1,27 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + d.once('error', common.mustCall(() => { })); + + d.run(function() { + const fs = require('fs'); + fs.exists('/non/existing/file', function onExists(exists) { + throw new Error('boom!'); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-6.js b/test/parallel/test-domain-abort-on-uncaught-6.js new file mode 100644 index 00000000000000..fa276392d20c15 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-6.js @@ -0,0 +1,35 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const net = require('net'); + const d = domain.create(); + d.on('error', common.mustCall(() => {})); + + d.run(function() { + const server = net.createServer(function(conn) { + conn.pipe(conn); + }); + server.listen(0, common.localhostIPv4, function() { + const conn = net.connect(this.address().port, common.localhostIPv4); + conn.once('data', function() { + throw new Error('ok'); + }); + conn.end('ok'); + server.close(); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-7.js b/test/parallel/test-domain-abort-on-uncaught-7.js new file mode 100644 index 00000000000000..5d98a4d110df90 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-7.js @@ -0,0 +1,27 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + d.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + throw new Error('boom!'); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-8.js b/test/parallel/test-domain-abort-on-uncaught-8.js new file mode 100644 index 00000000000000..abf09d32e34ded --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-8.js @@ -0,0 +1,28 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + + d2.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + throw new Error('boom!'); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/parallel/test-domain-abort-on-uncaught-9.js b/test/parallel/test-domain-abort-on-uncaught-9.js new file mode 100644 index 00000000000000..b340d9ffa66562 --- /dev/null +++ b/test/parallel/test-domain-abort-on-uncaught-9.js @@ -0,0 +1,30 @@ +'use strict'; + +// This test makes sure that when using --abort-on-uncaught-exception and +// when throwing an error from within a domain that has an error handler +// setup, the process _does not_ abort. + +const common = require('../common'); +const domain = require('domain'); + +const test = () => { + const d = domain.create(); + const d2 = domain.create(); + d2.on('error', common.mustCall(() => {})); + + d.run(function() { + d2.run(function() { + setTimeout(function() { + console.log('foo'); + throw new Error('boom!'); + }, 33); + }); + }); +}; + + +if (process.argv[2] === 'child') { + test(); +} else { + common.childShouldNotThrowAndAbort(); +} diff --git a/test/sequential/test-domain-abort-on-uncaught.js b/test/sequential/test-domain-abort-on-uncaught.js deleted file mode 100644 index f754541f37462b..00000000000000 --- a/test/sequential/test-domain-abort-on-uncaught.js +++ /dev/null @@ -1,256 +0,0 @@ -'use strict'; - -// This test makes sure that when using --abort-on-uncaught-exception and -// when throwing an error from within a domain that has an error handler -// setup, the process _does not_ abort. - -const common = require('../common'); -const assert = require('assert'); -const domain = require('domain'); -const child_process = require('child_process'); - -let errorHandlerCalled = false; - -const tests = [ - function nextTick() { - const d = domain.create(); - - d.once('error', function(err) { - errorHandlerCalled = true; - }); - - d.run(function() { - process.nextTick(function() { - throw new Error('exceptional!'); - }); - }); - }, - - function timer() { - const d = domain.create(); - - d.on('error', function(err) { - errorHandlerCalled = true; - }); - - d.run(function() { - setTimeout(function() { - throw new Error('exceptional!'); - }, 33); - }); - }, - - function immediate() { - const d = domain.create(); - - d.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - setImmediate(function() { - throw new Error('boom!'); - }); - }); - }, - - function timerPlusNextTick() { - const d = domain.create(); - - d.on('error', function(err) { - errorHandlerCalled = true; - }); - - d.run(function() { - setTimeout(function() { - process.nextTick(function() { - throw new Error('exceptional!'); - }); - }, 33); - }); - }, - - function firstRun() { - const d = domain.create(); - - d.on('error', function(err) { - errorHandlerCalled = true; - }); - - d.run(function() { - throw new Error('exceptional!'); - }); - }, - - function fsAsync() { - const d = domain.create(); - - d.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - const fs = require('fs'); - fs.exists('/non/existing/file', function onExists(exists) { - throw new Error('boom!'); - }); - }); - }, - - function netServer() { - const net = require('net'); - const d = domain.create(); - - d.on('error', function(err) { - errorHandlerCalled = true; - }); - - d.run(function() { - const server = net.createServer(function(conn) { - conn.pipe(conn); - }); - server.listen(0, common.localhostIPv4, function() { - const conn = net.connect(this.address().port, common.localhostIPv4); - conn.once('data', function() { - throw new Error('ok'); - }); - conn.end('ok'); - server.close(); - }); - }); - }, - - function firstRunOnlyTopLevelErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - throw new Error('boom!'); - }); - }); - }, - - function firstRunNestedWithErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d2.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - throw new Error('boom!'); - }); - }); - }, - - function timeoutNestedWithErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d2.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - setTimeout(function() { - console.log('foo'); - throw new Error('boom!'); - }, 33); - }); - }); - }, - - function setImmediateNestedWithErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d2.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - setImmediate(function() { - throw new Error('boom!'); - }); - }); - }); - }, - - function nextTickNestedWithErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d2.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - process.nextTick(function() { - throw new Error('boom!'); - }); - }); - }); - }, - - function fsAsyncNestedWithErrorHandler() { - const d = domain.create(); - const d2 = domain.create(); - - d2.on('error', function errorHandler() { - errorHandlerCalled = true; - }); - - d.run(function() { - d2.run(function() { - const fs = require('fs'); - fs.exists('/non/existing/file', function onExists(exists) { - throw new Error('boom!'); - }); - }); - }); - } -]; - -if (process.argv[2] === 'child') { - const testIndex = +process.argv[3]; - - tests[testIndex](); - - process.on('exit', function onExit() { - assert.strictEqual(errorHandlerCalled, true); - }); -} else { - - tests.forEach(function(test, testIndex) { - let testCmd = ''; - if (!common.isWindows) { - // Do not create core files, as it can take a lot of disk space on - // continuous testing and developers' machines - testCmd += 'ulimit -c 0 && '; - } - - testCmd += process.argv[0]; - testCmd += ' ' + '--abort-on-uncaught-exception'; - testCmd += ' ' + process.argv[1]; - testCmd += ' ' + 'child'; - testCmd += ' ' + testIndex; - - const child = child_process.exec(testCmd); - - child.on('exit', function onExit(code, signal) { - assert.strictEqual(code, 0, 'Test at index ' + testIndex + - ' should have exited with exit code 0 but instead exited with code ' + - code + ' and signal ' + signal); - }); - }); -}