Skip to content

Commit 68e06e6

Browse files
DavidCai1111jasnell
authored andcommitted
test: increase coverage of async_hooks
PR-URL: #13336 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Andreas Madsen <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 9be8b63 commit 68e06e6

11 files changed

+184
-4
lines changed

lib/async_hooks.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,15 @@ class AsyncResource {
205205
}
206206
this[trigger_id_symbol] = triggerId;
207207

208-
// Return immediately if there's nothing to do.
209-
if (async_hook_fields[kInit] === 0)
210-
return;
211-
212208
if (typeof type !== 'string' || type.length <= 0)
213209
throw new TypeError('type must be a string with length > 0');
214210
if (!Number.isSafeInteger(triggerId) || triggerId < 0)
215211
throw new RangeError('triggerId must be an unsigned integer');
216212

213+
// Return immediately if there's nothing to do.
214+
if (async_hook_fields[kInit] === 0)
215+
return;
216+
217217
processing_hook = true;
218218
for (var i = 0; i < active_hooks_array.length; i++) {
219219
if (typeof active_hooks_array[i][init_symbol] === 'function') {
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const spawnSync = require('child_process').spawnSync;
6+
const async_hooks = require('async_hooks');
7+
const initHooks = require('./init-hooks');
8+
9+
switch (process.argv[2]) {
10+
case 'test_init_callback':
11+
initHooks({
12+
oninit: common.mustCall(() => { throw new Error('test_init_callback'); })
13+
}).enable();
14+
15+
async_hooks.emitInit(async_hooks.currentId(), 'test_init_callback_type',
16+
async_hooks.triggerId());
17+
break;
18+
case 'test_callback':
19+
initHooks({
20+
onbefore: common.mustCall(() => { throw new Error('test_callback'); })
21+
}).enable();
22+
23+
async_hooks.emitInit(async_hooks.currentId(), 'test_callback_type',
24+
async_hooks.triggerId());
25+
async_hooks.emitBefore(async_hooks.currentId());
26+
break;
27+
}
28+
29+
if (process.execArgv.includes('--abort-on-uncaught-exception')) {
30+
initHooks({
31+
oninit: common.mustCall(() => { throw new Error('test_callback_abort'); })
32+
}).enable();
33+
34+
async_hooks.emitInit(async_hooks.currentId(), 'test_callback_abort',
35+
async_hooks.triggerId());
36+
}
37+
38+
const c1 = spawnSync(`${process.execPath}`, [__filename, 'test_init_callback']);
39+
assert.strictEqual(c1.stderr.toString().split('\n')[0],
40+
'Error: test_init_callback');
41+
assert.strictEqual(c1.status, 1);
42+
43+
const c2 = spawnSync(`${process.execPath}`, [__filename, 'test_callback']);
44+
assert.strictEqual(c2.stderr.toString().split('\n')[0], 'Error: test_callback');
45+
assert.strictEqual(c2.status, 1);
46+
47+
const c3 = spawnSync(`${process.execPath}`, ['--abort-on-uncaught-exception',
48+
__filename,
49+
'test_callback_abort']);
50+
assert.strictEqual(c3.stdout.toString(), '');
51+
52+
const stderrOutput = c3.stderr.toString()
53+
.trim()
54+
.split('\n')
55+
.map((s) => s.trim());
56+
assert.strictEqual(stderrOutput[0], 'Error: test_callback_abort');

test/async-hooks/test-embedder.api.async-event.js test/async-hooks/test-embedder.api.async-resource.js

+12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ const { checkInvocations } = require('./hook-checks');
1212
const hooks = initHooks();
1313
hooks.enable();
1414

15+
assert.throws(() => new AsyncResource(),
16+
/^TypeError: type must be a string with length > 0$/);
17+
assert.throws(() => new AsyncResource('invalid_trigger_id', null),
18+
/^RangeError: triggerId must be an unsigned integer$/);
19+
20+
assert.strictEqual(typeof new AsyncResource('default_trigger_id').triggerId(),
21+
'number');
22+
1523
// create first custom event 'alcazares' with triggerId derived
1624
// from async_hooks currentId
1725
const alcaTriggerId = async_hooks.currentId();
@@ -26,6 +34,10 @@ assert.strictEqual(typeof alcazares.uid, 'number');
2634
assert.strictEqual(alcazares.triggerId, alcaTriggerId);
2735
checkInvocations(alcazares, { init: 1 }, 'alcazares constructed');
2836

37+
assert.strictEqual(typeof alcaEvent.asyncId(), 'number');
38+
assert.notStrictEqual(alcaEvent.asyncId(), alcaTriggerId);
39+
assert.strictEqual(alcaEvent.triggerId(), alcaTriggerId);
40+
2941
alcaEvent.emitBefore();
3042
checkInvocations(alcazares, { init: 1, before: 1 },
3143
'alcazares emitted before');
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const spawnSync = require('child_process').spawnSync;
6+
const async_hooks = require('async_hooks');
7+
const initHooks = require('./init-hooks');
8+
9+
switch (process.argv[2]) {
10+
case 'test_invalid_async_id':
11+
async_hooks.emitBefore(-1);
12+
break;
13+
case 'test_invalid_trigger_id':
14+
async_hooks.emitBefore(1, -1);
15+
break;
16+
}
17+
18+
const c1 = spawnSync(process.execPath, [__filename, 'test_invalid_async_id']);
19+
assert.strictEqual(c1.stderr.toString().split('\n')[0],
20+
'Error: before(): asyncId or triggerId is less than zero ' +
21+
'(asyncId: -1, triggerId: -1)');
22+
assert.strictEqual(c1.status, 1);
23+
24+
const c2 = spawnSync(process.execPath, [__filename, 'test_invalid_trigger_id']);
25+
assert.strictEqual(c2.stderr.toString().split('\n')[0],
26+
'Error: before(): asyncId or triggerId is less than zero ' +
27+
'(asyncId: 1, triggerId: -1)');
28+
assert.strictEqual(c2.status, 1);
29+
30+
const expectedId = async_hooks.newUid();
31+
const expectedTriggerId = async_hooks.newUid();
32+
const expectedType = 'test_emit_before_after_type';
33+
34+
// Verify that if there is no registered hook, then nothing will happen.
35+
async_hooks.emitBefore(expectedId);
36+
async_hooks.emitAfter(expectedId);
37+
38+
initHooks({
39+
onbefore: common.mustCall((id) => assert.strictEqual(id, expectedId)),
40+
onafter: common.mustCall((id) => assert.strictEqual(id, expectedId)),
41+
allowNoInit: true
42+
}).enable();
43+
44+
async_hooks.emitInit(expectedId, expectedType, expectedTriggerId);
45+
async_hooks.emitBefore(expectedId);
46+
async_hooks.emitAfter(expectedId);

test/async-hooks/test-emit-init.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const async_hooks = require('async_hooks');
6+
const initHooks = require('./init-hooks');
7+
8+
// Verify that if there is no registered hook, then those invalid parameters
9+
// won't be checked.
10+
assert.doesNotThrow(() => async_hooks.emitInit());
11+
12+
const expectedId = async_hooks.newUid();
13+
const expectedTriggerId = async_hooks.newUid();
14+
const expectedType = 'test_emit_init_type';
15+
const expectedResource = { key: 'test_emit_init_resource' };
16+
17+
const hooks1 = initHooks({
18+
oninit: common.mustCall((id, type, triggerId, resource) => {
19+
assert.strictEqual(id, expectedId);
20+
assert.strictEqual(type, expectedType);
21+
assert.strictEqual(triggerId, expectedTriggerId);
22+
assert.strictEqual(resource.key, expectedResource.key);
23+
})
24+
});
25+
26+
hooks1.enable();
27+
28+
assert.throws(() => async_hooks.emitInit(),
29+
/^RangeError: asyncId must be an unsigned integer$/);
30+
assert.throws(() => async_hooks.emitInit(expectedId),
31+
/^TypeError: type must be a string with length > 0$/);
32+
assert.throws(() => async_hooks.emitInit(expectedId, expectedType, -1),
33+
/^RangeError: triggerId must be an unsigned integer$/);
34+
35+
async_hooks.emitInit(expectedId, expectedType, expectedTriggerId,
36+
expectedResource);
37+
38+
hooks1.disable();
39+
40+
initHooks({
41+
oninit: common.mustCall((id, type, triggerId, resource) => {
42+
assert.strictEqual(id, expectedId);
43+
assert.strictEqual(type, expectedType);
44+
assert.notStrictEqual(triggerId, expectedTriggerId);
45+
assert.strictEqual(resource.key, expectedResource.key);
46+
})
47+
}).enable();
48+
49+
async_hooks.emitInit(expectedId, expectedType, expectedResource);

test/async-hooks/test-enable-disable.js

+4
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ const hook3 = initHooks({ onbefore: onhook3Before, onafter: onhook3After });
103103
// Enabling hook1 and hook3 only, hook2 is still disabled
104104
//
105105
hook1.enable();
106+
// Verify that the hook is enabled even if .enable() is called twice.
107+
hook1.enable();
106108
hook3.enable();
107109

108110
//
@@ -122,6 +124,8 @@ let disabledHook3 = false;
122124
function onhook2Before() {
123125
if (disabledHook3) return;
124126
hook1.disable();
127+
// Verify that the hook is disabled even if .disable() is called twice.
128+
hook1.disable();
125129
disabledHook3 = true;
126130
}
127131

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const async_hooks = require('async_hooks');
6+
7+
const asyncId = async_hooks.newUid();
8+
9+
assert.notStrictEqual(async_hooks.currentId(), asyncId);
10+
11+
async_hooks.runInAsyncIdScope(asyncId, common.mustCall(() => {
12+
assert.strictEqual(async_hooks.currentId(), asyncId);
13+
}));

0 commit comments

Comments
 (0)