From 06534528014a1c8e8399c150220e6e33c1907fa2 Mon Sep 17 00:00:00 2001
From: Weijia Wang <381152119@qq.com>
Date: Thu, 13 Jul 2017 07:58:59 +0800
Subject: [PATCH] dns, errors: Migrate to use internal/errors
---
doc/api/errors.md | 8 ++
lib/dns.js | 33 +++----
lib/internal/errors.js | 3 +
test/parallel/test-c-ares.js | 20 +++--
test/parallel/test-dns-lookup.js | 28 ++++--
test/parallel/test-dns-regress-7070.js | 13 ++-
test/parallel/test-dns.js | 90 +++++++++++++------
.../parallel/test-net-connect-options-port.js | 8 +-
8 files changed, 147 insertions(+), 56 deletions(-)
diff --git a/doc/api/errors.md b/doc/api/errors.md
index 2d4f3f02e94e79..38aa9f82bc3924 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -596,6 +596,10 @@ Used when `Console` is instantiated without `stdout` stream or when `stdout` or
Used when the native call from `process.cpuUsage` cannot be processed properly.
+
+
+Used when `c-ares` failed to set the DNS server.
+
### ERR_FALSY_VALUE_REJECTION
@@ -685,6 +689,10 @@ Used when an attempt is made to send an unsupported "handle" over an IPC
communication channel to a child process. See [`child.send()`] and
[`process.send()`] for more information.
+
+
+Used when an IP address is not valid.
+
### ERR_INVALID_OPT_VALUE
diff --git a/lib/dns.js b/lib/dns.js
index 877dc6218a09f7..4e39cfe49e18c2 100644
--- a/lib/dns.js
+++ b/lib/dns.js
@@ -27,6 +27,7 @@ const cares = process.binding('cares_wrap');
const uv = process.binding('uv');
const internalNet = require('internal/net');
const { customPromisifyArgs } = require('internal/util');
+const errors = require('internal/errors');
const GetAddrInfoReqWrap = cares.GetAddrInfoReqWrap;
const GetNameInfoReqWrap = cares.GetNameInfoReqWrap;
@@ -126,13 +127,13 @@ function lookup(hostname, options, callback) {
// Parse arguments
if (hostname && typeof hostname !== 'string') {
- throw new TypeError('Invalid arguments: ' +
- 'hostname must be a string or falsey');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'hostname',
+ ['string', 'falsey'], hostname);
} else if (typeof options === 'function') {
callback = options;
family = 0;
} else if (typeof callback !== 'function') {
- throw new TypeError('Invalid arguments: callback must be passed');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
} else if (options !== null && typeof options === 'object') {
hints = options.hints >>> 0;
family = options.family >>> 0;
@@ -142,14 +143,14 @@ function lookup(hostname, options, callback) {
hints !== cares.AI_ADDRCONFIG &&
hints !== cares.AI_V4MAPPED &&
hints !== (cares.AI_ADDRCONFIG | cares.AI_V4MAPPED)) {
- throw new TypeError('Invalid argument: hints must use valid flags');
+ throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'hints', hints);
}
} else {
family = options >>> 0;
}
if (family !== 0 && family !== 4 && family !== 6)
- throw new TypeError('Invalid argument: family must be 4 or 6');
+ throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'family', family);
if (!hostname) {
if (all) {
@@ -200,16 +201,16 @@ function onlookupservice(err, host, service) {
// lookupService(address, port, callback)
function lookupService(host, port, callback) {
if (arguments.length !== 3)
- throw new Error('Invalid arguments');
+ throw new errors.TypeError('ERR_MISSING_ARGS', 'host', 'port', 'callback');
if (isIP(host) === 0)
- throw new TypeError('"host" argument needs to be a valid IP address');
+ throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'host', host);
if (!isLegalPort(port))
- throw new TypeError(`"port" should be >= 0 and < 65536, got "${port}"`);
+ throw new errors.RangeError('ERR_SOCKET_BAD_PORT');
if (typeof callback !== 'function')
- throw new TypeError('"callback" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
port = +port;
@@ -250,9 +251,10 @@ function resolver(bindingName) {
}
if (typeof name !== 'string') {
- throw new Error('"name" argument must be a string');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'name',
+ 'string', name);
} else if (typeof callback !== 'function') {
- throw new Error('"callback" argument must be a function');
+ throw new errors.TypeError('ERR_INVALID_CALLBACK');
}
var req = new QueryReqWrap();
@@ -290,13 +292,14 @@ function resolve(hostname, rrtype, callback) {
resolver = resolveMap.A;
callback = rrtype;
} else {
- throw new TypeError('"rrtype" argument must be a string');
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'rrtype',
+ 'string', rrtype);
}
if (typeof resolver === 'function') {
return resolver(hostname, callback);
} else {
- throw new Error(`Unknown type "${rrtype}"`);
+ throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'rrtype', rrtype);
}
}
@@ -344,7 +347,7 @@ function setServers(servers) {
return newSet.push([ipVersion, s, parseInt(p)]);
}
- throw new Error(`IP address is not properly formatted: ${serv}`);
+ throw new errors.Error('ERR_INVALID_IP_ADDRESS', serv);
});
const errorNumber = cares.setServers(newSet);
@@ -354,7 +357,7 @@ function setServers(servers) {
cares.setServers(orig.join(','));
var err = cares.strerror(errorNumber);
- throw new Error(`c-ares failed to set servers: "${err}" [${servers}]`);
+ throw new errors.Error('ERR_DNS_SET_SERVERS_FAILED', err, servers);
}
}
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index a85a730e1563e8..aa5e4ca1b342e6 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -106,6 +106,8 @@ E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received');
E('ERR_CONSOLE_WRITABLE_STREAM',
'Console expects a writable stream instance for %s');
E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s');
+E('ERR_DNS_SET_SERVERS_FAILED', (err, servers) =>
+ `c-ares failed to set servers: "${err}" [${servers}]`);
E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value');
E('ERR_HTTP_HEADERS_SENT',
'Cannot render headers after they are sent to the client');
@@ -129,6 +131,7 @@ E('ERR_INVALID_FILE_URL_HOST',
'File URL host must be "localhost" or empty on %s');
E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s');
E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent');
+E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s');
E('ERR_INVALID_OPT_VALUE',
(name, value) => {
return `The value "${String(value)}" is invalid for option "${name}"`;
diff --git a/test/parallel/test-c-ares.js b/test/parallel/test-c-ares.js
index 6a8b08fd2064bb..8ba221ca99ee4b 100644
--- a/test/parallel/test-c-ares.js
+++ b/test/parallel/test-c-ares.js
@@ -46,11 +46,21 @@ dns.lookup('::1', common.mustCall((error, result, addressType) => {
assert.strictEqual(6, addressType);
}));
-// Try calling resolve with an unsupported type.
-assert.throws(() => dns.resolve('www.google.com', 'HI'), /Unknown type/);
-
-// Try calling resolve with an unsupported type that's an object key
-assert.throws(() => dns.resolve('www.google.com', 'toString'), /Unknown type/);
+[
+ // Try calling resolve with an unsupported type.
+ 'HI',
+ // Try calling resolve with an unsupported type that's an object key
+ 'toString'
+].forEach((val) => {
+ common.expectsError(
+ () => dns.resolve('www.google.com', val),
+ {
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: `The value "${val}" is invalid for option "rrtype"`
+ }
+ );
+});
// Windows doesn't usually have an entry for localhost 127.0.0.1 in
// C:\Windows\System32\drivers\etc\hosts
diff --git a/test/parallel/test-dns-lookup.js b/test/parallel/test-dns-lookup.js
index a1fad873e33f37..52c0a7d2955ecc 100644
--- a/test/parallel/test-dns-lookup.js
+++ b/test/parallel/test-dns-lookup.js
@@ -9,15 +9,25 @@ cares.getaddrinfo = () => process.binding('uv').UV_ENOENT;
assert.throws(() => {
dns.lookup(1, {});
-}, /^TypeError: Invalid arguments: hostname must be a string or falsey$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: /^The "hostname" argument must be one of type string or falsey/
+}));
assert.throws(() => {
dns.lookup(false, 'cb');
-}, /^TypeError: Invalid arguments: callback must be passed$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+}));
assert.throws(() => {
dns.lookup(false, 'options', 'cb');
-}, /^TypeError: Invalid arguments: callback must be passed$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+}));
assert.throws(() => {
dns.lookup(false, {
@@ -25,7 +35,11 @@ assert.throws(() => {
family: 0,
all: false
}, common.mustNotCall());
-}, /^TypeError: Invalid argument: hints must use valid flags$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: 'The value "100" is invalid for option "hints"'
+}));
assert.throws(() => {
dns.lookup(false, {
@@ -33,7 +47,11 @@ assert.throws(() => {
family: 20,
all: false
}, common.mustNotCall());
-}, /^TypeError: Invalid argument: family must be 4 or 6$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: 'The value "20" is invalid for option "family"'
+}));
assert.doesNotThrow(() => {
dns.lookup(false, {
diff --git a/test/parallel/test-dns-regress-7070.js b/test/parallel/test-dns-regress-7070.js
index 1082a0ce699671..f0e6554fdc7edf 100644
--- a/test/parallel/test-dns-regress-7070.js
+++ b/test/parallel/test-dns-regress-7070.js
@@ -20,12 +20,19 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
-require('../common');
+const common = require('../common');
const assert = require('assert');
const dns = require('dns');
// Should not raise assertion error. Issue #7070
assert.throws(() => dns.resolveNs([]), // bad name
- /^Error: "name" argument must be a string$/);
+ common.expectsError({
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: /^The "name" argument must be of type string/
+ }));
assert.throws(() => dns.resolveNs(''), // bad callback
- /^Error: "callback" argument must be a function$/);
+ common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+ }));
diff --git a/test/parallel/test-dns.js b/test/parallel/test-dns.js
index 8041587677a8db..ba905d7490d1e9 100644
--- a/test/parallel/test-dns.js
+++ b/test/parallel/test-dns.js
@@ -68,10 +68,16 @@ const goog = [
];
assert.doesNotThrow(() => dns.setServers(goog));
assert.deepStrictEqual(dns.getServers(), goog);
-assert.throws(() => dns.setServers(['foobar']),
- /^Error: IP address is not properly formatted: foobar$/);
-assert.throws(() => dns.setServers(['127.0.0.1:va']),
- /^Error: IP address is not properly formatted: 127\.0\.0\.1:va$/);
+assert.throws(() => dns.setServers(['foobar']), common.expectsError({
+ code: 'ERR_INVALID_IP_ADDRESS',
+ type: Error,
+ message: 'Invalid IP address: foobar'
+}));
+assert.throws(() => dns.setServers(['127.0.0.1:va']), common.expectsError({
+ code: 'ERR_INVALID_IP_ADDRESS',
+ type: Error,
+ message: 'Invalid IP address: 127.0.0.1:va'
+}));
assert.deepStrictEqual(dns.getServers(), goog);
const goog6 = [
@@ -105,12 +111,20 @@ assert.deepStrictEqual(dns.getServers(), []);
assert.throws(() => {
dns.resolve('example.com', [], common.mustNotCall());
-}, /^TypeError: "rrtype" argument must be a string$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: 'The "rrtype" argument must be of type string. ' +
+ 'Received type object'
+}));
// dns.lookup should accept only falsey and string values
{
- const errorReg =
- /^TypeError: Invalid arguments: hostname must be a string or falsey$/;
+ const errorReg = common.expectsError({
+ code: 'ERR_INVALID_ARG_TYPE',
+ type: TypeError,
+ message: /^The "hostname" argument must be one of type string or falsey/
+ }, 5);
assert.throws(() => dns.lookup({}, common.mustNotCall()), errorReg);
@@ -156,13 +170,21 @@ assert.throws(() => {
assert.throws(() => {
dns.lookup('nodejs.org', { hints: (dns.V4MAPPED | dns.ADDRCONFIG) + 1 },
common.mustNotCall());
-}, /^TypeError: Invalid argument: hints must use valid flags$/);
-
-assert.throws(() => dns.lookup('nodejs.org'),
- /^TypeError: Invalid arguments: callback must be passed$/);
-
-assert.throws(() => dns.lookup('nodejs.org', 4),
- /^TypeError: Invalid arguments: callback must be passed$/);
+}, common.expectsError({
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: /The value "\d+" is invalid for option "hints"/
+}));
+
+assert.throws(() => dns.lookup('nodejs.org'), common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+}));
+
+assert.throws(() => dns.lookup('nodejs.org', 4), common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+}));
assert.doesNotThrow(() => dns.lookup('', { family: 4, hints: 0 },
common.mustCall()));
@@ -183,25 +205,43 @@ assert.doesNotThrow(() => {
}, common.mustCall());
});
-assert.throws(() => dns.lookupService('0.0.0.0'),
- /^Error: Invalid arguments$/);
-
-assert.throws(() => dns.lookupService('fasdfdsaf', 0, common.mustNotCall()),
- /^TypeError: "host" argument needs to be a valid IP address$/);
+assert.throws(() => dns.lookupService('0.0.0.0'), common.expectsError({
+ code: 'ERR_MISSING_ARGS',
+ type: TypeError,
+ message: 'The "host", "port", and "callback" arguments must be specified'
+}));
+const invalidHost = 'fasdfdsaf';
+assert.throws(() => {
+ dns.lookupService(invalidHost, 0, common.mustNotCall());
+}, common.expectsError({
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: `The value "${invalidHost}" is invalid for option "host"`
+}));
+
+const badPortMsg = common.expectsError({
+ code: 'ERR_SOCKET_BAD_PORT',
+ type: RangeError,
+ message: 'Port should be > 0 and < 65536'
+}, 4);
assert.throws(() => dns.lookupService('0.0.0.0', null, common.mustNotCall()),
- /^TypeError: "port" should be >= 0 and < 65536, got "null"$/);
+ badPortMsg);
assert.throws(
() => dns.lookupService('0.0.0.0', undefined, common.mustNotCall()),
- /^TypeError: "port" should be >= 0 and < 65536, got "undefined"$/
+ badPortMsg
);
assert.throws(() => dns.lookupService('0.0.0.0', 65538, common.mustNotCall()),
- /^TypeError: "port" should be >= 0 and < 65536, got "65538"$/);
+ badPortMsg);
assert.throws(() => dns.lookupService('0.0.0.0', 'test', common.mustNotCall()),
- /^TypeError: "port" should be >= 0 and < 65536, got "test"$/);
+ badPortMsg);
-assert.throws(() => dns.lookupService('0.0.0.0', 80, null),
- /^TypeError: "callback" argument must be a function$/);
+assert.throws(() => {
+ dns.lookupService('0.0.0.0', 80, null);
+}, common.expectsError({
+ code: 'ERR_INVALID_CALLBACK',
+ type: TypeError
+}));
diff --git a/test/parallel/test-net-connect-options-port.js b/test/parallel/test-net-connect-options-port.js
index bc9e76df6546ee..9e4d5991fd62dd 100644
--- a/test/parallel/test-net-connect-options-port.js
+++ b/test/parallel/test-net-connect-options-port.js
@@ -60,14 +60,16 @@ const net = require('net');
// Test invalid hints
{
- const regexp = /^TypeError: Invalid argument: hints must use valid flags$/;
// connect({hint}, cb) and connect({hint})
const hints = (dns.ADDRCONFIG | dns.V4MAPPED) + 42;
const hintOptBlocks = doConnect([{ hints: hints }],
() => common.mustNotCall());
for (const block of hintOptBlocks) {
- assert.throws(block, regexp,
- `${block.name}({hints: ${hints})`);
+ assert.throws(block, common.expectsError({
+ code: 'ERR_INVALID_OPT_VALUE',
+ type: TypeError,
+ message: /The value "\d+" is invalid for option "hints"/
+ }));
}
}