From 7b830f4e4acdfd469e4a62ed63039132ffa99032 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Mon, 13 Mar 2017 23:14:14 +0800 Subject: [PATCH] test: add more and refactor test cases to net.connect PR-URL: https://github.com/nodejs/node/pull/11847 Reviewed-By: James M Snell --- .../test-net-connect-options-allowhalfopen.js | 124 ++++++++++ test/parallel/test-net-connect-options-fd.js | 100 ++++++++ .../parallel/test-net-connect-options-path.js | 53 +++++ .../parallel/test-net-connect-options-port.js | 221 ++++++++++++++++++ test/parallel/test-net-connect-options.js | 53 ----- test/parallel/test-net-create-connection.js | 127 ---------- 6 files changed, 498 insertions(+), 180 deletions(-) create mode 100644 test/parallel/test-net-connect-options-allowhalfopen.js create mode 100644 test/parallel/test-net-connect-options-fd.js create mode 100644 test/parallel/test-net-connect-options-path.js create mode 100644 test/parallel/test-net-connect-options-port.js delete mode 100644 test/parallel/test-net-connect-options.js delete mode 100644 test/parallel/test-net-create-connection.js diff --git a/test/parallel/test-net-connect-options-allowhalfopen.js b/test/parallel/test-net-connect-options-allowhalfopen.js new file mode 100644 index 00000000000000..4bf6b9094bdc4d --- /dev/null +++ b/test/parallel/test-net-connect-options-allowhalfopen.js @@ -0,0 +1,124 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +function testClients(getSocketOpt, getConnectOpt, getConnectCb) { + const cloneOptions = (index) => + Object.assign({}, getSocketOpt(index), getConnectOpt(index)); + return [ + net.connect(cloneOptions(0), getConnectCb(0)), + net.connect(cloneOptions(1)) + .on('connect', getConnectCb(1)), + net.createConnection(cloneOptions(2), getConnectCb(2)), + net.createConnection(cloneOptions(3)) + .on('connect', getConnectCb(3)), + new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)), + new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5)) + .on('connect', getConnectCb(5)) + ]; +} + +const CLIENT_VARIANTS = 6; // Same length as array above +const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); + +// Test allowHalfOpen +{ + let clientReceivedFIN = 0; + let serverConnections = 0; + let clientSentFIN = 0; + let serverReceivedFIN = 0; + const server = net.createServer({ + allowHalfOpen: true + }) + .on('connection', forAllClients(function serverOnConnection(socket) { + const serverConnection = ++serverConnections; + let clientId; + console.error(`${serverConnections} 'connection' emitted on server`); + socket.resume(); + // 'end' on each socket must not be emitted twice + socket.on('data', common.mustCall(function(data) { + clientId = data.toString(); + console.error(`${serverConnection} server connection is started ` + + `by client No. ${clientId}`); + })); + socket.on('end', common.mustCall(function() { + serverReceivedFIN++; + console.error(`Server recieved FIN sent by No. ${clientId}`); + if (serverReceivedFIN === CLIENT_VARIANTS) { + setTimeout(() => { + server.close(); + console.error(`No. ${clientId} connection is closing server: ` + + `${serverReceivedFIN} FIN received by server, ` + + `${clientReceivedFIN} FIN received by client, ` + + `${clientSentFIN} FIN sent by client, ` + + `${serverConnections} FIN sent by server`); + }, 50); + } + }, 1)); + socket.end(); + console.error(`Server has sent ${serverConnections} FIN`); + })) + .on('close', common.mustCall(function serverOnClose() { + console.error('Server has been closed: ' + + `${serverReceivedFIN} FIN received by server, ` + + `${clientReceivedFIN} FIN received by client, ` + + `${clientSentFIN} FIN sent by client, ` + + `${serverConnections} FIN sent by server`); + })) + .listen(0, 'localhost', common.mustCall(function serverOnListen() { + const host = 'localhost'; + const port = server.address().port; + + console.error(`Server starts at ${host}:${port}`); + const getSocketOpt = () => ({ allowHalfOpen: true }); + const getConnectOpt = () => ({ host, port }); + const getConnectCb = (index) => common.mustCall(function clientOnConnect() { + const client = this; + console.error(`'connect' emitted on Client ${index}`); + client.resume(); + client.on('end', common.mustCall(function clientOnEnd() { + setTimeout(function() { + // when allowHalfOpen is true, client must still be writable + // after the server closes the connections, but not readable + console.error(`No. ${index} client received FIN`); + assert(!client.readable); + assert(client.writable); + assert(client.write(index + '')); + client.end(); + clientSentFIN++; + console.error(`No. ${index} client sent FIN, ` + + `${clientSentFIN} have been sent`); + }, 50); + })); + client.on('close', common.mustCall(function clientOnClose() { + clientReceivedFIN++; + console.error(`No. ${index} connection has been closed by both ` + + `sides, ${clientReceivedFIN} clients have closed`); + })); + }); + + testClients(getSocketOpt, getConnectOpt, getConnectCb); + })); +} diff --git a/test/parallel/test-net-connect-options-fd.js b/test/parallel/test-net-connect-options-fd.js new file mode 100644 index 00000000000000..5a0db83184ed0c --- /dev/null +++ b/test/parallel/test-net-connect-options-fd.js @@ -0,0 +1,100 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); +const Pipe = process.binding('pipe_wrap').Pipe; + +if (common.isWindows) { + common.skip('Does not support wrapping sockets with fd on Windows'); + return; +} + +common.refreshTmpDir(); + +function testClients(getSocketOpt, getConnectOpt, getConnectCb) { + const cloneOptions = (index) => + Object.assign({}, getSocketOpt(index), getConnectOpt(index)); + return [ + net.connect(cloneOptions(0), getConnectCb(0)), + net.connect(cloneOptions(1)) + .on('connect', getConnectCb(1)), + net.createConnection(cloneOptions(2), getConnectCb(2)), + net.createConnection(cloneOptions(3)) + .on('connect', getConnectCb(3)), + new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)), + new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5)) + .on('connect', getConnectCb(5)) + ]; +} + +const CLIENT_VARIANTS = 6; // Same length as array above +const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); + +// Test Pipe fd is wrapped correctly +{ + const prefix = `${common.PIPE}-net-connect-options-fd`; + const serverPath = `${prefix}-server`; + let counter = 0; + let socketCounter = 0; + const handleMap = new Map(); + const server = net.createServer() + .on('connection', forAllClients(function serverOnConnection(socket) { + let clientFd; + socket.on('data', common.mustCall(function(data) { + clientFd = data.toString(); + console.error(`[Pipe]Received data from fd ${clientFd}`); + socket.end(); + })); + socket.on('end', common.mustCall(function() { + counter++; + console.error(`[Pipe]Received end from fd ${clientFd}, total ${counter}`); + if (counter === CLIENT_VARIANTS) { + setTimeout(() => { + console.error(`[Pipe]Server closed by fd ${clientFd}`); + server.close(); + }, 10); + } + }, 1)); + })) + .on('close', function() { + setTimeout(() => { + for (const pair of handleMap) { + console.error(`[Pipe]Clean up handle with fd ${pair[1].fd}`); + pair[1].close(); // clean up handles + } + }, 10); + }) + .on('error', function(err) { + console.error(err); + assert.fail(null, null, '[Pipe server]' + err); + }) + .listen({path: serverPath}, common.mustCall(function serverOnListen() { + const getSocketOpt = (index) => { + const handle = new Pipe(); + const err = handle.bind(`${prefix}-client-${socketCounter++}`); + assert(err >= 0, '' + err); + assert.notStrictEqual(handle.fd, -1); + handleMap.set(index, handle); + console.error(`[Pipe]Bound handle with Pipe ${handle.fd}`); + return { fd: handle.fd, readable: true, writable: true }; + }; + const getConnectOpt = () => ({ + path: serverPath + }); + const getConnectCb = (index) => common.mustCall(function clientOnConnect() { + const client = this; + // Test if it's wrapping an existing fd + assert(handleMap.has(index)); + const oldHandle = handleMap.get(index); + assert.strictEqual(oldHandle.fd, this._handle.fd); + client.write(oldHandle.fd + ''); + console.error(`[Pipe]Sending data through fd ${oldHandle.fd}`); + client.on('error', function(err) { + console.error(err); + assert.fail(null, null, '[Pipe Client]' + err); + }); + }); + + testClients(getSocketOpt, getConnectOpt, getConnectCb); + })); +} diff --git a/test/parallel/test-net-connect-options-path.js b/test/parallel/test-net-connect-options-path.js new file mode 100644 index 00000000000000..927bd95207370d --- /dev/null +++ b/test/parallel/test-net-connect-options-path.js @@ -0,0 +1,53 @@ +'use strict'; +const common = require('../common'); +const net = require('net'); + +// This file tests the option handling of net.connect, +// net.createConnect, and new Socket().connect + +common.refreshTmpDir(); + +const CLIENT_VARIANTS = 12; + +// Test connect(path) +{ + const prefix = `${common.PIPE}-net-connect-options-path`; + const serverPath = `${prefix}-server`; + let counter = 0; + const server = net.createServer() + .on('connection', common.mustCall(function(socket) { + socket.end('ok'); + }, CLIENT_VARIANTS)) + .listen(serverPath, common.mustCall(function() { + const getConnectCb = () => common.mustCall(function() { + const client = this; + client.end(); + client.on('close', common.mustCall(function() { + counter++; + if (counter === CLIENT_VARIANTS) { + server.close(); + } + })); + }); + + // CLIENT_VARIANTS depends on the following code + net.connect(serverPath, getConnectCb()); + net.connect(serverPath) + .on('connect', getConnectCb()); + net.createConnection(serverPath, getConnectCb()); + net.createConnection(serverPath) + .on('connect', getConnectCb()); + new net.Socket().connect(serverPath, getConnectCb()); + new net.Socket().connect(serverPath) + .on('connect', getConnectCb()); + net.connect({path: serverPath}, getConnectCb()); + net.connect({path: serverPath}) + .on('connect', getConnectCb()); + net.createConnection({path: serverPath}, getConnectCb()); + net.createConnection({path: serverPath}) + .on('connect', getConnectCb()); + new net.Socket().connect({path: serverPath}, getConnectCb()); + new net.Socket().connect({path: serverPath}) + .on('connect', getConnectCb()); + })); +} diff --git a/test/parallel/test-net-connect-options-port.js b/test/parallel/test-net-connect-options-port.js new file mode 100644 index 00000000000000..6f17bb2856c453 --- /dev/null +++ b/test/parallel/test-net-connect-options-port.js @@ -0,0 +1,221 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const dns = require('dns'); +const net = require('net'); + +// Test wrong type of ports +{ + function portTypeError(opt) { + const prefix = '"port" option should be a number or string: '; + const cleaned = opt.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&'); + return new RegExp(`^TypeError: ${prefix}${cleaned}$`); + } + + syncFailToConnect(true, portTypeError('true')); + syncFailToConnect(false, portTypeError('false')); + syncFailToConnect([], portTypeError(''), true); + syncFailToConnect({}, portTypeError('[object Object]'), true); + syncFailToConnect(null, portTypeError('null')); +} + +// Test out of range ports +{ + function portRangeError(opt) { + const prefix = '"port" option should be >= 0 and < 65536: '; + const cleaned = opt.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&'); + return new RegExp(`^RangeError: ${prefix}${cleaned}$`); + } + + syncFailToConnect('', portRangeError('')); + syncFailToConnect(' ', portRangeError(' ')); + syncFailToConnect('0x', portRangeError('0x'), true); + syncFailToConnect('-0x1', portRangeError('-0x1'), true); + syncFailToConnect(NaN, portRangeError('NaN')); + syncFailToConnect(Infinity, portRangeError('Infinity')); + syncFailToConnect(-1, portRangeError('-1')); + syncFailToConnect(65536, portRangeError('65536')); +} + +// 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})`); + } +} + +// Test valid combinations of connect(port) and connect(port, host) +{ + const expectedConnections = 72; + let serverConnected = 0; + + const server = net.createServer(common.mustCall(function(socket) { + socket.end('ok'); + if (++serverConnected === expectedConnections) { + server.close(); + } + }, expectedConnections)); + + server.listen(0, 'localhost', common.mustCall(function() { + const port = this.address().port; + + // Total connections = 3 * 4(canConnect) * 6(doConnect) = 72 + canConnect(port); + canConnect(port + ''); + canConnect('0x' + port.toString(16)); + })); + + // Try connecting to random ports, but do so once the server is closed + server.on('close', function() { + asyncFailToConnect(0); + asyncFailToConnect(/* undefined */); + }); +} + +function doConnect(args, getCb) { + return [ + function createConnectionWithCb() { + return net.createConnection.apply(net, args.concat(getCb())); + }, + function createConnectionWithoutCb() { + return net.createConnection.apply(net, args) + .on('connect', getCb()); + }, + function connectWithCb() { + return net.connect.apply(net, args.concat(getCb())); + }, + function connectWithoutCb() { + return net.connect.apply(net, args) + .on('connect', getCb()); + }, + function socketConnectWithCb() { + const socket = new net.Socket(); + return socket.connect.apply(socket, args.concat(getCb())); + }, + function socketConnectWithoutCb() { + const socket = new net.Socket(); + return socket.connect.apply(socket, args) + .on('connect', getCb()); + } + ]; +} + +function syncFailToConnect(port, regexp, optOnly) { + if (!optOnly) { + // connect(port, cb) and connect(port) + const portArgBlocks = doConnect([port], () => common.mustNotCall()); + for (const block of portArgBlocks) { + assert.throws(block, regexp, `${block.name}(${port})`); + } + + // connect(port, host, cb) and connect(port, host) + const portHostArgBlocks = doConnect([port, 'localhost'], + () => common.mustNotCall()); + for (const block of portHostArgBlocks) { + assert.throws(block, regexp, `${block.name}(${port}, 'localhost')`); + } + } + // connect({port}, cb) and connect({port}) + const portOptBlocks = doConnect([{port}], + () => common.mustNotCall()); + for (const block of portOptBlocks) { + assert.throws(block, regexp, `${block.name}({port: ${port}})`); + } + + // connect({port, host}, cb) and connect({port, host}) + const portHostOptBlocks = doConnect([{port: port, host: 'localhost'}], + () => common.mustNotCall()); + for (const block of portHostOptBlocks) { + assert.throws(block, regexp, + `${block.name}({port: ${port}, host: 'localhost'})`); + } +} + +function canConnect(port) { + const noop = () => common.mustCall(function() {}); + // connect(port, cb) and connect(port) + const portArgBlocks = doConnect([port], noop); + for (const block of portArgBlocks) { + assert.doesNotThrow(block, `${block.name}(${port})`); + } + + // connect(port, host, cb) and connect(port, host) + const portHostArgBlocks = doConnect([port, 'localhost'], noop); + for (const block of portHostArgBlocks) { + assert.doesNotThrow(block, `${block.name}(${port})`); + } + + // connect({port}, cb) and connect({port}) + const portOptBlocks = doConnect([{port}], noop); + for (const block of portOptBlocks) { + assert.doesNotThrow(block, `${block.name}({port: ${port}})`); + } + + // connect({port, host}, cb) and connect({port, host}) + const portHostOptBlocks = doConnect([{port: port, host: 'localhost'}], + noop); + for (const block of portHostOptBlocks) { + assert.doesNotThrow(block, + `${block.name}({port: ${port}, host: 'localhost'})`); + } +} + +function asyncFailToConnect(port) { + const onError = () => common.mustCall(function(err) { + const regexp = /^Error: connect (E\w+)(.+)$/; + assert(regexp.test(err + ''), err + ''); + }); + + const dont = () => common.mustNotCall(); + // connect(port, cb) and connect(port) + const portArgBlocks = doConnect([port], dont); + for (const block of portArgBlocks) { + assert.doesNotThrow(function() { + block().on('error', onError()); + }, `${block.name}(${port})`); + } + + // connect({port}, cb) and connect({port}) + const portOptBlocks = doConnect([{port}], dont); + for (const block of portOptBlocks) { + assert.doesNotThrow(function() { + block().on('error', onError()); + }, `${block.name}({port: ${port}})`); + } + + // connect({port, host}, cb) and connect({port, host}) + const portHostOptBlocks = doConnect([{port: port, host: 'localhost'}], + dont); + for (const block of portHostOptBlocks) { + assert.doesNotThrow(function() { + block().on('error', onError()); + }, `${block.name}({port: ${port}, host: 'localhost'})`); + } +} diff --git a/test/parallel/test-net-connect-options.js b/test/parallel/test-net-connect-options.js deleted file mode 100644 index d75b62a4c147d0..00000000000000 --- a/test/parallel/test-net-connect-options.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; -const common = require('../common'); -const assert = require('assert'); -const net = require('net'); - -const server = net.createServer({ - allowHalfOpen: true -}, common.mustCall(function(socket) { - socket.resume(); - socket.on('end', common.mustCall(function() {})); - socket.end(); -})); - -server.listen(0, function() { - const client = net.connect({ - host: '127.0.0.1', - port: this.address().port, - allowHalfOpen: true - }, common.mustCall(function() { - console.error('client connect cb'); - client.resume(); - client.on('end', common.mustCall(function() { - setTimeout(function() { - assert(client.writable); - client.end(); - }, 10); - })); - client.on('close', function() { - server.close(); - }); - })); -}); diff --git a/test/parallel/test-net-create-connection.js b/test/parallel/test-net-create-connection.js deleted file mode 100644 index ebe777b00c1931..00000000000000 --- a/test/parallel/test-net-create-connection.js +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; -require('../common'); -const assert = require('assert'); -const dns = require('dns'); -const net = require('net'); - -const expectedConnections = 7; -let clientConnected = 0; -let serverConnected = 0; - -const server = net.createServer(function(socket) { - socket.end(); - if (++serverConnected === expectedConnections) { - server.close(); - } -}); - -server.listen(0, 'localhost', function() { - function cb() { - ++clientConnected; - } - - function fail(opts, errtype, msg) { - assert.throws(function() { - net.createConnection(opts, cb); - }, function(err) { - return err instanceof errtype && msg === err.message; - }); - } - - net.createConnection(this.address().port).on('connect', cb); - net.createConnection(this.address().port, 'localhost').on('connect', cb); - net.createConnection(this.address().port, cb); - net.createConnection(this.address().port, 'localhost', cb); - net.createConnection(this.address().port + '', 'localhost', cb); - net.createConnection({port: this.address().port + ''}).on('connect', cb); - net.createConnection({port: '0x' + this.address().port.toString(16)}, cb); - - fail({ - port: true - }, TypeError, '"port" option should be a number or string: true'); - - fail({ - port: false - }, TypeError, '"port" option should be a number or string: false'); - - fail({ - port: [] - }, TypeError, '"port" option should be a number or string: '); - - fail({ - port: {} - }, TypeError, '"port" option should be a number or string: [object Object]'); - - fail({ - port: null - }, TypeError, '"port" option should be a number or string: null'); - - fail({ - port: '' - }, RangeError, '"port" option should be >= 0 and < 65536: '); - - fail({ - port: ' ' - }, RangeError, '"port" option should be >= 0 and < 65536: '); - - fail({ - port: '0x' - }, RangeError, '"port" option should be >= 0 and < 65536: 0x'); - - fail({ - port: '-0x1' - }, RangeError, '"port" option should be >= 0 and < 65536: -0x1'); - - fail({ - port: NaN - }, RangeError, '"port" option should be >= 0 and < 65536: NaN'); - - fail({ - port: Infinity - }, RangeError, '"port" option should be >= 0 and < 65536: Infinity'); - - fail({ - port: -1 - }, RangeError, '"port" option should be >= 0 and < 65536: -1'); - - fail({ - port: 65536 - }, RangeError, '"port" option should be >= 0 and < 65536: 65536'); - - fail({ - hints: (dns.ADDRCONFIG | dns.V4MAPPED) + 42, - }, TypeError, 'Invalid argument: hints must use valid flags'); -}); - -// Try connecting to random ports, but do so once the server is closed -server.on('close', function() { - function nop() {} - - net.createConnection({port: 0}).on('error', nop); - net.createConnection({port: undefined}).on('error', nop); -}); - -process.on('exit', function() { - assert.strictEqual(clientConnected, expectedConnections); -});