~ubuntu-branches/ubuntu/saucy/nodejs/saucy-proposed

« back to all changes in this revision

Viewing changes to test/internet/test-dgram-multicast-multi-process.js

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
var common = require('../common'),
 
23
    assert = require('assert'),
 
24
    dgram = require('dgram'),
 
25
    util = require('util'),
 
26
    assert = require('assert'),
 
27
    Buffer = require('buffer').Buffer,
 
28
    fork = require('child_process').fork,
 
29
    LOCAL_BROADCAST_HOST = '224.0.0.114',
 
30
    TIMEOUT = 5000,
 
31
    messages = [
 
32
      new Buffer('First message to send'),
 
33
      new Buffer('Second message to send'),
 
34
      new Buffer('Third message to send'),
 
35
      new Buffer('Fourth message to send')
 
36
    ];
 
37
 
 
38
if (process.argv[2] !== 'child') {
 
39
  var workers = {},
 
40
      listeners = 3,
 
41
      listening = 0,
 
42
      dead = 0,
 
43
      i = 0,
 
44
      done = 0,
 
45
      timer = null;
 
46
 
 
47
  //exit the test if it doesn't succeed within TIMEOUT
 
48
  timer = setTimeout(function() {
 
49
    console.error('[PARENT] Responses were not received within %d ms.',
 
50
                  TIMEOUT);
 
51
    console.error('[PARENT] Fail');
 
52
 
 
53
    killChildren(workers);
 
54
 
 
55
    process.exit(1);
 
56
  }, TIMEOUT);
 
57
 
 
58
  //launch child processes
 
59
  for (var x = 0; x < listeners; x++) {
 
60
    (function() {
 
61
      var worker = fork(process.argv[1], ['child']);
 
62
      workers[worker.pid] = worker;
 
63
 
 
64
      worker.messagesReceived = [];
 
65
 
 
66
      //handle the death of workers
 
67
      worker.on('exit', function(code, signal) {
 
68
        // don't consider this the true death if the
 
69
        // worker has finished successfully
 
70
 
 
71
        // or if the exit code is 0
 
72
        if (worker.isDone || code === 0) {
 
73
          return;
 
74
        }
 
75
 
 
76
        dead += 1;
 
77
        console.error('[PARENT] Worker %d died. %d dead of %d',
 
78
                      worker.pid,
 
79
                      dead,
 
80
                      listeners);
 
81
 
 
82
        if (dead === listeners) {
 
83
          console.error('[PARENT] All workers have died.');
 
84
          console.error('[PARENT] Fail');
 
85
 
 
86
          killChildren(workers);
 
87
 
 
88
          process.exit(1);
 
89
        }
 
90
      });
 
91
 
 
92
      worker.on('message', function(msg) {
 
93
        if (msg.listening) {
 
94
          listening += 1;
 
95
 
 
96
          if (listening === listeners) {
 
97
            //all child process are listening, so start sending
 
98
            sendSocket.sendNext();
 
99
          }
 
100
        }
 
101
        else if (msg.message) {
 
102
          worker.messagesReceived.push(msg.message);
 
103
 
 
104
          if (worker.messagesReceived.length === messages.length) {
 
105
            done += 1;
 
106
            worker.isDone = true;
 
107
            console.error('[PARENT] %d received %d messages total.',
 
108
                          worker.pid,
 
109
                          worker.messagesReceived.length);
 
110
          }
 
111
 
 
112
          if (done === listeners) {
 
113
            console.error('[PARENT] All workers have received the ' +
 
114
                          'required number of messages. Will now compare.');
 
115
 
 
116
            Object.keys(workers).forEach(function(pid) {
 
117
              var worker = workers[pid];
 
118
 
 
119
              var count = 0;
 
120
 
 
121
              worker.messagesReceived.forEach(function(buf) {
 
122
                for (var i = 0; i < messages.length; ++i) {
 
123
                  if (buf.toString() === messages[i].toString()) {
 
124
                    count++;
 
125
                    break;
 
126
                  }
 
127
                }
 
128
              });
 
129
 
 
130
              console.error('[PARENT] %d received %d matching messages.',
 
131
                            worker.pid, count);
 
132
 
 
133
              assert.equal(count, messages.length,
 
134
                           'A worker received an invalid multicast message');
 
135
            });
 
136
 
 
137
            clearTimeout(timer);
 
138
            console.error('[PARENT] Success');
 
139
            killChildren(workers);
 
140
          }
 
141
        }
 
142
      });
 
143
    })(x);
 
144
  }
 
145
 
 
146
  var sendSocket = dgram.createSocket('udp4');
 
147
  // FIXME a libuv limitation makes it necessary to bind()
 
148
  // before calling any of the set*() functions - the bind()
 
149
  // call is what creates the actual socket...
 
150
  sendSocket.bind();
 
151
 
 
152
  // The socket is actually created async now
 
153
  sendSocket.on('listening', function () {
 
154
    sendSocket.setTTL(1);
 
155
    sendSocket.setBroadcast(true);
 
156
    sendSocket.setMulticastTTL(1);
 
157
    sendSocket.setMulticastLoopback(true);
 
158
  });
 
159
 
 
160
  sendSocket.on('close', function() {
 
161
    console.error('[PARENT] sendSocket closed');
 
162
  });
 
163
 
 
164
  sendSocket.sendNext = function() {
 
165
    var buf = messages[i++];
 
166
 
 
167
    if (!buf) {
 
168
      try { sendSocket.close(); } catch (e) {}
 
169
      return;
 
170
    }
 
171
 
 
172
    sendSocket.send(buf, 0, buf.length,
 
173
                    common.PORT, LOCAL_BROADCAST_HOST, function(err) {
 
174
          if (err) throw err;
 
175
          console.error('[PARENT] sent %s to %s:%s',
 
176
                        util.inspect(buf.toString()),
 
177
                        LOCAL_BROADCAST_HOST, common.PORT);
 
178
          process.nextTick(sendSocket.sendNext);
 
179
        });
 
180
  };
 
181
 
 
182
  function killChildren(children) {
 
183
    Object.keys(children).forEach(function(key) {
 
184
      var child = children[key];
 
185
      child.kill();
 
186
    });
 
187
  }
 
188
}
 
189
 
 
190
if (process.argv[2] === 'child') {
 
191
  var receivedMessages = [];
 
192
  var listenSocket = dgram.createSocket('udp4');
 
193
 
 
194
  listenSocket.on('message', function(buf, rinfo) {
 
195
    console.error('[CHILD] %s received %s from %j', process.pid,
 
196
                  util.inspect(buf.toString()), rinfo);
 
197
 
 
198
    receivedMessages.push(buf);
 
199
 
 
200
    process.send({ message: buf.toString() });
 
201
 
 
202
    if (receivedMessages.length == messages.length) {
 
203
      listenSocket.dropMembership(LOCAL_BROADCAST_HOST);
 
204
 
 
205
      process.nextTick(function() { // TODO should be changed to below.
 
206
        // listenSocket.dropMembership(LOCAL_BROADCAST_HOST, function() {
 
207
        listenSocket.close();
 
208
      });
 
209
    }
 
210
  });
 
211
 
 
212
  listenSocket.on('close', function() {
 
213
    //HACK: Wait to exit the process to ensure that the parent
 
214
    //process has had time to receive all messages via process.send()
 
215
    //This may be indicitave of some other issue.
 
216
    setTimeout(function() {
 
217
      process.exit();
 
218
    }, 1000);
 
219
  });
 
220
 
 
221
  listenSocket.on('listening', function() {
 
222
    process.send({ listening: true });
 
223
  });
 
224
 
 
225
  listenSocket.bind(common.PORT);
 
226
 
 
227
  listenSocket.on('listening', function () {
 
228
    listenSocket.addMembership(LOCAL_BROADCAST_HOST);
 
229
  });
 
230
}