2016-11-22 17:13:44 +01:00
|
|
|
// Covers TCPWRAP and related TCPCONNECTWRAP
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const common = require('../common');
|
2017-07-01 01:29:09 +02:00
|
|
|
if (!common.hasIPv6)
|
|
|
|
common.skip('IPv6 support required');
|
|
|
|
|
2016-11-22 17:13:44 +01:00
|
|
|
const assert = require('assert');
|
2018-10-12 19:35:08 +02:00
|
|
|
const tick = require('../common/tick');
|
2016-11-22 17:13:44 +01:00
|
|
|
const initHooks = require('./init-hooks');
|
|
|
|
const { checkInvocations } = require('./hook-checks');
|
|
|
|
const net = require('net');
|
|
|
|
|
2017-11-20 17:18:40 +01:00
|
|
|
let tcp1, tcp2;
|
|
|
|
let tcpserver;
|
2016-11-22 17:13:44 +01:00
|
|
|
let tcpconnect;
|
|
|
|
|
|
|
|
const hooks = initHooks();
|
|
|
|
hooks.enable();
|
|
|
|
|
|
|
|
const server = net
|
|
|
|
.createServer(common.mustCall(onconnection))
|
|
|
|
.on('listening', common.mustCall(onlistening));
|
|
|
|
|
|
|
|
// Calling server.listen creates a TCPWRAP synchronously
|
|
|
|
{
|
2017-11-22 23:39:38 +01:00
|
|
|
server.listen(0);
|
2017-11-20 17:18:40 +01:00
|
|
|
const tcpsservers = hooks.activitiesOfTypes('TCPSERVERWRAP');
|
2016-11-22 17:13:44 +01:00
|
|
|
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
|
2017-11-20 17:18:40 +01:00
|
|
|
assert.strictEqual(tcpsservers.length, 1);
|
2017-05-26 17:53:06 +02:00
|
|
|
assert.strictEqual(tcpconnects.length, 0);
|
2017-11-20 17:18:40 +01:00
|
|
|
tcpserver = tcpsservers[0];
|
|
|
|
assert.strictEqual(tcpserver.type, 'TCPSERVERWRAP');
|
|
|
|
assert.strictEqual(typeof tcpserver.uid, 'number');
|
|
|
|
assert.strictEqual(typeof tcpserver.triggerAsyncId, 'number');
|
|
|
|
checkInvocations(tcpserver, { init: 1 }, 'when calling server.listen');
|
2016-11-22 17:13:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calling net.connect creates another TCPWRAP synchronously
|
|
|
|
{
|
|
|
|
net.connect(
|
2017-08-17 19:18:06 +02:00
|
|
|
{ port: server.address().port, host: '::1' },
|
2016-11-22 17:13:44 +01:00
|
|
|
common.mustCall(onconnected));
|
|
|
|
const tcps = hooks.activitiesOfTypes('TCPWRAP');
|
2017-11-20 17:18:40 +01:00
|
|
|
assert.strictEqual(tcps.length, 1);
|
2017-05-05 13:10:43 +02:00
|
|
|
process.nextTick(() => {
|
|
|
|
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
|
2017-05-26 17:53:06 +02:00
|
|
|
assert.strictEqual(tcpconnects.length, 1);
|
2017-05-05 13:10:43 +02:00
|
|
|
});
|
|
|
|
|
2017-11-20 17:18:40 +01:00
|
|
|
tcp1 = tcps[0];
|
|
|
|
assert.strictEqual(tcps.length, 1);
|
|
|
|
assert.strictEqual(tcp1.type, 'TCPWRAP');
|
|
|
|
assert.strictEqual(typeof tcp1.uid, 'number');
|
|
|
|
assert.strictEqual(typeof tcp1.triggerAsyncId, 'number');
|
2016-11-22 17:13:44 +01:00
|
|
|
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcpserver, { init: 1 },
|
|
|
|
'tcpserver when client is connecting');
|
2016-11-22 17:13:44 +01:00
|
|
|
checkInvocations(tcp1, { init: 1 }, 'tcp1 when client is connecting');
|
|
|
|
}
|
|
|
|
|
|
|
|
function onlistening() {
|
2017-11-20 17:18:40 +01:00
|
|
|
assert.strictEqual(hooks.activitiesOfTypes('TCPWRAP').length, 1);
|
2016-11-22 17:13:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Depending on timing we see client: onconnected or server: onconnection first
|
|
|
|
// Therefore we can't depend on any ordering, but when we see a connection for
|
|
|
|
// the first time we assign the tcpconnectwrap.
|
|
|
|
function ontcpConnection(serverConnection) {
|
|
|
|
if (tcpconnect != null) {
|
|
|
|
// When client receives connection first ('onconnected') and the server
|
|
|
|
// second then we see an 'after' here, otherwise not
|
|
|
|
const expected = serverConnection ?
|
|
|
|
{ init: 1, before: 1, after: 1 } :
|
|
|
|
{ init: 1, before: 1 };
|
|
|
|
checkInvocations(
|
|
|
|
tcpconnect, expected,
|
|
|
|
'tcpconnect: when both client and server received connection');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-07 01:03:53 +01:00
|
|
|
// Only focusing on TCPCONNECTWRAP here
|
2016-11-22 17:13:44 +01:00
|
|
|
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
|
2017-05-26 17:53:06 +02:00
|
|
|
assert.strictEqual(tcpconnects.length, 1);
|
2016-11-22 17:13:44 +01:00
|
|
|
tcpconnect = tcpconnects[0];
|
2017-05-26 17:53:06 +02:00
|
|
|
assert.strictEqual(tcpconnect.type, 'TCPCONNECTWRAP');
|
|
|
|
assert.strictEqual(typeof tcpconnect.uid, 'number');
|
2017-06-14 12:39:53 +02:00
|
|
|
assert.strictEqual(typeof tcpconnect.triggerAsyncId, 'number');
|
2016-11-22 17:13:44 +01:00
|
|
|
// When client receives connection first ('onconnected'), we 'before' has
|
|
|
|
// been invoked at this point already, otherwise it only was 'init'ed
|
|
|
|
const expected = serverConnection ? { init: 1 } : { init: 1, before: 1 };
|
|
|
|
checkInvocations(tcpconnect, expected,
|
|
|
|
'tcpconnect: when tcp connection is established');
|
|
|
|
}
|
|
|
|
|
|
|
|
let serverConnected = false;
|
|
|
|
function onconnected() {
|
|
|
|
ontcpConnection(false);
|
|
|
|
// In the case that the client connects before the server TCPWRAP 'before'
|
|
|
|
// and 'after' weren't invoked yet. Also @see ontcpConnection.
|
|
|
|
const expected = serverConnected ?
|
|
|
|
{ init: 1, before: 1, after: 1 } :
|
|
|
|
{ init: 1 };
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcpserver, expected, 'tcpserver when client connects');
|
|
|
|
checkInvocations(tcp1, { init: 1 }, 'tcp1 when client connects');
|
2016-11-22 17:13:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function onconnection(c) {
|
|
|
|
serverConnected = true;
|
|
|
|
ontcpConnection(true);
|
|
|
|
|
|
|
|
const tcps = hooks.activitiesOfTypes([ 'TCPWRAP' ]);
|
|
|
|
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
|
2017-11-20 17:18:40 +01:00
|
|
|
assert.strictEqual(tcps.length, 2);
|
2017-05-26 17:53:06 +02:00
|
|
|
assert.strictEqual(tcpconnects.length, 1);
|
2017-11-20 17:18:40 +01:00
|
|
|
tcp2 = tcps[1];
|
|
|
|
assert.strictEqual(tcp2.type, 'TCPWRAP');
|
|
|
|
assert.strictEqual(typeof tcp2.uid, 'number');
|
|
|
|
assert.strictEqual(typeof tcp2.triggerAsyncId, 'number');
|
2016-11-22 17:13:44 +01:00
|
|
|
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcpserver, { init: 1, before: 1 },
|
|
|
|
'tcpserver when server receives connection');
|
|
|
|
checkInvocations(tcp1, { init: 1 }, 'tcp1 when server receives connection');
|
2016-11-22 17:13:44 +01:00
|
|
|
checkInvocations(tcp2, { init: 1 }, 'tcp2 when server receives connection');
|
|
|
|
|
|
|
|
c.end();
|
|
|
|
this.close(common.mustCall(onserverClosed));
|
|
|
|
}
|
|
|
|
|
|
|
|
function onserverClosed() {
|
2017-11-18 14:54:06 +01:00
|
|
|
setImmediate(() => {
|
2022-10-25 20:21:02 +02:00
|
|
|
checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 },
|
|
|
|
'tcpserver when server is closed');
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcp1, { init: 1, before: 2, after: 2, destroy: 1 },
|
|
|
|
'tcp1 after server is closed');
|
2017-11-18 14:54:06 +01:00
|
|
|
});
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcp2, { init: 1, before: 1, after: 1 },
|
|
|
|
'tcp2 synchronously when server is closed');
|
|
|
|
|
2016-11-22 17:13:44 +01:00
|
|
|
tick(2, () => {
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcp2, { init: 1, before: 2, after: 2, destroy: 1 },
|
|
|
|
'tcp2 when server is closed');
|
2016-11-22 17:13:44 +01:00
|
|
|
checkInvocations(tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 },
|
|
|
|
'tcpconnect when server is closed');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
process.on('exit', onexit);
|
|
|
|
|
|
|
|
function onexit() {
|
|
|
|
hooks.disable();
|
2017-11-20 17:18:40 +01:00
|
|
|
hooks.sanityCheck([ 'TCPWRAP', 'TCPSERVERWRAP', 'TCPCONNECTWRAP' ]);
|
2016-11-22 17:13:44 +01:00
|
|
|
|
2017-11-20 17:18:40 +01:00
|
|
|
checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 },
|
|
|
|
'tcpserver when process exits');
|
|
|
|
checkInvocations(
|
|
|
|
tcp1, { init: 1, before: 2, after: 2, destroy: 1 },
|
|
|
|
'tcp1 when process exits');
|
2016-11-22 17:13:44 +01:00
|
|
|
checkInvocations(
|
|
|
|
tcp2, { init: 1, before: 2, after: 2, destroy: 1 },
|
|
|
|
'tcp2 when process exits');
|
|
|
|
checkInvocations(
|
|
|
|
tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 },
|
|
|
|
'tcpconnect when process exits');
|
|
|
|
}
|