Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: mock dns lookup function in parallel tests #17296

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,26 @@ called before the callback is invoked.

## DNS Module

The `DNS` module provides a naïve DNS parser/serializer.
The `DNS` module provides utilities related to the `dns` built-in module.

### errorLookupMock(code, syscall)

* `code` [<String>] Defaults to `dns.mockedErrorCode`.
* `syscall` [<String>] Defaults to `dns.mockedSysCall`.
* return [<Function>]


A mock for the `lookup` option of `net.connect()` that would result in an error
with the `code` and the `syscall` specified. Returns a function that has the
same signature as `dns.lookup()`.

### mockedErrorCode

The default `code` of errors generated by `errorLookupMock`.

### mockedSysCall

The default `syscall` of errors generated by `errorLookupMock`.

### readDomainFromPacket(buffer, offset)

Expand Down
26 changes: 23 additions & 3 deletions test/common/dns.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/* eslint-disable required-modules */
'use strict';

// Naïve DNS parser/serializer.

const assert = require('assert');
const os = require('os');

Expand All @@ -22,6 +20,8 @@ const classes = {
IN: 1
};

// Naïve DNS parser/serializer.

function readDomainFromPacket(buffer, offset) {
assert.ok(offset < buffer.length);
const length = buffer[offset];
Expand Down Expand Up @@ -287,6 +287,26 @@ function writeDNSPacket(parsed) {
}));
}

const mockedErrorCode = 'ENOTFOUND';
const mockedSysCall = 'getaddrinfo';

function errorLookupMock(code = mockedErrorCode, syscall = mockedSysCall) {
return function lookupWithError(host, dnsopts, cb) {
const err = new Error(`${syscall} ${code} ${host}`);
err.code = code;
err.errno = code;
err.syscall = syscall;
err.hostname = host;
cb(err);
};
}

module.exports = {
types, classes, writeDNSPacket, parseDNSPacket
types,
classes,
writeDNSPacket,
parseDNSPacket,
errorLookupMock,
mockedErrorCode,
mockedSysCall
};
16 changes: 13 additions & 3 deletions test/parallel/test-http-client-req-error-dont-double-fire.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
'use strict';

// This tests that the error emitted on the socket does
// not get fired again when the 'error' event handler throws
// an error.

const assert = require('assert');
const http = require('http');
const common = require('../common');
const { addresses } = require('../common/internet');
const { errorLookupMock } = require('../common/dns');

const host = addresses.INVALID_HOST;

// Invalid hostname as per https://tools.ietf.org/html/rfc2606#section-2
const host = 'this.hostname.is.invalid';
const req = http.get({ host });
const req = http.get({
host,
lookup: common.mustCall(errorLookupMock())
});
const err = new Error('mock unexpected code error');
req.on('error', common.mustCall(() => {
throw err;
Expand Down
27 changes: 18 additions & 9 deletions test/parallel/test-net-better-error-messages-port-hostname.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
'use strict';

// This tests that the error thrown from net.createConnection
// comes with host and port properties.
// See https://github.com/nodejs/node-v0.x-archive/issues/7005

const common = require('../common');
const net = require('net');
const assert = require('assert');

const { addresses } = require('../common/internet');
const {
errorLookupMock,
mockedErrorCode
} = require('../common/dns');

// Using port 0 as hostname used is already invalid.
const c = net.createConnection(0, 'this.hostname.is.invalid');
const c = net.createConnection({
port: 0,
host: addresses.INVALID_HOST,
lookup: common.mustCall(errorLookupMock())
});

c.on('connect', common.mustNotCall());

c.on('error', common.mustCall(function(e) {
// If Name Service Switch is available on the operating system then it
// might be configured differently (/etc/nsswitch.conf).
// If the system is configured with no dns the error code will be EAI_AGAIN,
// but if there are more services after the dns entry, for example some
// linux distributions ship a myhostname service by default which would
// still produce the ENOTFOUND error.
assert.ok(e.code === 'ENOTFOUND' || e.code === 'EAI_AGAIN');
assert.strictEqual(e.code, mockedErrorCode);
assert.strictEqual(e.port, 0);
assert.strictEqual(e.hostname, 'this.hostname.is.invalid');
assert.strictEqual(e.hostname, addresses.INVALID_HOST);
}));
29 changes: 18 additions & 11 deletions test/parallel/test-net-connect-immediate-finish.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,35 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

'use strict';

// This tests that if the socket is still in the 'connecting' state
// when the user calls socket.end() ('finish'), the socket would emit
// 'connect' and defer the handling until the 'connect' event is handled.

const common = require('../common');
const assert = require('assert');
const net = require('net');

const { addresses } = require('../common/internet');
const {
errorLookupMock,
mockedErrorCode,
mockedSysCall
} = require('../common/dns');

const client = net.connect({
host: 'this.hostname.is.invalid',
port: common.PORT
host: addresses.INVALID_HOST,
port: common.PORT,
lookup: common.mustCall(errorLookupMock())
});

client.once('error', common.mustCall((err) => {
assert(err);
assert.strictEqual(err.code, err.errno);
// If Name Service Switch is available on the operating system then it
// might be configured differently (/etc/nsswitch.conf).
// If the system is configured with no dns the error code will be EAI_AGAIN,
// but if there are more services after the dns entry, for example some
// linux distributions ship a myhostname service by default which would
// still produce the ENOTFOUND error.
assert.ok(err.code === 'ENOTFOUND' || err.code === 'EAI_AGAIN');
assert.strictEqual(err.code, mockedErrorCode);
assert.strictEqual(err.host, err.hostname);
assert.strictEqual(err.host, 'this.hostname.is.invalid');
assert.strictEqual(err.syscall, 'getaddrinfo');
assert.strictEqual(err.host, addresses.INVALID_HOST);
assert.strictEqual(err.syscall, mockedSysCall);
}));

client.end();