• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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');
24const assert = require('assert');
25const cluster = require('cluster');
26const net = require('net');
27
28if (cluster.isWorker) {
29  net.createServer((socket) => {
30    socket.end('echo');
31  }).listen(0, '127.0.0.1');
32
33  net.createServer((socket) => {
34    socket.end('echo');
35  }).listen(0, '127.0.0.1');
36} else if (cluster.isMaster) {
37  const servers = 2;
38  const serverPorts = new Set();
39
40  // Test a single TCP server
41  const testConnection = (port, cb) => {
42    const socket = net.connect(port, '127.0.0.1', () => {
43      // buffer result
44      let result = '';
45      socket.on('data', (chunk) => { result += chunk; });
46
47      // check result
48      socket.on('end', common.mustCall(() => {
49        cb(result === 'echo');
50        serverPorts.delete(port);
51      }));
52    });
53  };
54
55  // Test both servers created in the cluster
56  const testCluster = (cb) => {
57    let done = 0;
58    const portsArray = Array.from(serverPorts);
59
60    for (let i = 0; i < servers; i++) {
61      testConnection(portsArray[i], (success) => {
62        assert.ok(success);
63        done += 1;
64        if (done === servers) {
65          cb();
66        }
67      });
68    }
69  };
70
71  // Start two workers and execute callback when both is listening
72  const startCluster = (cb) => {
73    const workers = 8;
74    let online = 0;
75
76    for (let i = 0, l = workers; i < l; i++) {
77      cluster.fork().on('listening', common.mustCall((address) => {
78        serverPorts.add(address.port);
79
80        online += 1;
81        if (online === workers * servers) {
82          cb();
83        }
84      }, servers));
85    }
86  };
87
88  const test = (again) => {
89    // 1. start cluster
90    startCluster(common.mustCall(() => {
91      // 2. test cluster
92      testCluster(common.mustCall(() => {
93        // 3. disconnect cluster
94        cluster.disconnect(common.mustCall(() => {
95          // Run test again to confirm cleanup
96          if (again) {
97            test();
98          }
99        }));
100      }));
101    }));
102  };
103
104  test(true);
105}
106