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: refactor test-net-connect-options-allowhalfopen.js #13003

Merged
merged 1 commit into from
Sep 20, 2017
Merged
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
132 changes: 63 additions & 69 deletions test/parallel/test-net-connect-options-allowhalfopen.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,101 +24,95 @@ 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`);
const host = common.localhostIPv4;

function serverOnConnection(socket) {
console.log(`'connection' ${++serverConnections} emitted on server`);
const srvConn = serverConnections;
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('data', common.mustCall(function socketOnData(data) {
this.clientId = data.toString();
console.log(
`server connection ${srvConn} is started by client ${this.clientId}`);
}));
socket.on('end', common.mustCall(function() {
serverReceivedFIN++;
console.error(`Server received 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);
}
// 'end' on each socket must not be emitted twice
socket.on('end', common.mustCall(function socketOnEnd() {
console.log(`Server received FIN sent by client ${this.clientId}`);
if (++serverReceivedFIN < CLIENT_VARIANTS) return;
setTimeout(() => {
server.close();
console.log(`connection ${this.clientId} is closing the server:
FIN ${serverReceivedFIN} received by server,
FIN ${clientReceivedFIN} received by client
FIN ${clientSentFIN} sent by client,
FIN ${serverConnections} sent by server`.replace(/ {3,}/g, ''));
}, 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.log(`Server has sent ${serverConnections} FIN`);
}

console.error(`Server starts at ${host}:${port}`);
const getSocketOpt = () => ({ allowHalfOpen: true });
const getConnectOpt = () => ({ host, port });
const getConnectCb = (index) => common.mustCall(function clientOnConnect() {
// These two levels of functions (and not arrows) are necessary in order to
// bind the `index`, and the calling socket (`this`)
function clientOnConnect(index) {
return common.mustCall(function clientOnConnectInner() {
const client = this;
console.error(`'connect' emitted on Client ${index}`);
console.log(`'connect' emitted on Client ${index}`);
client.resume();
client.on('end', common.mustCall(function clientOnEnd() {
setTimeout(function() {
setTimeout(function closeServer() {
// 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`);
console.log(`client ${index} received FIN`);
assert(!client.readable);
assert(client.writable);
assert(client.write(String(index)));
client.end();
clientSentFIN++;
console.error(`No. ${index} client sent FIN, ` +
`${clientSentFIN} have been sent`);
console.log(
`client ${index} 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`);
console.log(`connection ${index} has been closed by both sides,` +
` ${clientReceivedFIN} clients have closed`);
}));
});
}

function serverOnClose() {
console.log(`Server has been closed:
FIN ${serverReceivedFIN} received by server
FIN ${clientReceivedFIN} received by client
FIN ${clientSentFIN} sent by client
FIN ${serverConnections} sent by server`.replace(/ {3,}/g, ''));
}

function serverOnListen() {
const port = server.address().port;
console.log(`Server started listening at ${host}:${port}`);
const opts = { allowHalfOpen: true, host, port };
// 6 variations === CLIENT_VARIANTS
net.connect(opts, clientOnConnect(1));
net.connect(opts).on('connect', clientOnConnect(2));
net.createConnection(opts, clientOnConnect(3));
net.createConnection(opts).on('connect', clientOnConnect(4));
new net.Socket(opts).connect(opts, clientOnConnect(5));
new net.Socket(opts).connect(opts).on('connect', clientOnConnect(6));
}

const CLIENT_VARIANTS = 6;

testClients(getSocketOpt, getConnectOpt, getConnectCb);
}));
// The trigger
const server = net.createServer({ allowHalfOpen: true })
.on('connection', common.mustCall(serverOnConnection, CLIENT_VARIANTS))
.on('close', common.mustCall(serverOnClose))
.listen(0, host, common.mustCall(serverOnListen));
}