Browse Source

test: refactor/cleanup a number of cluster tests

* Move shared code into common
* Favor use of strictEqual
* Add some missing common.mustCalls
* Other general cleanup

PR-URL: https://github.com/nodejs/node/pull/8261
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
v6.x
James M Snell 8 years ago
committed by Jeremiah Senkpiel
parent
commit
1aa7168e91
  1. 9
      test/common.js
  2. 91
      test/parallel/test-cluster-basic.js
  3. 16
      test/parallel/test-cluster-bind-privileged-port.js
  4. 74
      test/parallel/test-cluster-bind-twice.js
  5. 39
      test/parallel/test-cluster-dgram-1.js
  6. 22
      test/parallel/test-cluster-dgram-2.js
  7. 8
      test/parallel/test-cluster-dgram-reuse.js
  8. 8
      test/parallel/test-cluster-disconnect-before-exit.js
  9. 52
      test/parallel/test-cluster-disconnect.js
  10. 68
      test/parallel/test-cluster-master-error.js
  11. 50
      test/parallel/test-cluster-master-kill.js
  12. 62
      test/parallel/test-cluster-worker-disconnect.js
  13. 77
      test/parallel/test-cluster-worker-exit.js
  14. 62
      test/parallel/test-cluster-worker-kill.js

9
test/common.js

@ -498,3 +498,12 @@ exports.busyLoop = function busyLoop(time) {
var stopTime = startTime + time;
while (Timer.now() < stopTime) {}
};
exports.isAlive = function isAlive(pid) {
try {
process.kill(pid, 'SIGCONT');
return true;
} catch (e) {
return false;
}
};

91
test/parallel/test-cluster-basic.js

@ -1,26 +1,26 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
assert.equal('NODE_UNIQUE_ID' in process.env, false,
'NODE_UNIQUE_ID should be removed on startup');
assert.strictEqual('NODE_UNIQUE_ID' in process.env, false,
'NODE_UNIQUE_ID should be removed on startup');
function forEach(obj, fn) {
Object.keys(obj).forEach(function(name, index) {
Object.keys(obj).forEach((name, index) => {
fn(obj[name], name, index);
});
}
if (cluster.isWorker) {
var http = require('http');
const http = require('http');
http.Server(function() {
}).listen(common.PORT, '127.0.0.1');
} else if (cluster.isMaster) {
var checks = {
const checks = {
cluster: {
events: {
fork: false,
@ -57,13 +57,13 @@ if (cluster.isWorker) {
};
var worker;
var stateNames = Object.keys(checks.worker.states);
const stateNames = Object.keys(checks.worker.states);
//Check events, states, and emit arguments
forEach(checks.cluster.events, function(bool, name, index) {
forEach(checks.cluster.events, (bool, name, index) => {
//Listen on event
cluster.on(name, function(/* worker */) {
cluster.on(name, common.mustCall(function(/* worker */) {
//Set event
checks.cluster.events[name] = true;
@ -74,28 +74,26 @@ if (cluster.isWorker) {
//Check state
var state = stateNames[index];
checks.worker.states[state] = (state === worker.state);
});
}));
});
//Kill worker when listening
cluster.on('listening', function() {
cluster.on('listening', common.mustCall(() => {
worker.kill();
});
}));
//Kill process when worker is killed
cluster.on('exit', function() {
process.exit(0);
});
cluster.on('exit', common.mustCall(() => {}));
//Create worker
worker = cluster.fork();
assert.equal(worker.id, 1);
assert.ok(worker instanceof cluster.Worker,
'the worker is not a instance of the Worker constructor');
assert.strictEqual(worker.id, 1);
assert(worker instanceof cluster.Worker,
'the worker is not a instance of the Worker constructor');
//Check event
forEach(checks.worker.events, function(bool, name, index) {
worker.on(name, function() {
worker.on(name, common.mustCall(function() {
//Set event
checks.worker.events[name] = true;
@ -104,56 +102,57 @@ if (cluster.isWorker) {
switch (name) {
case 'exit':
assert.equal(arguments[0], worker.process.exitCode);
assert.equal(arguments[1], worker.process.signalCode);
assert.equal(arguments.length, 2);
assert.strictEqual(arguments[0], worker.process.exitCode);
assert.strictEqual(arguments[1], worker.process.signalCode);
assert.strictEqual(arguments.length, 2);
break;
case 'listening':
assert.equal(arguments.length, 1);
var expect = { address: '127.0.0.1',
port: common.PORT,
addressType: 4,
fd: undefined };
assert.strictEqual(arguments.length, 1);
const expect = { address: '127.0.0.1',
port: common.PORT,
addressType: 4,
fd: undefined };
assert.deepStrictEqual(arguments[0], expect);
break;
default:
assert.equal(arguments.length, 0);
assert.strictEqual(arguments.length, 0);
break;
}
});
}));
});
//Check all values
process.once('exit', function() {
process.once('exit', () => {
//Check cluster events
forEach(checks.cluster.events, function(check, name) {
assert.ok(check, 'The cluster event "' + name + '" on the cluster ' +
'object did not fire');
forEach(checks.cluster.events, (check, name) => {
assert(check,
`The cluster event "${name}" on the cluster object did not fire`);
});
//Check cluster event arguments
forEach(checks.cluster.equal, function(check, name) {
assert.ok(check, 'The cluster event "' + name + '" did not emit ' +
'with correct argument');
forEach(checks.cluster.equal, (check, name) => {
assert(check,
`The cluster event "${name}" did not emit with correct argument`);
});
//Check worker states
forEach(checks.worker.states, function(check, name) {
assert.ok(check, 'The worker state "' + name + '" was not set to true');
forEach(checks.worker.states, (check, name) => {
assert(check,
`The worker state "${name}" was not set to true`);
});
//Check worker events
forEach(checks.worker.events, function(check, name) {
assert.ok(check, 'The worker event "' + name + '" on the worker object ' +
'did not fire');
forEach(checks.worker.events, (check, name) => {
assert(check,
`The worker event "${name}" on the worker object did not fire`);
});
//Check worker event arguments
forEach(checks.worker.equal, function(check, name) {
assert.ok(check, 'The worker event "' + name + '" did not emit with ' +
'corrent argument');
forEach(checks.worker.equal, (check, name) => {
assert(check,
`The worker event "${name}" did not emit with correct argument`);
});
});

16
test/parallel/test-cluster-bind-privileged-port.js

@ -1,8 +1,8 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
var net = require('net');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
const net = require('net');
if (common.isWindows) {
common.skip('not reliable on Windows.');
@ -15,14 +15,14 @@ if (process.getuid() === 0) {
}
if (cluster.isMaster) {
cluster.fork().on('exit', common.mustCall(function(exitCode) {
assert.equal(exitCode, 0);
cluster.fork().on('exit', common.mustCall((exitCode) => {
assert.strictEqual(exitCode, 0);
}));
} else {
var s = net.createServer(common.fail);
s.listen(42, common.fail.bind(null, 'listen should have failed'));
s.on('error', common.mustCall(function(err) {
assert.equal(err.code, 'EACCES');
s.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'EACCES');
process.disconnect();
}));
}

74
test/parallel/test-cluster-bind-twice.js

@ -18,88 +18,74 @@
//
// See https://github.com/joyent/node/issues/2721 for more details.
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
var fork = require('child_process').fork;
var http = require('http');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
const fork = require('child_process').fork;
const http = require('http');
var id = process.argv[2];
const id = process.argv[2];
if (!id) {
var a = fork(__filename, ['one']);
var b = fork(__filename, ['two']);
const a = fork(__filename, ['one']);
const b = fork(__filename, ['two']);
a.on('exit', function(c) {
a.on('exit', common.mustCall((c) => {
if (c) {
b.send('QUIT');
throw new Error('A exited with ' + c);
}
});
}));
b.on('exit', function(c) {
b.on('exit', common.mustCall((c) => {
if (c) {
a.send('QUIT');
throw new Error('B exited with ' + c);
}
});
}));
a.on('message', function(m) {
a.on('message', common.mustCall((m) => {
if (typeof m === 'object') return;
assert.equal(m, 'READY');
assert.strictEqual(m, 'READY');
b.send('START');
});
}));
let ok = false;
b.on('message', function(m) {
if (typeof m === 'object') return; // ignore system messages
assert.equal(m, 'EADDRINUSE');
ok = true;
b.on('message', common.mustCall((m) => {
assert.strictEqual(m, 'EADDRINUSE');
a.send('QUIT');
b.send('QUIT');
});
}));
process.on('exit', function() {
assert(ok);
});
} else if (id === 'one') {
if (cluster.isMaster) return startWorker();
http.createServer(common.fail).listen(common.PORT, function() {
http.createServer(common.fail).listen(common.PORT, common.mustCall(() => {
process.send('READY');
});
}));
process.on('message', function(m) {
process.on('message', common.mustCall((m) => {
if (m === 'QUIT') process.exit();
});
}));
} else if (id === 'two') {
if (cluster.isMaster) return startWorker();
let ok = false;
process.on('exit', function() {
assert(ok);
});
var server = http.createServer(common.fail);
process.on('message', function(m) {
if (typeof m === 'object') return; // ignore system messages
const server = http.createServer(common.fail);
process.on('message', common.mustCall((m) => {
if (m === 'QUIT') process.exit();
assert.equal(m, 'START');
assert.strictEqual(m, 'START');
server.listen(common.PORT, common.fail);
server.on('error', function(e) {
assert.equal(e.code, 'EADDRINUSE');
server.on('error', common.mustCall((e) => {
assert.strictEqual(e.code, 'EADDRINUSE');
process.send(e.code);
ok = true;
});
});
}));
}, 2));
} else {
assert(0); // bad command line argument
}
function startWorker() {
var worker = cluster.fork();
const worker = cluster.fork();
worker.on('exit', process.exit);
worker.on('message', process.send.bind(process));
process.on('message', worker.send.bind(worker));

39
test/parallel/test-cluster-dgram-1.js

@ -1,11 +1,11 @@
'use strict';
const common = require('../common');
var NUM_WORKERS = 4;
var PACKETS_PER_WORKER = 10;
const NUM_WORKERS = 4;
const PACKETS_PER_WORKER = 10;
var assert = require('assert');
var cluster = require('cluster');
var dgram = require('dgram');
const assert = require('assert');
const cluster = require('cluster');
const dgram = require('dgram');
if (common.isWindows) {
@ -28,13 +28,13 @@ function master() {
cluster.fork();
// Wait until all workers are listening.
cluster.on('listening', function() {
cluster.on('listening', common.mustCall(() => {
if (++listening < NUM_WORKERS)
return;
// Start sending messages.
var buf = Buffer.from('hello world');
var socket = dgram.createSocket('udp4');
const buf = Buffer.from('hello world');
const socket = dgram.createSocket('udp4');
var sent = 0;
doSend();
@ -47,15 +47,14 @@ function master() {
if (sent < NUM_WORKERS * PACKETS_PER_WORKER) {
doSend();
} else {
console.log('master sent %d packets', sent);
socket.close();
}
}
});
}, NUM_WORKERS));
// Set up event handlers for every worker. Each worker sends a message when
// it has received the expected number of packets. After that it disconnects.
for (var key in cluster.workers) {
for (const key in cluster.workers) {
if (cluster.workers.hasOwnProperty(key))
setupWorker(cluster.workers[key]);
}
@ -63,15 +62,13 @@ function master() {
function setupWorker(worker) {
var received = 0;
worker.on('message', function(msg) {
worker.on('message', common.mustCall((msg) => {
received = msg.received;
console.log('worker %d received %d packets', worker.id, received);
});
}));
worker.on('disconnect', function() {
assert(received === PACKETS_PER_WORKER);
console.log('worker %d disconnected', worker.id);
});
worker.on('disconnect', common.mustCall(() => {
assert.strictEqual(received, PACKETS_PER_WORKER);
}));
}
}
@ -82,15 +79,15 @@ function worker() {
// Create udp socket and start listening.
var socket = dgram.createSocket('udp4');
socket.on('message', function(data, info) {
socket.on('message', common.mustCall((data, info) => {
received++;
// Every 10 messages, notify the master.
if (received == PACKETS_PER_WORKER) {
if (received === PACKETS_PER_WORKER) {
process.send({received: received});
process.disconnect();
}
});
}, PACKETS_PER_WORKER));
socket.bind(common.PORT);
}

22
test/parallel/test-cluster-dgram-2.js

@ -1,10 +1,10 @@
'use strict';
const common = require('../common');
var NUM_WORKERS = 4;
var PACKETS_PER_WORKER = 10;
const NUM_WORKERS = 4;
const PACKETS_PER_WORKER = 10;
var cluster = require('cluster');
var dgram = require('dgram');
const cluster = require('cluster');
const dgram = require('dgram');
if (common.isWindows) {
@ -28,11 +28,10 @@ function master() {
// Disconnect workers when the expected number of messages have been
// received.
socket.on('message', function(data, info) {
socket.on('message', common.mustCall((data, info) => {
received++;
if (received == PACKETS_PER_WORKER * NUM_WORKERS) {
console.log('master received %d packets', received);
if (received === PACKETS_PER_WORKER * NUM_WORKERS) {
// Close the socket.
socket.close();
@ -40,7 +39,7 @@ function master() {
// Disconnect all workers.
cluster.disconnect();
}
});
}, NUM_WORKERS * PACKETS_PER_WORKER));
// Fork workers.
for (var i = 0; i < NUM_WORKERS; i++)
@ -50,8 +49,8 @@ function master() {
function worker() {
// Create udp socket and send packets to master.
var socket = dgram.createSocket('udp4');
var buf = Buffer.from('hello world');
const socket = dgram.createSocket('udp4');
const buf = Buffer.from('hello world');
// This test is intended to exercise the cluster binding of udp sockets, but
// since sockets aren't clustered when implicitly bound by at first call of
@ -60,7 +59,4 @@ function worker() {
for (var i = 0; i < PACKETS_PER_WORKER; i++)
socket.send(buf, 0, buf.length, common.PORT, '127.0.0.1');
console.log('worker %d sent %d packets', cluster.worker.id,
PACKETS_PER_WORKER);
}

8
test/parallel/test-cluster-dgram-reuse.js

@ -11,9 +11,9 @@ if (common.isWindows) {
}
if (cluster.isMaster) {
cluster.fork().on('exit', function(code) {
assert.equal(code, 0);
});
cluster.fork().on('exit', common.mustCall((code) => {
assert.strictEqual(code, 0);
}));
return;
}
@ -24,7 +24,7 @@ function next() {
return;
// Work around health check issue
process.nextTick(function() {
process.nextTick(() => {
for (var i = 0; i < sockets.length; i++)
sockets[i].close(close);
});

8
test/parallel/test-cluster-disconnect-before-exit.js

@ -1,9 +1,9 @@
'use strict';
require('../common');
var cluster = require('cluster');
const common = require('../common');
const cluster = require('cluster');
if (cluster.isMaster) {
var worker = cluster.fork().on('online', disconnect);
const worker = cluster.fork().on('online', common.mustCall(disconnect));
function disconnect() {
worker.disconnect();
@ -11,6 +11,6 @@ if (cluster.isMaster) {
// Disconnect is supposed to disconnect all workers, but not workers that
// are already disconnected, since calling disconnect() on an already
// disconnected worker would error.
worker.on('disconnect', cluster.disconnect);
worker.on('disconnect', common.mustCall(cluster.disconnect));
}
}

52
test/parallel/test-cluster-disconnect.js

@ -1,15 +1,15 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
var net = require('net');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
const net = require('net');
if (cluster.isWorker) {
net.createServer(function(socket) {
net.createServer((socket) => {
socket.end('echo');
}).listen(common.PORT, '127.0.0.1');
net.createServer(function(socket) {
net.createServer((socket) => {
socket.end('echo');
}).listen(common.PORT + 1, '127.0.0.1');
@ -17,25 +17,25 @@ if (cluster.isWorker) {
var servers = 2;
// test a single TCP server
var testConnection = function(port, cb) {
var socket = net.connect(port, '127.0.0.1', function() {
const testConnection = function(port, cb) {
var socket = net.connect(port, '127.0.0.1', () => {
// buffer result
var result = '';
socket.on('data', function(chunk) { result += chunk; });
socket.on('data', common.mustCall((chunk) => { result += chunk; }));
// check result
socket.on('end', function() {
socket.on('end', common.mustCall(() => {
cb(result === 'echo');
});
}));
});
};
// test both servers created in the cluster
var testCluster = function(cb) {
const testCluster = function(cb) {
var done = 0;
for (var i = 0, l = servers; i < l; i++) {
testConnection(common.PORT + i, function(success) {
testConnection(common.PORT + i, (success) => {
assert.ok(success);
done += 1;
if (done === servers) {
@ -46,40 +46,38 @@ if (cluster.isWorker) {
};
// start two workers and execute callback when both is listening
var startCluster = function(cb) {
const startCluster = function(cb) {
var workers = 8;
var online = 0;
for (var i = 0, l = workers; i < l; i++) {
var worker = cluster.fork();
worker.on('listening', function() {
cluster.fork().on('listening', common.mustCall(() => {
online += 1;
if (online === workers * servers) {
cb();
}
});
}, servers));
}
};
var results = {
const results = {
start: 0,
test: 0,
disconnect: 0
};
var test = function(again) {
const test = function(again) {
//1. start cluster
startCluster(function() {
startCluster(() => {
results.start += 1;
//2. test cluster
testCluster(function() {
testCluster(() => {
results.test += 1;
//3. disconnect cluster
cluster.disconnect(function() {
cluster.disconnect(() => {
results.disconnect += 1;
// run test again to confirm cleanup
@ -93,9 +91,9 @@ if (cluster.isWorker) {
test(true);
process.once('exit', function() {
assert.equal(results.start, 2);
assert.equal(results.test, 2);
assert.equal(results.disconnect, 2);
process.once('exit', () => {
assert.strictEqual(results.start, 2);
assert.strictEqual(results.test, 2);
assert.strictEqual(results.disconnect, 2);
});
}

68
test/parallel/test-cluster-master-error.js

@ -1,22 +1,22 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
const totalWorkers = 2;
// Cluster setup
if (cluster.isWorker) {
var http = require('http');
http.Server(function() {
const http = require('http');
http.Server(() => {
}).listen(common.PORT, '127.0.0.1');
} else if (process.argv[2] === 'cluster') {
var totalWorkers = 2;
// Send PID to testcase process
var forkNum = 0;
cluster.on('fork', function forkEvent(worker) {
cluster.on('fork', common.mustCall(function forkEvent(worker) {
// Send PID
process.send({
@ -28,11 +28,11 @@ if (cluster.isWorker) {
if (++forkNum === totalWorkers) {
cluster.removeListener('fork', forkEvent);
}
});
}));
// Throw accidental error when all workers are listening
var listeningNum = 0;
cluster.on('listening', function listeningEvent() {
cluster.on('listening', common.mustCall(function listeningEvent() {
// When all workers are listening
if (++listeningNum === totalWorkers) {
@ -40,13 +40,12 @@ if (cluster.isWorker) {
cluster.removeListener('listening', listeningEvent);
// Throw accidental error
process.nextTick(function() {
console.error('about to throw');
process.nextTick(() => {
throw new Error('accidental error');
});
}
});
}));
// Startup a basic cluster
cluster.fork();
@ -55,51 +54,36 @@ if (cluster.isWorker) {
} else {
// This is the testcase
var fork = require('child_process').fork;
var isAlive = function(pid) {
try {
//this will throw an error if the process is dead
process.kill(pid, 0);
return true;
} catch (e) {
return false;
}
};
const fork = require('child_process').fork;
var masterExited = false;
var workersExited = false;
// List all workers
var workers = [];
const workers = [];
// Spawn a cluster process
var master = fork(process.argv[1], ['cluster'], {silent: true});
const master = fork(process.argv[1], ['cluster'], {silent: true});
// Handle messages from the cluster
master.on('message', function(data) {
master.on('message', common.mustCall((data) => {
// Add worker pid to list and progress tracker
if (data.cmd === 'worker') {
workers.push(data.workerPID);
}
});
}, totalWorkers));
// When cluster is dead
master.on('exit', function(code) {
master.on('exit', common.mustCall((code) => {
// Check that the cluster died accidentally (non-zero exit code)
masterExited = !!code;
var pollWorkers = function() {
const pollWorkers = function() {
// When master is dead all workers should be dead too
var alive = false;
workers.forEach(function(pid) {
if (isAlive(pid)) {
alive = true;
}
});
workers.forEach((pid) => alive = common.isAlive(pid));
if (alive) {
setTimeout(pollWorkers, 50);
} else {
@ -109,13 +93,13 @@ if (cluster.isWorker) {
// Loop indefinitely until worker exit
pollWorkers();
});
}));
process.once('exit', function() {
var m = 'The master did not die after an error was thrown';
assert.ok(masterExited, m);
m = 'The workers did not die after an error in the master';
assert.ok(workersExited, m);
process.once('exit', () => {
assert(masterExited,
'The master did not die after an error was thrown');
assert(workersExited,
'The workers did not die after an error in the master');
});
}

50
test/parallel/test-cluster-master-kill.js

@ -1,17 +1,17 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
if (cluster.isWorker) {
// keep the worker alive
var http = require('http');
const http = require('http');
http.Server().listen(common.PORT, '127.0.0.1');
} else if (process.argv[2] === 'cluster') {
var worker = cluster.fork();
const worker = cluster.fork();
// send PID info to testcase process
process.send({
@ -19,59 +19,47 @@ if (cluster.isWorker) {
});
// terminate the cluster process
worker.once('listening', function() {
setTimeout(function() {
worker.once('listening', common.mustCall(() => {
setTimeout(() => {
process.exit(0);
}, 1000);
});
}));
} else {
// This is the testcase
var fork = require('child_process').fork;
// is process alive helper
var isAlive = function(pid) {
try {
//this will throw an error if the process is dead
process.kill(pid, 0);
return true;
} catch (e) {
return false;
}
};
const fork = require('child_process').fork;
// Spawn a cluster process
var master = fork(process.argv[1], ['cluster']);
const master = fork(process.argv[1], ['cluster']);
// get pid info
var pid = null;
master.once('message', function(data) {
master.once('message', (data) => {
pid = data.pid;
});
// When master is dead
var alive = true;
master.on('exit', function(code) {
master.on('exit', common.mustCall((code) => {
// make sure that the master died on purpose
assert.equal(code, 0);
assert.strictEqual(code, 0);
// check worker process status
var pollWorker = function() {
alive = isAlive(pid);
const pollWorker = function() {
alive = common.isAlive(pid);
if (alive) {
setTimeout(pollWorker, 50);
}
};
// Loop indefinitely until worker exit.
pollWorker();
});
}));
process.once('exit', function() {
assert.equal(typeof pid, 'number', 'did not get worker pid info');
assert.equal(alive, false, 'worker was alive after master died');
process.once('exit', () => {
assert.strictEqual(typeof pid, 'number', 'did not get worker pid info');
assert.strictEqual(alive, false, 'worker was alive after master died');
});
}

62
test/parallel/test-cluster-worker-disconnect.js

@ -1,25 +1,25 @@
'use strict';
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
if (cluster.isWorker) {
var http = require('http');
http.Server(function() {
const http = require('http');
http.Server(() => {
}).listen(common.PORT, '127.0.0.1');
const worker = cluster.worker;
assert.strictEqual(worker.exitedAfterDisconnect, worker.suicide);
cluster.worker.on('disconnect', function() {
cluster.worker.on('disconnect', common.mustCall(() => {
assert.strictEqual(cluster.worker.exitedAfterDisconnect,
cluster.worker.suicide);
process.exit(42);
});
}));
} else if (cluster.isMaster) {
var checks = {
const checks = {
cluster: {
emitDisconnect: false,
emitExit: false,
@ -35,50 +35,40 @@ if (cluster.isWorker) {
}
};
// helper function to check if a process is alive
var alive = function(pid) {
try {
process.kill(pid, 0);
return true;
} catch (e) {
return false;
}
};
// start worker
var worker = cluster.fork();
const worker = cluster.fork();
// Disconnect worker when it is ready
worker.once('listening', function() {
worker.once('listening', common.mustCall(() => {
worker.disconnect();
});
}));
// Check cluster events
cluster.once('disconnect', function() {
cluster.once('disconnect', common.mustCall(() => {
checks.cluster.emitDisconnect = true;
});
cluster.once('exit', function() {
}));
cluster.once('exit', common.mustCall(() => {
checks.cluster.emitExit = true;
});
}));
// Check worker events and properties
worker.once('disconnect', function() {
worker.once('disconnect', common.mustCall(() => {
checks.worker.emitDisconnect = true;
checks.worker.voluntaryMode = worker.exitedAfterDisconnect;
checks.worker.state = worker.state;
});
}));
// Check that the worker died
worker.once('exit', function(code) {
worker.once('exit', common.mustCall((code) => {
checks.worker.emitExit = true;
checks.worker.died = !alive(worker.process.pid);
checks.worker.died = !common.isAlive(worker.process.pid);
checks.worker.emitDisconnectInsideWorker = code === 42;
});
}));
process.once('exit', function() {
process.once('exit', () => {
var w = checks.worker;
var c = checks.cluster;
const w = checks.worker;
const c = checks.cluster;
// events
assert.ok(w.emitDisconnect, 'Disconnect event did not emit');
@ -89,8 +79,10 @@ if (cluster.isWorker) {
assert.ok(c.emitExit, 'Exit event did not emit');
// flags
assert.equal(w.state, 'disconnected', 'The state property was not set');
assert.equal(w.voluntaryMode, true, 'Voluntary exit mode was not set');
assert.strictEqual(w.state, 'disconnected',
'The state property was not set');
assert.strictEqual(w.voluntaryMode, true,
'Voluntary exit mode was not set');
// is process alive
assert.ok(w.died, 'The worker did not die');

77
test/parallel/test-cluster-worker-exit.js

@ -6,24 +6,24 @@
// - the worker.exitedAfterDisconnect flag, and worker.state are correct
// - the worker process actually goes away
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
var EXIT_CODE = 42;
const EXIT_CODE = 42;
if (cluster.isWorker) {
var http = require('http');
var server = http.Server(function() { });
const http = require('http');
const server = http.Server(() => { });
server.once('listening', function() {
server.once('listening', common.mustCall(() => {
process.exit(EXIT_CODE);
});
}));
server.listen(common.PORT, '127.0.0.1');
} else if (cluster.isMaster) {
var expected_results = {
const expected_results = {
cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"],
cluster_emitExit: [1, "the cluster did not emit 'exit'"],
cluster_exitCode: [EXIT_CODE, 'the cluster exited w/ incorrect exitCode'],
@ -38,7 +38,7 @@ if (cluster.isWorker) {
worker_exitCode: [EXIT_CODE, 'the worker exited w/ incorrect exitCode'],
worker_signalCode: [null, 'the worker exited w/ incorrect signalCode']
};
var results = {
const results = {
cluster_emitDisconnect: 0,
cluster_emitExit: 0,
worker_emitDisconnect: 0,
@ -47,51 +47,45 @@ if (cluster.isWorker) {
// start worker
var worker = cluster.fork();
worker.once('listening', function() {
// the worker is up and running...
});
const worker = cluster.fork();
// Check cluster events
cluster.on('disconnect', function() {
cluster.on('disconnect', common.mustCall(() => {
results.cluster_emitDisconnect += 1;
});
cluster.on('exit', function(worker) {
}));
cluster.on('exit', common.mustCall((worker) => {
results.cluster_exitCode = worker.process.exitCode;
results.cluster_signalCode = worker.process.signalCode;
results.cluster_emitExit += 1;
});
}));
// Check worker events and properties
worker.on('disconnect', function() {
worker.on('disconnect', common.mustCall(() => {
results.worker_emitDisconnect += 1;
results.worker_suicideMode = worker.suicide;
results.worker_exitedAfterDisconnect = worker.exitedAfterDisconnect;
results.worker_state = worker.state;
if (results.worker_emitExit > 0) {
process.nextTick(function() { finish_test(); });
process.nextTick(() => finish_test());
}
});
}));
// Check that the worker died
worker.once('exit', function(exitCode, signalCode) {
worker.once('exit', common.mustCall((exitCode, signalCode) => {
results.worker_exitCode = exitCode;
results.worker_signalCode = signalCode;
results.worker_emitExit += 1;
results.worker_died = !alive(worker.process.pid);
results.worker_died = !common.isAlive(worker.process.pid);
if (results.worker_emitDisconnect > 0) {
process.nextTick(function() { finish_test(); });
process.nextTick(() => finish_test());
}
});
}));
var finish_test = function() {
const finish_test = function() {
try {
checkResults(expected_results, results);
} catch (exc) {
console.error('FAIL: ' + exc.message);
if (exc.name != 'AssertionError') {
if (exc.name !== 'AssertionError') {
console.trace(exc);
}
@ -105,26 +99,13 @@ if (cluster.isWorker) {
// some helper functions ...
function checkResults(expected_results, results) {
for (var k in expected_results) {
for (const k in expected_results) {
const actual = results[k];
const expected = expected_results[k];
var msg = (expected[1] || '') +
(' [expected: ' + expected[0] + ' / actual: ' + actual + ']');
if (expected && expected.length) {
assert.equal(actual, expected[0], msg);
} else {
assert.equal(actual, expected, msg);
}
}
}
function alive(pid) {
try {
process.kill(pid, 'SIGCONT');
return true;
} catch (e) {
return false;
assert.strictEqual(actual,
expected && expected.length ? expected[0] : expected,
(expected[1] || '') +
` [expected: ${expected[0]} / actual: ${actual}]`);
}
}

62
test/parallel/test-cluster-worker-kill.js

@ -6,20 +6,20 @@
// - the worker.exitedAfterDisconnect flag, and worker.state are correct
// - the worker process actually goes away
var common = require('../common');
var assert = require('assert');
var cluster = require('cluster');
const common = require('../common');
const assert = require('assert');
const cluster = require('cluster');
if (cluster.isWorker) {
var http = require('http');
var server = http.Server(function() { });
const http = require('http');
const server = http.Server(() => { });
server.once('listening', function() { });
server.once('listening', common.mustCall(() => { }));
server.listen(common.PORT, '127.0.0.1');
} else if (cluster.isMaster) {
var KILL_SIGNAL = 'SIGKILL',
const KILL_SIGNAL = 'SIGKILL',
expected_results = {
cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"],
cluster_emitExit: [1, "the cluster did not emit 'exit'"],
@ -45,40 +45,40 @@ if (cluster.isWorker) {
// start worker
var worker = cluster.fork();
const worker = cluster.fork();
// when the worker is up and running, kill it
worker.once('listening', function() {
worker.once('listening', common.mustCall(() => {
worker.process.kill(KILL_SIGNAL);
});
}));
// Check cluster events
cluster.on('disconnect', function() {
cluster.on('disconnect', common.mustCall(() => {
results.cluster_emitDisconnect += 1;
});
cluster.on('exit', function(worker) {
}));
cluster.on('exit', common.mustCall((worker) => {
results.cluster_exitCode = worker.process.exitCode;
results.cluster_signalCode = worker.process.signalCode;
results.cluster_emitExit += 1;
});
}));
// Check worker events and properties
worker.on('disconnect', function() {
worker.on('disconnect', common.mustCall(() => {
results.worker_emitDisconnect += 1;
results.worker_exitedAfter = worker.exitedAfterDisconnect;
results.worker_state = worker.state;
});
}));
// Check that the worker died
worker.once('exit', function(exitCode, signalCode) {
worker.once('exit', common.mustCall((exitCode, signalCode) => {
results.worker_exitCode = exitCode;
results.worker_signalCode = signalCode;
results.worker_emitExit += 1;
results.worker_died = !alive(worker.process.pid);
});
results.worker_died = !common.isAlive(worker.process.pid);
}));
process.on('exit', function() {
process.on('exit', () => {
checkResults(expected_results, results);
});
}
@ -86,25 +86,13 @@ if (cluster.isWorker) {
// some helper functions ...
function checkResults(expected_results, results) {
for (var k in expected_results) {
for (const k in expected_results) {
const actual = results[k];
const expected = expected_results[k];
var msg = (expected[1] || '') +
(' [expected: ' + expected[0] + ' / actual: ' + actual + ']');
if (expected && expected.length) {
assert.equal(actual, expected[0], msg);
} else {
assert.equal(actual, expected, msg);
}
}
}
function alive(pid) {
try {
process.kill(pid, 'SIGCONT');
return true;
} catch (e) {
return false;
assert.strictEqual(actual,
expected && expected.length ? expected[0] : expected,
(expected[1] || '') +
` [expected: ${expected[0]} / actual: ${actual}]`);
}
}

Loading…
Cancel
Save