diff --git a/test/cfork.test.ts b/test/cfork.test.ts index 3fb5cf5..26be3db 100644 --- a/test/cfork.test.ts +++ b/test/cfork.test.ts @@ -48,7 +48,7 @@ describe('test/cfork.test.ts', () => { await urllib.request('http://127.0.0.1:1984/error', { dataType: 'text', }); - }, /(timeout|other side closed)/); + }, /(timeout|other side closed|ECONNRESET)/); }); it('should worker exit', async () => { @@ -56,7 +56,7 @@ describe('test/cfork.test.ts', () => { await urllib.request('http://127.0.0.1:1984/exit', { dataType: 'text', }); - }, /other side closed/); + }, /other side closed|ECONNRESET/); }); it('should slave listen worked', async () => { @@ -109,7 +109,7 @@ describe('test/cfork.test.ts', () => { if (process.platform === 'win32') { assert.match(err.message, /ECONNRESET/); } else { - assert.match(err.message, /(socket hang up|other side closed|timeout)/); + assert.match(err.message, /(socket hang up|other side closed|timeout|ECONNRESET)/); } return true; }); @@ -148,7 +148,7 @@ describe('test/cfork.test.ts', () => { }); }, (err: any) => { // console.error(err); - assert.match(err.message, /(other side closed|ECONNREFUSED)/); + assert.match(err.message, /(other side closed|ECONNREFUSED|ECONNRESET)/); return true; }); @@ -187,7 +187,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); await assert.rejects(async () => { @@ -196,7 +196,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); await assert.rejects(async () => { @@ -205,7 +205,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); await assert.rejects(async () => { @@ -214,7 +214,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); await assert.rejects(async () => { @@ -223,7 +223,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); await assert.rejects(async () => { @@ -232,7 +232,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /(timeout|ECONNREFUSED|other side closed)/); + assert.match(err.message, /(timeout|ECONNREFUSED|other side closed|ECONNRESET)/); return true; }); }); @@ -244,7 +244,7 @@ describe('test/cfork.test.ts', () => { timeout: 5000, }); }, (err: any) => { - assert.match(err.message, /ECONNREFUSED/); + assert.match(err.message, /ECONNREFUSED|ECONNRESET/); return true; }); }); diff --git a/test/fixtures/kill_worker/master.cjs b/test/fixtures/kill_worker/master.cjs index 1a6b98a..359d9f2 100644 --- a/test/fixtures/kill_worker/master.cjs +++ b/test/fixtures/kill_worker/master.cjs @@ -1,8 +1,9 @@ -'use strict'; - -var path = require('path'); -var util = require('util'); -var cfork = require('../../'); +/* eslint-disable @typescript-eslint/no-var-requires */ +const path = require('node:path'); +const util = require('node:util'); +const cluster = require('node:cluster'); +const http = require('node:http'); +const { cfork, setDisableRefork } = require('../../..'); cfork({ exec: path.join(__dirname, '../worker.cjs'), @@ -15,44 +16,42 @@ cfork({ duration: 60000, autoCoverage: true, }) -.on('fork', function (worker) { - console.warn('[%s] [worker:%d] new worker start', Date(), worker.process.pid); -}) -.on('listening', function (worker, address) { - console.warn('[%s] [worker:%d] listening on %j', Date(), worker.process.pid, address.port); - process.send('listening'); -}) -.on('disconnect', function (worker) { - var propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; - console.warn('[%s] [master:%s] worker:%s disconnect, %s: %s, state: %s.', - Date(), process.pid, worker.process.pid, propertyName, worker[propertyName], worker.state); -}) -.on('exit', function (worker, code, signal) { - var exitCode = worker.process.exitCode; - var propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; - var err = new Error(util.format('worker %s died (code: %s, signal: %s, %s: %s, state: %s)', - worker.process.pid, exitCode, signal, propertyName, worker[propertyName], worker.state)); - err.name = 'WorkerDiedError'; - console.error('[%s] [master:%s] worker exit: %s', Date(), process.pid, err.stack); -}) -.on('reachReforkLimit', function () { - process.send('reach refork limit'); -}); + .on('fork', function(worker) { + console.warn('[%s] [worker:%d] new worker start', Date(), worker.process.pid); + }) + .on('listening', function(worker, address) { + console.warn('[%s] [worker:%d] listening on %j', Date(), worker.process.pid, address.port); + process.send('listening'); + }) + .on('disconnect', function(worker) { + const propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; + console.warn('[%s] [master:%s] worker:%s disconnect, %s: %s, state: %s.', + Date(), process.pid, worker.process.pid, propertyName, worker[propertyName], worker.state); + }) + .on('exit', function(worker, code, signal) { + const exitCode = worker.process.exitCode; + const propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; + const err = new Error(util.format('worker %s died (code: %s, signal: %s, %s: %s, state: %s)', + worker.process.pid, exitCode, signal, propertyName, worker[propertyName], worker.state)); + err.name = 'WorkerDiedError'; + console.error('[%s] [master:%s] worker exit: %s', Date(), process.pid, err.stack); + }) + .on('reachReforkLimit', function() { + process.send('reach refork limit'); + }); -process.once('SIGTERM', function () { +process.once('SIGTERM', function() { process.exit(0); }); -var cluster = require('cluster'); -var http = require('http'); -var port = 1986; +const port = 1986; -http.createServer(function (req, res) { +http.createServer(function(req, res) { // kill worker - var count = 0; - for (var id in cluster.workers) { - var worker = cluster.workers[id]; - cfork.setDisableRefork(worker, true); + let count = 0; + for (const id in cluster.workers) { + const worker = cluster.workers[id]; + setDisableRefork(worker, true); worker.process.kill('SIGTERM'); count++; } diff --git a/test/fixtures/one_worker_cluster/master.cjs b/test/fixtures/one_worker_cluster/master.cjs index be617ae..ab4595e 100644 --- a/test/fixtures/one_worker_cluster/master.cjs +++ b/test/fixtures/one_worker_cluster/master.cjs @@ -1,10 +1,9 @@ -'use strict'; +/* eslint-disable @typescript-eslint/no-var-requires */ +const path = require('node:path'); +const util = require('node:util'); +const { fork } = require('../../..'); -var path = require('path'); -var util = require('util'); -var cfork = require('../../'); - -cfork({ +fork({ exec: path.join(__dirname, '../worker.cjs'), slaves: [ path.join(__dirname, '../slave.cjs'), @@ -15,34 +14,34 @@ cfork({ duration: 60000, autoCoverage: true, }) -.on('fork', function (worker) { - console.warn('[%s] [worker:%d] new worker start', Date(), worker.process.pid); -}) -.on('listening', function (worker, address) { - console.warn('[%s] [worker:%d] listening on %j', Date(), worker.process.pid, address.port); - process.send('listening'); -}) -.on('disconnect', function (worker) { - var propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; - console.warn('[%s] [master:%s] worker:%s disconnect, %s: %s, state: %s.', - Date(), process.pid, worker.process.pid, propertyName, worker[propertyName], worker.state); -}) -.on('exit', function (worker, code, signal) { - var exitCode = worker.process.exitCode; - var propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; - var err = new Error(util.format('worker %s died (code: %s, signal: %s, %s: %s, state: %s)', - worker.process.pid, exitCode, signal, propertyName, worker[propertyName], worker.state)); - err.name = 'WorkerDiedError'; - console.error('[%s] [master:%s] worker exit: %s', Date(), process.pid, err.stack); -}) -.on('reachReforkLimit', function () { - process.send('reach refork limit'); -}); + .on('fork', function(worker) { + console.warn('[%s] [worker:%d] new worker start', Date(), worker.process.pid); + }) + .on('listening', function(worker, address) { + console.warn('[%s] [worker:%d] listening on %j', Date(), worker.process.pid, address.port); + process.send('listening'); + }) + .on('disconnect', function(worker) { + const propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; + console.warn('[%s] [master:%s] worker:%s disconnect, %s: %s, state: %s.', + Date(), process.pid, worker.process.pid, propertyName, worker[propertyName], worker.state); + }) + .on('exit', function(worker, code, signal) { + const exitCode = worker.process.exitCode; + const propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; + const err = new Error(util.format('worker %s died (code: %s, signal: %s, %s: %s, state: %s)', + worker.process.pid, exitCode, signal, propertyName, worker[propertyName], worker.state)); + err.name = 'WorkerDiedError'; + console.error('[%s] [master:%s] worker exit: %s', Date(), process.pid, err.stack); + }) + .on('reachReforkLimit', function() { + process.send('reach refork limit'); + }); -process.once('SIGTERM', function () { +process.once('SIGTERM', function() { process.exit(0); }); -setTimeout(function () { +setTimeout(function() { mock.uncaughtException; }, 500); diff --git a/test/kill_worker.test.js b/test/kill_worker.test.js deleted file mode 100644 index be94f19..0000000 --- a/test/kill_worker.test.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var urllib = require('urllib'); -var childprocess = require('childprocess'); -var path = require('path'); - -describe('kill_worker.test.test.js', function() { - var child; - var messages = []; - - before(function(done) { - var workerNum = 2; - var slaveNum = 1; - var listeningCount = 0; - child = childprocess.fork(path.join(__dirname, '..', 'fixtures', 'kill_worker', 'master.js')); - child.on('message', function (m) { - messages.push(m); - console.log(m, listeningCount); - if (m === 'listening') { - ++listeningCount; - if (listeningCount === (workerNum + slaveNum)) { - done(); - } - } - }); - }); - - after(function(done) { - setTimeout(function() { - child.kill('SIGTERM'); - setTimeout(done, 1000); - }, 1000); - }); - - it('should kill all workers', function(done) { - urllib.request('http://localhost:1986/', function (err, body) { - console.log(err, body.toString()); - assert(!err); - assert(body.toString() === 'kill 3 workers'); - done(); - }); - }); -}); diff --git a/test/kill_worker.test.ts b/test/kill_worker.test.ts new file mode 100644 index 0000000..87960b5 --- /dev/null +++ b/test/kill_worker.test.ts @@ -0,0 +1,44 @@ +import assert from 'node:assert'; +import childprocess, { ChildProcess } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import urllib from 'urllib'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +describe('test/kill_worker.test.ts', () => { + let child: ChildProcess; + const messages = []; + + before(function(done) { + const workerNum = 2; + const slaveNum = 1; + let listeningCount = 0; + child = childprocess.fork(path.join(__dirname, 'fixtures', 'kill_worker', 'master.cjs')); + child.on('message', function(m) { + messages.push(m); + console.log(m, listeningCount); + if (m === 'listening') { + ++listeningCount; + if (listeningCount === (workerNum + slaveNum)) { + done(); + } + } + }); + }); + + after(function(done) { + setTimeout(function() { + child.kill('SIGTERM'); + setTimeout(done, 1000); + }, 1000); + }); + + it('should kill all workers', async () => { + const response = await urllib.request('http://localhost:1986/', { + dataType: 'text', + }); + assert.equal(response.data, 'kill 3 workers'); + }); +}); diff --git a/test/one_worker_cluster.test.js b/test/one_worker_cluster.test.js deleted file mode 100644 index 2fa9f04..0000000 --- a/test/one_worker_cluster.test.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -var should = require('should'); -var pedding = require('pedding'); -var urllib = require('urllib'); -var childprocess = require('childprocess'); -var path = require('path'); - -describe('one_worker_cluster.test.js', function() { - var child; - var messages = []; - - before(function(done) { - var workerNum = 1; - var slaveNum = 1; - var listeningCount = 0; - child = childprocess.fork(path.join(__dirname, '..', 'fixtures', 'one_worker_cluster', 'master.js')); - child.on('message', function (m) { - messages.push(m); - if (m === 'listening') { - ++listeningCount; - if (listeningCount === (workerNum + slaveNum)) { - done(); - } - } - }); - }); - - after(function(done) { - setTimeout(function() { - child.kill('SIGTERM'); - setTimeout(done, 1000); - }, 1000); - }); - - it('should mock worker async_error', function(done) { - done = pedding(2, done); - urllib.request('http://localhost:1984/async_error', function(err) { - console.error('[cfork.test.js] get /async_error error: %s', err); - should.exist(err); - // ECONNRESET on windows - if (process.platform === 'win32') { - err.message.should.containEql('ECONNRESET'); - } else { - err.message.should.containEql('socket hang up'); - } - done(); - }); - - // request handle by same worker - urllib.request('http://localhost:1984/hold', { - timeout: 10000, - }, function (err) { - console.error('[cfork.test.js] get /hold error: %s', err); - should.exist(err); - // ECONNRESET on windows - if (process.platform === 'win32') { - err.message.should.containEql('ECONNRESET'); - } else { - err.message.should.containEql('socket hang up'); - } - done(); - }); - }); -}); diff --git a/test/one_worker_cluster.test.ts b/test/one_worker_cluster.test.ts new file mode 100644 index 0000000..a8ed8b1 --- /dev/null +++ b/test/one_worker_cluster.test.ts @@ -0,0 +1,59 @@ +import { strict as assert } from 'node:assert'; +import childprocess, { ChildProcess } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import urllib from 'urllib'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +describe('test/one_worker_cluster.test.ts', () => { + let child: ChildProcess; + const messages = []; + + before(function(done) { + const workerNum = 1; + const slaveNum = 1; + let listeningCount = 0; + child = childprocess.fork(path.join(__dirname, 'fixtures', 'one_worker_cluster', 'master.cjs')); + child.on('message', function(m) { + messages.push(m); + if (m === 'listening') { + ++listeningCount; + if (listeningCount === (workerNum + slaveNum)) { + done(); + } + } + }); + }); + + after(function(done) { + setTimeout(function() { + child.kill('SIGTERM'); + setTimeout(done, 1000); + }, 1000); + }); + + it('should mock worker async_error', async () => { + await urllib.request('http://localhost:1984/'); + await urllib.request('http://localhost:1985/'); + + await assert.rejects(async () => { + await urllib.request('http://localhost:1984/async_error'); + }, (err: any) => { + assert.match(err.message, /(ECONNRESET|socket hang up|timeout|ECONNRESET)/); + return true; + }); + + // request handle by same worker + await assert.rejects(async () => { + await urllib.request('http://localhost:1984/hold'); + }, (err: any) => { + assert.match(err.message, /(ECONNRESET|socket hang up|timeout|ECONNRESET)/); + return true; + }); + + await urllib.request('http://localhost:1984/'); + await urllib.request('http://localhost:1985/'); + }); +});