• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2// Copyright Joyent, Inc. and other Node contributors.
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the
6// "Software"), to deal in the Software without restriction, including
7// without limitation the rights to use, copy, modify, merge, publish,
8// distribute, sublicense, and/or sell copies of the Software, and to permit
9// persons to whom the Software is furnished to do so, subject to the
10// following conditions:
11//
12// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
18// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21// USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23'use strict';
24const common = require('../common');
25const { addresses } = require('../common/internet');
26const { internalBinding } = require('internal/test/binding');
27const assert = require('assert');
28const dns = require('dns');
29const net = require('net');
30const isIPv4 = net.isIPv4;
31const isIPv6 = net.isIPv6;
32const util = require('util');
33const dnsPromises = dns.promises;
34
35let expected = 0;
36let completed = 0;
37let running = false;
38const queue = [];
39
40
41function TEST(f) {
42  function next() {
43    const f = queue.shift();
44    if (f) {
45      running = true;
46      console.log(f.name);
47      f(done);
48    }
49  }
50
51  function done() {
52    running = false;
53    completed++;
54    process.nextTick(next);
55  }
56
57  expected++;
58  queue.push(f);
59
60  if (!running) {
61    next();
62  }
63}
64
65
66function checkWrap(req) {
67  assert.strictEqual(typeof req, 'object');
68}
69
70
71TEST(function test_reverse_bogus(done) {
72  dnsPromises.reverse('bogus ip')
73    .then(common.mustNotCall())
74    .catch(common.expectsError({ errno: 'EINVAL' }));
75
76  assert.throws(() => {
77    dns.reverse('bogus ip', common.mustNotCall());
78  }, /^Error: getHostByAddr EINVAL bogus ip$/);
79  done();
80});
81
82TEST(async function test_resolve4_ttl(done) {
83  function validateResult(result) {
84    assert.ok(result.length > 0);
85
86    for (const item of result) {
87      assert.strictEqual(typeof item, 'object');
88      assert.strictEqual(typeof item.ttl, 'number');
89      assert.strictEqual(typeof item.address, 'string');
90      assert.ok(item.ttl > 0);
91      assert.ok(isIPv4(item.address));
92    }
93  }
94
95  validateResult(await dnsPromises.resolve4(addresses.INET4_HOST, {
96    ttl: true
97  }));
98
99  const req = dns.resolve4(addresses.INET4_HOST, {
100    ttl: true
101  }, function(err, result) {
102    assert.ifError(err);
103    validateResult(result);
104    done();
105  });
106
107  checkWrap(req);
108});
109
110TEST(async function test_resolve6_ttl(done) {
111  function validateResult(result) {
112    assert.ok(result.length > 0);
113
114    for (const item of result) {
115      assert.strictEqual(typeof item, 'object');
116      assert.strictEqual(typeof item.ttl, 'number');
117      assert.strictEqual(typeof item.address, 'string');
118      assert.ok(item.ttl > 0);
119      assert.ok(isIPv6(item.address));
120    }
121  }
122
123  validateResult(await dnsPromises.resolve6(addresses.INET6_HOST, {
124    ttl: true
125  }));
126
127  const req = dns.resolve6(addresses.INET6_HOST, {
128    ttl: true
129  }, function(err, result) {
130    assert.ifError(err);
131    validateResult(result);
132    done();
133  });
134
135  checkWrap(req);
136});
137
138TEST(async function test_resolveMx(done) {
139  function validateResult(result) {
140    assert.ok(result.length > 0);
141
142    for (const item of result) {
143      assert.strictEqual(typeof item, 'object');
144      assert.ok(item.exchange);
145      assert.strictEqual(typeof item.exchange, 'string');
146      assert.strictEqual(typeof item.priority, 'number');
147    }
148  }
149
150  validateResult(await dnsPromises.resolveMx(addresses.MX_HOST));
151
152  const req = dns.resolveMx(addresses.MX_HOST, function(err, result) {
153    assert.ifError(err);
154    validateResult(result);
155    done();
156  });
157
158  checkWrap(req);
159});
160
161TEST(function test_resolveMx_failure(done) {
162  dnsPromises.resolveMx(addresses.INVALID_HOST)
163    .then(common.mustNotCall())
164    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
165
166  const req = dns.resolveMx(addresses.INVALID_HOST, function(err, result) {
167    assert.ok(err instanceof Error);
168    assert.strictEqual(err.errno, 'ENOTFOUND');
169
170    assert.strictEqual(result, undefined);
171
172    done();
173  });
174
175  checkWrap(req);
176});
177
178TEST(async function test_resolveNs(done) {
179  function validateResult(result) {
180    assert.ok(result.length > 0);
181
182    for (const item of result) {
183      assert.ok(item);
184      assert.strictEqual(typeof item, 'string');
185    }
186  }
187
188  validateResult(await dnsPromises.resolveNs(addresses.NS_HOST));
189
190  const req = dns.resolveNs(addresses.NS_HOST, function(err, names) {
191    assert.ifError(err);
192    validateResult(names);
193    done();
194  });
195
196  checkWrap(req);
197});
198
199TEST(function test_resolveNs_failure(done) {
200  dnsPromises.resolveNs(addresses.INVALID_HOST)
201    .then(common.mustNotCall())
202    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
203
204  const req = dns.resolveNs(addresses.INVALID_HOST, function(err, result) {
205    assert.ok(err instanceof Error);
206    assert.strictEqual(err.errno, 'ENOTFOUND');
207
208    assert.strictEqual(result, undefined);
209
210    done();
211  });
212
213  checkWrap(req);
214});
215
216TEST(async function test_resolveSrv(done) {
217  function validateResult(result) {
218    assert.ok(result.length > 0);
219
220    for (const item of result) {
221      assert.strictEqual(typeof item, 'object');
222      assert.ok(item.name);
223      assert.strictEqual(typeof item.name, 'string');
224      assert.strictEqual(typeof item.port, 'number');
225      assert.strictEqual(typeof item.priority, 'number');
226      assert.strictEqual(typeof item.weight, 'number');
227    }
228  }
229
230  validateResult(await dnsPromises.resolveSrv(addresses.SRV_HOST));
231
232  const req = dns.resolveSrv(addresses.SRV_HOST, function(err, result) {
233    assert.ifError(err);
234    validateResult(result);
235    done();
236  });
237
238  checkWrap(req);
239});
240
241TEST(function test_resolveSrv_failure(done) {
242  dnsPromises.resolveSrv(addresses.INVALID_HOST)
243    .then(common.mustNotCall())
244    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
245
246  const req = dns.resolveSrv(addresses.INVALID_HOST, function(err, result) {
247    assert.ok(err instanceof Error);
248    assert.strictEqual(err.errno, 'ENOTFOUND');
249
250    assert.strictEqual(result, undefined);
251
252    done();
253  });
254
255  checkWrap(req);
256});
257
258TEST(async function test_resolvePtr(done) {
259  function validateResult(result) {
260    assert.ok(result.length > 0);
261
262    for (const item of result) {
263      assert.ok(item);
264      assert.strictEqual(typeof item, 'string');
265    }
266  }
267
268  validateResult(await dnsPromises.resolvePtr(addresses.PTR_HOST));
269
270  const req = dns.resolvePtr(addresses.PTR_HOST, function(err, result) {
271    assert.ifError(err);
272    validateResult(result);
273    done();
274  });
275
276  checkWrap(req);
277});
278
279TEST(function test_resolvePtr_failure(done) {
280  dnsPromises.resolvePtr(addresses.INVALID_HOST)
281    .then(common.mustNotCall())
282    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
283
284  const req = dns.resolvePtr(addresses.INVALID_HOST, function(err, result) {
285    assert.ok(err instanceof Error);
286    assert.strictEqual(err.errno, 'ENOTFOUND');
287
288    assert.strictEqual(result, undefined);
289
290    done();
291  });
292
293  checkWrap(req);
294});
295
296TEST(async function test_resolveNaptr(done) {
297  function validateResult(result) {
298    assert.ok(result.length > 0);
299
300    for (const item of result) {
301      assert.strictEqual(typeof item, 'object');
302      assert.strictEqual(typeof item.flags, 'string');
303      assert.strictEqual(typeof item.service, 'string');
304      assert.strictEqual(typeof item.regexp, 'string');
305      assert.strictEqual(typeof item.replacement, 'string');
306      assert.strictEqual(typeof item.order, 'number');
307      assert.strictEqual(typeof item.preference, 'number');
308    }
309  }
310
311  validateResult(await dnsPromises.resolveNaptr(addresses.NAPTR_HOST));
312
313  const req = dns.resolveNaptr(addresses.NAPTR_HOST, function(err, result) {
314    assert.ifError(err);
315    validateResult(result);
316    done();
317  });
318
319  checkWrap(req);
320});
321
322TEST(function test_resolveNaptr_failure(done) {
323  dnsPromises.resolveNaptr(addresses.INVALID_HOST)
324    .then(common.mustNotCall())
325    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
326
327  const req = dns.resolveNaptr(addresses.INVALID_HOST, function(err, result) {
328    assert.ok(err instanceof Error);
329    assert.strictEqual(err.errno, 'ENOTFOUND');
330
331    assert.strictEqual(result, undefined);
332
333    done();
334  });
335
336  checkWrap(req);
337});
338
339TEST(async function test_resolveSoa(done) {
340  function validateResult(result) {
341    assert.strictEqual(typeof result, 'object');
342    assert.strictEqual(typeof result.nsname, 'string');
343    assert.ok(result.nsname.length > 0);
344    assert.strictEqual(typeof result.hostmaster, 'string');
345    assert.ok(result.hostmaster.length > 0);
346    assert.strictEqual(typeof result.serial, 'number');
347    assert.ok((result.serial > 0) && (result.serial < 4294967295));
348    assert.strictEqual(typeof result.refresh, 'number');
349    assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
350    assert.strictEqual(typeof result.retry, 'number');
351    assert.ok((result.retry > 0) && (result.retry < 2147483647));
352    assert.strictEqual(typeof result.expire, 'number');
353    assert.ok((result.expire > 0) && (result.expire < 2147483647));
354    assert.strictEqual(typeof result.minttl, 'number');
355    assert.ok((result.minttl >= 0) && (result.minttl < 2147483647));
356  }
357
358  validateResult(await dnsPromises.resolveSoa(addresses.SOA_HOST));
359
360  const req = dns.resolveSoa(addresses.SOA_HOST, function(err, result) {
361    assert.ifError(err);
362    validateResult(result);
363    done();
364  });
365
366  checkWrap(req);
367});
368
369TEST(function test_resolveSoa_failure(done) {
370  dnsPromises.resolveSoa(addresses.INVALID_HOST)
371    .then(common.mustNotCall())
372    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
373
374  const req = dns.resolveSoa(addresses.INVALID_HOST, function(err, result) {
375    assert.ok(err instanceof Error);
376    assert.strictEqual(err.errno, 'ENOTFOUND');
377
378    assert.strictEqual(result, undefined);
379
380    done();
381  });
382
383  checkWrap(req);
384});
385
386TEST(async function test_resolveCname(done) {
387  function validateResult(result) {
388    assert.ok(result.length > 0);
389
390    for (const item of result) {
391      assert.ok(item);
392      assert.strictEqual(typeof item, 'string');
393    }
394  }
395
396  validateResult(await dnsPromises.resolveCname(addresses.CNAME_HOST));
397
398  const req = dns.resolveCname(addresses.CNAME_HOST, function(err, names) {
399    assert.ifError(err);
400    validateResult(names);
401    done();
402  });
403
404  checkWrap(req);
405});
406
407TEST(function test_resolveCname_failure(done) {
408  dnsPromises.resolveCname(addresses.INVALID_HOST)
409    .then(common.mustNotCall())
410    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
411
412  const req = dns.resolveCname(addresses.INVALID_HOST, function(err, result) {
413    assert.ok(err instanceof Error);
414    assert.strictEqual(err.errno, 'ENOTFOUND');
415
416    assert.strictEqual(result, undefined);
417
418    done();
419  });
420
421  checkWrap(req);
422});
423
424
425TEST(async function test_resolveTxt(done) {
426  function validateResult(result) {
427    assert.ok(Array.isArray(result[0]));
428    assert.strictEqual(result.length, 1);
429    assert(result[0][0].startsWith('v=spf1'));
430  }
431
432  validateResult(await dnsPromises.resolveTxt(addresses.TXT_HOST));
433
434  const req = dns.resolveTxt(addresses.TXT_HOST, function(err, records) {
435    assert.ifError(err);
436    validateResult(records);
437    done();
438  });
439
440  checkWrap(req);
441});
442
443TEST(function test_resolveTxt_failure(done) {
444  dnsPromises.resolveTxt(addresses.INVALID_HOST)
445    .then(common.mustNotCall())
446    .catch(common.expectsError({ errno: 'ENOTFOUND' }));
447
448  const req = dns.resolveTxt(addresses.INVALID_HOST, function(err, result) {
449    assert.ok(err instanceof Error);
450    assert.strictEqual(err.errno, 'ENOTFOUND');
451
452    assert.strictEqual(result, undefined);
453
454    done();
455  });
456
457  checkWrap(req);
458});
459
460
461TEST(function test_lookup_failure(done) {
462  dnsPromises.lookup(addresses.INVALID_HOST, 4)
463    .then(common.mustNotCall())
464    .catch(common.expectsError({ errno: dns.NOTFOUND }));
465
466  const req = dns.lookup(addresses.INVALID_HOST, 4, (err) => {
467    assert.ok(err instanceof Error);
468    assert.strictEqual(err.errno, dns.NOTFOUND);
469    assert.strictEqual(err.errno, 'ENOTFOUND');
470    assert.ok(!/ENOENT/.test(err.message));
471    assert.ok(err.message.includes(addresses.INVALID_HOST));
472
473    done();
474  });
475
476  checkWrap(req);
477});
478
479
480TEST(async function test_lookup_ip_all(done) {
481  function validateResult(result) {
482    assert.ok(Array.isArray(result));
483    assert.ok(result.length > 0);
484    assert.strictEqual(result[0].address, '127.0.0.1');
485    assert.strictEqual(result[0].family, 4);
486  }
487
488  validateResult(await dnsPromises.lookup('127.0.0.1', { all: true }));
489
490  const req = dns.lookup(
491    '127.0.0.1',
492    { all: true },
493    function(err, ips, family) {
494      assert.ifError(err);
495      assert.strictEqual(family, undefined);
496      validateResult(ips);
497      done();
498    }
499  );
500
501  checkWrap(req);
502});
503
504
505TEST(function test_lookup_ip_all_promise(done) {
506  const req = util.promisify(dns.lookup)('127.0.0.1', { all: true })
507    .then(function(ips) {
508      assert.ok(Array.isArray(ips));
509      assert.ok(ips.length > 0);
510      assert.strictEqual(ips[0].address, '127.0.0.1');
511      assert.strictEqual(ips[0].family, 4);
512
513      done();
514    });
515
516  checkWrap(req);
517});
518
519
520TEST(function test_lookup_ip_promise(done) {
521  util.promisify(dns.lookup)('127.0.0.1')
522    .then(function({ address, family }) {
523      assert.strictEqual(address, '127.0.0.1');
524      assert.strictEqual(family, 4);
525
526      done();
527    });
528});
529
530
531TEST(async function test_lookup_null_all(done) {
532  assert.deepStrictEqual(await dnsPromises.lookup(null, { all: true }), []);
533
534  const req = dns.lookup(null, { all: true }, (err, ips) => {
535    assert.ifError(err);
536    assert.ok(Array.isArray(ips));
537    assert.strictEqual(ips.length, 0);
538
539    done();
540  });
541
542  checkWrap(req);
543});
544
545
546TEST(async function test_lookup_all_mixed(done) {
547  function validateResult(result) {
548    assert.ok(Array.isArray(result));
549    assert.ok(result.length > 0);
550
551    result.forEach(function(ip) {
552      if (isIPv4(ip.address))
553        assert.strictEqual(ip.family, 4);
554      else if (isIPv6(ip.address))
555        assert.strictEqual(ip.family, 6);
556      else
557        assert.fail('unexpected IP address');
558    });
559  }
560
561  validateResult(await dnsPromises.lookup(addresses.INET_HOST, { all: true }));
562
563  const req = dns.lookup(addresses.INET_HOST, {
564    all: true
565  }, function(err, ips) {
566    assert.ifError(err);
567    validateResult(ips);
568    done();
569  });
570
571  checkWrap(req);
572});
573
574
575TEST(function test_lookupservice_invalid(done) {
576  dnsPromises.lookupService('1.2.3.4', 80)
577    .then(common.mustNotCall())
578    .catch(common.expectsError({ code: 'ENOTFOUND' }));
579
580  const req = dns.lookupService('1.2.3.4', 80, (err) => {
581    assert(err instanceof Error);
582    assert.strictEqual(err.code, 'ENOTFOUND');
583    assert.ok(/1\.2\.3\.4/.test(err.message));
584
585    done();
586  });
587
588  checkWrap(req);
589});
590
591
592TEST(function test_reverse_failure(done) {
593  dnsPromises.reverse('203.0.113.0')
594    .then(common.mustNotCall())
595    .catch(common.expectsError({
596      code: 'ENOTFOUND',
597      hostname: '203.0.113.0'
598    }));
599
600  // 203.0.113.0/24 are addresses reserved for (RFC) documentation use only
601  const req = dns.reverse('203.0.113.0', function(err) {
602    assert(err instanceof Error);
603    assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
604    assert.strictEqual(err.hostname, '203.0.113.0');
605    assert.ok(/203\.0\.113\.0/.test(err.message));
606
607    done();
608  });
609
610  checkWrap(req);
611});
612
613
614TEST(function test_lookup_failure(done) {
615  dnsPromises.lookup(addresses.INVALID_HOST)
616    .then(common.mustNotCall())
617    .catch(common.expectsError({
618      code: 'ENOTFOUND',
619      hostname: addresses.INVALID_HOST
620    }));
621
622  const req = dns.lookup(addresses.INVALID_HOST, (err) => {
623    assert(err instanceof Error);
624    assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
625    assert.strictEqual(err.hostname, addresses.INVALID_HOST);
626    assert.ok(err.message.includes(addresses.INVALID_HOST));
627
628    done();
629  });
630
631  checkWrap(req);
632});
633
634
635TEST(function test_resolve_failure(done) {
636  const req = dns.resolve4(addresses.INVALID_HOST, (err) => {
637    assert(err instanceof Error);
638
639    switch (err.code) {
640      case 'ENOTFOUND':
641      case 'ESERVFAIL':
642        break;
643      default:
644        assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
645        break;
646    }
647
648    assert.strictEqual(err.hostname, addresses.INVALID_HOST);
649    assert.ok(err.message.includes(addresses.INVALID_HOST));
650
651    done();
652  });
653
654  checkWrap(req);
655});
656
657
658let getaddrinfoCallbackCalled = false;
659
660console.log(`looking up ${addresses.INET4_HOST}..`);
661
662const cares = internalBinding('cares_wrap');
663const req = new cares.GetAddrInfoReqWrap();
664cares.getaddrinfo(req, addresses.INET4_HOST, 4,
665  /* hints */ 0, /* verbatim */ true);
666
667req.oncomplete = function(err, domains) {
668  assert.strictEqual(err, 0);
669  console.log(`${addresses.INET4_HOST} = ${domains}`);
670  assert.ok(Array.isArray(domains));
671  assert.ok(domains.length >= 1);
672  assert.strictEqual(typeof domains[0], 'string');
673  getaddrinfoCallbackCalled = true;
674};
675
676process.on('exit', function() {
677  console.log(`${completed} tests completed`);
678  assert.strictEqual(running, false);
679  assert.strictEqual(completed, expected);
680  assert.ok(getaddrinfoCallbackCalled);
681});
682
683// Should not throw.
684dns.lookup(addresses.INET6_HOST, 6, common.mustCall());
685dns.lookup(addresses.INET_HOST, {}, common.mustCall());
686dns.lookupService('0.0.0.0', '0', common.mustCall());
687dns.lookupService('0.0.0.0', 0, common.mustCall());
688(async function() {
689  await dnsPromises.lookup(addresses.INET6_HOST, 6);
690  await dnsPromises.lookup(addresses.INET_HOST, {});
691})();
692