Tests: improve strategies initialization coverage
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
1 const { expect } = require('expect')
2 const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
5 FixedThreadPool
6 } = require('../../../lib/index')
7
8 describe('Selection strategies test suite', () => {
9 const min = 0
10 const max = 3
11
12 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
13 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
14 expect(WorkerChoiceStrategies.LESS_RECENTLY_USED).toBe('LESS_RECENTLY_USED')
15 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
16 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
17 'WEIGHTED_ROUND_ROBIN'
18 )
19 })
20
21 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
22 const pool = new DynamicThreadPool(
23 min,
24 max,
25 './tests/worker-files/thread/testWorker.js'
26 )
27 expect(pool.opts.workerChoiceStrategy).toBe(
28 WorkerChoiceStrategies.ROUND_ROBIN
29 )
30 // We need to clean up the resources after our test
31 await pool.destroy()
32 })
33
34 it('Verify ROUND_ROBIN strategy is taken at pool creation', async () => {
35 const pool = new FixedThreadPool(
36 max,
37 './tests/worker-files/thread/testWorker.js',
38 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
39 )
40 expect(pool.opts.workerChoiceStrategy).toBe(
41 WorkerChoiceStrategies.ROUND_ROBIN
42 )
43 expect(
44 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy().nextWorkerIndex
45 ).toBe(0)
46 // We need to clean up the resources after our test
47 await pool.destroy()
48 })
49
50 it('Verify ROUND_ROBIN strategy can be set after pool creation', async () => {
51 const pool = new DynamicThreadPool(
52 min,
53 max,
54 './tests/worker-files/thread/testWorker.js'
55 )
56 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
57 expect(pool.opts.workerChoiceStrategy).toBe(
58 WorkerChoiceStrategies.ROUND_ROBIN
59 )
60 // We need to clean up the resources after our test
61 await pool.destroy()
62 })
63
64 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
65 let pool = new FixedThreadPool(
66 max,
67 './tests/worker-files/thread/testWorker.js'
68 )
69 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
70 expect(
71 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
72 .requiredStatistics.runTime
73 ).toBe(false)
74 await pool.destroy()
75 pool = new DynamicThreadPool(
76 min,
77 max,
78 './tests/worker-files/thread/testWorker.js'
79 )
80 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
81 expect(
82 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
83 .requiredStatistics.runTime
84 ).toBe(false)
85 // We need to clean up the resources after our test
86 await pool.destroy()
87 })
88
89 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
90 const pool = new FixedThreadPool(
91 max,
92 './tests/worker-files/thread/testWorker.js',
93 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
94 )
95 expect(pool.opts.workerChoiceStrategy).toBe(
96 WorkerChoiceStrategies.ROUND_ROBIN
97 )
98 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
99 const promises = []
100 for (let i = 0; i < max * 2; i++) {
101 promises.push(pool.execute())
102 }
103 await Promise.all(promises)
104 // We need to clean up the resources after our test
105 await pool.destroy()
106 })
107
108 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
109 const pool = new DynamicThreadPool(
110 min,
111 max,
112 './tests/worker-files/thread/testWorker.js',
113 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
114 )
115 expect(pool.opts.workerChoiceStrategy).toBe(
116 WorkerChoiceStrategies.ROUND_ROBIN
117 )
118 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
119 const promises = []
120 for (let i = 0; i < max * 2; i++) {
121 promises.push(pool.execute())
122 }
123 await Promise.all(promises)
124 // We need to clean up the resources after our test
125 await pool.destroy()
126 })
127
128 it('Verify LESS_RECENTLY_USED strategy is taken at pool creation', async () => {
129 const pool = new FixedThreadPool(
130 max,
131 './tests/worker-files/thread/testWorker.js',
132 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
133 )
134 expect(pool.opts.workerChoiceStrategy).toBe(
135 WorkerChoiceStrategies.LESS_RECENTLY_USED
136 )
137 // We need to clean up the resources after our test
138 await pool.destroy()
139 })
140
141 it('Verify LESS_RECENTLY_USED strategy can be set after pool creation', async () => {
142 const pool = new FixedThreadPool(
143 max,
144 './tests/worker-files/thread/testWorker.js'
145 )
146 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
147 expect(pool.opts.workerChoiceStrategy).toBe(
148 WorkerChoiceStrategies.LESS_RECENTLY_USED
149 )
150 // We need to clean up the resources after our test
151 await pool.destroy()
152 })
153
154 it('Verify LESS_RECENTLY_USED strategy default tasks usage statistics requirements', async () => {
155 let pool = new FixedThreadPool(
156 max,
157 './tests/worker-files/thread/testWorker.js'
158 )
159 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
160 expect(
161 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
162 .requiredStatistics.runTime
163 ).toBe(false)
164 await pool.destroy()
165 pool = new DynamicThreadPool(
166 min,
167 max,
168 './tests/worker-files/thread/testWorker.js'
169 )
170 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
171 expect(
172 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
173 .requiredStatistics.runTime
174 ).toBe(false)
175 // We need to clean up the resources after our test
176 await pool.destroy()
177 })
178
179 it('Verify LESS_RECENTLY_USED strategy can be run in a fixed pool', async () => {
180 const pool = new FixedThreadPool(
181 max,
182 './tests/worker-files/thread/testWorker.js',
183 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
184 )
185 // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose`
186 const promises = []
187 for (let i = 0; i < max * 2; i++) {
188 promises.push(pool.execute())
189 }
190 await Promise.all(promises)
191 // We need to clean up the resources after our test
192 await pool.destroy()
193 })
194
195 it('Verify LESS_RECENTLY_USED strategy can be run in a dynamic pool', async () => {
196 const pool = new DynamicThreadPool(
197 min,
198 max,
199 './tests/worker-files/thread/testWorker.js',
200 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
201 )
202 // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose`
203 const promises = []
204 for (let i = 0; i < max * 2; i++) {
205 promises.push(pool.execute())
206 }
207 await Promise.all(promises)
208 // We need to clean up the resources after our test
209 await pool.destroy()
210 })
211
212 it('Verify FAIR_SHARE strategy is taken at pool creation', async () => {
213 const pool = new FixedThreadPool(
214 max,
215 './tests/worker-files/thread/testWorker.js',
216 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
217 )
218 expect(pool.opts.workerChoiceStrategy).toBe(
219 WorkerChoiceStrategies.FAIR_SHARE
220 )
221 for (const worker of pool.workerChoiceStrategyContext
222 .getWorkerChoiceStrategy()
223 .workerLastVirtualTaskTimestamp.keys()) {
224 expect(
225 pool.workerChoiceStrategyContext
226 .getWorkerChoiceStrategy()
227 .workerLastVirtualTaskTimestamp.get(worker).start
228 ).toBe(0)
229 expect(
230 pool.workerChoiceStrategyContext
231 .getWorkerChoiceStrategy()
232 .workerLastVirtualTaskTimestamp.get(worker).end
233 ).toBe(0)
234 }
235 // We need to clean up the resources after our test
236 await pool.destroy()
237 })
238
239 it('Verify FAIR_SHARE strategy can be set after pool creation', async () => {
240 const pool = new FixedThreadPool(
241 max,
242 './tests/worker-files/thread/testWorker.js'
243 )
244 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
245 expect(pool.opts.workerChoiceStrategy).toBe(
246 WorkerChoiceStrategies.FAIR_SHARE
247 )
248 // We need to clean up the resources after our test
249 await pool.destroy()
250 })
251
252 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
253 let pool = new FixedThreadPool(
254 max,
255 './tests/worker-files/thread/testWorker.js'
256 )
257 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
258 expect(
259 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
260 .requiredStatistics.runTime
261 ).toBe(true)
262 await pool.destroy()
263 pool = new DynamicThreadPool(
264 min,
265 max,
266 './tests/worker-files/thread/testWorker.js'
267 )
268 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
269 expect(
270 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
271 .requiredStatistics.runTime
272 ).toBe(true)
273 // We need to clean up the resources after our test
274 await pool.destroy()
275 })
276
277 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
278 const pool = new FixedThreadPool(
279 max,
280 './tests/worker-files/thread/testWorker.js',
281 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
282 )
283 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
284 const promises = []
285 for (let i = 0; i < max * 2; i++) {
286 promises.push(pool.execute())
287 }
288 await Promise.all(promises)
289 // We need to clean up the resources after our test
290 await pool.destroy()
291 })
292
293 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
294 const pool = new DynamicThreadPool(
295 min,
296 max,
297 './tests/worker-files/thread/testWorker.js',
298 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
299 )
300 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
301 const promises = []
302 for (let i = 0; i < max * 2; i++) {
303 promises.push(pool.execute())
304 }
305 await Promise.all(promises)
306 // We need to clean up the resources after our test
307 await pool.destroy()
308 })
309
310 it('Verify FAIR_SHARE strategy statistics are resets after setting it', async () => {
311 let pool = new FixedThreadPool(
312 max,
313 './tests/worker-files/thread/testWorker.js'
314 )
315 expect(
316 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
317 .workerLastVirtualTaskTimestamp
318 ).toBeUndefined()
319 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
320 for (const worker of pool.workerChoiceStrategyContext
321 .getWorkerChoiceStrategy()
322 .workerLastVirtualTaskTimestamp.keys()) {
323 expect(
324 pool.workerChoiceStrategyContext
325 .getWorkerChoiceStrategy()
326 .workerLastVirtualTaskTimestamp.get(worker).start
327 ).toBe(0)
328 expect(
329 pool.workerChoiceStrategyContext
330 .getWorkerChoiceStrategy()
331 .workerLastVirtualTaskTimestamp.get(worker).end
332 ).toBe(0)
333 }
334 await pool.destroy()
335 pool = new DynamicThreadPool(
336 min,
337 max,
338 './tests/worker-files/thread/testWorker.js'
339 )
340 expect(
341 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
342 .workerChoiceStrategy.workerLastVirtualTaskTimestamp
343 ).toBeUndefined()
344 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
345 for (const worker of pool.workerChoiceStrategyContext
346 .getWorkerChoiceStrategy()
347 .workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
348 expect(
349 pool.workerChoiceStrategyContext
350 .getWorkerChoiceStrategy()
351 .workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(worker).start
352 ).toBe(0)
353 expect(
354 pool.workerChoiceStrategyContext
355 .getWorkerChoiceStrategy()
356 .workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(worker).end
357 ).toBe(0)
358 }
359 // We need to clean up the resources after our test
360 await pool.destroy()
361 })
362
363 it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => {
364 const pool = new FixedThreadPool(
365 max,
366 './tests/worker-files/thread/testWorker.js',
367 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
368 )
369 expect(pool.opts.workerChoiceStrategy).toBe(
370 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
371 )
372 expect(
373 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
374 .previousWorkerIndex
375 ).toBe(0)
376 expect(
377 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
378 .currentWorkerIndex
379 ).toBe(0)
380 expect(
381 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
382 .defaultWorkerWeight
383 ).toBeGreaterThan(0)
384 for (const worker of pool.workerChoiceStrategyContext
385 .getWorkerChoiceStrategy()
386 .workersTaskRunTime.keys()) {
387 expect(
388 pool.workerChoiceStrategyContext
389 .getWorkerChoiceStrategy()
390 .workersTaskRunTime.get(worker).weight
391 ).toBeGreaterThan(0)
392 expect(
393 pool.workerChoiceStrategyContext
394 .getWorkerChoiceStrategy()
395 .workersTaskRunTime.get(worker).runTime
396 ).toBe(0)
397 }
398 // We need to clean up the resources after our test
399 await pool.destroy()
400 })
401
402 it('Verify WEIGHTED_ROUND_ROBIN strategy can be set after pool creation', async () => {
403 const pool = new FixedThreadPool(
404 max,
405 './tests/worker-files/thread/testWorker.js'
406 )
407 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
408 expect(pool.opts.workerChoiceStrategy).toBe(
409 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
410 )
411 // We need to clean up the resources after our test
412 await pool.destroy()
413 })
414
415 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
416 let pool = new FixedThreadPool(
417 max,
418 './tests/worker-files/thread/testWorker.js'
419 )
420 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
421 expect(
422 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
423 .requiredStatistics.runTime
424 ).toBe(true)
425 await pool.destroy()
426 pool = new DynamicThreadPool(
427 min,
428 max,
429 './tests/worker-files/thread/testWorker.js'
430 )
431 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
432 expect(
433 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
434 .requiredStatistics.runTime
435 ).toBe(true)
436 // We need to clean up the resources after our test
437 await pool.destroy()
438 })
439
440 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
441 const pool = new FixedThreadPool(
442 max,
443 './tests/worker-files/thread/testWorker.js',
444 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
445 )
446 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
447 const promises = []
448 for (let i = 0; i < max * 2; i++) {
449 promises.push(pool.execute())
450 }
451 await Promise.all(promises)
452 // We need to clean up the resources after our test
453 await pool.destroy()
454 })
455
456 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
457 const pool = new DynamicThreadPool(
458 min,
459 max,
460 './tests/worker-files/thread/testWorker.js',
461 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
462 )
463 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
464 const promises = []
465 for (let i = 0; i < max * 2; i++) {
466 promises.push(pool.execute())
467 }
468 await Promise.all(promises)
469 // We need to clean up the resources after our test
470 await pool.destroy()
471 })
472
473 it('Verify WEIGHTED_ROUND_ROBIN strategy statistics are resets after setting it', async () => {
474 let pool = new FixedThreadPool(
475 max,
476 './tests/worker-files/thread/testWorker.js'
477 )
478 expect(
479 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
480 .workersTaskRunTime
481 ).toBeUndefined()
482 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
483 for (const worker of pool.workerChoiceStrategyContext
484 .getWorkerChoiceStrategy()
485 .workersTaskRunTime.keys()) {
486 expect(
487 pool.workerChoiceStrategyContext
488 .getWorkerChoiceStrategy()
489 .workersTaskRunTime.get(worker).runTime
490 ).toBe(0)
491 }
492 await pool.destroy()
493 pool = new DynamicThreadPool(
494 min,
495 max,
496 './tests/worker-files/thread/testWorker.js'
497 )
498 expect(
499 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
500 .workerChoiceStrategy.workersTaskRunTime
501 ).toBeUndefined()
502 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
503 for (const worker of pool.workerChoiceStrategyContext
504 .getWorkerChoiceStrategy()
505 .workerChoiceStrategy.workersTaskRunTime.keys()) {
506 expect(
507 pool.workerChoiceStrategyContext
508 .getWorkerChoiceStrategy()
509 .workerChoiceStrategy.workersTaskRunTime.get(worker).runTime
510 ).toBe(0)
511 }
512 // We need to clean up the resources after our test
513 await pool.destroy()
514 })
515
516 it('Verify unknown strategies throw error', () => {
517 expect(
518 () =>
519 new DynamicThreadPool(
520 min,
521 max,
522 './tests/worker-files/thread/testWorker.js',
523 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
524 )
525 ).toThrowError(
526 new Error("Worker choice strategy 'UNKNOWN_STRATEGY' not found")
527 )
528 })
529 })