• 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 { getSystemErrorName } = require('util');
28const assert = require('assert');
29const dns = require('dns');
30const net = require('net');
31const isIPv4 = net.isIPv4;
32const isIPv6 = net.isIPv6;
33const util = require('util');
34const dnsPromises = dns.promises;
35
36let expected = 0;
37let completed = 0;
38let running = false;
39const queue = [];
40
41
42function TEST(f) {
43  function next() {
44    const f = queue.shift();
45    if (f) {
46      running = true;
47      console.log(f.name);
48      f(done);
49    }
50  }
51
52  function done() {
53    running = false;
54    completed++;
55    process.nextTick(next);
56  }
57
58  expected++;
59  queue.push(f);
60
61  if (!running) {
62    next();
63  }
64}
65
66
67function checkWrap(req) {
68  assert.strictEqual(typeof req, 'object');
69}
70
71
72TEST(function test_reverse_bogus(done) {
73  dnsPromises.reverse('bogus ip')
74    .then(common.mustNotCall())
75    .catch(common.mustCall((err) => {
76      assert.strictEqual(err.code, 'EINVAL');
77      assert.strictEqual(getSystemErrorName(err.errno), 'EINVAL');
78    }));
79
80  assert.throws(() => {
81    dns.reverse('bogus ip', common.mustNotCall());
82  }, /^Error: getHostByAddr EINVAL bogus ip$/);
83  done();
84});
85
86TEST(async function test_resolve4_ttl(done) {
87  function validateResult(result) {
88    assert.ok(result.length > 0);
89
90    for (const item of result) {
91      assert.strictEqual(typeof item, 'object');
92      assert.strictEqual(typeof item.ttl, 'number');
93      assert.strictEqual(typeof item.address, 'string');
94      assert.ok(item.ttl >= 0);
95      assert.ok(isIPv4(item.address));
96    }
97  }
98
99  validateResult(await dnsPromises.resolve4(addresses.INET4_HOST, {
100    ttl: true
101  }));
102
103  const req = dns.resolve4(addresses.INET4_HOST, {
104    ttl: true
105  }, function(err, result) {
106    assert.ifError(err);
107    validateResult(result);
108    done();
109  });
110
111  checkWrap(req);
112});
113
114TEST(async function test_resolve6_ttl(done) {
115  function validateResult(result) {
116    assert.ok(result.length > 0);
117
118    for (const item of result) {
119      assert.strictEqual(typeof item, 'object');
120      assert.strictEqual(typeof item.ttl, 'number');
121      assert.strictEqual(typeof item.address, 'string');
122      assert.ok(item.ttl >= 0);
123      assert.ok(isIPv6(item.address));
124    }
125  }
126
127  validateResult(await dnsPromises.resolve6(addresses.INET6_HOST, {
128    ttl: true
129  }));
130
131  const req = dns.resolve6(addresses.INET6_HOST, {
132    ttl: true
133  }, function(err, result) {
134    assert.ifError(err);
135    validateResult(result);
136    done();
137  });
138
139  checkWrap(req);
140});
141
142TEST(async function test_resolveMx(done) {
143  function validateResult(result) {
144    assert.ok(result.length > 0);
145
146    for (const item of result) {
147      assert.strictEqual(typeof item, 'object');
148      assert.ok(item.exchange);
149      assert.strictEqual(typeof item.exchange, 'string');
150      assert.strictEqual(typeof item.priority, 'number');
151    }
152  }
153
154  validateResult(await dnsPromises.resolveMx(addresses.MX_HOST));
155
156  const req = dns.resolveMx(addresses.MX_HOST, function(err, result) {
157    assert.ifError(err);
158    validateResult(result);
159    done();
160  });
161
162  checkWrap(req);
163});
164
165TEST(function test_resolveMx_failure(done) {
166  dnsPromises.resolveMx(addresses.NOT_FOUND)
167    .then(common.mustNotCall())
168    .catch(common.mustCall((err) => {
169      assert.strictEqual(err.code, 'ENOTFOUND');
170    }));
171
172  const req = dns.resolveMx(addresses.NOT_FOUND, function(err, result) {
173    assert.ok(err instanceof Error);
174    assert.strictEqual(err.code, 'ENOTFOUND');
175
176    assert.strictEqual(result, undefined);
177
178    done();
179  });
180
181  checkWrap(req);
182});
183
184TEST(async function test_resolveNs(done) {
185  function validateResult(result) {
186    assert.ok(result.length > 0);
187
188    for (const item of result) {
189      assert.ok(item);
190      assert.strictEqual(typeof item, 'string');
191    }
192  }
193
194  validateResult(await dnsPromises.resolveNs(addresses.NS_HOST));
195
196  const req = dns.resolveNs(addresses.NS_HOST, function(err, names) {
197    assert.ifError(err);
198    validateResult(names);
199    done();
200  });
201
202  checkWrap(req);
203});
204
205TEST(function test_resolveNs_failure(done) {
206  dnsPromises.resolveNs(addresses.NOT_FOUND)
207    .then(common.mustNotCall())
208    .catch(common.mustCall((err) => {
209      assert.strictEqual(err.code, 'ENOTFOUND');
210    }));
211
212  const req = dns.resolveNs(addresses.NOT_FOUND, function(err, result) {
213    assert.ok(err instanceof Error);
214    assert.strictEqual(err.code, 'ENOTFOUND');
215
216    assert.strictEqual(result, undefined);
217
218    done();
219  });
220
221  checkWrap(req);
222});
223
224TEST(async function test_resolveSrv(done) {
225  function validateResult(result) {
226    assert.ok(result.length > 0);
227
228    for (const item of result) {
229      assert.strictEqual(typeof item, 'object');
230      assert.ok(item.name);
231      assert.strictEqual(typeof item.name, 'string');
232      assert.strictEqual(typeof item.port, 'number');
233      assert.strictEqual(typeof item.priority, 'number');
234      assert.strictEqual(typeof item.weight, 'number');
235    }
236  }
237
238  validateResult(await dnsPromises.resolveSrv(addresses.SRV_HOST));
239
240  const req = dns.resolveSrv(addresses.SRV_HOST, function(err, result) {
241    assert.ifError(err);
242    validateResult(result);
243    done();
244  });
245
246  checkWrap(req);
247});
248
249TEST(function test_resolveSrv_failure(done) {
250  dnsPromises.resolveSrv(addresses.NOT_FOUND)
251    .then(common.mustNotCall())
252    .catch(common.mustCall((err) => {
253      assert.strictEqual(err.code, 'ENOTFOUND');
254    }));
255
256  const req = dns.resolveSrv(addresses.NOT_FOUND, function(err, result) {
257    assert.ok(err instanceof Error);
258    assert.strictEqual(err.code, 'ENOTFOUND');
259
260    assert.strictEqual(result, undefined);
261
262    done();
263  });
264
265  checkWrap(req);
266});
267
268TEST(async function test_resolvePtr(done) {
269  function validateResult(result) {
270    assert.ok(result.length > 0);
271
272    for (const item of result) {
273      assert.ok(item);
274      assert.strictEqual(typeof item, 'string');
275    }
276  }
277
278  validateResult(await dnsPromises.resolvePtr(addresses.PTR_HOST));
279
280  const req = dns.resolvePtr(addresses.PTR_HOST, function(err, result) {
281    assert.ifError(err);
282    validateResult(result);
283    done();
284  });
285
286  checkWrap(req);
287});
288
289TEST(function test_resolvePtr_failure(done) {
290  dnsPromises.resolvePtr(addresses.NOT_FOUND)
291    .then(common.mustNotCall())
292    .catch(common.mustCall((err) => {
293      assert.strictEqual(err.code, 'ENOTFOUND');
294    }));
295
296  const req = dns.resolvePtr(addresses.NOT_FOUND, function(err, result) {
297    assert.ok(err instanceof Error);
298    assert.strictEqual(err.code, 'ENOTFOUND');
299
300    assert.strictEqual(result, undefined);
301
302    done();
303  });
304
305  checkWrap(req);
306});
307
308TEST(async function test_resolveNaptr(done) {
309  function validateResult(result) {
310    assert.ok(result.length > 0);
311
312    for (const item of result) {
313      assert.strictEqual(typeof item, 'object');
314      assert.strictEqual(typeof item.flags, 'string');
315      assert.strictEqual(typeof item.service, 'string');
316      assert.strictEqual(typeof item.regexp, 'string');
317      assert.strictEqual(typeof item.replacement, 'string');
318      assert.strictEqual(typeof item.order, 'number');
319      assert.strictEqual(typeof item.preference, 'number');
320    }
321  }
322
323  validateResult(await dnsPromises.resolveNaptr(addresses.NAPTR_HOST));
324
325  const req = dns.resolveNaptr(addresses.NAPTR_HOST, function(err, result) {
326    assert.ifError(err);
327    validateResult(result);
328    done();
329  });
330
331  checkWrap(req);
332});
333
334TEST(function test_resolveNaptr_failure(done) {
335  dnsPromises.resolveNaptr(addresses.NOT_FOUND)
336    .then(common.mustNotCall())
337    .catch(common.mustCall((err) => {
338      assert.strictEqual(err.code, 'ENOTFOUND');
339    }));
340
341  const req = dns.resolveNaptr(addresses.NOT_FOUND, function(err, result) {
342    assert.ok(err instanceof Error);
343    assert.strictEqual(err.code, 'ENOTFOUND');
344
345    assert.strictEqual(result, undefined);
346
347    done();
348  });
349
350  checkWrap(req);
351});
352
353TEST(async function test_resolveSoa(done) {
354  function validateResult(result) {
355    assert.strictEqual(typeof result, 'object');
356    assert.strictEqual(typeof result.nsname, 'string');
357    assert.ok(result.nsname.length > 0);
358    assert.strictEqual(typeof result.hostmaster, 'string');
359    assert.ok(result.hostmaster.length > 0);
360    assert.strictEqual(typeof result.serial, 'number');
361    assert.ok((result.serial > 0) && (result.serial < 4294967295));
362    assert.strictEqual(typeof result.refresh, 'number');
363    assert.ok((result.refresh > 0) && (result.refresh < 2147483647));
364    assert.strictEqual(typeof result.retry, 'number');
365    assert.ok((result.retry > 0) && (result.retry < 2147483647));
366    assert.strictEqual(typeof result.expire, 'number');
367    assert.ok((result.expire > 0) && (result.expire < 2147483647));
368    assert.strictEqual(typeof result.minttl, 'number');
369    assert.ok((result.minttl >= 0) && (result.minttl < 2147483647));
370  }
371
372  validateResult(await dnsPromises.resolveSoa(addresses.SOA_HOST));
373
374  const req = dns.resolveSoa(addresses.SOA_HOST, function(err, result) {
375    assert.ifError(err);
376    validateResult(result);
377    done();
378  });
379
380  checkWrap(req);
381});
382
383TEST(function test_resolveSoa_failure(done) {
384  dnsPromises.resolveSoa(addresses.NOT_FOUND)
385    .then(common.mustNotCall())
386    .catch(common.mustCall((err) => {
387      assert.strictEqual(err.code, 'ENOTFOUND');
388    }));
389
390  const req = dns.resolveSoa(addresses.NOT_FOUND, function(err, result) {
391    assert.ok(err instanceof Error);
392    assert.strictEqual(err.code, 'ENOTFOUND');
393
394    assert.strictEqual(result, undefined);
395
396    done();
397  });
398
399  checkWrap(req);
400});
401
402TEST(async function test_resolveCaa(done) {
403  function validateResult(result) {
404    assert.ok(Array.isArray(result),
405              `expected array, got ${util.inspect(result)}`);
406    assert.strictEqual(result.length, 1);
407    assert.strictEqual(typeof result[0].critical, 'number');
408    assert.strictEqual(result[0].critical, 0);
409    assert.strictEqual(result[0].issue, 'pki.goog');
410  }
411
412  validateResult(await dnsPromises.resolveCaa(addresses.CAA_HOST));
413
414  const req = dns.resolveCaa(addresses.CAA_HOST, function(err, records) {
415    assert.ifError(err);
416    validateResult(records);
417    done();
418  });
419
420  checkWrap(req);
421});
422
423TEST(function test_resolveCaa_failure(done) {
424  dnsPromises.resolveTxt(addresses.NOT_FOUND)
425    .then(common.mustNotCall())
426    .catch(common.mustCall((err) => {
427      assert.strictEqual(err.code, 'ENOTFOUND');
428    }));
429
430  const req = dns.resolveCaa(addresses.NOT_FOUND, function(err, result) {
431    assert.ok(err instanceof Error);
432    assert.strictEqual(err.code, 'ENOTFOUND');
433
434    assert.strictEqual(result, undefined);
435
436    done();
437  });
438
439  checkWrap(req);
440});
441
442TEST(async function test_resolveCname(done) {
443  function validateResult(result) {
444    assert.ok(result.length > 0);
445
446    for (const item of result) {
447      assert.ok(item);
448      assert.strictEqual(typeof item, 'string');
449    }
450  }
451
452  validateResult(await dnsPromises.resolveCname(addresses.CNAME_HOST));
453
454  const req = dns.resolveCname(addresses.CNAME_HOST, function(err, names) {
455    assert.ifError(err);
456    validateResult(names);
457    done();
458  });
459
460  checkWrap(req);
461});
462
463TEST(function test_resolveCname_failure(done) {
464  dnsPromises.resolveCname(addresses.NOT_FOUND)
465    .then(common.mustNotCall())
466    .catch(common.mustCall((err) => {
467      assert.strictEqual(err.code, 'ENOTFOUND');
468    }));
469
470  const req = dns.resolveCname(addresses.NOT_FOUND, function(err, result) {
471    assert.ok(err instanceof Error);
472    assert.strictEqual(err.code, 'ENOTFOUND');
473
474    assert.strictEqual(result, undefined);
475
476    done();
477  });
478
479  checkWrap(req);
480});
481
482
483TEST(async function test_resolveTxt(done) {
484  function validateResult(result) {
485    assert.ok(Array.isArray(result[0]));
486    assert.strictEqual(result.length, 1);
487    assert(result[0][0].startsWith('v=spf1'));
488  }
489
490  validateResult(await dnsPromises.resolveTxt(addresses.TXT_HOST));
491
492  const req = dns.resolveTxt(addresses.TXT_HOST, function(err, records) {
493    assert.ifError(err);
494    validateResult(records);
495    done();
496  });
497
498  checkWrap(req);
499});
500
501TEST(function test_resolveTxt_failure(done) {
502  dnsPromises.resolveTxt(addresses.NOT_FOUND)
503    .then(common.mustNotCall())
504    .catch(common.mustCall((err) => {
505      assert.strictEqual(err.code, 'ENOTFOUND');
506    }));
507
508  const req = dns.resolveTxt(addresses.NOT_FOUND, function(err, result) {
509    assert.ok(err instanceof Error);
510    assert.strictEqual(err.code, 'ENOTFOUND');
511
512    assert.strictEqual(result, undefined);
513
514    done();
515  });
516
517  checkWrap(req);
518});
519
520
521TEST(function test_lookup_failure(done) {
522  dnsPromises.lookup(addresses.NOT_FOUND, 4)
523    .then(common.mustNotCall())
524    .catch(common.expectsError({ code: dns.NOTFOUND }));
525
526  const req = dns.lookup(addresses.NOT_FOUND, 4, (err) => {
527    assert.ok(err instanceof Error);
528    assert.strictEqual(err.code, dns.NOTFOUND);
529    assert.strictEqual(err.code, 'ENOTFOUND');
530    assert.ok(!/ENOENT/.test(err.message));
531    assert.ok(err.message.includes(addresses.NOT_FOUND));
532
533    done();
534  });
535
536  checkWrap(req);
537});
538
539
540TEST(async function test_lookup_ip_all(done) {
541  function validateResult(result) {
542    assert.ok(Array.isArray(result));
543    assert.ok(result.length > 0);
544    assert.strictEqual(result[0].address, '127.0.0.1');
545    assert.strictEqual(result[0].family, 4);
546  }
547
548  validateResult(await dnsPromises.lookup('127.0.0.1', { all: true }));
549
550  const req = dns.lookup(
551    '127.0.0.1',
552    { all: true },
553    function(err, ips, family) {
554      assert.ifError(err);
555      assert.strictEqual(family, undefined);
556      validateResult(ips);
557      done();
558    }
559  );
560
561  checkWrap(req);
562});
563
564
565TEST(function test_lookup_ip_all_promise(done) {
566  const req = util.promisify(dns.lookup)('127.0.0.1', { all: true })
567    .then(function(ips) {
568      assert.ok(Array.isArray(ips));
569      assert.ok(ips.length > 0);
570      assert.strictEqual(ips[0].address, '127.0.0.1');
571      assert.strictEqual(ips[0].family, 4);
572
573      done();
574    });
575
576  checkWrap(req);
577});
578
579
580TEST(function test_lookup_ip_promise(done) {
581  util.promisify(dns.lookup)('127.0.0.1')
582    .then(function({ address, family }) {
583      assert.strictEqual(address, '127.0.0.1');
584      assert.strictEqual(family, 4);
585
586      done();
587    });
588});
589
590
591TEST(async function test_lookup_null_all(done) {
592  assert.deepStrictEqual(await dnsPromises.lookup(null, { all: true }), []);
593
594  const req = dns.lookup(null, { all: true }, (err, ips) => {
595    assert.ifError(err);
596    assert.ok(Array.isArray(ips));
597    assert.strictEqual(ips.length, 0);
598
599    done();
600  });
601
602  checkWrap(req);
603});
604
605
606TEST(async function test_lookup_all_mixed(done) {
607  function validateResult(result) {
608    assert.ok(Array.isArray(result));
609    assert.ok(result.length > 0);
610
611    result.forEach(function(ip) {
612      if (isIPv4(ip.address))
613        assert.strictEqual(ip.family, 4);
614      else if (isIPv6(ip.address))
615        assert.strictEqual(ip.family, 6);
616      else
617        assert.fail('unexpected IP address');
618    });
619  }
620
621  validateResult(await dnsPromises.lookup(addresses.INET_HOST, { all: true }));
622
623  const req = dns.lookup(addresses.INET_HOST, {
624    all: true
625  }, function(err, ips) {
626    assert.ifError(err);
627    validateResult(ips);
628    done();
629  });
630
631  checkWrap(req);
632});
633
634
635TEST(function test_lookupservice_invalid(done) {
636  dnsPromises.lookupService('1.2.3.4', 80)
637    .then(common.mustNotCall())
638    .catch(common.expectsError({ code: 'ENOTFOUND' }));
639
640  const req = dns.lookupService('1.2.3.4', 80, (err) => {
641    assert(err instanceof Error);
642    assert.strictEqual(err.code, 'ENOTFOUND');
643    assert.ok(/1\.2\.3\.4/.test(err.message));
644
645    done();
646  });
647
648  checkWrap(req);
649});
650
651
652TEST(function test_reverse_failure(done) {
653  dnsPromises.reverse('203.0.113.0')
654    .then(common.mustNotCall())
655    .catch(common.expectsError({
656      code: 'ENOTFOUND',
657      hostname: '203.0.113.0'
658    }));
659
660  // 203.0.113.0/24 are addresses reserved for (RFC) documentation use only
661  const req = dns.reverse('203.0.113.0', function(err) {
662    assert(err instanceof Error);
663    assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
664    assert.strictEqual(err.hostname, '203.0.113.0');
665    assert.ok(/203\.0\.113\.0/.test(err.message));
666
667    done();
668  });
669
670  checkWrap(req);
671});
672
673
674TEST(function test_lookup_failure(done) {
675  dnsPromises.lookup(addresses.NOT_FOUND)
676    .then(common.mustNotCall())
677    .catch(common.expectsError({
678      code: 'ENOTFOUND',
679      hostname: addresses.NOT_FOUND
680    }));
681
682  const req = dns.lookup(addresses.NOT_FOUND, (err) => {
683    assert(err instanceof Error);
684    assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
685    assert.strictEqual(err.hostname, addresses.NOT_FOUND);
686    assert.ok(err.message.includes(addresses.NOT_FOUND));
687
688    done();
689  });
690
691  checkWrap(req);
692});
693
694
695TEST(function test_resolve_failure(done) {
696  const req = dns.resolve4(addresses.NOT_FOUND, (err) => {
697    assert(err instanceof Error);
698
699    switch (err.code) {
700      case 'ENOTFOUND':
701      case 'ESERVFAIL':
702        break;
703      default:
704        assert.strictEqual(err.code, 'ENOTFOUND');  // Silly error code...
705        break;
706    }
707
708    assert.strictEqual(err.hostname, addresses.NOT_FOUND);
709    assert.ok(err.message.includes(addresses.NOT_FOUND));
710
711    done();
712  });
713
714  checkWrap(req);
715});
716
717
718let getaddrinfoCallbackCalled = false;
719
720console.log(`looking up ${addresses.INET4_HOST}..`);
721
722const cares = internalBinding('cares_wrap');
723const req = new cares.GetAddrInfoReqWrap();
724cares.getaddrinfo(req, addresses.INET4_HOST, 4,
725  /* hints */ 0, /* verbatim */ true);
726
727req.oncomplete = function(err, domains) {
728  assert.strictEqual(err, 0);
729  console.log(`${addresses.INET4_HOST} = ${domains}`);
730  assert.ok(Array.isArray(domains));
731  assert.ok(domains.length >= 1);
732  assert.strictEqual(typeof domains[0], 'string');
733  getaddrinfoCallbackCalled = true;
734};
735
736process.on('exit', function() {
737  console.log(`${completed} tests completed`);
738  assert.strictEqual(running, false);
739  assert.strictEqual(completed, expected);
740  assert.ok(getaddrinfoCallbackCalled);
741});
742
743// Should not throw.
744dns.lookup(addresses.INET6_HOST, 6, common.mustCall());
745dns.lookup(addresses.INET_HOST, {}, common.mustCall());
746dns.lookupService('0.0.0.0', '0', common.mustCall());
747dns.lookupService('0.0.0.0', 0, common.mustCall());
748(async function() {
749  await dnsPromises.lookup(addresses.INET6_HOST, 6);
750  await dnsPromises.lookup(addresses.INET_HOST, {});
751})().then(common.mustCall());
752