0
0
mirror of https://github.com/nodejs/node.git synced 2024-11-29 23:16:30 +01:00
nodejs/test/sequential/test-async-wrap-getasyncid.js
Anna Henningsen 875a4d1a58 worker: add ability to take heap snapshot from parent thread
PR-URL: https://github.com/nodejs/node/pull/31569
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
2020-02-03 07:04:13 -08:00

318 lines
9.3 KiB
JavaScript

'use strict';
// Flags: --expose-gc --expose-internals --no-warnings --test-udp-no-try-send
const common = require('../common');
const { internalBinding } = require('internal/test/binding');
const assert = require('assert');
const fs = require('fs');
const v8 = require('v8');
const fsPromises = fs.promises;
const net = require('net');
const providers = { ...internalBinding('async_wrap').Providers };
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { getSystemErrorName } = require('util');
// Make sure that all Providers are tested.
{
const hooks = require('async_hooks').createHook({
init(id, type) {
if (type === 'NONE')
throw new Error('received a provider type of NONE');
delete providers[type];
},
}).enable();
process.on('beforeExit', common.mustCall(() => {
// This garbage collection call verifies that the wraps being garbage
// collected doesn't resurrect the process again due to weirdly timed
// uv_close calls and other similar instruments in destructors.
global.gc();
process.removeAllListeners('uncaughtException');
hooks.disable();
delete providers.NONE; // Should never be used.
// See test/pseudo-tty/test-async-wrap-getasyncid-tty.js
// Requires an 'actual' tty fd to be available.
delete providers.TTYWRAP;
// TODO(jasnell): Test for these
delete providers.HTTP2SESSION;
delete providers.HTTP2STREAM;
delete providers.HTTP2PING;
delete providers.HTTP2SETTINGS;
// TODO(addaleax): Test for these
delete providers.STREAMPIPE;
delete providers.MESSAGEPORT;
delete providers.WORKER;
if (!common.isMainThread)
delete providers.INSPECTORJSBINDING;
delete providers.KEYPAIRGENREQUEST;
delete providers.HTTPCLIENTREQUEST;
delete providers.HTTPINCOMINGMESSAGE;
delete providers.ELDHISTOGRAM;
delete providers.SIGINTWATCHDOG;
delete providers.WORKERHEAPSNAPSHOT;
const objKeys = Object.keys(providers);
if (objKeys.length > 0)
process._rawDebug(objKeys);
assert.strictEqual(objKeys.length, 0);
}));
}
function testUninitialized(req, ctor_name) {
assert.strictEqual(typeof req.getAsyncId, 'function');
assert.strictEqual(req.getAsyncId(), -1);
assert.strictEqual(req.constructor.name, ctor_name);
}
function testInitialized(req, ctor_name) {
assert.strictEqual(typeof req.getAsyncId, 'function');
assert(Number.isSafeInteger(req.getAsyncId()));
assert(req.getAsyncId() > 0);
assert.strictEqual(req.constructor.name, ctor_name);
}
{
const cares = internalBinding('cares_wrap');
const dns = require('dns');
testUninitialized(new cares.GetAddrInfoReqWrap(), 'GetAddrInfoReqWrap');
testUninitialized(new cares.GetNameInfoReqWrap(), 'GetNameInfoReqWrap');
testUninitialized(new cares.QueryReqWrap(), 'QueryReqWrap');
testInitialized(dns.lookup('www.google.com', () => {}), 'GetAddrInfoReqWrap');
testInitialized(dns.lookupService('::1', 22, () => {}), 'GetNameInfoReqWrap');
const resolver = new dns.Resolver();
resolver.setServers(['127.0.0.1']);
testInitialized(resolver._handle, 'ChannelWrap');
testInitialized(resolver.resolve6('::1', () => {}), 'QueryReqWrap');
resolver.cancel();
}
{
const FSEvent = internalBinding('fs_event_wrap').FSEvent;
testInitialized(new FSEvent(), 'FSEvent');
}
{
const JSStream = internalBinding('js_stream').JSStream;
testInitialized(new JSStream(), 'JSStream');
}
{
// We don't want to expose getAsyncId for promises but we need to construct
// one so that the corresponding provider type is removed from the
// providers list.
new Promise((res) => res(5));
}
if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check
const crypto = require('crypto');
// The handle for PBKDF2 and RandomBytes isn't returned by the function call,
// so need to check it from the callback.
const mc = common.mustCall(function pb() {
testInitialized(this, 'AsyncWrap');
});
crypto.pbkdf2('password', 'salt', 1, 20, 'sha256', mc);
crypto.randomBytes(1, common.mustCall(function rb() {
testInitialized(this, 'AsyncWrap');
}));
if (typeof internalBinding('crypto').scrypt === 'function') {
crypto.scrypt('password', 'salt', 8, common.mustCall(function() {
testInitialized(this, 'AsyncWrap');
}));
}
}
{
const binding = internalBinding('fs');
const path = require('path');
const FSReqCallback = binding.FSReqCallback;
const req = new FSReqCallback();
req.oncomplete = () => { };
testInitialized(req, 'FSReqCallback');
binding.access(path.toNamespacedPath('../'), fs.F_OK, req);
const StatWatcher = binding.StatWatcher;
testInitialized(new StatWatcher(), 'StatWatcher');
}
{
const { HTTPParser } = require('_http_common');
const parser = new HTTPParser();
testUninitialized(parser, 'HTTPParser');
parser.initialize(HTTPParser.REQUEST, {});
testInitialized(parser, 'HTTPParser');
}
{
const Gzip = require('zlib').Gzip;
testInitialized(new Gzip()._handle, 'Zlib');
}
{
const binding = internalBinding('pipe_wrap');
const handle = new binding.Pipe(binding.constants.IPC);
testInitialized(handle, 'Pipe');
}
{
tmpdir.refresh();
const server = net.createServer(common.mustCall((socket) => {
server.close();
})).listen(common.PIPE, common.mustCall(() => {
const binding = internalBinding('pipe_wrap');
const handle = new binding.Pipe(binding.constants.SOCKET);
testInitialized(handle, 'Pipe');
const req = new binding.PipeConnectWrap();
testUninitialized(req, 'PipeConnectWrap');
req.address = common.PIPE;
req.oncomplete = common.mustCall(() => handle.close());
handle.connect(req, req.address, req.oncomplete);
testInitialized(req, 'PipeConnectWrap');
}));
}
{
const Process = internalBinding('process_wrap').Process;
testInitialized(new Process(), 'Process');
}
{
const { Signal } = internalBinding('signal_wrap');
testInitialized(new Signal(), 'Signal');
}
{
async function openTest() {
const fd = await fsPromises.open(__filename, 'r');
testInitialized(fd, 'FileHandle');
await fd.close();
}
openTest().then(common.mustCall());
}
{
const binding = internalBinding('stream_wrap');
testUninitialized(new binding.WriteWrap(), 'WriteWrap');
}
{
const stream_wrap = internalBinding('stream_wrap');
const tcp_wrap = internalBinding('tcp_wrap');
const server = net.createServer(common.mustCall((socket) => {
server.close();
socket.on('data', () => {
socket.end();
socket.destroy();
});
socket.resume();
})).listen(0, common.localhostIPv4, common.mustCall(() => {
const handle = new tcp_wrap.TCP(tcp_wrap.constants.SOCKET);
const req = new tcp_wrap.TCPConnectWrap();
const sreq = new stream_wrap.ShutdownWrap();
testInitialized(handle, 'TCP');
testUninitialized(req, 'TCPConnectWrap');
testUninitialized(sreq, 'ShutdownWrap');
sreq.oncomplete = common.mustCall(() => {
handle.close();
});
req.oncomplete = common.mustCall(writeData);
function writeData() {
const wreq = new stream_wrap.WriteWrap();
wreq.handle = handle;
wreq.oncomplete = () => {
handle.shutdown(sreq);
testInitialized(sreq, 'ShutdownWrap');
};
const err = handle.writeLatin1String(wreq, 'hi'.repeat(100000));
if (err)
throw new Error(`write failed: ${getSystemErrorName(err)}`);
if (!stream_wrap.streamBaseState[stream_wrap.kLastWriteWasAsync]) {
testUninitialized(wreq, 'WriteWrap');
// Synchronous finish. Write more data until we hit an
// asynchronous write.
return writeData();
}
testInitialized(wreq, 'WriteWrap');
}
req.address = common.localhostIPv4;
req.port = server.address().port;
const err = handle.connect(req, req.address, req.port);
assert.strictEqual(err, 0);
testInitialized(req, 'TCPConnectWrap');
}));
}
if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check
const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap');
const tcp = new TCP(TCPConstants.SOCKET);
const ca = fixtures.readKey('rsa_ca.crt');
const cert = fixtures.readKey('rsa_cert.crt');
const key = fixtures.readKey('rsa_private.pem');
const credentials = require('tls').createSecureContext({ ca, cert, key });
// TLSWrap is exposed, but needs to be instantiated via tls_wrap.wrap().
const tls_wrap = internalBinding('tls_wrap');
testInitialized(tls_wrap.wrap(tcp, credentials.context, true), 'TLSWrap');
}
{
const binding = internalBinding('udp_wrap');
const handle = new binding.UDP();
const req = new binding.SendWrap();
testInitialized(handle, 'UDP');
testUninitialized(req, 'SendWrap');
handle.bind('0.0.0.0', 0, undefined);
const addr = {};
handle.getsockname(addr);
req.address = '127.0.0.1';
req.port = addr.port;
req.oncomplete = () => handle.close();
handle.send(req, [Buffer.alloc(1)], 1, req.port, req.address, true);
testInitialized(req, 'SendWrap');
}
if (process.features.inspector && common.isMainThread) {
const binding = internalBinding('inspector');
const handle = new binding.Connection(() => {});
testInitialized(handle, 'Connection');
handle.disconnect();
}
// PROVIDER_HEAPDUMP
{
v8.getHeapSnapshot().destroy();
}
// DIRHANDLE
{
const dirBinding = internalBinding('fs_dir');
const handle = dirBinding.opendir('./', 'utf8', undefined, {});
testInitialized(handle, 'DirHandle');
}