James M Snell | 98e54b0 | 2017-01-03 21:16:48 | [diff] [blame] | 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 | |
Roman Reiss | f29762f | 2015-05-19 11:00:06 | [diff] [blame] | 22 | 'use strict'; |
Fikret Burak Gazioglu | 0bfd103 | 2016-09-17 08:33:12 | [diff] [blame] | 23 | const common = require('../common'); |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 24 | |
| 25 | // This test asserts the semantics of dgram::socket.bind({ exclusive }) |
| 26 | // when called from a cluster.Worker |
| 27 | |
Fikret Burak Gazioglu | 0bfd103 | 2016-09-17 08:33:12 | [diff] [blame] | 28 | const assert = require('assert'); |
| 29 | const cluster = require('cluster'); |
| 30 | const dgram = require('dgram'); |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 31 | const BYE = 'bye'; |
| 32 | const WORKER2_NAME = 'wrker2'; |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 33 | |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 34 | if (cluster.isMaster) { |
Fikret Burak Gazioglu | 0bfd103 | 2016-09-17 08:33:12 | [diff] [blame] | 35 | const worker1 = cluster.fork(); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 36 | |
Rich Trott | 8e9089a | 2015-06-23 05:17:52 | [diff] [blame] | 37 | if (common.isWindows) { |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 38 | worker1.on('error', common.mustCall((err) => { |
| 39 | console.log(err); |
| 40 | assert.strictEqual(err.code, 'ENOTSUP'); |
Rich Trott | 8e9089a | 2015-06-23 05:17:52 | [diff] [blame] | 41 | worker1.kill(); |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 42 | })); |
Rich Trott | 8e9089a | 2015-06-23 05:17:52 | [diff] [blame] | 43 | return; |
| 44 | } |
| 45 | |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 46 | worker1.on('message', common.mustCall((msg) => { |
| 47 | console.log(msg); |
Fikret Burak Gazioglu | 0bfd103 | 2016-09-17 08:33:12 | [diff] [blame] | 48 | assert.strictEqual(msg, 'success'); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 49 | |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 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 master code |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 69 | } else { |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 70 | // worker code |
| 71 | process.on('message', common.mustCallAtLeast((msg) => { |
| 72 | if (msg === BYE) process.exit(0); |
| 73 | }), 1); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 74 | |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 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()); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 79 | |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 80 | socket1.on('error', (err) => assert.fail(err)); |
| 81 | socket2.on('error', (err) => assert.fail(err)); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 82 | |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 83 | // First worker should bind, second should err |
| 84 | const socket3OnBind = |
| 85 | isSecondWorker ? |
Rich Trott | aa6fac6 | 2017-07-25 17:37:08 | [diff] [blame^] | 86 | common.mustNotCall() : |
| 87 | common.mustCall(() => { |
| 88 | const port3 = socket3.address().port; |
| 89 | assert.strictEqual(typeof port3, 'number'); |
| 90 | process.send('success'); |
| 91 | }); |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 92 | // an error is expected only in the second worker |
| 93 | const socket3OnError = |
| 94 | !isSecondWorker ? |
Rich Trott | aa6fac6 | 2017-07-25 17:37:08 | [diff] [blame^] | 95 | common.mustNotCall() : |
| 96 | common.mustCall((err) => { |
| 97 | process.send(`socket3:${err.code}`); |
| 98 | }); |
Refael Ackermann | c9d45c4 | 2017-05-18 22:58:00 | [diff] [blame] | 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 | })); |
cjihrig | 029cfc1 | 2014-08-22 20:51:53 | [diff] [blame] | 113 | } |