koffi
Version:
Fast and simple C FFI (foreign function interface) for Node.js
123 lines (112 loc) • 3.36 kB
JavaScript
const assert = require('assert');
const common = require('./common');
// we only check async hooks on 8.x an higher were
// they are closer to working properly
const nodeVersion = process.versions.node.split('.')[0];
let asyncHooks;
function checkAsyncHooks () {
if (nodeVersion >= 8) {
if (asyncHooks === undefined) {
asyncHooks = require('async_hooks');
}
return true;
}
return false;
}
module.exports = common.runTest(test);
function installAsyncHooksForTest (resName) {
return new Promise((resolve, reject) => {
let id;
const events = [];
/**
* TODO(legendecas): investigate why resolving & disabling hooks in
* destroy callback causing crash with case 'callbackscope.js'.
*/
let destroyed = false;
const hook = asyncHooks.createHook({
init (asyncId, type, triggerAsyncId, resource) {
if (id === undefined && type === resName) {
id = asyncId;
events.push({ eventName: 'init', type, triggerAsyncId, resource });
}
},
before (asyncId) {
if (asyncId === id) {
events.push({ eventName: 'before' });
}
},
after (asyncId) {
if (asyncId === id) {
events.push({ eventName: 'after' });
}
},
destroy (asyncId) {
if (asyncId === id) {
events.push({ eventName: 'destroy' });
destroyed = true;
}
}
}).enable();
const interval = setInterval(() => {
if (destroyed) {
hook.disable();
clearInterval(interval);
resolve(events);
}
}, 10);
});
}
async function makeCallbackWithResource (binding) {
const hooks = installAsyncHooksForTest('async_context_test');
const triggerAsyncId = asyncHooks.executionAsyncId();
await new Promise((resolve, reject) => {
binding.asynccontext.makeCallback(common.mustCall(), { foo: 'foo' });
hooks.then(actual => {
assert.deepStrictEqual(actual, [
{
eventName: 'init',
type: 'async_context_test',
triggerAsyncId: triggerAsyncId,
resource: { foo: 'foo' }
},
{ eventName: 'before' },
{ eventName: 'after' },
{ eventName: 'destroy' }
]);
}).catch(common.mustNotCall());
resolve();
});
}
async function makeCallbackWithoutResource (binding) {
const hooks = installAsyncHooksForTest('async_context_no_res_test');
const triggerAsyncId = asyncHooks.executionAsyncId();
await new Promise((resolve, reject) => {
binding.asynccontext.makeCallbackNoResource(common.mustCall());
hooks.then(actual => {
assert.deepStrictEqual(actual, [
{
eventName: 'init',
type: 'async_context_no_res_test',
triggerAsyncId: triggerAsyncId,
resource: { }
},
{ eventName: 'before' },
{ eventName: 'after' },
{ eventName: 'destroy' }
]);
}).catch(common.mustNotCall());
resolve();
});
}
function assertAsyncContextReturnsCorrectEnv (binding) {
assert.strictEqual(binding.asynccontext.asyncCxtReturnCorrectEnv(), true);
}
async function test (binding) {
if (!checkAsyncHooks()) {
return;
}
await makeCallbackWithResource(binding);
await makeCallbackWithoutResource(binding);
assertAsyncContextReturnsCorrectEnv(binding);
}
;