11'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+ }
16111
17112if ( 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 ( ) {
28120 console . error ( '[PARENT] Responses were not received within %d ms.' ,
29121 TIMEOUT ) ;
30122 console . error ( '[PARENT] Fail' ) ;
@@ -34,101 +126,18 @@ if (process.argv[2] !== 'child') {
34126 process . exit ( 1 ) ;
35127 } , TIMEOUT ) ;
36128
37- //launch child processes
129+ // Launch child processes.
38130 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 ) ;
123132 }
124133
125134 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.
129138 sendSocket . bind ( ) ;
130139
131- // The socket is actually created async now
140+ // The socket is actually created async now.
132141 sendSocket . on ( 'listening' , function ( ) {
133142 sendSocket . setTTL ( 1 ) ;
134143 sendSocket . setBroadcast ( true ) ;
@@ -141,7 +150,7 @@ if (process.argv[2] !== 'child') {
141150 } ) ;
142151
143152 sendSocket . sendNext = function ( ) {
144- var buf = messages [ i ++ ] ;
153+ const buf = messages [ i ++ ] ;
145154
146155 if ( ! buf ) {
147156 try { sendSocket . close ( ) ; } catch ( e ) { }
@@ -151,61 +160,51 @@ if (process.argv[2] !== 'child') {
151160 sendSocket . send ( buf , 0 , buf . length ,
152161 common . PORT , LOCAL_BROADCAST_HOST , function ( err ) {
153162 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 ( ) ,
156165 LOCAL_BROADCAST_HOST , common . PORT ) ;
157166 process . nextTick ( sendSocket . sendNext ) ;
158167 } ) ;
159168 } ;
160-
161- function killChildren ( children ) {
162- Object . keys ( children ) . forEach ( function ( key ) {
163- var child = children [ key ] ;
164- child . kill ( ) ;
165- } ) ;
166- }
167169}
168170
169171if ( process . argv [ 2 ] === 'child' ) {
170- var receivedMessages = [ ] ;
171- var listenSocket = dgram . createSocket ( {
172+ const receivedMessages = [ ] ;
173+ const listenSocket = dgram . createSocket ( {
172174 type : 'udp4' ,
173175 reuseAddr : true
174176 } ) ;
175177
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 ) ;
179180
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 ) ;
181184
182- process . send ( { message : buf . toString ( ) } ) ;
185+ receivedMessages . push ( buf ) ;
183186
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 ( ) } ) ;
192188
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+ } ) ;
201197
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+ } ) ;
203206 process . send ( { listening : true } ) ;
204207 } ) ;
205208
206209 listenSocket . bind ( common . PORT ) ;
207-
208- listenSocket . on ( 'listening' , function ( ) {
209- listenSocket . addMembership ( LOCAL_BROADCAST_HOST ) ;
210- } ) ;
211210}
0 commit comments