You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
4.8 KiB
221 lines
4.8 KiB
'use strict' |
|
|
|
const test = require('tape') |
|
const buildQueue = require('../').promise |
|
const { promisify } = require('util') |
|
const sleep = promisify(setTimeout) |
|
const immediate = promisify(setImmediate) |
|
|
|
test('concurrency', function (t) { |
|
t.plan(2) |
|
t.throws(buildQueue.bind(null, worker, 0)) |
|
t.doesNotThrow(buildQueue.bind(null, worker, 1)) |
|
|
|
async function worker (arg) { |
|
return true |
|
} |
|
}) |
|
|
|
test('worker execution', async function (t) { |
|
const queue = buildQueue(worker, 1) |
|
|
|
const result = await queue.push(42) |
|
|
|
t.equal(result, true, 'result matches') |
|
|
|
async function worker (arg) { |
|
t.equal(arg, 42) |
|
return true |
|
} |
|
}) |
|
|
|
test('limit', async function (t) { |
|
const queue = buildQueue(worker, 1) |
|
|
|
const [res1, res2] = await Promise.all([queue.push(10), queue.push(0)]) |
|
t.equal(res1, 10, 'the result matches') |
|
t.equal(res2, 0, 'the result matches') |
|
|
|
async function worker (arg) { |
|
await sleep(arg) |
|
return arg |
|
} |
|
}) |
|
|
|
test('multiple executions', async function (t) { |
|
const queue = buildQueue(worker, 1) |
|
const toExec = [1, 2, 3, 4, 5] |
|
const expected = ['a', 'b', 'c', 'd', 'e'] |
|
let count = 0 |
|
|
|
await Promise.all(toExec.map(async function (task, i) { |
|
const result = await queue.push(task) |
|
t.equal(result, expected[i], 'the result matches') |
|
})) |
|
|
|
async function worker (arg) { |
|
t.equal(arg, toExec[count], 'arg matches') |
|
return expected[count++] |
|
} |
|
}) |
|
|
|
test('drained', async function (t) { |
|
const queue = buildQueue(worker, 2) |
|
|
|
const toExec = new Array(10).fill(10) |
|
let count = 0 |
|
|
|
async function worker (arg) { |
|
await sleep(arg) |
|
count++ |
|
} |
|
|
|
toExec.forEach(function (i) { |
|
queue.push(i) |
|
}) |
|
|
|
await queue.drained() |
|
|
|
t.equal(count, toExec.length) |
|
|
|
toExec.forEach(function (i) { |
|
queue.push(i) |
|
}) |
|
|
|
await queue.drained() |
|
|
|
t.equal(count, toExec.length * 2) |
|
}) |
|
|
|
test('drained with exception should not throw', async function (t) { |
|
const queue = buildQueue(worker, 2) |
|
|
|
const toExec = new Array(10).fill(10) |
|
|
|
async function worker () { |
|
throw new Error('foo') |
|
} |
|
|
|
toExec.forEach(function (i) { |
|
queue.push(i) |
|
}) |
|
|
|
await queue.drained() |
|
}) |
|
|
|
test('drained with drain function', async function (t) { |
|
let drainCalled = false |
|
const queue = buildQueue(worker, 2) |
|
|
|
queue.drain = function () { |
|
drainCalled = true |
|
} |
|
|
|
const toExec = new Array(10).fill(10) |
|
let count = 0 |
|
|
|
async function worker (arg) { |
|
await sleep(arg) |
|
count++ |
|
} |
|
|
|
toExec.forEach(function () { |
|
queue.push() |
|
}) |
|
|
|
await queue.drained() |
|
|
|
t.equal(count, toExec.length) |
|
t.equal(drainCalled, true) |
|
}) |
|
|
|
test('set this', async function (t) { |
|
t.plan(1) |
|
const that = {} |
|
const queue = buildQueue(that, worker, 1) |
|
|
|
await queue.push(42) |
|
|
|
async function worker (arg) { |
|
t.equal(this, that, 'this matches') |
|
} |
|
}) |
|
|
|
test('unshift', async function (t) { |
|
const queue = buildQueue(worker, 1) |
|
const expected = [1, 2, 3, 4] |
|
|
|
await Promise.all([ |
|
queue.push(1), |
|
queue.push(4), |
|
queue.unshift(3), |
|
queue.unshift(2) |
|
]) |
|
|
|
t.is(expected.length, 0) |
|
|
|
async function worker (arg) { |
|
t.equal(expected.shift(), arg, 'tasks come in order') |
|
} |
|
}) |
|
|
|
test('push with worker throwing error', async function (t) { |
|
t.plan(5) |
|
const q = buildQueue(async function (task, cb) { |
|
throw new Error('test error') |
|
}, 1) |
|
q.error(function (err, task) { |
|
t.ok(err instanceof Error, 'global error handler should catch the error') |
|
t.match(err.message, /test error/, 'error message should be "test error"') |
|
t.equal(task, 42, 'The task executed should be passed') |
|
}) |
|
try { |
|
await q.push(42) |
|
} catch (err) { |
|
t.ok(err instanceof Error, 'push callback should catch the error') |
|
t.match(err.message, /test error/, 'error message should be "test error"') |
|
} |
|
}) |
|
|
|
test('unshift with worker throwing error', async function (t) { |
|
t.plan(2) |
|
const q = buildQueue(async function (task, cb) { |
|
throw new Error('test error') |
|
}, 1) |
|
try { |
|
await q.unshift(42) |
|
} catch (err) { |
|
t.ok(err instanceof Error, 'push callback should catch the error') |
|
t.match(err.message, /test error/, 'error message should be "test error"') |
|
} |
|
}) |
|
|
|
test('no unhandledRejection (push)', async function (t) { |
|
function handleRejection () { |
|
t.fail('unhandledRejection') |
|
} |
|
process.once('unhandledRejection', handleRejection) |
|
const q = buildQueue(async function (task, cb) { |
|
throw new Error('test error') |
|
}, 1) |
|
|
|
q.push(42) |
|
|
|
await immediate() |
|
process.removeListener('unhandledRejection', handleRejection) |
|
}) |
|
|
|
test('no unhandledRejection (unshift)', async function (t) { |
|
function handleRejection () { |
|
t.fail('unhandledRejection') |
|
} |
|
process.once('unhandledRejection', handleRejection) |
|
const q = buildQueue(async function (task, cb) { |
|
throw new Error('test error') |
|
}, 1) |
|
|
|
q.unshift(42) |
|
|
|
await immediate() |
|
process.removeListener('unhandledRejection', handleRejection) |
|
})
|
|
|