diff --git a/test/Pool.test.js b/test/Pool.test.js index 4bf6c30e..9c60908e 100644 --- a/test/Pool.test.js +++ b/test/Pool.test.js @@ -1,304 +1,276 @@ -var assert = require('assert'), - Promise = require('../lib/Promise'), - Pool = require('../lib/Pool'); - -function add(a, b) { - return a + b; -} - - -function tryRequire(moduleName) { - try { - return require(moduleName); - } catch(error) { - if (typeof error === 'object' && error !== null && error.code == 'MODULE_NOT_FOUND') { - return null; - // no worker_threads, fallback to sub-process based workers - } else { - throw error; - } - } -} - -describe('Pool', function () { +const assert = require('assert'); +const Promise = require('../lib/Promise'); +const Pool = require('../lib/Pool'); +describe('Pool', function() { describe('nodeWorker', function() { - function add(a,b) { - return a+b; - } it('supports process', function() { - var pool = new Pool({ nodeWorker: 'process' }); + const pool = new Pool({ nodeWorker: 'process' }); + return pool.exec(add, [3, 4]) }); - var WorkerThreads = tryRequire('worker_threads'); + const WorkerThreads = tryRequire('worker_threads'); + it('supports auto', function() { - var pool = new Pool({ nodeWorker: 'auto' }); - var result = pool.exec(add, [3, 4]); + const pool = new Pool({ nodeWorker: 'auto' }); + const result = pool.exec(add, [3, 4]); + assert.equal(pool.workers.length, 1); - var worker = pool.workers[0].worker; + + const worker = pool.workers[0].worker; if (WorkerThreads) { assert.equal(worker.isWorkerThread, true); } else { assert.equal(worker.isChildProcess, true); } + return result; }); - if (WorkerThreads) { it('supports thread', function() { - var pool = new Pool({ nodeWorker: 'thread' }); - var work = pool.exec(add, [3, 4]); + const pool = new Pool({ nodeWorker: 'thread' }); + const work = pool.exec(add, [3, 4]); + assert.equal(pool.workers.length, 1); - var worker = pool.workers[0].worker; + + const worker = pool.workers[0].worker; + assert.equal(worker.isWorkerThread, true); + return work; }); } else { it('errors when not supporting worker thread', function() { assert.throws(function() { - var pool = new Pool({ nodeWorker: 'thread' }); + const pool = new Pool({ nodeWorker: 'thread' }); }, /WorkerPool: nodeWorkers = thread is not supported, Node >= 11\.7\.0 required/) }); } }) - it('should offload a function to a worker', function (done) { - var pool = new Pool({maxWorkers: 10}); - - function add(a, b) { - return a + b; - } + it('should offload a function to a worker', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); pool.exec(add, [3, 4]) - .then(function (result) { - assert.equal(result, 7); - assert.equal(pool.workers.length, 1); + .then((result) => { + assert.equal(result, 7); + assert.equal(pool.workers.length, 1); - pool.clear(); + pool.clear(); - assert.equal(pool.workers.length, 0); + assert.equal(pool.workers.length, 0); - done(); - }); + done(); + }); assert.equal(pool.workers.length, 1); }); - it('should offload functions to multiple workers', function (done) { - var pool = new Pool({maxWorkers: 10}); - - function add(a, b) { - return a + b; - } + it('should offload functions to multiple workers', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); Promise.all([ - pool.exec(add, [3, 4]), - pool.exec(add, [2, 3]) - ]) - .then(function (results) { - assert.deepEqual(results, [7, 5]); - assert.equal(pool.workers.length, 2); - - pool.clear(); - done(); - }); + pool.exec(add, [3, 4]), + pool.exec(add, [2, 3]) + ]) + .then((results) => { + assert.deepEqual(results, [7, 5]); + assert.equal(pool.workers.length, 2); + + pool.clear(); + done(); + }); assert.equal(pool.workers.length, 2); }); - it('should put tasks in queue when all workers are busy', function (done) { - var pool = new Pool({maxWorkers: 2}); - - function add(a, b) { - return a + b; - } + it('should put tasks in queue when all workers are busy', function(done) { + const pool = new Pool({ maxWorkers: 2 }); assert.equal(pool.tasks.length, 0); assert.equal(pool.workers.length, 0); - var task1 = pool.exec(add, [3, 4]); - var task2 = pool.exec(add, [2, 3]); + const task1 = pool.exec(add, [3, 4]); + const task2 = pool.exec(add, [2, 3]); assert.equal(pool.tasks.length, 0); assert.equal(pool.workers.length, 2); - var task3 = pool.exec(add, [5, 7]); - var task4 = pool.exec(add, [1, 1]); + const task3 = pool.exec(add, [5, 7]); + const task4 = pool.exec(add, [1, 1]); assert.equal(pool.tasks.length, 2); assert.equal(pool.workers.length, 2); Promise.all([ - task1, - task2, - task3, - task4 - ]) - .then(function (results) { - assert.deepEqual(results, [7, 5, 12, 2]); - assert.equal(pool.tasks.length, 0); - assert.equal(pool.workers.length, 2); - - pool.clear(); - done(); - }); + task1, + task2, + task3, + task4 + ]).then((results) => { + assert.deepEqual(results, [7, 5, 12, 2]); + assert.equal(pool.tasks.length, 0); + assert.equal(pool.workers.length, 2); + + pool.clear(); + done(); + }); }); - it('should create a proxy', function (done) { - var pool = new Pool(); + it('should create a proxy', function(done) { + const pool = new Pool(); - pool.proxy().then(function (proxy) { + pool.proxy().then((proxy) => { assert.deepEqual(Object.keys(proxy).sort(), ['methods', 'run']); proxy.methods() - .then(function (methods) { - assert.deepEqual(methods.sort(), ['methods', 'run']); - done(); - }) - .catch(function (err) { - assert('Should not throw an error'); - }); + .then((methods) => { + assert.deepEqual(methods.sort(), ['methods', 'run']); + + done(); + }) + .catch((err) => { + assert('Should not throw an error'); + }); }); }); - it('should create a proxy of a custom worker', function (done) { - var pool = new Pool(__dirname + '/workers/simple.js'); + it('should create a proxy of a custom worker', function(done) { + const pool = new Pool(`${__dirname}/workers/simple.js`); - pool.proxy().then(function (proxy) { + pool.proxy().then((proxy) => { assert.deepEqual(Object.keys(proxy).sort(), ['add','methods','multiply','run','timeout']); done(); }); }); - it('should invoke a method via a proxy', function (done) { - var pool = new Pool(__dirname + '/workers/simple.js'); + it('should invoke a method via a proxy', function(done) { + const pool = new Pool(`${__dirname}/workers/simple.js`); - pool.proxy().then(function (proxy) { + pool.proxy().then((proxy) => { proxy.multiply(4, 3) - .then(function (result) { - assert.equal(result, 12); - done(); - }) - .catch(function (err) { - console.log(err); - assert('Should not throw an error'); - }); + .then((result) => { + assert.equal(result, 12); + done(); + }) + .catch((err) => { + console.log(err); + assert('Should not throw an error'); + }); }); }); - it('should invoke an async method via a proxy', function (done) { - var pool = new Pool(__dirname + '/workers/simple.js'); + it('should invoke an async method via a proxy', function(done) { + const pool = new Pool(`${__dirname}/workers/simple.js`); - pool.proxy().then(function (proxy) { + pool.proxy().then((proxy) => { proxy.timeout(100) - .then(function (result) { - assert.equal(result, 'done'); - done(); - }) - .catch(function (err) { - console.log(err); - assert('Should not throw an error'); - }); + .then((result) => { + assert.equal(result, 'done'); + + done(); + }) + .catch((err) => { + console.log(err); + assert('Should not throw an error'); + }); }); }); - it('should handle errors thrown by a worker', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should handle errors thrown by a worker', function(done) { + const pool = new Pool({ maxWorkers: 10 }); function test() { throw new TypeError('Test error'); } pool.exec(test) - .catch(function (err) { - assert.ok(err instanceof Error); - assert.equal(err.message, 'Test error') + .catch((err) => { + assert.ok(err instanceof Error); + assert.equal(err.message, 'Test error') - pool.clear(); - done(); - }); + pool.clear(); + done(); + }); }); - it('should execute a function returning a Promise', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should execute a function returning a Promise', function(done) { + const pool = new Pool({ maxWorkers: 10 }); function testAsync() { return Promise.resolve('done'); } pool.exec(testAsync) - .then(function (result) { - assert.equal(result, 'done'); - done(); - }) - .catch(function (err) { - assert('Should not throw an error'); - }); + .then((result) => { + assert.equal(result, 'done'); + + done(); + }) + .catch((err) => { + assert('Should not throw an error'); + }); }); - it('should propagate a rejected Promise', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should propagate a rejected Promise', function(done) { + const pool = new Pool({ maxWorkers: 10 }); function testAsync() { return Promise.reject(new Error('I reject!')); } pool.exec(testAsync) - .then(function (result) { - assert('Should not resolve'); - }) - .catch(function (err) { - //assert.ok(err instanceof Error); // FIXME: returned error should be an instanceof Error - assert.equal(err, err.toString('Error: I reject!')); - done(); - }); + .then((result) => { + assert('Should not resolve'); + }) + .catch((err) => { + // assert.ok(err instanceof Error); // FIXME: returned error should be an instanceof Error + assert.equal(err, err.toString('Error: I reject!')); + done(); + }); }); - it('should cancel a task', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should cancel a task', function(done) { + const pool = new Pool({ maxWorkers: 10 }); function forever() { while (1 > 0) {} // runs forever } - var promise = pool.exec(forever) - .then(function (result) { - assert('promise should never resolve'); - }) + const promise = pool.exec(forever) + .then((result) => { + assert('promise should never resolve'); + }) //.catch(Promise.CancellationError, function (err) { // TODO: not yet supported - .catch(function (err) { - assert(err instanceof Promise.CancellationError); + .catch((err) => { + assert(err instanceof Promise.CancellationError); - assert.equal(pool.workers.length, 0); + assert.equal(pool.workers.length, 0); - done(); - }); + done(); + }); // cancel the task - setTimeout(function () { - promise.cancel(); - }, 0); + setTimeout(() => promise.cancel(), 0); }); - it('should cancel a queued task', function (done) { - var pool = new Pool({maxWorkers: 1}); - var reachedTheEnd = false; + it('should cancel a queued task', function(done) { + const pool = new Pool({ maxWorkers: 1 }); + let reachedTheEnd = false; function delayed() { - var Promise = require('../lib/Promise'); + const Promise = require('../lib/Promise'); - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve(1); - }, 0); + return new Promise((resolve, reject) => { + setTimeout(() => resolve(1), 0); }); } @@ -306,141 +278,137 @@ describe('Pool', function () { return 1; } - var p1 = pool.exec(delayed) - .then(function (result) { - assert.equal(result, 1); - assert.equal(reachedTheEnd, true); - - assert.equal(pool.workers.length, 1); - assert.equal(pool.tasks.length, 0); + const p1 = pool.exec(delayed) + .then((result) => { + assert.equal(result, 1); + assert.equal(reachedTheEnd, true); + assert.equal(pool.workers.length, 1); + assert.equal(pool.tasks.length, 0); - done(); - }); + done(); + }); assert.equal(pool.workers.length, 1); assert.equal(pool.tasks.length, 0); - var p2 = pool.exec(one); // will be queued + const p2 = pool.exec(one); // will be queued + assert.equal(pool.workers.length, 1); assert.equal(pool.tasks.length, 1); - p2.cancel(); // cancel immediately + p2.cancel(); // cancel immediately + assert.equal(pool.workers.length, 1); assert.equal(pool.tasks.length, 1); reachedTheEnd = true; }); - it('should run following tasks if a previous queued task is cancelled', function (done) { - - var pool = new Pool({maxWorkers: 1}); - var reachedTheEnd = false; + it('should run following tasks if a previous queued task is cancelled', function(done) { + const pool = new Pool({ maxWorkers: 1 }); + let reachedTheEnd = false; - function delayed() { - var Promise = require('../lib/Promise'); - - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve(1); - }, 0); - }); - } - - function two() { - var Promise = require('../lib/Promise'); + function delayed() { + const Promise = require('../lib/Promise'); - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve(2); - }, 0); - }); - } + return new Promise((resolve, reject) => { + setTimeout(() => resolve(1), 0); + }); + } - function one() { - return 1; - } + function two() { + const Promise = require('../lib/Promise'); - var oneDone = false; - var twoDone = false; - function checkDone() { - if (oneDone && twoDone) { - done(); - } - } + return new Promise((resolve, reject) => { + setTimeout(() => resolve(2), 0); + }); + } - var p1 = pool.exec(delayed) - .then(function (result) { - assert.equal(result, 1); - assert.equal(reachedTheEnd, true); + function one() { + return 1; + } - oneDone = true; + let oneDone = false; + let twoDone = false; - assert.equal(pool.workers.length, 1); - assert.equal(pool.tasks.length, 1); + function checkDone() { + if (oneDone && twoDone) { + done(); + } + } - checkDone(); - }); + const p1 = pool.exec(delayed) + .then((result) => { + assert.equal(result, 1); + assert.equal(reachedTheEnd, true); - assert.equal(pool.workers.length, 1); - assert.equal(pool.tasks.length, 0); + oneDone = true; - var p2 = pool.exec(one); // will be queued assert.equal(pool.workers.length, 1); assert.equal(pool.tasks.length, 1); - var p3 = pool.exec(two) - .then(function (result) { - assert.equal(result, 2); - assert.equal(reachedTheEnd, true); + checkDone(); + }); - twoDone = true; + assert.equal(pool.workers.length, 1); + assert.equal(pool.tasks.length, 0); - assert.equal(pool.workers.length, 1); - assert.equal(pool.tasks.length, 0); + const p2 = pool.exec(one); // will be queued - checkDone(); - }); + assert.equal(pool.workers.length, 1); + assert.equal(pool.tasks.length, 1); + + const p3 = pool.exec(two) + .then((result) => { + assert.equal(result, 2); + assert.equal(reachedTheEnd, true); + + twoDone = true; - p2.cancel(); // cancel immediately assert.equal(pool.workers.length, 1); - assert.equal(pool.tasks.length, 2); + assert.equal(pool.tasks.length, 0); - reachedTheEnd = true; - }); + checkDone(); + }); - // TODO: test whether a task in the queue can be neatly cancelled + p2.cancel(); // cancel immediately - it('should timeout a task', function (done) { - var pool = new Pool({maxWorkers: 10}); + assert.equal(pool.workers.length, 1); + assert.equal(pool.tasks.length, 2); + + reachedTheEnd = true; + }); + + // TODO: test whether a task in the queue can be neatly cancelled + + it('should timeout a task', function(done) { + const pool = new Pool({ maxWorkers: 10 }); function forever() { while (1 > 0) {} // runs forever } - var promise = pool.exec(forever) - .timeout(50) - .then(function (result) { - assert('promise should never resolve'); - }) + const promise = pool.exec(forever) + .timeout(50) + .then((result) => { + assert('promise should never resolve'); + }) //.catch(Promise.CancellationError, function (err) { // TODO: not yet supported - .catch(function (err) { - assert(err instanceof Promise.TimeoutError); - - assert.equal(pool.workers.length, 0); + .catch((err) => { + assert(err instanceof Promise.TimeoutError); + assert.equal(pool.workers.length, 0); - done(); - }); + done(); + }); }); - it('should start timeout timer of a task once the task is taken from the queue (1)', function (done) { - var pool = new Pool({maxWorkers: 1}); - var delay = 50 + it('should start timeout timer of a task once the task is taken from the queue (1)', function(done) { + const pool = new Pool({ maxWorkers: 1 }); + let delay = 50 function sleep() { - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve ('done :)') - }, 100) // 2 * delay + return new Promise((resolve, reject) => { + setTimeout(() => resolve('done :)'), 100) // 2 * delay }) } @@ -455,26 +423,24 @@ describe('Pool', function () { // the timeout is shorter than the currently executing task and longer than // the queued task, so it should not timeout pool.exec(doNothing) - .timeout(delay) - .then(function (result) { - assert.equal(result, 'ready'); + .timeout(delay) + .then((result) => { + assert.equal(result, 'ready'); - done(); - }) - .catch(function (err) { - assert('promise should not throw'); - }); + done(); + }) + .catch((err) => { + assert('promise should not throw'); + }); }); - it('should start timeout timer of a task once the task is taken from the queue (2)', function (done) { - var pool = new Pool({maxWorkers: 1}); - var delay = 50 + it('should start timeout timer of a task once the task is taken from the queue (1)', function(done) { + const pool = new Pool({ maxWorkers: 1 }); + let delay = 50 function sleep() { - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve ('done :)') - }, 100) // 2 * delay + return new Promise((resolve, reject) => { + setTimeout(() => resolve('done :)'), 100) // 2 * delay }) } @@ -483,42 +449,41 @@ describe('Pool', function () { // add a second task, will be queued until the first finishes pool.exec(sleep) - .timeout(delay) - .then(function (result) { - assert('promise should never resolve'); - }) - .catch(function (err) { - assert(err instanceof Promise.TimeoutError); + .timeout(delay) + .then((result) => { + assert('promise should never resolve'); + }) + .catch((err) => { + assert(err instanceof Promise.TimeoutError); - done(); - }); + done(); + }); }); - it('should handle crashed workers (1)', function (done) { - var pool = new Pool({maxWorkers: 1}); + it('should handle crashed workers (1)', function(done) { + const pool = new Pool({ maxWorkers: 1 }); pool.exec(add) - .then(function () { - assert('Promise should not be resolved'); - }) - .catch(function (err) { - assert.equal(err.toString(), 'Error: Worker terminated unexpectedly'); - - assert.equal(pool.workers.length, 0); + .then(() => { + assert('Promise should not be resolved'); + }) + .catch((err) => { + assert.equal(err.toString(), 'Error: Worker terminated unexpectedly'); - // validate whether a new worker is spawned - pool.exec(add, [2,3]) - .then(function (result) { - assert.equal(result, 5); + assert.equal(pool.workers.length, 0); - assert.equal(pool.workers.length, 1); + // validate whether a new worker is spawned + pool.exec(add, [2,3]) + .then((result) => { + assert.equal(result, 5); + assert.equal(pool.workers.length, 1); - pool.clear(); - done(); - }); + pool.clear(); + done(); + }); - assert.equal(pool.workers.length, 1); - }); + assert.equal(pool.workers.length, 1); + }); assert.equal(pool.workers.length, 1); @@ -528,28 +493,27 @@ describe('Pool', function () { assert.equal(pool.workers.length, 1); }); - describe('options', function () { - - it('should throw an error on invalid type or number of maxWorkers', function () { - assert.throws(function () { - new Pool({maxWorkers: 'a string'}); + describe('options', function() { + it('should throw an error on invalid type or number of maxWorkers', function() { + assert.throws(function() { + new Pool({ maxWorkers: 'a string' }); }, TypeError); - assert.throws(function () { - new Pool({maxWorkers: 2.5}); + assert.throws(function() { + new Pool({ maxWorkers: 2.5 }); }, TypeError); - assert.throws(function () { - new Pool({maxWorkers: 0}); + assert.throws(function() { + new Pool({ maxWorkers: 0 }); }, TypeError); - assert.throws(function () { - new Pool({maxWorkers: -1}); + assert.throws(function() { + new Pool({ maxWorkers: -1 }); }, TypeError); }); - it('should limit to the configured number of max workers', function () { - var pool = new Pool({maxWorkers: 2}); + it('should limit to the configured number of max workers', function() { + const pool = new Pool({ maxWorkers: 2 }); pool.exec(add, [1, 2]); pool.exec(add, [3, 4]); @@ -564,42 +528,44 @@ describe('Pool', function () { pool.clear(); }); - it('should take number of cpus minus one as default maxWorkers', function () { - var pool = new Pool(); + it('should take number of cpus minus one as default maxWorkers', function() { + const pool = new Pool(); + const cpus = require('os').cpus(); - var cpus = require('os').cpus(); assert.equal(pool.maxWorkers, cpus.length - 1); pool.clear(); }); - it('should throw an error on invalid type or number of minWorkers', function () { - assert.throws(function () { - new Pool({minWorkers: 'a string'}); + it('should throw an error on invalid type or number of minWorkers', function() { + assert.throws(function() { + new Pool({ minWorkers: 'a string' }); }, TypeError); - assert.throws(function () { - new Pool({minWorkers: 2.5}); + assert.throws(function() { + new Pool({ minWorkers: 2.5 }); }, TypeError); - assert.throws(function () { - new Pool({maxWorkers: -1}); + assert.throws(function() { + new Pool({ maxWorkers: -1 }); }, TypeError); }); - it('should create number of cpus minus one when minWorkers set to \'max\'', function () { - var pool = new Pool({minWorkers:'max'}); + it('should create number of cpus minus one when minWorkers set to \'max\'', function() { + const pool = new Pool({ minWorkers:'max' }); + const cpus = require('os').cpus(); - var cpus = require('os').cpus(); assert.equal(pool.workers.length, cpus.length - 1); pool.clear(); }); - it('should increase maxWorkers to match minWorkers', function () { - var pool = new Pool({minWorkers: 16}); + it('should increase maxWorkers to match minWorkers', function() { + const pool = new Pool({ minWorkers: 16 }); - for(var i=0;i<20;i++) pool.exec(add, [i, i*2]); + for (var i=0; i<20; i++) { + pool.exec(add, [i, i*2]); + } assert.equal(pool.minWorkers, 16); assert.equal(pool.maxWorkers, 16); @@ -610,12 +576,12 @@ describe('Pool', function () { }); }); - it.skip('should handle crashed workers (2)', function (done) { + it.skip('should handle crashed workers (2)', function(done) { // TODO: create a worker from a script, which really crashes itself }); - it('should clear all workers', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should clear all workers', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); @@ -624,23 +590,22 @@ describe('Pool', function () { } pool.exec(test) - .then(function (result) { - assert.equal(result, 'ok'); - - assert.equal(pool.workers.length, 1); + .then((result) => { + assert.equal(result, 'ok'); + assert.equal(pool.workers.length, 1); - pool.clear(); + pool.clear(); - assert.equal(pool.workers.length, 0); + assert.equal(pool.workers.length, 0); - done(); - }); + done(); + }); assert.equal(pool.workers.length, 1); }); - it('should clear all workers after tasks are finished', function (done) { - var pool = new Pool({maxWorkers: 10}); + it('should clear all workers after tasks are finished', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); @@ -649,178 +614,223 @@ describe('Pool', function () { } pool.exec(test) - .then(function (result) { - assert.equal(result, 'ok'); + .then((result) => { + assert.equal(result, 'ok'); + assert.equal(pool.workers.length, 0); + }); - assert.equal(pool.workers.length, 0); - }); assert.equal(pool.workers.length, 1); pool.terminate(false, 1000) - .then(function() { + .then(() => { assert.equal(pool.workers.length, 0); + done(); }); }); - it ('should wait for all workers if pool is terminated before multiple concurrent tasks are finished', function (done) { - - var pool = new Pool({maxWorkers: 10}); + it('should wait for all workers if pool is terminated before multiple concurrent tasks are finished', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); function test1() { - var start = new Date().getTime(); + const start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > 500) { break; } } + return 'test 1 ok'; } + function test2() { - var start = new Date().getTime(); + const start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > 1000) { break; } } + return 'test 2 ok'; } + function test3() { - var start = new Date().getTime(); + const start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > 200) { break; } } + return 'test 3 ok'; } - var promises = [ + const promises = [ pool.exec(test1), pool.exec(test2), pool.exec(test3) ]; + Promise.all(promises) - .then(function (results) { + .then((results) => { assert.equal(results[0], 'test 1 ok'); assert.equal(results[1], 'test 2 ok'); assert.equal(results[3], 'test 3 ok'); }) - .catch(function(error) { + .catch((error) => { assert.fail(error); }); + assert.equal(pool.workers.length, 3); pool.terminate(false, 2000) - .then(function() { + .then(() => { assert.equal(pool.workers.length, 0); + done(); }); }); - it ('should wait for all workers if pool is terminated before tasks are finished, even if a task fails', function (done) { - - var pool = new Pool({maxWorkers: 10}); + it('should wait for all workers if pool is terminated before tasks are finished, even if a task fails', function(done) { + const pool = new Pool({ maxWorkers: 10 }); assert.equal(pool.workers.length, 0); function test1() { - var start = new Date().getTime(); + const start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > 1000) { break; } } + return 'test 1 ok'; } + function test2() { - var start = new Date().getTime(); + const start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > 100) { break; } } + throw new Error('test 2 error'); } - var promises = [ + const promises = [ pool.exec(test1), pool.exec(test2) ]; Promise.all(promises) - .then(function (results) { + .then((results) => { assert.fail('test2 should have been rejected'); }) - .catch(function(error) { + .catch((error) => { assert.equal(error.message, 'test 2 error'); }); + assert.equal(pool.workers.length, 2); pool.terminate(false, 2000) - .then(function() { + .then(() => { assert.equal(pool.workers.length, 0); done(); }); }); - it('should return statistics', function () { - var pool = new Pool({maxWorkers: 4}); + it('should return statistics', function() { + const pool = new Pool({ maxWorkers: 4 }); function test() { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { setTimeout(resolve, 100); }); } function testError() { - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { throw new Error('Test error') }); } - assert.deepEqual(pool.stats(), {totalWorkers: 0, busyWorkers: 0, idleWorkers: 0, pendingTasks: 0, activeTasks: 0}); - - var promise = pool.exec(test) - .then(function () { - assert.deepEqual(pool.stats(), {totalWorkers: 1, busyWorkers: 0, idleWorkers: 1, pendingTasks: 0, activeTasks: 0 }); + assert.deepEqual(pool.stats(), { + totalWorkers: 0, busyWorkers: 0, idleWorkers: 0, pendingTasks: 0, activeTasks: 0 + }); - // start six tasks (max workers is 4, so we should get pending tasks) - var all = Promise.all([ - pool.exec(test), - pool.exec(test), - pool.exec(test), - pool.exec(test), - pool.exec(test), - pool.exec(test) - ]); + const promise = pool.exec(test) + .then(() => { + assert.deepEqual(pool.stats(), { + totalWorkers: 1, busyWorkers: 0, idleWorkers: 1, pendingTasks: 0, activeTasks: 0 + }); - assert.deepEqual(pool.stats(), {totalWorkers: 4, busyWorkers: 4, idleWorkers: 0, pendingTasks: 2, activeTasks: 4}); + // start six tasks (max workers is 4, so we should get pending tasks) + const all = Promise.all([ + pool.exec(test), + pool.exec(test), + pool.exec(test), + pool.exec(test), + pool.exec(test), + pool.exec(test) + ]); + + assert.deepEqual(pool.stats(), { + totalWorkers: 4, busyWorkers: 4, idleWorkers: 0, pendingTasks: 2, activeTasks: 4 + }); - return all; - }) - .then(function () { - assert.deepEqual(pool.stats(), {totalWorkers: 4, busyWorkers: 0, idleWorkers: 4, pendingTasks: 0, activeTasks: 0 }); + return all; + }) + .then(() => { + assert.deepEqual(pool.stats(), { + totalWorkers: 4, busyWorkers: 0, idleWorkers: 4, pendingTasks: 0, activeTasks: 0 + }); - return pool.exec(testError) - }) - .catch(function () { - assert.deepEqual(pool.stats(), {totalWorkers: 4, busyWorkers: 0, idleWorkers: 4, pendingTasks: 0, activeTasks: 0}); + return pool.exec(testError) + }) + .catch(() => { + assert.deepEqual(pool.stats(), { + totalWorkers: 4, busyWorkers: 0, idleWorkers: 4, pendingTasks: 0, activeTasks: 0 }); + }); - assert.deepEqual(pool.stats(), {totalWorkers: 1, busyWorkers: 1, idleWorkers: 0, pendingTasks: 0, activeTasks: 1}); + assert.deepEqual(pool.stats(), { + totalWorkers: 1, busyWorkers: 1, idleWorkers: 0, pendingTasks: 0, activeTasks: 1 + }); return promise; }); - it('should throw an error in case of wrong type of arguments in function exec', function () { - var pool = new Pool(); - assert.throws(function () {pool.exec()}, TypeError); - assert.throws(function () {pool.exec(23)}, TypeError); - assert.throws(function () {pool.exec(add, {})}, TypeError); - assert.throws(function () {pool.exec(add, 2, 3)}, TypeError); - assert.throws(function () {pool.exec(add, 'a string')}, TypeError); - }); + it('should throw an error in case of wrong type of arguments in function exec', function() { + const pool = new Pool(); + assert.throws(function() { pool.exec() }, TypeError); + assert.throws(function() { pool.exec(23) }, TypeError); + assert.throws(function() { pool.exec(add, {}) }, TypeError); + assert.throws(function() { pool.exec(add, 2, 3) }, TypeError); + assert.throws(function() { pool.exec(add, 'a string') }, TypeError); + }); }); + +function add(a, b) { + return a + b; +} + +function tryRequire(moduleName) { + try { + return require(moduleName); + } catch(error) { + if (typeof error === 'object' && error !== null && error.code == 'MODULE_NOT_FOUND') { + return null; + // no worker_threads, fallback to sub-process based workers + } else { + throw error; + } + } +} diff --git a/test/Promise.test.js b/test/Promise.test.js index fa5ef606..0a3d4d7b 100644 --- a/test/Promise.test.js +++ b/test/Promise.test.js @@ -1,63 +1,60 @@ -var assert = require('assert'), - Promise = require('../lib/Promise'); +const assert = require('assert'); +const Promise = require('../lib/Promise'); -describe ('Promise', function () { - - describe('construction', function () { - it('should throw an error when constructed without handler', function () { - assert.throws(function () {new Promise();}, SyntaxError); +describe('Promise', function() { + describe('construction', function() { + it('should throw an error when constructed without handler', function() { + assert.throws(function() { new Promise(); }, SyntaxError); }); - it('should construct a promise with handler and resolve it', function (done) { - new Promise(function (resolve, reject) { + it('should construct a promise with handler and resolve it', function(done) { + new Promise((resolve, reject) => { resolve(2) - }) - .then(function (result) { - assert.equal(result, 2); - done(); - }); + }).then((result) => { + assert.equal(result, 2); + + done(); + }); }); - it('should construct a promise with handler and reject it', function (done) { - new Promise(function (resolve, reject) { + it('should construct a promise with handler and reject it', function(done) { + new Promise((resolve, reject) => { reject(2) - }) - .catch(function (error) { - assert.equal(error, 2); - done(); - }); + }).catch((error) => { + assert.equal(error, 2); + + done(); + }); }); - it('should throw an error when constructed without new keyword', function () { - assert.throws(function () {Promise()}, /Error/); + it('should throw an error when constructed without new keyword', function() { + assert.throws(function () { Promise() }, /Error/); }); }); - describe('then', function () { - it('should call onSuccess when resolved', function (done) { - new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('foo'); - }, 0); - }).then(function (result) { + describe('then', function() { + it('should call onSuccess when resolved', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => resolve('foo'), 0); + }).then((result) => { assert.equal(result, 'foo'); + done(); }); }); - it('should call onSuccess when resolved before then is attached', function (done) { - var promise = new Promise(function (resolve, reject) { + it('should call onSuccess when resolved before then is attached', function(done) { + new Promise((resolve, reject) => { resolve('foo'); - }); - - promise.then(function (result) { + }).then((result) => { assert.equal(result, 'foo'); + done(); }); }); - it('should NOT throw an error when resolving a promise twice', function (done) { - new Promise(function (resolve, reject) { + it('should NOT throw an error when resolving a promise twice', function(done) { + new Promise((resolve, reject) => { resolve('foo'); resolve('foo'); @@ -65,54 +62,44 @@ describe ('Promise', function () { }); }); - it('should not call onFail when resolved', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('foo'); - }, 0); - }); - - promise.then(function (result) { + it('should not call onFail when resolved', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => resolve('foo'), 0); + }).then((result) => { assert.equal(result, 'foo'); + done(); - }, function (err) { + }, (err) => { assert.ok(false, 'shouldn\'t throw an error'); }); }); - it('should not call onSuccess when rejected', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - reject('err'); - }, 0); - }); - - promise.then(function () { + it('should not call onSuccess when rejected', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => reject('err'), 0); + }).then(() => { assert.ok(false, 'should not resolve'); - }, function (err) { + }, (err) => { assert.equal(err, 'err'); + done(); }); }); - }); - describe('catch', function () { - it('should call onFail when rejected', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - reject('err'); - }, 0); - }); - - promise.catch(function (err) { + describe('catch', function() { + it('should call onFail when rejected', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => reject('err'), 0); + }).catch((err) => { assert.equal(err, 'err'); + done(); }); }); - it('should NOT throw an error when rejecting a promise twice', function (done) { - var promise = new Promise(function (resolve, reject) { + it('should NOT throw an error when rejecting a promise twice', function(done) { + new Promise((resolve, reject) => { reject('foo'); reject('foo'); @@ -120,12 +107,11 @@ describe ('Promise', function () { }); }); - it('should not propagate an error when caught', function (done) { - var log = []; - - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { + it('should not propagate an error when caught', function(done) { + let log = []; + const promise = new Promise((resolve, reject) => { + setTimeout(() => { reject(new Error('My Error')); assert.deepEqual(log, ['catch', 'then']); @@ -134,87 +120,86 @@ describe ('Promise', function () { }, 0); }); - promise.catch(function (err) { + promise.catch((err) => { assert.equal(err, 'Error: My Error'); + log.push('catch'); }) - .then(function (result) { - assert.strictEqual(result, undefined); - log.push('then'); - }) - .catch(function (err) { - assert.ok(false, 'should not catch error another time'); - log.push('catch2') - }); + .then((result) => { + assert.strictEqual(result, undefined); + log.push('then'); + }) + .catch((err) => { + assert.ok(false, 'should not catch error another time'); + + log.push('catch2') + }); }); - it('should rethrow an error', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - reject(new Error('My Error')); - }, 0); + it('should rethrow an error', function(done) { + const promise = new Promise((resolve, reject) => { + setTimeout(() => reject(new Error('My Error')), 0); }); - promise.catch(function (err) { + promise.catch((err) => { assert.equal(err, 'Error: My Error'); + throw new Error('My Error 2'); }) - .catch(function (err) { - assert.equal(err, 'Error: My Error 2'); - done(); - }); + .catch((err) => { + assert.equal(err, 'Error: My Error 2'); + + done(); + }); }); - it('should pass onFail to chained promises', function (done) { - new Promise(function (resolve, reject) { - setTimeout(function () { - reject(new Error('My Error')); - }, 0); + it('should pass onFail to chained promises', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => reject(new Error('My Error')), 0); }) - .then(function () { - assert.ok(false, 'should not call onSuccess'); - }) - .catch(function (err) { - assert.equal(err, 'Error: My Error'); - done(); - }); + .then(() => { + assert.ok(false, 'should not call onSuccess'); + }) + .catch((err) => { + assert.equal(err, 'Error: My Error'); + + done(); + }); }); }); - describe('always', function () { - it('should call always when resolved', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('foo'); - }, 0); + describe('always', function() { + it('should call always when resolved', function(done) { + const promise = new Promise((resolve, reject) => { + setTimeout(() => resolve('foo'), 0); }); - promise.always(function (result) { + promise.always((result) => { assert.equal(result, 'foo'); + done(); }); }); - it('should call always when rejected', function (done) { - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { - reject('err'); - }, 0); + it('should call always when rejected', function(done) { + const promise = new Promise((resolve, reject) => { + setTimeout(() => reject('err'), 0); }); - promise.always(function (result) { + promise.always((result) => { assert.equal(result, 'err'); + done(); }); }); }); - describe('status', function () { - it('should have correct status before and after being resolved', function (done) { - var p = new Promise(function (resolve, reject) { - setTimeout(function () { + describe('status', function() { + it('should have correct status before and after being resolved', function(done) { + const p = new Promise((resolve, reject) => { + setTimeout(() => { resolve(1); assert.equal(p.resolved, true); @@ -230,11 +215,11 @@ describe ('Promise', function () { assert.equal(p.pending, true); }); - it('should have correct status before and after being rejected', function (done) { - var p = new Promise(function (resolve, reject) { - setTimeout(function () { + it('should have correct status before and after being rejected', function(done) { + const p = new Promise((resolve, reject) => { + setTimeout(() => { reject(1); - + assert.equal(p.resolved, false); assert.equal(p.rejected, true); assert.equal(p.pending, false); @@ -249,234 +234,259 @@ describe ('Promise', function () { }); }); - it('should resolve a promise returned by a onSuccess callback', function (done) { - new Promise(function (resolve, reject) { + it('should resolve a promise returned by a onSuccess callback', function(done) { + new Promise((resolve, reject) => { resolve(1) - }) - .then(function (result) { - assert.equal(result, 1); - return new Promise(function (resolve, reject) { - resolve(2); - }); - }) - .then(function (result) { - assert.equal(result, 2); - done(); - }); + }).then((result) => { + assert.equal(result, 1); + + return new Promise((resolve, reject) => { + resolve(2); + }); + }).then((result) => { + assert.equal(result, 2); + + done(); + }); }); - it('should resolve a promise returned by an onFail callback', function (done) { - new Promise(function (resolve, reject) { + it('should resolve a promise returned by an onFail callback', function(done) { + new Promise((resolve, reject) => { reject(1) - }) - .catch(function (err) { - assert.equal(err, 1); - return new Promise(function (resolve, reject) { - resolve(2) - }); - }) - .then(function (result) { - assert.equal(result, 2); - done(); - }); + }).catch((err) => { + assert.equal(err, 1); + + return new Promise((resolve, reject) => { + resolve(2) + }); + }).then((result) => { + assert.equal(result, 2); + + done(); + }); }); - it('should resolve a rejected error from a returned promise (2)', function (done) { - new Promise(function (resolve, reject) { + it('should resolve a rejected error from a returned promise (2)', function(done) { + new Promise((resolve, reject) => { reject(1) - }) - .catch(function (err) { - assert.equal(err, 1); - return new Promise(function (resolve, reject) { - reject(2); - }); - }) - .catch(function (err) { - assert.equal(err, 2); - done(); - }); + }).catch((err) => { + assert.equal(err, 1); + + return new Promise((resolve, reject) => { + reject(2); + }); + }).catch((err) => { + assert.equal(err, 2); + done(); + }); }); - it('should catch an error thrown by an onSuccess callback', function (done) { - new Promise(function (resolve, reject) { + it('should catch an error thrown by an onSuccess callback', function(done) { + new Promise((resolve, reject) => { resolve(1) - }) - .then(function (result) { - assert.equal(result, 1); - throw new Error('2'); - }) - .catch(function (err) { - assert.equal(err.toString(), 'Error: 2'); - done(); - }); + }).then((result) => { + assert.equal(result, 1); + + throw new Error('2'); + }).catch((err) => { + assert.equal(err.toString(), 'Error: 2'); + + done(); + }); }); - it('should catch an error thrown by an onFail callback', function (done) { - new Promise(function (resolve, reject) { + it('should catch an error thrown by an onFail callback', function(done) { + new Promise((resolve, reject) => { reject(new Error(1)) - }) - .catch(function (err) { - assert.equal(err.toString(), 'Error: 1'); - throw new Error('2'); - }) - .catch(function (err) { - assert.equal(err.toString(), 'Error: 2'); - done(); - }); + }).catch((err) => { + assert.equal(err.toString(), 'Error: 1'); + + throw new Error('2'); + }).catch((err) => { + assert.equal(err.toString(), 'Error: 2'); + + done(); + }); }); - it('should pass arguments through the promise chain which is already resolved', function (done) { - var log = []; - var promise = new Promise(function (resolve, reject) { + it('should pass arguments through the promise chain which is already resolved', function(done) { + let log = []; + + const promise = new Promise((resolve, reject) => { resolve(1); }); // first chain - promise - .then(function (res){ - log.push(res); - assert.equal(res, 1); - }); + promise.then((res) => { + log.push(res); + + assert.equal(res, 1); + }); // second chain - promise.then(function (res){ - log.push(res); - assert.equal(res, 1); - return new Promise(function (resolve, reject) { - reject(2) - }); - }) - .then(function (){ - assert.ok(false, 'should not resolve') - }) - .catch(function (res) { - assert.equal(res, 2); - log.push(res); - throw 3; - }) - .catch(function (err) { - log.push(err); - assert.equal(err, 3); - return new Promise(function (resolve, reject) { - reject(4) - }) - }) - .then(null, function (err){ - log.push(err); - assert.equal(err, 4); - return new Promise(function (resolve, reject) { - resolve(5) - }); - }) - .then(function (res) { - log.push(res); - assert.equal(res, 5); - }) - .catch(function (){ - log.push('fail') - }); + promise.then((res) => { + log.push(res); + + assert.equal(res, 1); + + return new Promise((resolve, reject) => { + reject(2) + }); + }) + .then(() => { + assert.ok(false, 'should not resolve') + }) + .catch((res) => { + assert.equal(res, 2); + + log.push(res); + + throw 3; + }) + .catch((err) => { + log.push(err); + + assert.equal(err, 3); + + return new Promise((resolve, reject) => { + reject(4) + }) + }) + .then(null, (err) => { + log.push(err); + + assert.equal(err, 4); + + return new Promise((resolve, reject) => { + resolve(5) + }); + }) + .then((res) => { + log.push(res); + + assert.equal(res, 5); + }) + .catch(() => { + log.push('fail') + }); assert.equal(log.join(','), '1,1,2,3,4,5'); + done(); }); - it('should pass arguments through the promise chain which is not yet resolved', function (done) { - var log = []; + it('should pass arguments through the promise chain which is not yet resolved', function(done) { + let log = []; - var promise = new Promise(function (resolve, reject) { - setTimeout(function () { + const promise = new Promise((resolve, reject) => { + setTimeout(() => { resolve(1) assert.equal(log.join(','), '1,1,2,3,4,5'); + done(); }, 0) }); // first chain - promise - .then(function (res){ - log.push(res); - assert.equal(res, 1); - }); + promise.then((res) => { + log.push(res); + + assert.equal(res, 1); + }); // second chain - promise - .then(function (res){ - log.push(res); - assert.equal(res, 1); - return new Promise(function (resolve, reject) { - reject(2) - }) - }) - .then(function (){ - assert.ok(false, 'should not resolve') - }) - .catch(function (res) { - assert.equal(res, 2); - log.push(res); - throw 3; - }) - .catch(function (err) { - log.push(err); - assert.equal(err, 3); - return new Promise(function (resolve, reject) { - reject(4) - }) - }) - .then(null, function (err){ - log.push(err); - assert.equal(err, 4); - return new Promise(function (resolve, reject) { - resolve(5) - }) - }) - .then(function (res) { - log.push(res); - assert.equal(res, 5); - }) - .catch(function (){ - log.push('fail') - }); + promise.then((res) => { + log.push(res); + + assert.equal(res, 1); + + return new Promise((resolve, reject) => { + reject(2) + }) + }) + .then(() => { + assert.ok(false, 'should not resolve') + }) + .catch((res) => { + assert.equal(res, 2); + + log.push(res); + + throw 3; + }) + .catch((err) => { + log.push(err); + + assert.equal(err, 3); + + return new Promise((resolve, reject) => { + reject(4) + }) + }) + .then(null, (err) => { + log.push(err); + + assert.equal(err, 4); + + return new Promise((resolve, reject) => { + resolve(5) + }) + }) + .then((res) => { + log.push(res); + + assert.equal(res, 5); + }) + .catch(() => { + log.push('fail') + }); }); - describe('cancel', function () { - it('should cancel a promise', function (done) { - var p = new Promise(function (resolve, reject) {}) - .catch(function (err) { - assert(err instanceof Promise.CancellationError); - done(); - }); + describe('cancel', function() { + it('should cancel a promise', function(done) { + const p = new Promise((resolve, reject) => {}) + .catch((err) => { + assert(err instanceof Promise.CancellationError); - setTimeout(function () { - p.cancel(); - }, 10); + done(); + }); + + setTimeout(() => p.cancel(), 10); }); - it('should cancel a promise and catch afterwards', function (done) { - var p = new Promise(function (resolve, reject) {}).cancel(); + it('should cancel a promise and catch afterwards', function(done) { + const p = new Promise((resolve, reject) => {}).cancel(); - p.catch(function (err) { + p.catch((err) => { assert(err instanceof Promise.CancellationError); + done(); }) }); - it('should propagate cancellation of a promise to the promise parent', function (done) { - var p = new Promise(function (resolve, reject) {}); + it('should propagate cancellation of a promise to the promise parent', function(done) { + const p = new Promise((resolve, reject) => {}); + + let processing = 2; - var processing = 2; function next() { processing--; - if (processing == 0) done(); + + if (processing == 0) { + done(); + } } - var p1 = p.catch(function (err) { + const p1 = p.catch((err) => { assert(err instanceof Promise.CancellationError); + next(); }); - var p2 = p.catch(function (err) { + const p2 = p.catch((err) => { assert(err instanceof Promise.CancellationError); + next(); }); @@ -484,83 +494,90 @@ describe ('Promise', function () { }); }); - describe('timeout', function () { - it('should timeout a promise', function (done) { - new Promise(function (resolve, reject) {}) - .timeout(30) - .catch(function (err) { - assert(err instanceof Promise.TimeoutError); - done(); - }) + describe('timeout', function() { + it('should timeout a promise', function(done) { + new Promise((resolve, reject) => {}) + .timeout(30) + .catch((err) => { + assert(err instanceof Promise.TimeoutError); + + done(); + }) }); - it('should timeout a promise afterwards', function (done) { - var p = new Promise(function (resolve, reject) {}) - .catch(function (err) { - assert(err instanceof Promise.TimeoutError); - done(); - }); + it('should timeout a promise afterwards', function(done) { + const p = new Promise((resolve, reject) => {}) + .catch((err) => { + assert(err instanceof Promise.TimeoutError); + + done(); + }); p.timeout(30) }); - it('timeout should be stopped when promise resolves', function (done) { - new Promise(function (resolve, reject) { - setTimeout(function () { + it('timeout should be stopped when promise resolves', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => { resolve(1); }, 0); }) - .timeout(30) - .then(function (result) { - assert.equal(result, 1); - done(); - }) - .catch(function (err) { - assert.ok(false, 'should not throw an error'); - }); - }); - - it('timeout should be stopped when promise rejects', function (done) { - new Promise(function (resolve, reject) { - setTimeout(function () { + .timeout(30) + .then((result) => { + assert.equal(result, 1); + + done(); + }) + .catch((err) => { + assert.ok(false, 'should not throw an error'); + }); + }); + + it('timeout should be stopped when promise rejects', function(done) { + new Promise((resolve, reject) => { + setTimeout(() => { reject(new Error('My Error')); }, 0); }) - .timeout(30) - .catch(function (err) { - assert.equal(err.toString(), 'Error: My Error'); - done(); - }); - }); - - it('timeout should be propagated to parent promise', function (done) { - new Promise(function (resolve, reject) {}) - .then() // force creation of a child promise - .catch(function (err) { - assert(err instanceof Promise.TimeoutError); - done(); - }) - .timeout(30); + .timeout(30) + .catch((err) => { + assert.equal(err.toString(), 'Error: My Error'); + + done(); + }); + }); + + it('timeout should be propagated to parent promise', function(done) { + new Promise((resolve, reject) => {}) + .then() // force creation of a child promise + .catch((err) => { + assert(err instanceof Promise.TimeoutError); + + done(); + }) + .timeout(30); }); }); - describe('defer', function () { - it('should create a resolver and resolve it', function (done) { - var resolver = Promise.defer(); + describe('defer', function() { + it('should create a resolver and resolve it', function(done) { + const resolver = Promise.defer(); - resolver.promise.then(function (result) { + resolver.promise.then((result) => { assert.equal(result, 3); + done(); }); resolver.resolve(3); }); - it('should create a resolver and reject it', function (done) { - var resolver = Promise.defer(); + it('should create a resolver and reject it', function(done) { + const resolver = Promise.defer(); - resolver.promise.catch(function (err) { + resolver.promise.catch((err) => { assert.equal(err.toString(), 'Error: My Error'); + done(); }); @@ -568,105 +585,104 @@ describe ('Promise', function () { }) }); - describe('all', function () { - - it('should resolve "all" when all promises are resolved', function (done) { - var foo = new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('foo'); - }, 25); - }), - bar = new Promise(function (resolve, reject) { - resolve('bar'); - }), - baz = new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('baz'); - }, 40); - }), - qux = new Promise(function (resolve, reject) { - resolve('qux'); - }); + describe('all', function() { + it('should resolve "all" when all promises are resolved', function(done) { + const foo = new Promise((resolve, reject) => { + setTimeout(() => { + resolve('foo'); + }, 25); + }); + const bar = new Promise((resolve, reject) => { + resolve('bar'); + }); + const baz = new Promise((resolve, reject) => { + setTimeout(() => { + resolve('baz'); + }, 40); + }); + const qux = new Promise((resolve, reject) => { + resolve('qux'); + }); Promise.all([foo, bar, baz, qux]) - .then(function (results) { - assert.ok(true, 'then'); - assert.deepEqual(results, ['foo', 'bar', 'baz', 'qux']); - - done(); - }) - .catch(function (){ - assert.ok(false, 'catch'); - }); - }); - - it('should reject "all" when any of the promises failed', function (done) { - var foo = new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('foo'); - }, 40); - }), - bar = new Promise(function (resolve, reject) { - resolve('bar'); - }), - baz = new Promise(function (resolve, reject) { - setTimeout(function () { - reject('The Error'); - }, 25); - }), - qux = new Promise(function (resolve, reject) { - resolve('qux'); - }); + .then((results) => { + assert.ok(true, 'then'); + assert.deepEqual(results, ['foo', 'bar', 'baz', 'qux']); + + done(); + }) + .catch(() => { + assert.ok(false, 'catch'); + }); + }); + + it('should reject "all" when any of the promises failed', function(done) { + const foo = new Promise((resolve, reject) => { + setTimeout(() => { + resolve('foo'); + }, 40); + }); + const bar = new Promise((resolve, reject) => { + resolve('bar'); + }); + const baz = new Promise((resolve, reject) => { + setTimeout(() => { + reject('The Error'); + }, 25); + }); + const qux = new Promise((resolve, reject) => { + resolve('qux'); + }); Promise.all([foo, bar, baz, qux]) - .then(function (result){ - assert.ok(false, 'should not resolve'); - }) - .catch(function (err){ - assert.ok(true, 'catch'); - assert.equal(err, 'The Error'); - done(); - }); - }); - - it('should resolve "all" when all of the promises are already resolved', function (done) { - var foo = new Promise(function (resolve, reject) { - resolve('foo'); - }), - bar = new Promise(function (resolve, reject) { - resolve('bar'); - }), - baz = new Promise(function (resolve, reject) { - resolve('baz'); - }), - qux = new Promise(function (resolve, reject) { - resolve('qux'); - }); + .then((result) => { + assert.ok(false, 'should not resolve'); + }) + .catch((err) => { + assert.ok(true, 'catch'); + assert.equal(err, 'The Error'); + + done(); + }); + }); + + it('should resolve "all" when all of the promises are already resolved', function(done) { + const foo = new Promise((resolve, reject) => { + resolve('foo'); + }); + const bar = new Promise((resolve, reject) => { + resolve('bar'); + }); + const baz = new Promise((resolve, reject) => { + resolve('baz'); + }); + const qux = new Promise((resolve, reject) => { + resolve('qux'); + }); Promise.all([foo, bar, baz, qux]) - .then(function (results) { - assert.ok(true, 'then'); - assert.deepEqual(results, ['foo', 'bar', 'baz', 'qux']); + .then((results) => { + assert.ok(true, 'then'); + assert.deepEqual(results, ['foo', 'bar', 'baz', 'qux']); - done(); - }) - .catch(function (){ - assert.ok(false, 'catch'); - }); + done(); + }) + .catch(() => { + assert.ok(false, 'catch'); + }); }); - it('should resolve "all" when empty', function (done) { + it('should resolve "all" when empty', function(done) { Promise.all([]) - .then(function (results) { - assert.ok(true, 'then'); - assert.deepEqual(results, []); + .then((results) => { + assert.ok(true, 'then'); + assert.deepEqual(results, []); - done(); - }) - .catch(function (){ - assert.ok(false, 'catch'); - }); + done(); + }) + .catch(() => { + assert.ok(false, 'catch'); + }); }); }); - }); diff --git a/test/WorkerHandler.test.js b/test/WorkerHandler.test.js index f1efc138..d08fa439 100644 --- a/test/WorkerHandler.test.js +++ b/test/WorkerHandler.test.js @@ -1,82 +1,80 @@ -var assert = require('assert'), - Promise = require('../lib/Promise'), - WorkerHandler = require('../lib/WorkerHandler'); +const assert = require('assert'); +const Promise = require('../lib/Promise'); +const WorkerHandler = require('../lib/WorkerHandler'); -function add(a, b) { - return a + b; -} - -describe('WorkerHandler', function () { - - it('should handle a request', function (done) { - var handler = new WorkerHandler(); +describe('WorkerHandler', function() { + it('should handle a request', function(done) { + const handler = new WorkerHandler(); handler.exec('run', [String(add), [2, 4]]) - .then(function (result) { - assert.equal(result, 6); - done(); - }) + .then((result) => { + assert.equal(result, 6); + + done(); + }) }); - it('should get all methods', function (done) { - var handler = new WorkerHandler(); + it('should get all methods', function(done) { + const handler = new WorkerHandler(); handler.methods() - .then(function (methods) { - assert.deepEqual(methods.sort(), ['methods', 'run']); - done(); - }) + .then((methods) => { + assert.deepEqual(methods.sort(), ['methods', 'run']); + + done(); + }) }); - it('should handle multiple requests at once', function (done) { - var handler = new WorkerHandler(); + it('should handle multiple requests at once', function(done) { + const handler = new WorkerHandler(); - var task1 = handler.exec('run', [add + '', [2, 4]]); - var task2 = handler.exec('run', [add + '', [4, 7]]); + const task1 = handler.exec('run', [add + '', [2, 4]]); + const task2 = handler.exec('run', [add + '', [4, 7]]); Promise.all([task1, task2]) - .then(function (results) { - assert.deepEqual(results, [6, 11]); - done(); - }) + .then((results) => { + assert.deepEqual(results, [6, 11]); + + done(); + }) }); - it('should test whether a worker is available', function (done) { - var handler = new WorkerHandler(); + it('should test whether a worker is available', function(done) { + const handler = new WorkerHandler(); assert.equal(handler.busy(), false); handler.exec('run', [String(add), [2, 4]]) - .then(function (result) { - assert.equal(result, 6); - assert.equal(handler.busy(), false); - done(); - }); + .then((result) => { + assert.equal(result, 6); + assert.equal(handler.busy(), false); + + done(); + }); assert.equal(handler.busy(), true); }); - it('should terminate', function () { - var handler = new WorkerHandler(); + it('should terminate', function() { + const handler = new WorkerHandler(); handler.terminate(); assert.equal(handler.terminated, true); }); - it('should terminate after finishing running requests', function (done) { - var handler = new WorkerHandler(); + it('should terminate after finishing running requests', function(done) { + const handler = new WorkerHandler(); handler.exec('run', [String(add), [2, 4]]) - .then(function (result) { - assert.equal(result, 6); - - assert.equal(handler.terminating, false); - assert.equal(handler.terminated, true); + .then((result) => { + assert.equal(result, 6); + assert.equal(handler.terminating, false); + assert.equal(handler.terminated, true); - done(); - }); + done(); + }); handler.terminate(); @@ -84,85 +82,87 @@ describe('WorkerHandler', function () { assert.equal(handler.terminated, false); }); - it('should force termination without finishing running requests', function (done) { - var handler = new WorkerHandler(); + it('should force termination without finishing running requests', function(done) { + const handler = new WorkerHandler(); handler.exec('run', [String(add), [2, 4]]) - /* - .then(function (result) { - assert('Should not complete request'); - }) - */ - .catch(function (err) { - assert.ok(err.stack.match(/Error: Worker terminated/)) - done(); - }); + /* + .then(function (result) { + assert('Should not complete request'); + }) + */ + .catch((err) => { + assert.ok(err.stack.match(/Error: Worker terminated/)) + + done(); + }); + + let force = true; - var force = true; handler.terminate(force); assert.equal(handler.terminated, true); }); - it('handle a promise based result', function (done) { - var handler = new WorkerHandler(); + it('handle a promise based result', function(done) { + const handler = new WorkerHandler(); function asyncAdd(a, b) { - var Promise = require('../lib/Promise'); + const Promise = require('../lib/Promise'); - return new Promise(function (resolve, reject) { + return new Promise((resolve, reject) => { if (typeof a === 'number' && typeof b === 'number') { resolve(a + b); - } - else { + } else { reject(new TypeError('Invalid input, two numbers expected')) } }); } handler.exec('run', [String(asyncAdd), [2, 4]]) - .then(function (result) { - assert.equal(result, 6); - - handler.exec('run', [String(asyncAdd), [2, 'oops']]) - .catch(function (err) { - assert.ok(err.stack.match(/TypeError: Invalid input, two numbers expected/)) - done(); - }); - }); + .then((result) => { + assert.equal(result, 6); + + handler.exec('run', [String(asyncAdd), [2, 'oops']]) + .catch((err) => { + assert.ok(err.stack.match(/TypeError: Invalid input, two numbers expected/)) + + done(); + }); + }); }); - it('create a worker handler with custom script', function (done) { - var handler = new WorkerHandler(__dirname + '/workers/simple.js'); + it('create a worker handler with custom script', function(done) { + const handler = new WorkerHandler(__dirname + '/workers/simple.js'); // test build in function run handler.exec('run', [String(add), [2, 4]]) - .then(function (result) { - assert.equal(result, 6); + .then((result) => { + assert.equal(result, 6); - // test one of the functions defined in the simple.js worker - handler.exec('multiply', [2, 4]) - .then(function (result) { - assert.equal(result, 8); + // test one of the functions defined in the simple.js worker + handler.exec('multiply', [2, 4]) + .then((result) => { + assert.equal(result, 8); - done(); - }); - }); + done(); + }); + }); }); - it('should handle the asynchronous initialization of a worker', function (done) { + it('should handle the asynchronous initialization of a worker', function(done) { + const handler = new WorkerHandler(__dirname + '/workers/async.js'); - var handler = new WorkerHandler(__dirname + '/workers/async.js'); + handler.exec('add', [2, 4]) + .then((result) => { + assert.equal(result, 6); - handler.exec('add', [2, 4]) - .then(function (result) { - assert.equal(result, 6); - done(); - }); + done(); + }); }); - it('should cancel a task', function (done) { - var handler = new WorkerHandler(); + it('should cancel a task', function(done) { + const handler = new WorkerHandler(); function forever() { while(1 > 0) { @@ -170,26 +170,26 @@ describe('WorkerHandler', function () { } } - var promise = handler.exec('run', [String(forever)]) - .then(function (result) { - assert('promise should never resolve'); - }) - //.catch(Promise.CancellationError, function (err) { // TODO: not yet supported - .catch(function (err) { - assert.ok(err.stack.match(/CancellationError/)) + const promise = handler.exec('run', [String(forever)]) + .then((result) => { + assert('promise should never resolve'); + }) + //.catch(Promise.CancellationError, function (err) { // TODO: not yet supported + .catch((err) => { + assert.ok(err.stack.match(/CancellationError/)) - assert.equal(handler.worker, null); - assert.equal(handler.terminated, true); + assert.equal(handler.worker, null); + assert.equal(handler.terminated, true); - done(); - }); + done(); + }); // cancel the task promise.cancel(); }); - it('should timeout a task', function (done) { - var handler = new WorkerHandler(); + it('should timeout a task', function(done) { + const handler = new WorkerHandler(); function forever() { while(1 > 0) { @@ -199,13 +199,12 @@ describe('WorkerHandler', function () { handler.exec('run', [String(forever)]) .timeout(50) - .then(function (result) { + .then((result) => { assert('promise should never resolve'); }) //.catch(Promise.TimeoutError, function (err) { // TODO: not yet supported - .catch(function (err) { + .catch((err) => { assert(err instanceof Promise.TimeoutError); - assert.equal(handler.worker, null); assert.equal(handler.terminated, true); @@ -213,74 +212,73 @@ describe('WorkerHandler', function () { }); }); - it('should handle errors thrown by a worker (1)', function (done) { - var handler = new WorkerHandler(); + it('should handle errors thrown by a worker (1)', function(done) { + const handler = new WorkerHandler(); function test() { throw new TypeError('Test error'); } handler.exec('run', [String(test)]) - .catch(function (err) { - assert.ok(err.stack.match(/TypeError: Test error/)) + .catch((err) => { + assert.ok(err.stack.match(/TypeError: Test error/)) - done(); - }); + done(); + }); }); - it('should handle errors thrown by a worker (2)', function (done) { - var handler = new WorkerHandler(); + it('should handle errors thrown by a worker (2)', function(done) { + const handler = new WorkerHandler(); function test() { return test(); } handler.exec('run', [String(test)]) - .catch(function (err) { - assert.ok(err.stack.match(/RangeError: Maximum call stack size exceeded/)) + .catch((err) => { + assert.ok(err.stack.match(/RangeError: Maximum call stack size exceeded/)) - done(); - }); + done(); + }); }); - it('should handle crashing of a worker (1)', function (done) { - var handler = new WorkerHandler(); + it('should handle crashing of a worker (1)', function(done) { + const handler = new WorkerHandler(); handler.exec('run', [String(add), [2, 4]]) - .then(function () { - assert('Promise should not be resolved'); - }) - .catch(function (err) { - assert(err instanceof Error); - assert.ok(err.stack.match(/Error: Worker terminated unexpectedly/)); - - done(); - }); + .then(() => { + assert('Promise should not be resolved'); + }) + .catch((err) => { + assert(err instanceof Error); + assert.ok(err.stack.match(/Error: Worker terminated unexpectedly/)); + + done(); + }); // to fake a problem with a worker, we disconnect it handler.worker.disconnect(); }); - it('should handle crashing of a worker (2)', function (done) { - var handler = new WorkerHandler(); + it('should handle crashing of a worker (2)', function(done) { + const handler = new WorkerHandler(); handler.exec('run', [String(add), [2, 4]]) - .then(function () { - assert('Promise should not be resolved'); - }) - .catch(function (err) { - assert(err instanceof Error); - assert.ok(err.stack.match(/Error: Worker terminated unexpectedly/)); - - done(); - }); + .then(() => { + assert('Promise should not be resolved'); + }) + .catch((err) => { + assert(err instanceof Error); + assert.ok(err.stack.match(/Error: Worker terminated unexpectedly/)); + + done(); + }); // to fake a problem with a worker, we kill it handler.worker.kill(); - }); - it.skip('should handle crashing of a worker (3)', function (done) { + it.skip('should handle crashing of a worker (3)', function(done) { // TODO: create a worker from a script, which really crashes itself }); @@ -295,18 +293,20 @@ describe('WorkerHandler', function () { // these next tests are mock heavy, this is to ensure they can be tested cross platform with confidence describe('setupProcessWorker', function() { it('correctly configures a child_process', function() { - var SCRIPT = 'I AM SCRIPT'; - var FORK_ARGS = {}; - var FORK_OPTS = {}; - var RESULT = {}; - var forkCalls = 0; - - var child_process = { - fork: function(script, forkArgs, forkOpts) { + const SCRIPT = 'I AM SCRIPT'; + const FORK_ARGS = {}; + const FORK_OPTS = {}; + let RESULT = {}; + let forkCalls = 0; + + const child_process = { + fork(script, forkArgs, forkOpts) { forkCalls++; + assert.equal(script, SCRIPT); assert.equal(forkArgs, FORK_ARGS); assert.equal(forkOpts, forkOpts); + return RESULT; } }; @@ -315,16 +315,15 @@ describe('WorkerHandler', function () { forkArgs: FORK_ARGS, forkOpts: FORK_OPTS }, child_process), RESULT); - assert.equal(forkCalls, 1); }); }); describe('setupBrowserWorker', function() { it('correctly sets up the browser worker', function() { - var SCRIPT = 'the script'; - var postMessage; - var addEventListener; + const SCRIPT = 'the script'; + let postMessage; + let addEventListener; function Worker(script) { assert.equal(script, SCRIPT); @@ -338,31 +337,36 @@ describe('WorkerHandler', function () { postMessage = message; }; - var worker = WorkerHandler._setupBrowserWorker(SCRIPT, Worker); + const worker = WorkerHandler._setupBrowserWorker(SCRIPT, Worker); assert.ok(worker instanceof Worker); assert.ok(typeof worker.on === 'function'); assert.ok(typeof worker.send === 'function'); assert.equal(addEventListener, undefined); + worker.on('foo', function() {}); + assert.equal(addEventListener.eventName, 'foo'); assert.ok(typeof addEventListener.callback === 'function'); - assert.equal(postMessage, undefined); + worker.send('the message'); + assert.equal(postMessage, 'the message'); + worker.send('next message'); + assert.equal(postMessage, 'next message'); }) }); describe('setupWorkerThreadWorker', function() { it('works', function() { - var SCRIPT = 'the script'; - var postMessage; - var addEventListener; - var terminate = 0; + const SCRIPT = 'the script'; + let postMessage; + let addEventListener; + let terminate = 0; function Worker(script, options) { assert.equal(script, SCRIPT); @@ -382,7 +386,7 @@ describe('WorkerHandler', function () { terminate++; } - var worker = WorkerHandler._setupWorkerThreadWorker(SCRIPT, { Worker: Worker }); + const worker = WorkerHandler._setupWorkerThreadWorker(SCRIPT, { Worker: Worker }); assert.ok(worker instanceof Worker); @@ -390,18 +394,28 @@ describe('WorkerHandler', function () { assert.ok(typeof worker.send === 'function'); assert.ok(typeof worker.kill === 'function'); assert.ok(typeof worker.disconnect === 'function'); - assert.equal(terminate, 0); + worker.kill(); + assert.equal(terminate, 1); + worker.disconnect(); - assert.equal(terminate, 2); + assert.equal(terminate, 2); assert.equal(postMessage, undefined); + worker.send('the message'); + assert.equal(postMessage, 'the message'); + worker.send('next message'); + assert.equal(postMessage, 'next message'); }); }); }); + +function add(a, b) { + return a + b; +} diff --git a/test/workers/async.js b/test/workers/async.js index a5a7251a..a9dd29d8 100644 --- a/test/workers/async.js +++ b/test/workers/async.js @@ -1,13 +1,11 @@ // a worker which does initialization asynchronously -var workerpool = require('../../index'); +const workerpool = require('../../index'); function add(a, b) { return a + b; } -setTimeout(function() { +setTimeout(() => { // create a worker and register some functions - workerpool.worker({ - add: add - }); + workerpool.worker({ add: add }); }, 500); diff --git a/test/workers/simple.js b/test/workers/simple.js index 13a203a9..00b8ea91 100644 --- a/test/workers/simple.js +++ b/test/workers/simple.js @@ -1,5 +1,5 @@ // a simple worker -var workerpool = require('../../index'); +const workerpool = require('../../index'); function add(a, b) { return a + b; @@ -10,10 +10,8 @@ function multiply(a, b) { } function timeout(delay) { - return new Promise(function (resolve, reject) { - setTimeout(function () { - resolve('done'); - }, delay) + return new Promise((resolve, reject) => { + setTimeout(() => resolve('done'), delay) }); }