mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
test: split up and refactor test-domain
Split up test-domain into multiple, more focused test files and use more modern JS inside of them. PR-URL: https://github.com/nodejs/node/pull/13614 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
parent
c81fd7c5ea
commit
1a2f579ba0
17
test/parallel/test-domain-bind-timeout.js
Normal file
17
test/parallel/test-domain-bind-timeout.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, undefined);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, true);
|
||||
}));
|
||||
|
||||
setTimeout(d.bind(() => { throw new Error('foobar'); }), 1);
|
28
test/parallel/test-domain-ee-implicit.js
Normal file
28
test/parallel/test-domain-ee-implicit.js
Normal file
@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
const d = new domain.Domain();
|
||||
let implicit;
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, implicit);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, false);
|
||||
}));
|
||||
|
||||
// Implicit addition of the EventEmitter by being created within a domain-bound
|
||||
// context.
|
||||
d.run(common.mustCall(() => {
|
||||
implicit = new EventEmitter();
|
||||
}));
|
||||
|
||||
setTimeout(common.mustCall(() => {
|
||||
// escape from the domain, but implicit is still bound to it.
|
||||
implicit.emit('error', new Error('foobar'));
|
||||
}), 1);
|
20
test/parallel/test-domain-ee.js
Normal file
20
test/parallel/test-domain-ee.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
const d = new domain.Domain();
|
||||
const e = new EventEmitter();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, e);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, false);
|
||||
}));
|
||||
|
||||
d.add(e);
|
||||
e.emit('error', new Error('foobar'));
|
23
test/parallel/test-domain-error-types.js
Normal file
23
test/parallel/test-domain-error-types.js
Normal file
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
// This test is similar to test-domain-multiple-errors, but uses a new domain
|
||||
// for each errors.
|
||||
|
||||
for (const something of [
|
||||
42, null, undefined, false, () => {}, 'string', Symbol('foo')
|
||||
]) {
|
||||
const d = new domain.Domain();
|
||||
d.run(common.mustCall(() => {
|
||||
process.nextTick(common.mustCall(() => {
|
||||
throw something;
|
||||
}));
|
||||
}));
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(something, err);
|
||||
}));
|
||||
}
|
20
test/parallel/test-domain-fs-enoent-stream.js
Normal file
20
test/parallel/test-domain-fs-enoent-stream.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
const fs = require('fs');
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
const fst = fs.createReadStream('stream for nonexistent file');
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.ok(err.message.match(/^ENOENT: no such file or directory, open '/));
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, fst);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, false);
|
||||
}));
|
||||
|
||||
d.add(fst);
|
31
test/parallel/test-domain-implicit-binding.js
Normal file
31
test/parallel/test-domain-implicit-binding.js
Normal file
@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
const fs = require('fs');
|
||||
|
||||
{
|
||||
const d = new domain.Domain();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, undefined);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, true);
|
||||
}));
|
||||
|
||||
d.run(common.mustCall(() => {
|
||||
process.nextTick(common.mustCall(() => {
|
||||
const i = setInterval(common.mustCall(() => {
|
||||
clearInterval(i);
|
||||
setTimeout(common.mustCall(() => {
|
||||
fs.stat('this file does not exist', common.mustCall((er, stat) => {
|
||||
throw new Error('foobar');
|
||||
}));
|
||||
}), 1);
|
||||
}), 1);
|
||||
}));
|
||||
}));
|
||||
}
|
43
test/parallel/test-domain-intercept.js
Normal file
43
test/parallel/test-domain-intercept.js
Normal file
@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
{
|
||||
const d = new domain.Domain();
|
||||
|
||||
const mustNotCall = common.mustNotCall();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, undefined);
|
||||
assert.strictEqual(err.domainBound, mustNotCall);
|
||||
assert.strictEqual(err.domainThrown, false);
|
||||
}));
|
||||
|
||||
const bound = d.intercept(mustNotCall);
|
||||
bound(new Error('foobar'));
|
||||
}
|
||||
|
||||
{
|
||||
const d = new domain.Domain();
|
||||
|
||||
const bound = d.intercept(common.mustCall((data) => {
|
||||
assert.strictEqual(data, 'data');
|
||||
}));
|
||||
|
||||
bound(null, 'data');
|
||||
}
|
||||
|
||||
{
|
||||
const d = new domain.Domain();
|
||||
|
||||
const bound = d.intercept(common.mustCall((data, data2) => {
|
||||
assert.strictEqual(data, 'data');
|
||||
assert.strictEqual(data2, 'data2');
|
||||
}));
|
||||
|
||||
bound(null, 'data', 'data2');
|
||||
}
|
26
test/parallel/test-domain-multiple-errors.js
Normal file
26
test/parallel/test-domain-multiple-errors.js
Normal file
@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
// This test is similar to test-domain-error-types, but uses a single domain
|
||||
// to emit all errors.
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
const values = [
|
||||
42, null, undefined, false, () => {}, 'string', Symbol('foo')
|
||||
];
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert(values.includes(err));
|
||||
}, values.length));
|
||||
|
||||
for (const something of values) {
|
||||
d.run(common.mustCall(() => {
|
||||
process.nextTick(common.mustCall(() => {
|
||||
throw something;
|
||||
}));
|
||||
}));
|
||||
}
|
21
test/parallel/test-domain-nexttick.js
Normal file
21
test/parallel/test-domain-nexttick.js
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, undefined);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, true);
|
||||
}));
|
||||
|
||||
d.run(common.mustCall(() => {
|
||||
process.nextTick(common.mustCall(() => {
|
||||
throw new Error('foobar');
|
||||
}));
|
||||
}));
|
13
test/parallel/test-domain-run.js
Normal file
13
test/parallel/test-domain-run.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
assert.strictEqual(d.run(() => 'return value'),
|
||||
'return value');
|
||||
|
||||
assert.strictEqual(d.run((a, b) => `${a} ${b}`, 'return', 'value'),
|
||||
'return value');
|
21
test/parallel/test-domain-timer.js
Normal file
21
test/parallel/test-domain-timer.js
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
|
||||
const d = new domain.Domain();
|
||||
|
||||
d.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'foobar');
|
||||
assert.strictEqual(err.domain, d);
|
||||
assert.strictEqual(err.domainEmitter, undefined);
|
||||
assert.strictEqual(err.domainBound, undefined);
|
||||
assert.strictEqual(err.domainThrown, true);
|
||||
}));
|
||||
|
||||
d.run(common.mustCall(() => {
|
||||
setTimeout(common.mustCall(() => {
|
||||
throw new Error('foobar');
|
||||
}), 1);
|
||||
}));
|
@ -1,275 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
// Simple tests of most basic domain functionality.
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const domain = require('domain');
|
||||
const events = require('events');
|
||||
const fs = require('fs');
|
||||
let caught = 0;
|
||||
let expectCaught = 0;
|
||||
|
||||
const d = new domain.Domain();
|
||||
const e = new events.EventEmitter();
|
||||
|
||||
d.on('error', function(er) {
|
||||
console.error('caught', er && (er.message || er));
|
||||
|
||||
let er_message = er.message;
|
||||
let er_path = er.path;
|
||||
|
||||
// On windows, error messages can contain full path names. If this is the
|
||||
// case, remove the directory part.
|
||||
if (typeof er_path === 'string') {
|
||||
const slash = er_path.lastIndexOf('\\');
|
||||
if (slash !== -1) {
|
||||
const dir = er_path.slice(0, slash + 1);
|
||||
er_path = er_path.replace(dir, '');
|
||||
er_message = er_message.replace(dir, '');
|
||||
}
|
||||
}
|
||||
|
||||
switch (er_message) {
|
||||
case 'emitted':
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainEmitter, e);
|
||||
assert.strictEqual(er.domainThrown, false);
|
||||
break;
|
||||
|
||||
case 'bound':
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainBound, fn);
|
||||
assert.strictEqual(er.domainThrown, false);
|
||||
break;
|
||||
|
||||
case 'thrown':
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainThrown, true);
|
||||
break;
|
||||
|
||||
case "ENOENT: no such file or directory, open 'this file does not exist'":
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainThrown, false);
|
||||
assert.strictEqual(typeof er.domainBound, 'function');
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.strictEqual(er.code, 'ENOENT');
|
||||
assert.strictEqual(er_path, 'this file does not exist');
|
||||
assert.strictEqual(typeof er.errno, 'number');
|
||||
break;
|
||||
|
||||
case
|
||||
"ENOENT: no such file or directory, open 'stream for nonexistent file'":
|
||||
assert.strictEqual(typeof er.errno, 'number');
|
||||
assert.strictEqual(er.code, 'ENOENT');
|
||||
assert.strictEqual(er_path, 'stream for nonexistent file');
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainEmitter, fst);
|
||||
assert.ok(!er.domainBound);
|
||||
assert.strictEqual(er.domainThrown, false);
|
||||
break;
|
||||
|
||||
case 'implicit':
|
||||
assert.strictEqual(er.domainEmitter, implicit);
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainThrown, false);
|
||||
assert.ok(!er.domainBound);
|
||||
break;
|
||||
|
||||
case 'implicit timer':
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.strictEqual(er.domainThrown, true);
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.ok(!er.domainBound);
|
||||
break;
|
||||
|
||||
case 'Cannot read property \'isDirectory\' of undefined':
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.ok(!er.domainBound);
|
||||
break;
|
||||
|
||||
case 'nextTick execution loop':
|
||||
assert.strictEqual(er.domain, d);
|
||||
assert.ok(!er.domainEmitter);
|
||||
assert.ok(!er.domainBound);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('unexpected error, throwing %j', er.message, er);
|
||||
throw er;
|
||||
}
|
||||
|
||||
caught++;
|
||||
});
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
console.error('exit', caught, expectCaught);
|
||||
assert.strictEqual(caught, expectCaught,
|
||||
'caught the expected number of errors');
|
||||
console.log('ok');
|
||||
});
|
||||
|
||||
|
||||
// revert to using the domain when a callback is passed to nextTick in
|
||||
// the middle of a tickCallback loop
|
||||
d.run(function() {
|
||||
process.nextTick(function() {
|
||||
throw new Error('nextTick execution loop');
|
||||
});
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// catch thrown errors no matter how many times we enter the event loop
|
||||
// this only uses implicit binding, except for the first function
|
||||
// passed to d.run(). The rest are implicitly bound by virtue of being
|
||||
// set up while in the scope of the d domain.
|
||||
d.run(function() {
|
||||
process.nextTick(function() {
|
||||
const i = setInterval(function() {
|
||||
clearInterval(i);
|
||||
setTimeout(function() {
|
||||
fs.stat('this file does not exist', function(er, stat) {
|
||||
// uh oh! stat isn't set!
|
||||
// pretty common error.
|
||||
console.log(stat.isDirectory());
|
||||
});
|
||||
}, 1);
|
||||
}, 1);
|
||||
});
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// implicit addition of a timer created within a domain-bound context.
|
||||
d.run(function() {
|
||||
setTimeout(function() {
|
||||
throw new Error('implicit timer');
|
||||
}, 1);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// Event emitters added to the domain have their errors routed.
|
||||
d.add(e);
|
||||
e.emit('error', new Error('emitted'));
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// get rid of the `if (er) return cb(er)` malarky, by intercepting
|
||||
// the cb functions to the domain, and using the intercepted function
|
||||
// as a callback instead.
|
||||
function fn() {
|
||||
throw new Error('This function should never be called!');
|
||||
}
|
||||
|
||||
let bound = d.intercept(fn);
|
||||
bound(new Error('bound'));
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// intercepted should never pass first argument to callback
|
||||
function fn2(data) {
|
||||
assert.strictEqual(data, 'data', 'should not be null err argument');
|
||||
}
|
||||
|
||||
bound = d.intercept(fn2);
|
||||
bound(null, 'data');
|
||||
|
||||
// intercepted should never pass first argument to callback
|
||||
// even if arguments length is more than 2.
|
||||
function fn3(data, data2) {
|
||||
assert.strictEqual(data, 'data', 'should not be null err argument');
|
||||
assert.strictEqual(data2, 'data2', 'should not be data argument');
|
||||
}
|
||||
|
||||
bound = d.intercept(fn3);
|
||||
bound(null, 'data', 'data2');
|
||||
|
||||
// throwing in a bound fn is also caught,
|
||||
// even if it's asynchronous, by hitting the
|
||||
// global uncaughtException handler. This doesn't
|
||||
// require interception, since throws are always
|
||||
// caught by the domain.
|
||||
function thrower() {
|
||||
throw new Error('thrown');
|
||||
}
|
||||
setTimeout(d.bind(thrower), 100);
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// Pass an intercepted function to an fs operation that fails.
|
||||
fs.open('this file does not exist', 'r', d.intercept(function(er) {
|
||||
console.error('should not get here!', er);
|
||||
throw new Error('should not get here!');
|
||||
}, true));
|
||||
expectCaught++;
|
||||
|
||||
|
||||
// implicit addition by being created within a domain-bound context.
|
||||
let implicit;
|
||||
|
||||
d.run(function() {
|
||||
implicit = new events.EventEmitter();
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
// escape from the domain, but implicit is still bound to it.
|
||||
implicit.emit('error', new Error('implicit'));
|
||||
}, 10);
|
||||
expectCaught++;
|
||||
|
||||
|
||||
let result = d.run(function() {
|
||||
return 'return value';
|
||||
});
|
||||
assert.strictEqual(result, 'return value');
|
||||
|
||||
|
||||
// check if the executed function take in count the applied parameters
|
||||
result = d.run((a, b) => `${a} ${b}`, 'return', 'value');
|
||||
assert.strictEqual(result, 'return value');
|
||||
|
||||
|
||||
const fst = fs.createReadStream('stream for nonexistent file');
|
||||
d.add(fst);
|
||||
expectCaught++;
|
||||
|
||||
[42, null, undefined, false, () => {}, 'string'].forEach(function(something) {
|
||||
const d = new domain.Domain();
|
||||
d.run(function() {
|
||||
process.nextTick(function() {
|
||||
throw something;
|
||||
});
|
||||
expectCaught++;
|
||||
});
|
||||
|
||||
d.on('error', function(er) {
|
||||
assert.strictEqual(something, er);
|
||||
caught++;
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user