1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24 25// This test asserts the semantics of dgram::socket.bind({ exclusive }) 26// when called from a cluster.Worker 27 28const assert = require('assert'); 29const cluster = require('cluster'); 30const dgram = require('dgram'); 31const BYE = 'bye'; 32const WORKER2_NAME = 'wrker2'; 33 34if (cluster.isPrimary) { 35 const worker1 = cluster.fork(); 36 37 if (common.isWindows) { 38 worker1.on('error', common.mustCall((err) => { 39 console.log(err); 40 assert.strictEqual(err.code, 'ENOTSUP'); 41 worker1.kill(); 42 })); 43 return; 44 } 45 46 worker1.on('message', common.mustCall((msg) => { 47 console.log(msg); 48 assert.strictEqual(msg, 'success'); 49 50 const worker2 = cluster.fork({ WORKER2_NAME }); 51 worker2.on('message', common.mustCall((msg) => { 52 console.log(msg); 53 assert.strictEqual(msg, 'socket3:EADDRINUSE'); 54 55 // finish test 56 worker1.send(BYE); 57 worker2.send(BYE); 58 })); 59 worker2.on('exit', common.mustCall((code, signal) => { 60 assert.strictEqual(signal, null); 61 assert.strictEqual(code, 0); 62 })); 63 })); 64 worker1.on('exit', common.mustCall((code, signal) => { 65 assert.strictEqual(signal, null); 66 assert.strictEqual(code, 0); 67 })); 68 // end primary code 69} else { 70 // worker code 71 process.on('message', common.mustCallAtLeast((msg) => { 72 if (msg === BYE) process.exit(0); 73 }), 1); 74 75 const isSecondWorker = process.env.WORKER2_NAME === WORKER2_NAME; 76 const socket1 = dgram.createSocket('udp4', common.mustNotCall()); 77 const socket2 = dgram.createSocket('udp4', common.mustNotCall()); 78 const socket3 = dgram.createSocket('udp4', common.mustNotCall()); 79 80 socket1.on('error', (err) => assert.fail(err)); 81 socket2.on('error', (err) => assert.fail(err)); 82 83 // First worker should bind, second should err 84 const socket3OnBind = 85 isSecondWorker ? 86 common.mustNotCall() : 87 common.mustCall(() => { 88 const port3 = socket3.address().port; 89 assert.strictEqual(typeof port3, 'number'); 90 process.send('success'); 91 }); 92 // An error is expected only in the second worker 93 const socket3OnError = 94 !isSecondWorker ? 95 common.mustNotCall() : 96 common.mustCall((err) => { 97 process.send(`socket3:${err.code}`); 98 }); 99 const address = common.localhostIPv4; 100 const opt1 = { address, port: 0, exclusive: false }; 101 const opt2 = { address, port: common.PORT, exclusive: false }; 102 const opt3 = { address, port: common.PORT + 1, exclusive: true }; 103 socket1.bind(opt1, common.mustCall(() => { 104 const port1 = socket1.address().port; 105 assert.strictEqual(typeof port1, 'number'); 106 socket2.bind(opt2, common.mustCall(() => { 107 const port2 = socket2.address().port; 108 assert.strictEqual(typeof port2, 'number'); 109 socket3.on('error', socket3OnError); 110 socket3.bind(opt3, socket3OnBind); 111 })); 112 })); 113} 114