11cb0ef41Sopenharmony_ci// Covers TCPWRAP and related TCPCONNECTWRAP 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst common = require('../common'); 51cb0ef41Sopenharmony_ciif (!common.hasIPv6) 61cb0ef41Sopenharmony_ci common.skip('IPv6 support required'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciconst assert = require('assert'); 91cb0ef41Sopenharmony_ciconst tick = require('../common/tick'); 101cb0ef41Sopenharmony_ciconst initHooks = require('./init-hooks'); 111cb0ef41Sopenharmony_ciconst { checkInvocations } = require('./hook-checks'); 121cb0ef41Sopenharmony_ciconst net = require('net'); 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cilet tcp1, tcp2; 151cb0ef41Sopenharmony_cilet tcpserver; 161cb0ef41Sopenharmony_cilet tcpconnect; 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciconst hooks = initHooks(); 191cb0ef41Sopenharmony_cihooks.enable(); 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ciconst server = net 221cb0ef41Sopenharmony_ci .createServer(common.mustCall(onconnection)) 231cb0ef41Sopenharmony_ci .on('listening', common.mustCall(onlistening)); 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci// Calling server.listen creates a TCPWRAP synchronously 261cb0ef41Sopenharmony_ci{ 271cb0ef41Sopenharmony_ci server.listen(0); 281cb0ef41Sopenharmony_ci const tcpsservers = hooks.activitiesOfTypes('TCPSERVERWRAP'); 291cb0ef41Sopenharmony_ci const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP'); 301cb0ef41Sopenharmony_ci assert.strictEqual(tcpsservers.length, 1); 311cb0ef41Sopenharmony_ci assert.strictEqual(tcpconnects.length, 0); 321cb0ef41Sopenharmony_ci tcpserver = tcpsservers[0]; 331cb0ef41Sopenharmony_ci assert.strictEqual(tcpserver.type, 'TCPSERVERWRAP'); 341cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcpserver.uid, 'number'); 351cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcpserver.triggerAsyncId, 'number'); 361cb0ef41Sopenharmony_ci checkInvocations(tcpserver, { init: 1 }, 'when calling server.listen'); 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci// Calling net.connect creates another TCPWRAP synchronously 401cb0ef41Sopenharmony_ci{ 411cb0ef41Sopenharmony_ci net.connect( 421cb0ef41Sopenharmony_ci { port: server.address().port, host: '::1' }, 431cb0ef41Sopenharmony_ci common.mustCall(onconnected)); 441cb0ef41Sopenharmony_ci const tcps = hooks.activitiesOfTypes('TCPWRAP'); 451cb0ef41Sopenharmony_ci assert.strictEqual(tcps.length, 1); 461cb0ef41Sopenharmony_ci process.nextTick(() => { 471cb0ef41Sopenharmony_ci const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP'); 481cb0ef41Sopenharmony_ci assert.strictEqual(tcpconnects.length, 1); 491cb0ef41Sopenharmony_ci }); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci tcp1 = tcps[0]; 521cb0ef41Sopenharmony_ci assert.strictEqual(tcps.length, 1); 531cb0ef41Sopenharmony_ci assert.strictEqual(tcp1.type, 'TCPWRAP'); 541cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcp1.uid, 'number'); 551cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcp1.triggerAsyncId, 'number'); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci checkInvocations(tcpserver, { init: 1 }, 581cb0ef41Sopenharmony_ci 'tcpserver when client is connecting'); 591cb0ef41Sopenharmony_ci checkInvocations(tcp1, { init: 1 }, 'tcp1 when client is connecting'); 601cb0ef41Sopenharmony_ci} 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_cifunction onlistening() { 631cb0ef41Sopenharmony_ci assert.strictEqual(hooks.activitiesOfTypes('TCPWRAP').length, 1); 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci// Depending on timing we see client: onconnected or server: onconnection first 671cb0ef41Sopenharmony_ci// Therefore we can't depend on any ordering, but when we see a connection for 681cb0ef41Sopenharmony_ci// the first time we assign the tcpconnectwrap. 691cb0ef41Sopenharmony_cifunction ontcpConnection(serverConnection) { 701cb0ef41Sopenharmony_ci if (tcpconnect != null) { 711cb0ef41Sopenharmony_ci // When client receives connection first ('onconnected') and the server 721cb0ef41Sopenharmony_ci // second then we see an 'after' here, otherwise not 731cb0ef41Sopenharmony_ci const expected = serverConnection ? 741cb0ef41Sopenharmony_ci { init: 1, before: 1, after: 1 } : 751cb0ef41Sopenharmony_ci { init: 1, before: 1 }; 761cb0ef41Sopenharmony_ci checkInvocations( 771cb0ef41Sopenharmony_ci tcpconnect, expected, 781cb0ef41Sopenharmony_ci 'tcpconnect: when both client and server received connection'); 791cb0ef41Sopenharmony_ci return; 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci // Only focusing on TCPCONNECTWRAP here 831cb0ef41Sopenharmony_ci const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP'); 841cb0ef41Sopenharmony_ci assert.strictEqual(tcpconnects.length, 1); 851cb0ef41Sopenharmony_ci tcpconnect = tcpconnects[0]; 861cb0ef41Sopenharmony_ci assert.strictEqual(tcpconnect.type, 'TCPCONNECTWRAP'); 871cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcpconnect.uid, 'number'); 881cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcpconnect.triggerAsyncId, 'number'); 891cb0ef41Sopenharmony_ci // When client receives connection first ('onconnected'), we 'before' has 901cb0ef41Sopenharmony_ci // been invoked at this point already, otherwise it only was 'init'ed 911cb0ef41Sopenharmony_ci const expected = serverConnection ? { init: 1 } : { init: 1, before: 1 }; 921cb0ef41Sopenharmony_ci checkInvocations(tcpconnect, expected, 931cb0ef41Sopenharmony_ci 'tcpconnect: when tcp connection is established'); 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_cilet serverConnected = false; 971cb0ef41Sopenharmony_cifunction onconnected() { 981cb0ef41Sopenharmony_ci ontcpConnection(false); 991cb0ef41Sopenharmony_ci // In the case that the client connects before the server TCPWRAP 'before' 1001cb0ef41Sopenharmony_ci // and 'after' weren't invoked yet. Also @see ontcpConnection. 1011cb0ef41Sopenharmony_ci const expected = serverConnected ? 1021cb0ef41Sopenharmony_ci { init: 1, before: 1, after: 1 } : 1031cb0ef41Sopenharmony_ci { init: 1 }; 1041cb0ef41Sopenharmony_ci checkInvocations(tcpserver, expected, 'tcpserver when client connects'); 1051cb0ef41Sopenharmony_ci checkInvocations(tcp1, { init: 1 }, 'tcp1 when client connects'); 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_cifunction onconnection(c) { 1091cb0ef41Sopenharmony_ci serverConnected = true; 1101cb0ef41Sopenharmony_ci ontcpConnection(true); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci const tcps = hooks.activitiesOfTypes([ 'TCPWRAP' ]); 1131cb0ef41Sopenharmony_ci const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP'); 1141cb0ef41Sopenharmony_ci assert.strictEqual(tcps.length, 2); 1151cb0ef41Sopenharmony_ci assert.strictEqual(tcpconnects.length, 1); 1161cb0ef41Sopenharmony_ci tcp2 = tcps[1]; 1171cb0ef41Sopenharmony_ci assert.strictEqual(tcp2.type, 'TCPWRAP'); 1181cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcp2.uid, 'number'); 1191cb0ef41Sopenharmony_ci assert.strictEqual(typeof tcp2.triggerAsyncId, 'number'); 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci checkInvocations(tcpserver, { init: 1, before: 1 }, 1221cb0ef41Sopenharmony_ci 'tcpserver when server receives connection'); 1231cb0ef41Sopenharmony_ci checkInvocations(tcp1, { init: 1 }, 'tcp1 when server receives connection'); 1241cb0ef41Sopenharmony_ci checkInvocations(tcp2, { init: 1 }, 'tcp2 when server receives connection'); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci c.end(); 1271cb0ef41Sopenharmony_ci this.close(common.mustCall(onserverClosed)); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_cifunction onserverClosed() { 1311cb0ef41Sopenharmony_ci setImmediate(() => { 1321cb0ef41Sopenharmony_ci checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 }, 1331cb0ef41Sopenharmony_ci 'tcpserver when server is closed'); 1341cb0ef41Sopenharmony_ci checkInvocations(tcp1, { init: 1, before: 2, after: 2, destroy: 1 }, 1351cb0ef41Sopenharmony_ci 'tcp1 after server is closed'); 1361cb0ef41Sopenharmony_ci }); 1371cb0ef41Sopenharmony_ci checkInvocations(tcp2, { init: 1, before: 1, after: 1 }, 1381cb0ef41Sopenharmony_ci 'tcp2 synchronously when server is closed'); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci tick(2, () => { 1411cb0ef41Sopenharmony_ci checkInvocations(tcp2, { init: 1, before: 2, after: 2, destroy: 1 }, 1421cb0ef41Sopenharmony_ci 'tcp2 when server is closed'); 1431cb0ef41Sopenharmony_ci checkInvocations(tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 }, 1441cb0ef41Sopenharmony_ci 'tcpconnect when server is closed'); 1451cb0ef41Sopenharmony_ci }); 1461cb0ef41Sopenharmony_ci} 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciprocess.on('exit', onexit); 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_cifunction onexit() { 1511cb0ef41Sopenharmony_ci hooks.disable(); 1521cb0ef41Sopenharmony_ci hooks.sanityCheck([ 'TCPWRAP', 'TCPSERVERWRAP', 'TCPCONNECTWRAP' ]); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 }, 1551cb0ef41Sopenharmony_ci 'tcpserver when process exits'); 1561cb0ef41Sopenharmony_ci checkInvocations( 1571cb0ef41Sopenharmony_ci tcp1, { init: 1, before: 2, after: 2, destroy: 1 }, 1581cb0ef41Sopenharmony_ci 'tcp1 when process exits'); 1591cb0ef41Sopenharmony_ci checkInvocations( 1601cb0ef41Sopenharmony_ci tcp2, { init: 1, before: 2, after: 2, destroy: 1 }, 1611cb0ef41Sopenharmony_ci 'tcp2 when process exits'); 1621cb0ef41Sopenharmony_ci checkInvocations( 1631cb0ef41Sopenharmony_ci tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 }, 1641cb0ef41Sopenharmony_ci 'tcpconnect when process exits'); 1651cb0ef41Sopenharmony_ci} 166