• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2// Flags: --expose-gc --expose-internals --no-warnings --test-udp-no-try-send
3
4const common = require('../common');
5const { internalBinding } = require('internal/test/binding');
6const assert = require('assert');
7const fs = require('fs');
8const v8 = require('v8');
9const fsPromises = fs.promises;
10const net = require('net');
11const providers = { ...internalBinding('async_wrap').Providers };
12const fixtures = require('../common/fixtures');
13const tmpdir = require('../common/tmpdir');
14const { getSystemErrorName } = require('util');
15
16// Make sure that all Providers are tested.
17{
18  const hooks = require('async_hooks').createHook({
19    init(id, type) {
20      if (type === 'NONE')
21        throw new Error('received a provider type of NONE');
22      delete providers[type];
23    },
24  }).enable();
25  process.on('beforeExit', common.mustCall(() => {
26    // This garbage collection call verifies that the wraps being garbage
27    // collected doesn't resurrect the process again due to weirdly timed
28    // uv_close calls and other similar instruments in destructors.
29    global.gc();
30
31    process.removeAllListeners('uncaughtException');
32    hooks.disable();
33    delete providers.NONE;  // Should never be used.
34
35    // See test/pseudo-tty/test-async-wrap-getasyncid-tty.js
36    // Requires an 'actual' tty fd to be available.
37    delete providers.TTYWRAP;
38
39    // TODO(jasnell): Test for these
40    delete providers.HTTP2SESSION;
41    delete providers.HTTP2STREAM;
42    delete providers.HTTP2PING;
43    delete providers.HTTP2SETTINGS;
44    // TODO(addaleax): Test for these
45    delete providers.STREAMPIPE;
46    delete providers.MESSAGEPORT;
47    delete providers.WORKER;
48    // TODO(danbev): Test for these
49    delete providers.JSUDPWRAP;
50    if (!common.isMainThread)
51      delete providers.INSPECTORJSBINDING;
52    delete providers.KEYPAIRGENREQUEST;
53    delete providers.KEYGENREQUEST;
54    delete providers.KEYEXPORTREQUEST;
55    delete providers.CIPHERREQUEST;
56    delete providers.DERIVEBITSREQUEST;
57    delete providers.SCRYPTREQUEST;
58    delete providers.SIGNREQUEST;
59    delete providers.VERIFYREQUEST;
60    delete providers.HASHREQUEST;
61    delete providers.HTTPCLIENTREQUEST;
62    delete providers.HTTPINCOMINGMESSAGE;
63    delete providers.ELDHISTOGRAM;
64    delete providers.SIGINTWATCHDOG;
65    delete providers.WORKERHEAPSNAPSHOT;
66    delete providers.FIXEDSIZEBLOBCOPY;
67    delete providers.RANDOMPRIMEREQUEST;
68    delete providers.CHECKPRIMEREQUEST;
69    delete providers.QUIC_LOGSTREAM;
70    delete providers.QUIC_PACKET;
71
72    const objKeys = Object.keys(providers);
73    if (objKeys.length > 0)
74      process._rawDebug(objKeys);
75    assert.strictEqual(objKeys.length, 0);
76  }));
77}
78
79function testUninitialized(req, ctor_name) {
80  assert.strictEqual(typeof req.getAsyncId, 'function');
81  assert.strictEqual(req.getAsyncId(), -1);
82  assert.strictEqual(req.constructor.name, ctor_name);
83}
84
85function testInitialized(req, ctor_name) {
86  assert.strictEqual(typeof req.getAsyncId, 'function');
87  assert(Number.isSafeInteger(req.getAsyncId()));
88  assert(req.getAsyncId() > 0);
89  assert.strictEqual(req.constructor.name, ctor_name);
90}
91
92
93{
94  const cares = internalBinding('cares_wrap');
95  const dns = require('dns');
96
97  testUninitialized(new cares.GetAddrInfoReqWrap(), 'GetAddrInfoReqWrap');
98  testUninitialized(new cares.GetNameInfoReqWrap(), 'GetNameInfoReqWrap');
99  testUninitialized(new cares.QueryReqWrap(), 'QueryReqWrap');
100
101  testInitialized(dns.lookup('www.google.com', () => {}), 'GetAddrInfoReqWrap');
102  testInitialized(dns.lookupService('::1', 22, () => {}), 'GetNameInfoReqWrap');
103
104  const resolver = new dns.Resolver();
105  resolver.setServers(['127.0.0.1']);
106  testInitialized(resolver._handle, 'ChannelWrap');
107  testInitialized(resolver.resolve6('::1', () => {}), 'QueryReqWrap');
108  resolver.cancel();
109}
110
111
112{
113  const FSEvent = internalBinding('fs_event_wrap').FSEvent;
114  testInitialized(new FSEvent(), 'FSEvent');
115}
116
117
118{
119  const JSStream = internalBinding('js_stream').JSStream;
120  testInitialized(new JSStream(), 'JSStream');
121}
122
123
124{
125  // We don't want to expose getAsyncId for promises but we need to construct
126  // one so that the corresponding provider type is removed from the
127  // providers list.
128  new Promise((res) => res(5));
129}
130
131
132if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check
133  const crypto = require('crypto');
134
135  // The handle for PBKDF2 and RandomBytes isn't returned by the function call,
136  // so need to check it from the callback.
137
138  const mc = common.mustCall(function pb() {
139    testInitialized(this, 'PBKDF2Job');
140  });
141  crypto.pbkdf2('password', 'salt', 1, 20, 'sha256', mc);
142
143  crypto.randomBytes(1, common.mustCall(function rb() {
144    testInitialized(this, 'RandomBytesJob');
145  }));
146
147  if (typeof internalBinding('crypto').ScryptJob === 'function') {
148    crypto.scrypt('password', 'salt', 8, common.mustCall(function() {
149      testInitialized(this, 'ScryptJob');
150    }));
151  }
152}
153
154
155{
156  const binding = internalBinding('fs');
157  const path = require('path');
158
159  const FSReqCallback = binding.FSReqCallback;
160  const req = new FSReqCallback();
161  req.oncomplete = () => { };
162
163  testInitialized(req, 'FSReqCallback');
164  binding.access(path.toNamespacedPath('../'), fs.F_OK, req);
165
166  const StatWatcher = binding.StatWatcher;
167  testInitialized(new StatWatcher(), 'StatWatcher');
168}
169
170
171{
172  const { HTTPParser } = require('_http_common');
173  const parser = new HTTPParser();
174  testUninitialized(parser, 'HTTPParser');
175  parser.initialize(HTTPParser.REQUEST, {});
176  testInitialized(parser, 'HTTPParser');
177}
178
179
180{
181  const Gzip = require('zlib').Gzip;
182  testInitialized(new Gzip()._handle, 'Zlib');
183}
184
185{
186  const binding = internalBinding('pipe_wrap');
187  const handle = new binding.Pipe(binding.constants.IPC);
188  testInitialized(handle, 'Pipe');
189}
190
191{
192  tmpdir.refresh();
193
194  const server = net.createServer(common.mustCall((socket) => {
195    server.close();
196  })).listen(common.PIPE, common.mustCall(() => {
197    const binding = internalBinding('pipe_wrap');
198    const handle = new binding.Pipe(binding.constants.SOCKET);
199    testInitialized(handle, 'Pipe');
200    const req = new binding.PipeConnectWrap();
201    testUninitialized(req, 'PipeConnectWrap');
202    req.address = common.PIPE;
203    req.oncomplete = common.mustCall(() => handle.close());
204    handle.connect(req, req.address, req.oncomplete);
205    testInitialized(req, 'PipeConnectWrap');
206  }));
207}
208
209{
210  const Process = internalBinding('process_wrap').Process;
211  testInitialized(new Process(), 'Process');
212}
213
214{
215  const { Signal } = internalBinding('signal_wrap');
216  testInitialized(new Signal(), 'Signal');
217}
218
219{
220  async function openTest() {
221    const fd = await fsPromises.open(__filename, 'r');
222    testInitialized(fd, 'FileHandle');
223    await fd.close();
224  }
225  openTest().then(common.mustCall());
226}
227
228{
229  const binding = internalBinding('stream_wrap');
230  testUninitialized(new binding.WriteWrap(), 'WriteWrap');
231}
232
233{
234  const stream_wrap = internalBinding('stream_wrap');
235  const tcp_wrap = internalBinding('tcp_wrap');
236  const server = net.createServer(common.mustCall((socket) => {
237    server.close();
238    socket.on('data', () => {
239      socket.end();
240      socket.destroy();
241    });
242    socket.resume();
243  })).listen(0, common.localhostIPv4, common.mustCall(() => {
244    const handle = new tcp_wrap.TCP(tcp_wrap.constants.SOCKET);
245    const req = new tcp_wrap.TCPConnectWrap();
246    const sreq = new stream_wrap.ShutdownWrap();
247    testInitialized(handle, 'TCP');
248    testUninitialized(req, 'TCPConnectWrap');
249    testUninitialized(sreq, 'ShutdownWrap');
250
251    sreq.oncomplete = common.mustCall(() => {
252      handle.close();
253    });
254
255    req.oncomplete = common.mustCall(writeData);
256    function writeData() {
257      const wreq = new stream_wrap.WriteWrap();
258      wreq.handle = handle;
259      wreq.oncomplete = () => {
260        handle.shutdown(sreq);
261        testInitialized(sreq, 'ShutdownWrap');
262      };
263      const err = handle.writeLatin1String(wreq, 'hi'.repeat(100000));
264      if (err)
265        throw new Error(`write failed: ${getSystemErrorName(err)}`);
266      if (!stream_wrap.streamBaseState[stream_wrap.kLastWriteWasAsync]) {
267        testUninitialized(wreq, 'WriteWrap');
268        // Synchronous finish. Write more data until we hit an
269        // asynchronous write.
270        return writeData();
271      }
272      testInitialized(wreq, 'WriteWrap');
273    }
274    req.address = common.localhostIPv4;
275    req.port = server.address().port;
276    const err = handle.connect(req, req.address, req.port);
277    assert.strictEqual(err, 0);
278    testInitialized(req, 'TCPConnectWrap');
279  }));
280}
281
282
283if (common.hasCrypto) { // eslint-disable-line node-core/crypto-check
284  const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap');
285  const tcp = new TCP(TCPConstants.SOCKET);
286
287  const ca = fixtures.readKey('rsa_ca.crt');
288  const cert = fixtures.readKey('rsa_cert.crt');
289  const key = fixtures.readKey('rsa_private.pem');
290
291  const credentials = require('tls').createSecureContext({ ca, cert, key });
292
293  // TLSWrap is exposed, but needs to be instantiated via tls_wrap.wrap().
294  const tls_wrap = internalBinding('tls_wrap');
295  testInitialized(tls_wrap.wrap(tcp, credentials.context, true, false), 'TLSWrap');
296}
297
298{
299  const binding = internalBinding('udp_wrap');
300  const handle = new binding.UDP();
301  const req = new binding.SendWrap();
302  testInitialized(handle, 'UDP');
303  testUninitialized(req, 'SendWrap');
304
305  handle.bind('0.0.0.0', 0, undefined);
306  const addr = {};
307  handle.getsockname(addr);
308  req.address = '127.0.0.1';
309  req.port = addr.port;
310  req.oncomplete = () => handle.close();
311  handle.send(req, [Buffer.alloc(1)], 1, req.port, req.address, true);
312  testInitialized(req, 'SendWrap');
313}
314
315if (process.features.inspector && common.isMainThread) {
316  const binding = internalBinding('inspector');
317  const handle = new binding.Connection(() => {});
318  testInitialized(handle, 'Connection');
319  handle.disconnect();
320}
321
322// PROVIDER_HEAPDUMP
323{
324  v8.getHeapSnapshot().destroy();
325}
326
327// DIRHANDLE
328{
329  const dirBinding = internalBinding('fs_dir');
330  const handle = dirBinding.opendir('./', 'utf8', undefined, {});
331  testInitialized(handle, 'DirHandle');
332}
333