diff --git a/test/parallel/test-net-connect-options.js b/test/parallel/test-net-connect-options-allowhalfopen.js similarity index 61% rename from test/parallel/test-net-connect-options.js rename to test/parallel/test-net-connect-options-allowhalfopen.js index e71ea14592b290..4bf6b9094bdc4d 100644 --- a/test/parallel/test-net-connect-options.js +++ b/test/parallel/test-net-connect-options-allowhalfopen.js @@ -23,10 +23,6 @@ const common = require('../common'); const assert = require('assert'); const net = require('net'); -const TCP = process.binding('tcp_wrap').TCP; -const Pipe = process.binding('pipe_wrap').Pipe; - -common.refreshTmpDir(); function testClients(getSocketOpt, getConnectOpt, getConnectCb) { const cloneOptions = (index) => @@ -126,104 +122,3 @@ const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); testClients(getSocketOpt, getConnectOpt, getConnectCb); })); } - -// Test TCP fd is wrapped correctly -if (!common.isWindows) { // Doesn't support this on windows - let counter = 0; - const server = net.createServer() - .on('connection', forAllClients(function serverOnConnection(socket) { - socket.end('ok'); - socket.on('end', common.mustCall(function() { - counter++; - if (counter === CLIENT_VARIANTS) { - setTimeout(() => { - server.close(); - }, 50); - } - }, 1)); - })) - .listen(0, 'localhost', common.mustCall(function serverOnListen() { - const handleMap = new Map(); - const getSocketOpt = (index) => { - const handle = new TCP(); - const address = server.address().address; - let err = 0; - if (net.isIPv6(address)) { - err = handle.bind6(address, 0); - } else { - err = handle.bind(address, 0); - } - - assert(err >= 0, '' + err); - assert.notStrictEqual(handle.fd, -1); - handleMap.set(index, handle); - return { fd: handle.fd }; - }; - - const getConnectOpt = () => ({ - host: 'localhost', - port: server.address().port, - }); - - 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.end(); - client.on('close', common.mustCall(function() { - oldHandle.close(); - })); - }); - - testClients(getSocketOpt, getConnectOpt, getConnectCb); - })); -} - -// Test Pipe fd is wrapped correctly -if (!common.isWindows) { // Doesn't support this on windows - const prefix = `${common.PIPE}-net-connect-options-fd`; - const serverPath = `${prefix}-server`; - let counter = 0; - let socketCounter = 0; - const server = net.createServer() - .on('connection', forAllClients(function serverOnConnection(socket) { - socket.end('ok'); - socket.on('end', common.mustCall(function() { - counter++; - if (counter === CLIENT_VARIANTS) { - setTimeout(() => { - server.close(); - }, 50); - } - }, 1)); - })) - .listen({path: serverPath}, common.mustCall(function serverOnListen() { - const handleMap = new Map(); - 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); - return { fd: handle.fd }; - }; - 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.end(); - client.on('close', common.mustCall(function clientOnClose() { - oldHandle.close(); - })); - }); - - 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); + })); +}