Commit | Line | Data |
---|---|---|
a61a0724 | 1 | const { expect } = require('expect') |
df9aaf20 | 2 | const sinon = require('sinon') |
8620fb25 | 3 | const { ClusterWorker, KillBehaviors, ThreadWorker } = require('../../lib') |
df9aaf20 | 4 | const { EMPTY_FUNCTION } = require('../../lib/utils') |
7fc5cce6 | 5 | |
e1ffb94f | 6 | describe('Abstract worker test suite', () => { |
1f68cede | 7 | class StubWorkerWithMainWorker extends ThreadWorker { |
e1ffb94f JB |
8 | constructor (fn, opts) { |
9 | super(fn, opts) | |
78cea37e | 10 | this.mainWorker = undefined |
e1ffb94f | 11 | } |
7fc5cce6 | 12 | } |
c510fea7 | 13 | |
e088a00c | 14 | it('Verify worker options default values', () => { |
8620fb25 | 15 | const worker = new ThreadWorker(() => {}) |
978aad6f | 16 | expect(worker.opts.maxInactiveTime).toStrictEqual(60000) |
e088a00c | 17 | expect(worker.opts.killBehavior).toBe(KillBehaviors.SOFT) |
df9aaf20 | 18 | expect(worker.opts.killHandler).toStrictEqual(EMPTY_FUNCTION) |
571227f4 | 19 | expect(worker.opts.async).toBe(undefined) |
8620fb25 JB |
20 | }) |
21 | ||
22 | it('Verify that worker options are set at worker creation', () => { | |
df9aaf20 JB |
23 | const killHandler = () => { |
24 | console.info('Worker received kill message') | |
25 | } | |
8620fb25 JB |
26 | const worker = new ClusterWorker(() => {}, { |
27 | maxInactiveTime: 6000, | |
df9aaf20 JB |
28 | killBehavior: KillBehaviors.HARD, |
29 | killHandler, | |
30 | async: true | |
8620fb25 | 31 | }) |
978aad6f | 32 | expect(worker.opts.maxInactiveTime).toStrictEqual(6000) |
e088a00c | 33 | expect(worker.opts.killBehavior).toBe(KillBehaviors.HARD) |
df9aaf20 | 34 | expect(worker.opts.killHandler).toStrictEqual(killHandler) |
571227f4 | 35 | expect(worker.opts.async).toBe(undefined) |
8620fb25 JB |
36 | }) |
37 | ||
a86b6df1 JB |
38 | it('Verify that taskFunctions parameter is mandatory', () => { |
39 | expect(() => new ClusterWorker()).toThrowError( | |
40 | 'taskFunctions parameter is mandatory' | |
41 | ) | |
d4aeae5a JB |
42 | }) |
43 | ||
f34fdabe | 44 | it('Verify that taskFunctions parameter is a function or a plain object', () => { |
a86b6df1 | 45 | expect(() => new ClusterWorker(0)).toThrowError( |
f34fdabe JB |
46 | new TypeError( |
47 | 'taskFunctions parameter is not a function or a plain object' | |
48 | ) | |
d4aeae5a JB |
49 | ) |
50 | expect(() => new ClusterWorker('')).toThrowError( | |
f34fdabe JB |
51 | new TypeError( |
52 | 'taskFunctions parameter is not a function or a plain object' | |
53 | ) | |
a86b6df1 JB |
54 | ) |
55 | expect(() => new ClusterWorker(true)).toThrowError( | |
f34fdabe JB |
56 | new TypeError( |
57 | 'taskFunctions parameter is not a function or a plain object' | |
58 | ) | |
d4aeae5a | 59 | ) |
a86b6df1 | 60 | expect(() => new ClusterWorker([])).toThrowError( |
f34fdabe JB |
61 | new TypeError( |
62 | 'taskFunctions parameter is not a function or a plain object' | |
63 | ) | |
a86b6df1 JB |
64 | ) |
65 | expect(() => new ClusterWorker(new Map())).toThrowError( | |
f34fdabe JB |
66 | new TypeError( |
67 | 'taskFunctions parameter is not a function or a plain object' | |
68 | ) | |
a86b6df1 JB |
69 | ) |
70 | expect(() => new ClusterWorker(new Set())).toThrowError( | |
f34fdabe JB |
71 | new TypeError( |
72 | 'taskFunctions parameter is not a function or a plain object' | |
73 | ) | |
a86b6df1 JB |
74 | ) |
75 | expect(() => new ClusterWorker(new WeakMap())).toThrowError( | |
f34fdabe JB |
76 | new TypeError( |
77 | 'taskFunctions parameter is not a function or a plain object' | |
78 | ) | |
d4aeae5a | 79 | ) |
a86b6df1 | 80 | expect(() => new ClusterWorker(new WeakSet())).toThrowError( |
f34fdabe JB |
81 | new TypeError( |
82 | 'taskFunctions parameter is not a function or a plain object' | |
83 | ) | |
a86b6df1 | 84 | ) |
f34fdabe JB |
85 | }) |
86 | ||
87 | it('Verify that taskFunctions parameter is not an empty object', () => { | |
630f0acf | 88 | expect(() => new ClusterWorker({})).toThrowError( |
0d80593b | 89 | new Error('taskFunctions parameter object is empty') |
630f0acf | 90 | ) |
a86b6df1 JB |
91 | }) |
92 | ||
2a69b8c5 JB |
93 | it('Verify that taskFunctions parameter with unique function is taken', () => { |
94 | const worker = new ThreadWorker(() => {}) | |
95 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
96 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
97 | expect(worker.taskFunctions.size).toBe(2) | |
98 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
99 | worker.taskFunctions.get('fn1') | |
100 | ) | |
101 | }) | |
102 | ||
f34fdabe JB |
103 | it('Verify that taskFunctions parameter with multiple task functions contains function', () => { |
104 | const fn1 = () => { | |
105 | return 1 | |
106 | } | |
107 | const fn2 = '' | |
108 | expect(() => new ThreadWorker({ fn1, fn2 })).toThrowError( | |
109 | new TypeError('A taskFunctions parameter object value is not a function') | |
110 | ) | |
111 | }) | |
112 | ||
a86b6df1 JB |
113 | it('Verify that taskFunctions parameter with multiple task functions is taken', () => { |
114 | const fn1 = () => { | |
115 | return 1 | |
116 | } | |
117 | const fn2 = () => { | |
118 | return 2 | |
119 | } | |
120 | const worker = new ClusterWorker({ fn1, fn2 }) | |
2a69b8c5 JB |
121 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) |
122 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
123 | expect(worker.taskFunctions.get('fn2')).toBeInstanceOf(Function) | |
124 | expect(worker.taskFunctions.size).toBe(3) | |
125 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
126 | worker.taskFunctions.get('fn1') | |
127 | ) | |
d4aeae5a JB |
128 | }) |
129 | ||
df9aaf20 JB |
130 | it('Verify that sync kill handler is called when worker is killed', () => { |
131 | const worker = new ClusterWorker(() => {}, { | |
132 | killHandler: sinon.stub().returns() | |
133 | }) | |
134 | worker.isMain = false | |
1e3214b6 JB |
135 | worker.getMainWorker = sinon.stub().returns({ |
136 | id: 1, | |
137 | send: sinon.stub().returns() | |
138 | }) | |
df9aaf20 | 139 | worker.handleKillMessage() |
1e3214b6 | 140 | expect(worker.getMainWorker().send.calledOnce).toBe(true) |
df9aaf20 JB |
141 | expect(worker.opts.killHandler.calledOnce).toBe(true) |
142 | }) | |
143 | ||
07588f30 JB |
144 | it('Verify that async kill handler is called when worker is killed', () => { |
145 | const killHandlerStub = sinon.stub().returns() | |
146 | const worker = new ClusterWorker(() => {}, { | |
147 | killHandler: async () => Promise.resolve(killHandlerStub()) | |
148 | }) | |
149 | worker.isMain = false | |
150 | worker.handleKillMessage() | |
151 | expect(killHandlerStub.calledOnce).toBe(true) | |
152 | }) | |
df9aaf20 | 153 | |
2431bdb4 JB |
154 | it('Verify that handleError() method works properly', () => { |
155 | const error = new Error('Error as an error') | |
156 | const worker = new ClusterWorker(() => {}) | |
157 | expect(worker.handleError(error)).not.toBeInstanceOf(Error) | |
158 | expect(worker.handleError(error)).toStrictEqual(error.message) | |
159 | const errorMessage = 'Error as a string' | |
160 | expect(worker.handleError(errorMessage)).toStrictEqual(errorMessage) | |
7fc5cce6 APA |
161 | }) |
162 | ||
318d4156 | 163 | it('Verify that getMainWorker() throw error if main worker is not set', () => { |
7fc5cce6 | 164 | expect(() => |
1f68cede | 165 | new StubWorkerWithMainWorker(() => {}).getMainWorker() |
e102732c | 166 | ).toThrowError('Main worker not set') |
7fc5cce6 | 167 | }) |
2a69b8c5 JB |
168 | |
169 | it('Verify that hasTaskFunction() works', () => { | |
170 | const fn1 = () => { | |
171 | return 1 | |
172 | } | |
173 | const fn2 = () => { | |
174 | return 2 | |
175 | } | |
176 | const worker = new ClusterWorker({ fn1, fn2 }) | |
177 | expect(worker.hasTaskFunction('default')).toBe(true) | |
178 | expect(worker.hasTaskFunction('fn1')).toBe(true) | |
179 | expect(worker.hasTaskFunction('fn2')).toBe(true) | |
180 | expect(worker.hasTaskFunction('fn3')).toBe(false) | |
181 | }) | |
182 | ||
183 | it('Verify that addTaskFunction() works', () => { | |
184 | const fn1 = () => { | |
185 | return 1 | |
186 | } | |
187 | const fn2 = () => { | |
188 | return 2 | |
189 | } | |
190 | const fn1Replacement = () => { | |
191 | return 3 | |
192 | } | |
193 | const worker = new ThreadWorker(fn1) | |
194 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
195 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
196 | expect(worker.taskFunctions.size).toBe(2) | |
197 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
198 | worker.taskFunctions.get('fn1') | |
199 | ) | |
200 | expect(() => worker.addTaskFunction('default', fn2)).toThrowError( | |
201 | new Error('Cannot add a task function with the default reserved name') | |
202 | ) | |
203 | worker.addTaskFunction('fn2', fn2) | |
204 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
205 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
206 | expect(worker.taskFunctions.get('fn2')).toBeInstanceOf(Function) | |
207 | expect(worker.taskFunctions.size).toBe(3) | |
208 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
209 | worker.taskFunctions.get('fn1') | |
210 | ) | |
211 | worker.addTaskFunction('fn1', fn1Replacement) | |
212 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
213 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
214 | expect(worker.taskFunctions.get('fn2')).toBeInstanceOf(Function) | |
215 | expect(worker.taskFunctions.size).toBe(3) | |
216 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
217 | worker.taskFunctions.get('fn1') | |
218 | ) | |
219 | }) | |
220 | ||
221 | it('Verify that removeTaskFunction() works', () => { | |
222 | const fn1 = () => { | |
223 | return 1 | |
224 | } | |
225 | const fn2 = () => { | |
226 | return 2 | |
227 | } | |
135f2a9f | 228 | const worker = new ClusterWorker({ fn1, fn2 }) |
90d7d101 JB |
229 | worker.getMainWorker = sinon.stub().returns({ |
230 | id: 1, | |
231 | send: sinon.stub().returns() | |
232 | }) | |
2a69b8c5 JB |
233 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) |
234 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
235 | expect(worker.taskFunctions.get('fn2')).toBeInstanceOf(Function) | |
236 | expect(worker.taskFunctions.size).toBe(3) | |
237 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
238 | worker.taskFunctions.get('fn1') | |
239 | ) | |
240 | expect(() => worker.removeTaskFunction('default')).toThrowError( | |
241 | new Error( | |
242 | 'Cannot remove the task function with the default reserved name' | |
243 | ) | |
244 | ) | |
245 | expect(() => worker.removeTaskFunction('fn1')).toThrowError( | |
246 | new Error( | |
247 | 'Cannot remove the task function used as the default task function' | |
248 | ) | |
249 | ) | |
250 | worker.removeTaskFunction('fn2') | |
251 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
252 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
253 | expect(worker.taskFunctions.get('fn2')).toBeUndefined() | |
254 | expect(worker.taskFunctions.size).toBe(2) | |
90d7d101 | 255 | expect(worker.getMainWorker().send.calledOnce).toBe(true) |
2a69b8c5 JB |
256 | }) |
257 | ||
c50b93fb JB |
258 | it('Verify that listTaskFunctions() works', () => { |
259 | const fn1 = () => { | |
260 | return 1 | |
261 | } | |
262 | const fn2 = () => { | |
263 | return 2 | |
264 | } | |
265 | const worker = new ClusterWorker({ fn1, fn2 }) | |
266 | expect(worker.listTaskFunctions()).toStrictEqual(['default', 'fn1', 'fn2']) | |
267 | }) | |
268 | ||
2a69b8c5 JB |
269 | it('Verify that setDefaultTaskFunction() works', () => { |
270 | const fn1 = () => { | |
271 | return 1 | |
272 | } | |
273 | const fn2 = () => { | |
274 | return 2 | |
275 | } | |
276 | const worker = new ThreadWorker({ fn1, fn2 }) | |
277 | expect(worker.taskFunctions.get('default')).toBeInstanceOf(Function) | |
278 | expect(worker.taskFunctions.get('fn1')).toBeInstanceOf(Function) | |
279 | expect(worker.taskFunctions.get('fn2')).toBeInstanceOf(Function) | |
280 | expect(worker.taskFunctions.size).toBe(3) | |
281 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
282 | worker.taskFunctions.get('fn1') | |
283 | ) | |
284 | expect(() => worker.setDefaultTaskFunction('default')).toThrowError( | |
285 | new Error( | |
286 | 'Cannot set the default task function reserved name as the default task function' | |
287 | ) | |
288 | ) | |
289 | worker.setDefaultTaskFunction('fn1') | |
290 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
291 | worker.taskFunctions.get('fn1') | |
292 | ) | |
293 | worker.setDefaultTaskFunction('fn2') | |
294 | expect(worker.taskFunctions.get('default')).toStrictEqual( | |
295 | worker.taskFunctions.get('fn2') | |
296 | ) | |
297 | }) | |
c510fea7 | 298 | }) |