Skip to content
Closed
Changes from 1 commit
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
Next Next commit
test: add more test cases to net.connect
  • Loading branch information
joyeecheung committed Mar 14, 2017
commit c0fc1196389eb19dc0785d6fe9c6ea587b2ebe91
181 changes: 157 additions & 24 deletions test/parallel/test-net-connect-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,164 @@
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;

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,
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 allowHalfOpen
{
let counter = 0;
const server = net.createServer({
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();
})
.on('connection', forAllClients(function(socket) {
socket.resume();
// 'end' on each socket must not be emitted twice
socket.on('end', common.mustCall(function() {}, 1));
socket.end();
}))
.listen(0, common.mustCall(function() {
const getSocketOpt = () => ({ allowHalfOpen: true });
const getConnectOpt = () => ({
host: server.address().address,
port: server.address().port,
});
const getConnectCb = () => common.mustCall(function() {
const client = this;
client.resume();
client.on('end', common.mustCall(function() {
setTimeout(function() {
// when allowHalfOpen is true, client must still be writable
// after the server closes the connections, but not readable
assert(!client.readable);
assert(client.writable);
assert(client.write('foo'));
client.end();
}, 50);
}));
client.on('close', common.mustCall(function() {
counter++;
if (counter === CLIENT_VARIANTS) {
setTimeout(() => {
server.close();
}, 50);
}
}));
});

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(socket) {
socket.end('ok');
}))
.listen(0, common.mustCall(function() {
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: server.address().address,
port: server.address().port,
});

const getConnectCb = (index) => common.mustCall(function() {
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();
counter++;
if (counter === CLIENT_VARIANTS) {
server.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(socket) {
socket.end('ok');
}))
.listen({path: serverPath}, common.mustCall(function() {
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() {
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();
counter++;
if (counter === CLIENT_VARIANTS) {
server.close();
}
}));
});

testClients(getSocketOpt, getConnectOpt, getConnectCb);
}));
});
}