1 | 'use strict'
|
---|
2 |
|
---|
3 | const test = require('tape')
|
---|
4 | const buildQueue = require('../').promise
|
---|
5 | const { promisify } = require('util')
|
---|
6 | const sleep = promisify(setTimeout)
|
---|
7 | const immediate = promisify(setImmediate)
|
---|
8 |
|
---|
9 | test('concurrency', function (t) {
|
---|
10 | t.plan(2)
|
---|
11 | t.throws(buildQueue.bind(null, worker, 0))
|
---|
12 | t.doesNotThrow(buildQueue.bind(null, worker, 1))
|
---|
13 |
|
---|
14 | async function worker (arg) {
|
---|
15 | return true
|
---|
16 | }
|
---|
17 | })
|
---|
18 |
|
---|
19 | test('worker execution', async function (t) {
|
---|
20 | const queue = buildQueue(worker, 1)
|
---|
21 |
|
---|
22 | const result = await queue.push(42)
|
---|
23 |
|
---|
24 | t.equal(result, true, 'result matches')
|
---|
25 |
|
---|
26 | async function worker (arg) {
|
---|
27 | t.equal(arg, 42)
|
---|
28 | return true
|
---|
29 | }
|
---|
30 | })
|
---|
31 |
|
---|
32 | test('limit', async function (t) {
|
---|
33 | const queue = buildQueue(worker, 1)
|
---|
34 |
|
---|
35 | const [res1, res2] = await Promise.all([queue.push(10), queue.push(0)])
|
---|
36 | t.equal(res1, 10, 'the result matches')
|
---|
37 | t.equal(res2, 0, 'the result matches')
|
---|
38 |
|
---|
39 | async function worker (arg) {
|
---|
40 | await sleep(arg)
|
---|
41 | return arg
|
---|
42 | }
|
---|
43 | })
|
---|
44 |
|
---|
45 | test('multiple executions', async function (t) {
|
---|
46 | const queue = buildQueue(worker, 1)
|
---|
47 | const toExec = [1, 2, 3, 4, 5]
|
---|
48 | const expected = ['a', 'b', 'c', 'd', 'e']
|
---|
49 | let count = 0
|
---|
50 |
|
---|
51 | await Promise.all(toExec.map(async function (task, i) {
|
---|
52 | const result = await queue.push(task)
|
---|
53 | t.equal(result, expected[i], 'the result matches')
|
---|
54 | }))
|
---|
55 |
|
---|
56 | async function worker (arg) {
|
---|
57 | t.equal(arg, toExec[count], 'arg matches')
|
---|
58 | return expected[count++]
|
---|
59 | }
|
---|
60 | })
|
---|
61 |
|
---|
62 | test('drained', async function (t) {
|
---|
63 | const queue = buildQueue(worker, 2)
|
---|
64 |
|
---|
65 | const toExec = new Array(10).fill(10)
|
---|
66 | let count = 0
|
---|
67 |
|
---|
68 | async function worker (arg) {
|
---|
69 | await sleep(arg)
|
---|
70 | count++
|
---|
71 | }
|
---|
72 |
|
---|
73 | toExec.forEach(function (i) {
|
---|
74 | queue.push(i)
|
---|
75 | })
|
---|
76 |
|
---|
77 | await queue.drained()
|
---|
78 |
|
---|
79 | t.equal(count, toExec.length)
|
---|
80 |
|
---|
81 | toExec.forEach(function (i) {
|
---|
82 | queue.push(i)
|
---|
83 | })
|
---|
84 |
|
---|
85 | await queue.drained()
|
---|
86 |
|
---|
87 | t.equal(count, toExec.length * 2)
|
---|
88 | })
|
---|
89 |
|
---|
90 | test('drained with exception should not throw', async function (t) {
|
---|
91 | const queue = buildQueue(worker, 2)
|
---|
92 |
|
---|
93 | const toExec = new Array(10).fill(10)
|
---|
94 |
|
---|
95 | async function worker () {
|
---|
96 | throw new Error('foo')
|
---|
97 | }
|
---|
98 |
|
---|
99 | toExec.forEach(function (i) {
|
---|
100 | queue.push(i)
|
---|
101 | })
|
---|
102 |
|
---|
103 | await queue.drained()
|
---|
104 | })
|
---|
105 |
|
---|
106 | test('drained with drain function', async function (t) {
|
---|
107 | let drainCalled = false
|
---|
108 | const queue = buildQueue(worker, 2)
|
---|
109 |
|
---|
110 | queue.drain = function () {
|
---|
111 | drainCalled = true
|
---|
112 | }
|
---|
113 |
|
---|
114 | const toExec = new Array(10).fill(10)
|
---|
115 | let count = 0
|
---|
116 |
|
---|
117 | async function worker (arg) {
|
---|
118 | await sleep(arg)
|
---|
119 | count++
|
---|
120 | }
|
---|
121 |
|
---|
122 | toExec.forEach(function () {
|
---|
123 | queue.push()
|
---|
124 | })
|
---|
125 |
|
---|
126 | await queue.drained()
|
---|
127 |
|
---|
128 | t.equal(count, toExec.length)
|
---|
129 | t.equal(drainCalled, true)
|
---|
130 | })
|
---|
131 |
|
---|
132 | test('set this', async function (t) {
|
---|
133 | t.plan(1)
|
---|
134 | const that = {}
|
---|
135 | const queue = buildQueue(that, worker, 1)
|
---|
136 |
|
---|
137 | await queue.push(42)
|
---|
138 |
|
---|
139 | async function worker (arg) {
|
---|
140 | t.equal(this, that, 'this matches')
|
---|
141 | }
|
---|
142 | })
|
---|
143 |
|
---|
144 | test('unshift', async function (t) {
|
---|
145 | const queue = buildQueue(worker, 1)
|
---|
146 | const expected = [1, 2, 3, 4]
|
---|
147 |
|
---|
148 | await Promise.all([
|
---|
149 | queue.push(1),
|
---|
150 | queue.push(4),
|
---|
151 | queue.unshift(3),
|
---|
152 | queue.unshift(2)
|
---|
153 | ])
|
---|
154 |
|
---|
155 | t.is(expected.length, 0)
|
---|
156 |
|
---|
157 | async function worker (arg) {
|
---|
158 | t.equal(expected.shift(), arg, 'tasks come in order')
|
---|
159 | }
|
---|
160 | })
|
---|
161 |
|
---|
162 | test('push with worker throwing error', async function (t) {
|
---|
163 | t.plan(5)
|
---|
164 | const q = buildQueue(async function (task, cb) {
|
---|
165 | throw new Error('test error')
|
---|
166 | }, 1)
|
---|
167 | q.error(function (err, task) {
|
---|
168 | t.ok(err instanceof Error, 'global error handler should catch the error')
|
---|
169 | t.match(err.message, /test error/, 'error message should be "test error"')
|
---|
170 | t.equal(task, 42, 'The task executed should be passed')
|
---|
171 | })
|
---|
172 | try {
|
---|
173 | await q.push(42)
|
---|
174 | } catch (err) {
|
---|
175 | t.ok(err instanceof Error, 'push callback should catch the error')
|
---|
176 | t.match(err.message, /test error/, 'error message should be "test error"')
|
---|
177 | }
|
---|
178 | })
|
---|
179 |
|
---|
180 | test('unshift with worker throwing error', async function (t) {
|
---|
181 | t.plan(2)
|
---|
182 | const q = buildQueue(async function (task, cb) {
|
---|
183 | throw new Error('test error')
|
---|
184 | }, 1)
|
---|
185 | try {
|
---|
186 | await q.unshift(42)
|
---|
187 | } catch (err) {
|
---|
188 | t.ok(err instanceof Error, 'push callback should catch the error')
|
---|
189 | t.match(err.message, /test error/, 'error message should be "test error"')
|
---|
190 | }
|
---|
191 | })
|
---|
192 |
|
---|
193 | test('no unhandledRejection (push)', async function (t) {
|
---|
194 | function handleRejection () {
|
---|
195 | t.fail('unhandledRejection')
|
---|
196 | }
|
---|
197 | process.once('unhandledRejection', handleRejection)
|
---|
198 | const q = buildQueue(async function (task, cb) {
|
---|
199 | throw new Error('test error')
|
---|
200 | }, 1)
|
---|
201 |
|
---|
202 | q.push(42)
|
---|
203 |
|
---|
204 | await immediate()
|
---|
205 | process.removeListener('unhandledRejection', handleRejection)
|
---|
206 | })
|
---|
207 |
|
---|
208 | test('no unhandledRejection (unshift)', async function (t) {
|
---|
209 | function handleRejection () {
|
---|
210 | t.fail('unhandledRejection')
|
---|
211 | }
|
---|
212 | process.once('unhandledRejection', handleRejection)
|
---|
213 | const q = buildQueue(async function (task, cb) {
|
---|
214 | throw new Error('test error')
|
---|
215 | }, 1)
|
---|
216 |
|
---|
217 | q.unshift(42)
|
---|
218 |
|
---|
219 | await immediate()
|
---|
220 | process.removeListener('unhandledRejection', handleRejection)
|
---|
221 | })
|
---|