| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c93e267 commit 22b0971
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,30 +1,122 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | - var common = require('../common'), | ||
| 3 | - assert = require('assert'), | ||
| 4 | - dgram = require('dgram'), | ||
| 5 | - util = require('util'), | ||
| 6 | - Buffer = require('buffer').Buffer, | ||
| 7 | - fork = require('child_process').fork, | ||
| 8 | - LOCAL_BROADCAST_HOST = '224.0.0.114', | ||
| 9 | - TIMEOUT = common.platformTimeout(5000), | ||
| 10 | - messages = [ | ||
| 11 | - new Buffer('First message to send'), | ||
| 12 | - new Buffer('Second message to send'), | ||
| 13 | - new Buffer('Third message to send'), | ||
| 14 | - new Buffer('Fourth message to send') | ||
| 15 | - ]; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const dgram = require('dgram'); | ||
| 5 | + const fork = require('child_process').fork; | ||
| 6 | + const LOCAL_BROADCAST_HOST = '224.0.0.114'; | ||
| 7 | + const TIMEOUT = common.platformTimeout(5000); | ||
| 8 | + const messages = [ | ||
| 9 | + new Buffer('First message to send'), | ||
| 10 | + new Buffer('Second message to send'), | ||
| 11 | + new Buffer('Third message to send'), | ||
| 12 | + new Buffer('Fourth message to send') | ||
| 13 | + ]; | ||
| 14 | + const workers = {}; | ||
| 15 | + const listeners = 3; | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + // Skip test in FreeBSD jails. | ||
| 19 | + if (common.inFreeBSDJail) { | ||
| 20 | + console.log('1..0 # Skipped: In a FreeBSD jail'); | ||
| 21 | + return; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + function launchChildProcess(index) { | ||
| 25 | + const worker = fork(__filename, ['child']); | ||
| 26 | + workers[worker.pid] = worker; | ||
| 27 | + | ||
| 28 | + worker.messagesReceived = []; | ||
| 29 | + | ||
| 30 | + // Handle the death of workers. | ||
| 31 | + worker.on('exit', function(code, signal) { | ||
| 32 | + // Don't consider this the true death if the worker has finished | ||
| 33 | + // successfully or if the exit code is 0. | ||
| 34 | + if (worker.isDone || code === 0) { | ||
| 35 | + return; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + dead += 1; | ||
| 39 | + console.error('[PARENT] Worker %d died. %d dead of %d', | ||
| 40 | + worker.pid, | ||
| 41 | + dead, | ||
| 42 | + listeners); | ||
| 43 | + | ||
| 44 | + if (dead === listeners) { | ||
| 45 | + console.error('[PARENT] All workers have died.'); | ||
| 46 | + console.error('[PARENT] Fail'); | ||
| 47 | + process.exit(1); | ||
| 48 | + } | ||
| 49 | + }); | ||
| 50 | + | ||
| 51 | + worker.on('message', function(msg) { | ||
| 52 | + if (msg.listening) { | ||
| 53 | + listening += 1; | ||
| 54 | + | ||
| 55 | + if (listening === listeners) { | ||
| 56 | + // All child process are listening, so start sending. | ||
| 57 | + sendSocket.sendNext(); | ||
| 58 | + } | ||
| 59 | + return; | ||
| 60 | + } | ||
| 61 | + if (msg.message) { | ||
| 62 | + worker.messagesReceived.push(msg.message); | ||
| 63 | + | ||
| 64 | + if (worker.messagesReceived.length === messages.length) { | ||
| 65 | + done += 1; | ||
| 66 | + worker.isDone = true; | ||
| 67 | + console.error('[PARENT] %d received %d messages total.', | ||
| 68 | + worker.pid, | ||
| 69 | + worker.messagesReceived.length); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + if (done === listeners) { | ||
| 73 | + console.error('[PARENT] All workers have received the ' + | ||
| 74 | + 'required number of messages. Will now compare.'); | ||
| 75 | + | ||
| 76 | + Object.keys(workers).forEach(function(pid) { | ||
| 77 | + const worker = workers[pid]; | ||
| 78 | + | ||
| 79 | + var count = 0; | ||
| 80 | + | ||
| 81 | + worker.messagesReceived.forEach(function(buf) { | ||
| 82 | + for (var i = 0; i < messages.length; ++i) { | ||
| 83 | + if (buf.toString() === messages[i].toString()) { | ||
| 84 | + count++; | ||
| 85 | + break; | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + }); | ||
| 89 | + | ||
| 90 | + console.error('[PARENT] %d received %d matching messages.', | ||
| 91 | + worker.pid, count); | ||
| 92 | + | ||
| 93 | + assert.strictEqual(count, messages.length, | ||
| 94 | + 'A worker received an invalid multicast message'); | ||
| 95 | + }); | ||
| 96 | + | ||
| 97 | + clearTimeout(timer); | ||
| 98 | + console.error('[PARENT] Success'); | ||
| 99 | + killChildren(workers); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + }); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + function killChildren(children) { | ||
| 106 | + Object.keys(children).forEach(function(key) { | ||
| 107 | + const child = children[key]; | ||
| 108 | + child.kill(); | ||
| 109 | + }); | ||
| 110 | + } | ||
| 16 | 111 | ||
| 17 | 112 | if (process.argv[2] !== 'child') { | |
| 18 | - var workers = {}, | ||
| 19 | - listeners = 3, | ||
| 20 | - listening = 0, | ||
| 21 | - dead = 0, | ||
| 22 | - i = 0, | ||
| 23 | - done = 0, | ||
| 24 | - timer = null; | ||
| 25 | - | ||
| 26 | - //exit the test if it doesn't succeed within TIMEOUT | ||
| 27 | - timer = setTimeout(function() { | ||
| 113 | + var listening = 0; | ||
| 114 | + var dead = 0; | ||
| 115 | + var i = 0; | ||
| 116 | + var done = 0; | ||
| 117 | + | ||
| 118 | + // Exit the test if it doesn't succeed within TIMEOUT. | ||
| 119 | + var timer = setTimeout(function() { | ||
| 28 | 120 | console.error('[PARENT] Responses were not received within %d ms.', | |
| 29 | 121 | TIMEOUT); | |
| 30 | 122 | console.error('[PARENT] Fail'); | |
@@ -34,101 +126,18 @@ if (process.argv[2] !== 'child') { | |||
| 34 | 126 | process.exit(1); | |
| 35 | 127 | }, TIMEOUT); | |
| 36 | 128 | ||
| 37 | - //launch child processes | ||
| 129 | + // Launch child processes. | ||
| 38 | 130 | for (var x = 0; x < listeners; x++) { | |
| 39 | - (function() { | ||
| 40 | - var worker = fork(process.argv[1], ['child']); | ||
| 41 | - workers[worker.pid] = worker; | ||
| 42 | - | ||
| 43 | - worker.messagesReceived = []; | ||
| 44 | - | ||
| 45 | - //handle the death of workers | ||
| 46 | - worker.on('exit', function(code, signal) { | ||
| 47 | - // don't consider this the true death if the | ||
| 48 | - // worker has finished successfully | ||
| 49 | - | ||
| 50 | - // or if the exit code is 0 | ||
| 51 | - if (worker.isDone || code === 0) { | ||
| 52 | - return; | ||
| 53 | - } | ||
| 54 | - | ||
| 55 | - dead += 1; | ||
| 56 | - console.error('[PARENT] Worker %d died. %d dead of %d', | ||
| 57 | - worker.pid, | ||
| 58 | - dead, | ||
| 59 | - listeners); | ||
| 60 | - | ||
| 61 | - if (dead === listeners) { | ||
| 62 | - console.error('[PARENT] All workers have died.'); | ||
| 63 | - console.error('[PARENT] Fail'); | ||
| 64 | - | ||
| 65 | - killChildren(workers); | ||
| 66 | - | ||
| 67 | - process.exit(1); | ||
| 68 | - } | ||
| 69 | - }); | ||
| 70 | - | ||
| 71 | - worker.on('message', function(msg) { | ||
| 72 | - if (msg.listening) { | ||
| 73 | - listening += 1; | ||
| 74 | - | ||
| 75 | - if (listening === listeners) { | ||
| 76 | - //all child process are listening, so start sending | ||
| 77 | - sendSocket.sendNext(); | ||
| 78 | - } | ||
| 79 | - } | ||
| 80 | - else if (msg.message) { | ||
| 81 | - worker.messagesReceived.push(msg.message); | ||
| 82 | - | ||
| 83 | - if (worker.messagesReceived.length === messages.length) { | ||
| 84 | - done += 1; | ||
| 85 | - worker.isDone = true; | ||
| 86 | - console.error('[PARENT] %d received %d messages total.', | ||
| 87 | - worker.pid, | ||
| 88 | - worker.messagesReceived.length); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - if (done === listeners) { | ||
| 92 | - console.error('[PARENT] All workers have received the ' + | ||
| 93 | - 'required number of messages. Will now compare.'); | ||
| 94 | - | ||
| 95 | - Object.keys(workers).forEach(function(pid) { | ||
| 96 | - var worker = workers[pid]; | ||
| 97 | - | ||
| 98 | - var count = 0; | ||
| 99 | - | ||
| 100 | - worker.messagesReceived.forEach(function(buf) { | ||
| 101 | - for (var i = 0; i < messages.length; ++i) { | ||
| 102 | - if (buf.toString() === messages[i].toString()) { | ||
| 103 | - count++; | ||
| 104 | - break; | ||
| 105 | - } | ||
| 106 | - } | ||
| 107 | - }); | ||
| 108 | - | ||
| 109 | - console.error('[PARENT] %d received %d matching messages.', | ||
| 110 | - worker.pid, count); | ||
| 111 | - | ||
| 112 | - assert.equal(count, messages.length, | ||
| 113 | - 'A worker received an invalid multicast message'); | ||
| 114 | - }); | ||
| 115 | - | ||
| 116 | - clearTimeout(timer); | ||
| 117 | - console.error('[PARENT] Success'); | ||
| 118 | - killChildren(workers); | ||
| 119 | - } | ||
| 120 | - } | ||
| 121 | - }); | ||
| 122 | - })(x); | ||
| 131 | + launchChildProcess(x); | ||
| 123 | 132 | } | |
| 124 | 133 | ||
| 125 | 134 | var sendSocket = dgram.createSocket('udp4'); | |
| 126 | - // FIXME a libuv limitation makes it necessary to bind() | ||
| 127 | - // before calling any of the set*() functions - the bind() | ||
| 128 | - // call is what creates the actual socket... | ||
| 135 | + // FIXME: a libuv limitation makes it necessary to bind() | ||
| 136 | + // before calling any of the set*() functions. The bind() | ||
| 137 | + // call is what creates the actual socket. | ||
| 129 | 138 | sendSocket.bind(); | |
| 130 | 139 | ||
| 131 | - // The socket is actually created async now | ||
| 140 | + // The socket is actually created async now. | ||
| 132 | 141 | sendSocket.on('listening', function() { | |
| 133 | 142 | sendSocket.setTTL(1); | |
| 134 | 143 | sendSocket.setBroadcast(true); | |
@@ -141,7 +150,7 @@ if (process.argv[2] !== 'child') { | |||
| 141 | 150 | }); | |
| 142 | 151 | ||
| 143 | 152 | sendSocket.sendNext = function() { | |
| 144 | - var buf = messages[i++]; | ||
| 153 | + const buf = messages[i++]; | ||
| 145 | 154 | ||
| 146 | 155 | if (!buf) { | |
| 147 | 156 | try { sendSocket.close(); } catch (e) {} | |
@@ -151,61 +160,51 @@ if (process.argv[2] !== 'child') { | |||
| 151 | 160 | sendSocket.send(buf, 0, buf.length, | |
| 152 | 161 | common.PORT, LOCAL_BROADCAST_HOST, function(err) { | |
| 153 | 162 | if (err) throw err; | |
| 154 | - console.error('[PARENT] sent %s to %s:%s', | ||
| 155 | - util.inspect(buf.toString()), | ||
| 163 | + console.error('[PARENT] sent "%s" to %s:%s', | ||
| 164 | + buf.toString(), | ||
| 156 | 165 | LOCAL_BROADCAST_HOST, common.PORT); | |
| 157 | 166 | process.nextTick(sendSocket.sendNext); | |
| 158 | 167 | }); | |
| 159 | 168 | }; | |
| 160 | - | ||
| 161 | - function killChildren(children) { | ||
| 162 | - Object.keys(children).forEach(function(key) { | ||
| 163 | - var child = children[key]; | ||
| 164 | - child.kill(); | ||
| 165 | - }); | ||
| 166 | - } | ||
| 167 | 169 | } | |
| 168 | 170 | ||
| 169 | 171 | if (process.argv[2] === 'child') { | |
| 170 | - var receivedMessages = []; | ||
| 171 | - var listenSocket = dgram.createSocket({ | ||
| 172 | + const receivedMessages = []; | ||
| 173 | + const listenSocket = dgram.createSocket({ | ||
| 172 | 174 | type: 'udp4', | |
| 173 | 175 | reuseAddr: true | |
| 174 | 176 | }); | |
| 175 | 177 | ||
| 176 | - listenSocket.on('message', function(buf, rinfo) { | ||
| 177 | - console.error('[CHILD] %s received %s from %j', process.pid, | ||
| 178 | - util.inspect(buf.toString()), rinfo); | ||
| 178 | + listenSocket.on('listening', function() { | ||
| 179 | + listenSocket.addMembership(LOCAL_BROADCAST_HOST); | ||
| 179 | 180 | ||
| 180 | - receivedMessages.push(buf); | ||
| 181 | + listenSocket.on('message', function(buf, rinfo) { | ||
| 182 | + console.error('[CHILD] %s received "%s" from %j', process.pid, | ||
| 183 | + buf.toString(), rinfo); | ||
| 181 | 184 | ||
| 182 | - process.send({ message: buf.toString() }); | ||
| 185 | + receivedMessages.push(buf); | ||
| 183 | 186 | ||
| 184 | - if (receivedMessages.length == messages.length) { | ||
| 185 | - // .dropMembership() not strictly needed but here as a sanity check | ||
| 186 | - listenSocket.dropMembership(LOCAL_BROADCAST_HOST); | ||
| 187 | - process.nextTick(function() { | ||
| 188 | - listenSocket.close(); | ||
| 189 | - }); | ||
| 190 | - } | ||
| 191 | - }); | ||
| 187 | + process.send({ message: buf.toString() }); | ||
| 192 | 188 | ||
| 193 | - listenSocket.on('close', function() { | ||
| 194 | - //HACK: Wait to exit the process to ensure that the parent | ||
| 195 | - //process has had time to receive all messages via process.send() | ||
| 196 | - //This may be indicitave of some other issue. | ||
| 197 | - setTimeout(function() { | ||
| 198 | - process.exit(); | ||
| 199 | - }, 1000); | ||
| 200 | - }); | ||
| 189 | + if (receivedMessages.length == messages.length) { | ||
| 190 | + // .dropMembership() not strictly needed but here as a sanity check. | ||
| 191 | + listenSocket.dropMembership(LOCAL_BROADCAST_HOST); | ||
| 192 | + process.nextTick(function() { | ||
| 193 | + listenSocket.close(); | ||
| 194 | + }); | ||
| 195 | + } | ||
| 196 | + }); | ||
| 201 | 197 | ||
| 202 | - listenSocket.on('listening', function() { | ||
| 198 | + listenSocket.on('close', function() { | ||
| 199 | + // HACK: Wait to exit the process to ensure that the parent | ||
| 200 | + // process has had time to receive all messages via process.send() | ||
| 201 | + // This may be indicative of some other issue. | ||
| 202 | + setTimeout(function() { | ||
| 203 | + process.exit(); | ||
| 204 | + }, common.platformTimeout(1000)); | ||
| 205 | + }); | ||
| 203 | 206 | process.send({ listening: true }); | |
| 204 | 207 | }); | |
| 205 | 208 | ||
| 206 | 209 | listenSocket.bind(common.PORT); | |
| 207 | - | ||
| 208 | - listenSocket.on('listening', function() { | ||
| 209 | - listenSocket.addMembership(LOCAL_BROADCAST_HOST); | ||
| 210 | - }); | ||
| 211 | 210 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments