11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci'use strict'; 231cb0ef41Sopenharmony_ciconst common = require('../common'); 241cb0ef41Sopenharmony_ciconst assert = require('assert'); 251cb0ef41Sopenharmony_ciconst fork = require('child_process').fork; 261cb0ef41Sopenharmony_ciconst net = require('net'); 271cb0ef41Sopenharmony_ciconst debug = require('util').debuglog('test'); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciconst Countdown = require('../common/countdown'); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciif (process.argv[2] === 'child') { 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci let serverScope; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // TODO(@jasnell): The message event is not called consistently 361cb0ef41Sopenharmony_ci // across platforms. Need to investigate if it can be made 371cb0ef41Sopenharmony_ci // more consistent. 381cb0ef41Sopenharmony_ci const onServer = (msg, server) => { 391cb0ef41Sopenharmony_ci if (msg.what !== 'server') return; 401cb0ef41Sopenharmony_ci process.removeListener('message', onServer); 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci serverScope = server; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // TODO(@jasnell): This is apparently not called consistently 451cb0ef41Sopenharmony_ci // across platforms. Need to investigate if it can be made 461cb0ef41Sopenharmony_ci // more consistent. 471cb0ef41Sopenharmony_ci server.on('connection', (socket) => { 481cb0ef41Sopenharmony_ci debug('CHILD: got connection'); 491cb0ef41Sopenharmony_ci process.send({ what: 'connection' }); 501cb0ef41Sopenharmony_ci socket.destroy(); 511cb0ef41Sopenharmony_ci }); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // Start making connection from parent. 541cb0ef41Sopenharmony_ci debug('CHILD: server listening'); 551cb0ef41Sopenharmony_ci process.send({ what: 'listening' }); 561cb0ef41Sopenharmony_ci }; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci process.on('message', onServer); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // TODO(@jasnell): The close event is not called consistently 611cb0ef41Sopenharmony_ci // across platforms. Need to investigate if it can be made 621cb0ef41Sopenharmony_ci // more consistent. 631cb0ef41Sopenharmony_ci const onClose = (msg) => { 641cb0ef41Sopenharmony_ci if (msg.what !== 'close') return; 651cb0ef41Sopenharmony_ci process.removeListener('message', onClose); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci serverScope.on('close', common.mustCall(() => { 681cb0ef41Sopenharmony_ci process.send({ what: 'close' }); 691cb0ef41Sopenharmony_ci })); 701cb0ef41Sopenharmony_ci serverScope.close(); 711cb0ef41Sopenharmony_ci }; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci process.on('message', onClose); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci process.send({ what: 'ready' }); 761cb0ef41Sopenharmony_ci} else { 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci const child = fork(process.argv[1], ['child']); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci child.on('exit', common.mustCall((code, signal) => { 811cb0ef41Sopenharmony_ci const message = `CHILD: died with ${code}, ${signal}`; 821cb0ef41Sopenharmony_ci assert.strictEqual(code, 0, message); 831cb0ef41Sopenharmony_ci })); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci // Send net.Server to child and test by connecting. 861cb0ef41Sopenharmony_ci function testServer(callback) { 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci // Destroy server execute callback when done. 891cb0ef41Sopenharmony_ci const countdown = new Countdown(2, () => { 901cb0ef41Sopenharmony_ci server.on('close', common.mustCall(() => { 911cb0ef41Sopenharmony_ci debug('PARENT: server closed'); 921cb0ef41Sopenharmony_ci child.send({ what: 'close' }); 931cb0ef41Sopenharmony_ci })); 941cb0ef41Sopenharmony_ci server.close(); 951cb0ef41Sopenharmony_ci }); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci // We expect 4 connections and close events. 981cb0ef41Sopenharmony_ci const connections = new Countdown(4, () => countdown.dec()); 991cb0ef41Sopenharmony_ci const closed = new Countdown(4, () => countdown.dec()); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci // Create server and send it to child. 1021cb0ef41Sopenharmony_ci const server = net.createServer(); 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci // TODO(@jasnell): The specific number of times the connection 1051cb0ef41Sopenharmony_ci // event is emitted appears to be variable across platforms. 1061cb0ef41Sopenharmony_ci // Need to investigate why and whether it can be made 1071cb0ef41Sopenharmony_ci // more consistent. 1081cb0ef41Sopenharmony_ci server.on('connection', (socket) => { 1091cb0ef41Sopenharmony_ci debug('PARENT: got connection'); 1101cb0ef41Sopenharmony_ci socket.destroy(); 1111cb0ef41Sopenharmony_ci connections.dec(); 1121cb0ef41Sopenharmony_ci }); 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci server.on('listening', common.mustCall(() => { 1151cb0ef41Sopenharmony_ci debug('PARENT: server listening'); 1161cb0ef41Sopenharmony_ci child.send({ what: 'server' }, server); 1171cb0ef41Sopenharmony_ci })); 1181cb0ef41Sopenharmony_ci server.listen(0); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci // Handle client messages. 1211cb0ef41Sopenharmony_ci // TODO(@jasnell): The specific number of times the message 1221cb0ef41Sopenharmony_ci // event is emitted appears to be variable across platforms. 1231cb0ef41Sopenharmony_ci // Need to investigate why and whether it can be made 1241cb0ef41Sopenharmony_ci // more consistent. 1251cb0ef41Sopenharmony_ci const messageHandlers = (msg) => { 1261cb0ef41Sopenharmony_ci if (msg.what === 'listening') { 1271cb0ef41Sopenharmony_ci // Make connections. 1281cb0ef41Sopenharmony_ci let socket; 1291cb0ef41Sopenharmony_ci for (let i = 0; i < 4; i++) { 1301cb0ef41Sopenharmony_ci socket = net.connect(server.address().port, common.mustCall(() => { 1311cb0ef41Sopenharmony_ci debug('CLIENT: connected'); 1321cb0ef41Sopenharmony_ci })); 1331cb0ef41Sopenharmony_ci socket.on('close', common.mustCall(() => { 1341cb0ef41Sopenharmony_ci closed.dec(); 1351cb0ef41Sopenharmony_ci debug('CLIENT: closed'); 1361cb0ef41Sopenharmony_ci })); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci } else if (msg.what === 'connection') { 1401cb0ef41Sopenharmony_ci // Child got connection 1411cb0ef41Sopenharmony_ci connections.dec(); 1421cb0ef41Sopenharmony_ci } else if (msg.what === 'close') { 1431cb0ef41Sopenharmony_ci child.removeListener('message', messageHandlers); 1441cb0ef41Sopenharmony_ci callback(); 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci }; 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci child.on('message', messageHandlers); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci const onReady = common.mustCall((msg) => { 1521cb0ef41Sopenharmony_ci if (msg.what !== 'ready') return; 1531cb0ef41Sopenharmony_ci child.removeListener('message', onReady); 1541cb0ef41Sopenharmony_ci testServer(common.mustCall()); 1551cb0ef41Sopenharmony_ci }); 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci // Create server and send it to child. 1581cb0ef41Sopenharmony_ci child.on('message', onReady); 1591cb0ef41Sopenharmony_ci} 160