Bones/node_modules/throat/test/index.js
SOUTHERNCO\x2mjbyrn 7efe7605b8 Template Upload
2017-05-17 13:45:25 -04:00

246 lines
7.5 KiB
JavaScript

'use strict';
var assert = require('assert');
var fs = require('fs');
var test = require('testit');
var Promise = require('promise/lib/es6-extensions.js');
var throat = require('../')(Promise);
var sentA = {}, sentB = {}, sentC = {}
function job() {
var resolve, reject;
var promise = new Promise(function (_resolve, _reject) {
resolve = _resolve;
reject = _reject;
});
function executeJob() {
if (executeJob.isRun) throw new Error('Job was run multiple times');
executeJob.isRun = true;
executeJob.args = Array.prototype.slice.call(arguments);
return promise;
}
executeJob.fail = function (err) {
reject(err);
};
executeJob.complete = function (val) {
resolve(val);
};
executeJob.isRun = false
return executeJob;
}
function Processed(val) {
this.val = val
}
function worker(max) {
var concurrent = 0
function execute() {
concurrent++
if (concurrent > max) throw new Error('Extra processes were run in parallel.')
var res = new Processed(Array.prototype.slice.call(arguments))
return new Promise(function (resolve) {
setTimeout(function () {
concurrent--
resolve(res)
}, 100)
})
}
return execute
}
test('throat(n)', function () {
test('throat(1) acts as a lock', function (done) {
var lock = throat(1)
var a = job(), b = job(), c = job();
var resA = lock(a, 123)
var resB = lock(b, 456)
var resC = lock(c, 789)
assert(a.isRun)
assert(!b.isRun)
assert(!c.isRun)
a.complete(sentA)
resA.then(function (resA) {
assert(resA === sentA)
assert(a.isRun)
assert(b.isRun)
assert(!c.isRun)
b.fail(sentB)
return resB
.then(function () {
throw new Error('b should have been rejected')
}, function (errB) {
assert(errB === sentB)
})
})
.then(function () {
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
assert.deepEqual(a.args, [123]);
assert.deepEqual(b.args, [456]);
assert.deepEqual(c.args, [789]);
c.complete(sentC)
return resC
})
.then(function (resC) {
assert(resC === sentC)
})
.nodeify(done)
})
test('throat(2) lets two processes acquire the same lock', function (done) {
var lock = throat(2)
var a = job(), b = job(), c = job();
var resA = lock(a)
var resB = lock(b)
var resC = lock(c)
assert(a.isRun)
assert(b.isRun)
assert(!c.isRun)
a.complete(sentA)
resA.then(function (resA) {
assert(resA === sentA)
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
b.fail(sentB)
return resB
.then(function () {
throw new Error('b should have been rejected')
}, function (errB) {
assert(errB === sentB)
})
})
.then(function () {
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
c.complete(sentC)
return resC
})
.then(function (resC) {
assert(resC === sentC)
})
.nodeify(done)
})
test('throat(3) lets three processes acquire the same lock', function (done) {
var lock = throat(3)
var a = job(), b = job(), c = job();
var resA = lock(a)
var resB = lock(b)
var resC = lock(c)
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
a.complete(sentA)
resA.then(function (resA) {
assert(resA === sentA)
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
b.fail(sentB)
return resB
.then(function () {
throw new Error('b should have been rejected')
}, function (errB) {
assert(errB === sentB)
})
})
.then(function () {
assert(a.isRun)
assert(b.isRun)
assert(c.isRun)
c.complete(sentC)
return resC
})
.then(function (resC) {
assert(resC === sentC)
})
.nodeify(done)
})
})
test('throat(n, fn)', function () {
test('throat(1, fn) acts as a sequential worker', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(1, worker(1))))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
test('throat(2, fn) works on two inputs in parallel', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(2, worker(2))))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
test('throat(3, fn) works on three inputs in parallel', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(3, worker(3))))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
})
test('throat(fn, n)', function () {
test('throat(fn, 1) acts as a sequential worker', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(worker(1), 1)))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
test('throat(fn, 2) works on two inputs in parallel', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(worker(2), 2)))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
test('throat(fn, 3) works on three inputs in parallel', function (done) {
Promise.all([sentA, sentB, sentC].map(throat(worker(3), 3)))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
})
test('with native promises', function (done) {
var throat = require('../')
throat.Promise = Promise
Promise.all([sentA, sentB, sentC].map(throat(1, worker(1))))
.then(function (res) {
assert(res[0] instanceof Processed && res[0].val.length > 1 && res[0].val[0] === sentA)
assert(res[1] instanceof Processed && res[1].val.length > 1 && res[1].val[0] === sentB)
assert(res[2] instanceof Processed && res[2].val.length > 1 && res[2].val[0] === sentC)
})
.nodeify(done)
})
test('without native promises', function () {
var throat = require('../')
throat.Promise = null
try {
throat(1)
} catch (ex) {
assert(/provide a Promise polyfill/.test(ex.message));
return;
}
throw new Error('Expected a failure');
})