refactor: factor out inputs type check
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
a35560ba
S
2const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
2ced693a
JB
5 FixedThreadPool,
6 FixedClusterPool
cdace0e5 7} = require('../../../lib')
a35560ba
S
8
9describe('Selection strategies test suite', () => {
e1ffb94f
JB
10 const min = 0
11 const max = 3
12
a35560ba
S
13 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
14 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
737c6d97 15 expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED')
168c526f 16 expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY')
23ff945a 17 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
18 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
19 'WEIGHTED_ROUND_ROBIN'
20 )
a35560ba
S
21 })
22
e843b904 23 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
24 const pool = new DynamicThreadPool(
25 min,
26 max,
27 './tests/worker-files/thread/testWorker.js'
28 )
29 expect(pool.opts.workerChoiceStrategy).toBe(
30 WorkerChoiceStrategies.ROUND_ROBIN
31 )
32 // We need to clean up the resources after our test
33 await pool.destroy()
34 })
35
594bfb84
JB
36 it('Verify available strategies are taken at pool creation', async () => {
37 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
38 const pool = new FixedThreadPool(
39 max,
40 './tests/worker-files/thread/testWorker.js',
41 { workerChoiceStrategy }
42 )
43 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
44 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
45 workerChoiceStrategy
46 )
47 await pool.destroy()
48 }
d2f7b7a2
JB
49 })
50
594bfb84
JB
51 it('Verify available strategies can be set after pool creation', async () => {
52 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
53 const pool = new DynamicThreadPool(
54 min,
55 max,
ec82cfa1 56 './tests/worker-files/thread/testWorker.js'
594bfb84
JB
57 )
58 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
59 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
60 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
61 workerChoiceStrategy
62 )
63 await pool.destroy()
64 }
65 })
66
67 it('Verify available strategies default internals at pool creation', async () => {
68 const pool = new FixedThreadPool(
e843b904
JB
69 max,
70 './tests/worker-files/thread/testWorker.js'
71 )
594bfb84
JB
72 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
73 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
74 expect(
75 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
76 workerChoiceStrategy
77 ).nextWorkerNodeId
78 ).toBe(0)
79 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
08f3f44c
JB
80 expect(
81 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
82 workerChoiceStrategy
83 ).workersVirtualTaskTimestamp
84 ).toBeInstanceOf(Array)
85 expect(
86 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
87 workerChoiceStrategy
88 ).workersVirtualTaskTimestamp.length
89 ).toBe(0)
594bfb84
JB
90 } else if (
91 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
92 ) {
93 expect(
94 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
95 workerChoiceStrategy
96 ).currentWorkerNodeId
97 ).toBe(0)
98 expect(
99 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
100 workerChoiceStrategy
101 ).defaultWorkerWeight
102 ).toBeGreaterThan(0)
08f3f44c
JB
103 expect(
104 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
105 workerChoiceStrategy
106 ).workerVirtualTaskRunTime
107 ).toBe(0)
594bfb84
JB
108 }
109 }
e843b904
JB
110 await pool.destroy()
111 })
112
10fcfaf4 113 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 114 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
115 let pool = new FixedThreadPool(
116 max,
d710242d 117 './tests/worker-files/thread/testWorker.js',
594bfb84 118 { workerChoiceStrategy }
10fcfaf4 119 )
10fcfaf4 120 expect(
97a2abc3 121 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 122 ).toBe(false)
c6bd2650
JB
123 expect(
124 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
125 ).toBe(false)
78099a15
JB
126 expect(
127 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
128 ).toBe(false)
fd7ebd49 129 await pool.destroy()
10fcfaf4
JB
130 pool = new DynamicThreadPool(
131 min,
132 max,
d710242d 133 './tests/worker-files/thread/testWorker.js',
594bfb84 134 { workerChoiceStrategy }
10fcfaf4 135 )
10fcfaf4 136 expect(
97a2abc3 137 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 138 ).toBe(false)
c6bd2650
JB
139 expect(
140 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
141 ).toBe(false)
78099a15
JB
142 expect(
143 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
144 ).toBe(false)
10fcfaf4
JB
145 // We need to clean up the resources after our test
146 await pool.destroy()
147 })
148
bdaf31cd 149 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
bdaf31cd
JB
150 const pool = new FixedThreadPool(
151 max,
152 './tests/worker-files/thread/testWorker.js',
153 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
154 )
bdaf31cd
JB
155 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
156 const promises = []
a20f0ba5
JB
157 const maxMultiplier = 2
158 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 159 promises.push(pool.execute())
bdaf31cd
JB
160 }
161 await Promise.all(promises)
162 // We need to clean up the resources after our test
163 await pool.destroy()
164 })
165
166 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
bdaf31cd
JB
167 const pool = new DynamicThreadPool(
168 min,
169 max,
170 './tests/worker-files/thread/testWorker.js',
171 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
172 )
bdaf31cd
JB
173 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
174 const promises = []
a20f0ba5
JB
175 const maxMultiplier = 2
176 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 177 promises.push(pool.execute())
bdaf31cd
JB
178 }
179 await Promise.all(promises)
180 // We need to clean up the resources after our test
181 await pool.destroy()
182 })
183
2ced693a 184 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 185 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
186 let pool = new FixedClusterPool(
187 max,
594bfb84
JB
188 './tests/worker-files/cluster/testWorker.js',
189 { workerChoiceStrategy }
2ced693a
JB
190 )
191 let results = new Set()
192 for (let i = 0; i < max; i++) {
adc3c320 193 results.add(pool.chooseWorkerNode()[1].worker.id)
2ced693a
JB
194 }
195 expect(results.size).toBe(max)
196 await pool.destroy()
594bfb84
JB
197 pool = new FixedThreadPool(
198 max,
199 './tests/worker-files/thread/testWorker.js',
200 { workerChoiceStrategy }
201 )
2ced693a
JB
202 results = new Set()
203 for (let i = 0; i < max; i++) {
adc3c320 204 results.add(pool.chooseWorkerNode()[1].worker.threadId)
2ced693a
JB
205 }
206 expect(results.size).toBe(max)
207 await pool.destroy()
208 })
209
a6f7f1b4 210 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 211 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
212 let pool = new FixedThreadPool(
213 max,
214 './tests/worker-files/thread/testWorker.js',
215 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
216 )
38f6e859 217 expect(
95c83464 218 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 219 workerChoiceStrategy
f06e48d8 220 ).nextWorkerNodeId
b529c323 221 ).toBeDefined()
594bfb84 222 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 223 expect(
95c83464 224 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 225 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 226 ).nextWorkerNodeId
a6f7f1b4
JB
227 ).toBe(0)
228 await pool.destroy()
229 pool = new DynamicThreadPool(
230 min,
231 max,
232 './tests/worker-files/thread/testWorker.js',
233 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
234 )
38f6e859 235 expect(
95c83464 236 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 237 workerChoiceStrategy
f06e48d8 238 ).nextWorkerNodeId
b529c323 239 ).toBeDefined()
594bfb84 240 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 241 expect(
95c83464 242 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 243 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 244 ).nextWorkerNodeId
a6f7f1b4
JB
245 ).toBe(0)
246 // We need to clean up the resources after our test
247 await pool.destroy()
248 })
249
737c6d97 250 it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => {
594bfb84 251 const workerChoiceStrategy = WorkerChoiceStrategies.LESS_USED
10fcfaf4
JB
252 let pool = new FixedThreadPool(
253 max,
d710242d 254 './tests/worker-files/thread/testWorker.js',
594bfb84 255 { workerChoiceStrategy }
10fcfaf4 256 )
10fcfaf4 257 expect(
97a2abc3 258 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 259 ).toBe(false)
c6bd2650
JB
260 expect(
261 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
262 ).toBe(false)
78099a15
JB
263 expect(
264 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
265 ).toBe(false)
fd7ebd49 266 await pool.destroy()
10fcfaf4
JB
267 pool = new DynamicThreadPool(
268 min,
269 max,
d710242d 270 './tests/worker-files/thread/testWorker.js',
594bfb84 271 { workerChoiceStrategy }
10fcfaf4 272 )
10fcfaf4 273 expect(
97a2abc3 274 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 275 ).toBe(false)
c6bd2650
JB
276 expect(
277 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
278 ).toBe(false)
78099a15
JB
279 expect(
280 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
281 ).toBe(false)
10fcfaf4
JB
282 // We need to clean up the resources after our test
283 await pool.destroy()
284 })
285
737c6d97 286 it('Verify LESS_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
287 const pool = new FixedThreadPool(
288 max,
289 './tests/worker-files/thread/testWorker.js',
737c6d97 290 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
b98ec2e6 291 )
168c526f 292 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
a35560ba 293 const promises = []
a20f0ba5
JB
294 const maxMultiplier = 2
295 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 296 promises.push(pool.execute())
a35560ba
S
297 }
298 await Promise.all(promises)
a35560ba
S
299 // We need to clean up the resources after our test
300 await pool.destroy()
301 })
302
737c6d97 303 it('Verify LESS_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
304 const pool = new DynamicThreadPool(
305 min,
306 max,
307 './tests/worker-files/thread/testWorker.js',
737c6d97 308 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
ff5e76e1 309 )
168c526f
JB
310 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
311 const promises = []
a20f0ba5
JB
312 const maxMultiplier = 2
313 for (let i = 0; i < max * maxMultiplier; i++) {
168c526f
JB
314 promises.push(pool.execute())
315 }
316 await Promise.all(promises)
317 // We need to clean up the resources after our test
318 await pool.destroy()
319 })
320
168c526f 321 it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => {
594bfb84 322 const workerChoiceStrategy = WorkerChoiceStrategies.LESS_BUSY
168c526f
JB
323 let pool = new FixedThreadPool(
324 max,
d710242d 325 './tests/worker-files/thread/testWorker.js',
594bfb84 326 { workerChoiceStrategy }
168c526f 327 )
168c526f 328 expect(
97a2abc3 329 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
168c526f 330 ).toBe(true)
c6bd2650
JB
331 expect(
332 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
333 ).toBe(false)
78099a15
JB
334 expect(
335 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
336 ).toBe(false)
168c526f
JB
337 await pool.destroy()
338 pool = new DynamicThreadPool(
339 min,
340 max,
d710242d 341 './tests/worker-files/thread/testWorker.js',
594bfb84 342 { workerChoiceStrategy }
168c526f 343 )
168c526f 344 expect(
97a2abc3 345 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
168c526f 346 ).toBe(true)
c6bd2650
JB
347 expect(
348 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
349 ).toBe(false)
78099a15
JB
350 expect(
351 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
352 ).toBe(false)
168c526f
JB
353 // We need to clean up the resources after our test
354 await pool.destroy()
355 })
356
357 it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => {
358 const pool = new FixedThreadPool(
359 max,
360 './tests/worker-files/thread/testWorker.js',
361 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
362 )
363 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
364 const promises = []
a20f0ba5
JB
365 const maxMultiplier = 2
366 for (let i = 0; i < max * maxMultiplier; i++) {
168c526f
JB
367 promises.push(pool.execute())
368 }
369 await Promise.all(promises)
370 // We need to clean up the resources after our test
371 await pool.destroy()
372 })
373
374 it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => {
375 const pool = new DynamicThreadPool(
376 min,
377 max,
378 './tests/worker-files/thread/testWorker.js',
379 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
380 )
381 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
ff5e76e1 382 const promises = []
a20f0ba5
JB
383 const maxMultiplier = 2
384 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 385 promises.push(pool.execute())
ff5e76e1
JB
386 }
387 await Promise.all(promises)
ff5e76e1
JB
388 // We need to clean up the resources after our test
389 await pool.destroy()
390 })
391
10fcfaf4 392 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
594bfb84 393 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
394 let pool = new FixedThreadPool(
395 max,
d710242d 396 './tests/worker-files/thread/testWorker.js',
594bfb84 397 { workerChoiceStrategy }
10fcfaf4 398 )
10fcfaf4 399 expect(
97a2abc3 400 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 401 ).toBe(true)
c6bd2650
JB
402 expect(
403 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
404 ).toBe(true)
78099a15
JB
405 expect(
406 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
407 ).toBe(false)
fd7ebd49 408 await pool.destroy()
10fcfaf4
JB
409 pool = new DynamicThreadPool(
410 min,
411 max,
d710242d 412 './tests/worker-files/thread/testWorker.js',
594bfb84 413 { workerChoiceStrategy }
10fcfaf4 414 )
10fcfaf4 415 expect(
97a2abc3 416 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 417 ).toBe(true)
c6bd2650
JB
418 expect(
419 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
420 ).toBe(true)
78099a15
JB
421 expect(
422 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
423 ).toBe(false)
10fcfaf4
JB
424 // We need to clean up the resources after our test
425 await pool.destroy()
426 })
427
23ff945a 428 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
429 const pool = new FixedThreadPool(
430 max,
431 './tests/worker-files/thread/testWorker.js',
432 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
433 )
434 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
435 const promises = []
a20f0ba5
JB
436 const maxMultiplier = 2
437 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 438 promises.push(pool.execute())
23ff945a
JB
439 }
440 await Promise.all(promises)
97a2abc3 441 expect(
95c83464 442 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 443 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c 444 ).workersVirtualTaskTimestamp.length
f06e48d8 445 ).toBe(pool.workerNodes.length)
23ff945a
JB
446 // We need to clean up the resources after our test
447 await pool.destroy()
448 })
449
450 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
451 const pool = new DynamicThreadPool(
452 min,
453 max,
454 './tests/worker-files/thread/testWorker.js',
455 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
456 )
457 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
458 const promises = []
f7070eee 459 const maxMultiplier = 2
804a889e 460 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 461 promises.push(pool.execute())
23ff945a
JB
462 }
463 await Promise.all(promises)
2b4fddb8
JB
464 expect(
465 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
466 pool.workerChoiceStrategyContext.workerChoiceStrategy
467 ).workersVirtualTaskTimestamp.length
468 ).toBe(pool.workerNodes.length)
23ff945a
JB
469 // We need to clean up the resources after our test
470 await pool.destroy()
471 })
472
010d7020
JB
473 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median run time statistic', async () => {
474 const pool = new DynamicThreadPool(
475 min,
476 max,
477 './tests/worker-files/thread/testWorker.js',
478 {
479 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
480 workerChoiceStrategyOptions: {
481 medRunTime: true
482 }
483 }
484 )
485 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
486 const promises = []
487 const maxMultiplier = 2
488 for (let i = 0; i < max * maxMultiplier; i++) {
489 promises.push(pool.execute())
490 }
491 await Promise.all(promises)
492 for (const workerNode of pool.workerNodes) {
493 expect(workerNode.tasksUsage.avgRunTime).toBeDefined()
494 expect(workerNode.tasksUsage.avgRunTime).toBe(0)
495 expect(workerNode.tasksUsage.medRunTime).toBeDefined()
496 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
497 }
2b4fddb8
JB
498 expect(
499 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
500 pool.workerChoiceStrategyContext.workerChoiceStrategy
501 ).workersVirtualTaskTimestamp.length
502 ).toBe(pool.workerNodes.length)
010d7020
JB
503 // We need to clean up the resources after our test
504 await pool.destroy()
505 })
506
a6f7f1b4 507 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 508 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 509 let pool = new FixedThreadPool(
caeb9817
JB
510 max,
511 './tests/worker-files/thread/testWorker.js'
512 )
513 expect(
95c83464 514 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 515 workerChoiceStrategy
08f3f44c
JB
516 ).workersVirtualTaskTimestamp
517 ).toBeInstanceOf(Array)
518 expect(
519 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
520 workerChoiceStrategy
521 ).workersVirtualTaskTimestamp.length
522 ).toBe(0)
2b4fddb8
JB
523 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
524 workerChoiceStrategy
525 ).workersVirtualTaskTimestamp[0] = 0
526 expect(
527 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
528 workerChoiceStrategy
529 ).workersVirtualTaskTimestamp.length
530 ).toBe(1)
594bfb84 531 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
532 expect(
533 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
534 workerChoiceStrategy
535 ).workersVirtualTaskTimestamp
536 ).toBeInstanceOf(Array)
08f3f44c
JB
537 expect(
538 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
539 workerChoiceStrategy
540 ).workersVirtualTaskTimestamp.length
2b4fddb8 541 ).toBe(0)
f0829c53
JB
542 await pool.destroy()
543 pool = new DynamicThreadPool(
544 min,
545 max,
546 './tests/worker-files/thread/testWorker.js'
547 )
548 expect(
95c83464 549 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 550 workerChoiceStrategy
08f3f44c
JB
551 ).workersVirtualTaskTimestamp
552 ).toBeInstanceOf(Array)
2b4fddb8
JB
553 expect(
554 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
555 workerChoiceStrategy
556 ).workersVirtualTaskTimestamp.length
557 ).toBe(0)
08f3f44c
JB
558 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
559 workerChoiceStrategy
560 ).workersVirtualTaskTimestamp[0] = 0
561 expect(
562 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
563 workerChoiceStrategy
564 ).workersVirtualTaskTimestamp.length
565 ).toBe(1)
594bfb84 566 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
567 expect(
568 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
569 workerChoiceStrategy
570 ).workersVirtualTaskTimestamp
571 ).toBeInstanceOf(Array)
572 expect(
573 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
574 workerChoiceStrategy
575 ).workersVirtualTaskTimestamp.length
576 ).toBe(0)
caeb9817
JB
577 // We need to clean up the resources after our test
578 await pool.destroy()
579 })
580
10fcfaf4 581 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 582 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
583 let pool = new FixedThreadPool(
584 max,
d710242d 585 './tests/worker-files/thread/testWorker.js',
594bfb84 586 { workerChoiceStrategy }
10fcfaf4 587 )
10fcfaf4 588 expect(
97a2abc3 589 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 590 ).toBe(true)
c6bd2650
JB
591 expect(
592 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
593 ).toBe(true)
78099a15
JB
594 expect(
595 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
596 ).toBe(false)
fd7ebd49 597 await pool.destroy()
10fcfaf4
JB
598 pool = new DynamicThreadPool(
599 min,
600 max,
d710242d 601 './tests/worker-files/thread/testWorker.js',
594bfb84 602 { workerChoiceStrategy }
10fcfaf4 603 )
10fcfaf4 604 expect(
97a2abc3 605 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
10fcfaf4 606 ).toBe(true)
c6bd2650
JB
607 expect(
608 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
609 ).toBe(true)
78099a15
JB
610 expect(
611 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
612 ).toBe(false)
10fcfaf4
JB
613 // We need to clean up the resources after our test
614 await pool.destroy()
615 })
616
b3432a63 617 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
618 const pool = new FixedThreadPool(
619 max,
620 './tests/worker-files/thread/testWorker.js',
621 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
622 )
623 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
624 const promises = []
a20f0ba5
JB
625 const maxMultiplier = 2
626 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 627 promises.push(pool.execute())
b3432a63
JB
628 }
629 await Promise.all(promises)
97a2abc3 630 expect(
95c83464 631 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 632 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
633 ).defaultWorkerWeight
634 ).toBeGreaterThan(0)
635 expect(
636 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
637 pool.workerChoiceStrategyContext.workerChoiceStrategy
638 ).workerVirtualTaskRunTime
639 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
640 // We need to clean up the resources after our test
641 await pool.destroy()
642 })
643
644 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
645 const pool = new DynamicThreadPool(
646 min,
647 max,
648 './tests/worker-files/thread/testWorker.js',
649 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
650 )
651 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
652 const promises = []
5502c07c 653 const maxMultiplier =
95c83464 654 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 655 pool.workerChoiceStrategyContext.workerChoiceStrategy
8da9e84d 656 ).defaultWorkerWeight * 50
5502c07c 657 for (let i = 0; i < max * maxMultiplier; i++) {
6db75ad9 658 promises.push(pool.execute())
b3432a63
JB
659 }
660 await Promise.all(promises)
2b4fddb8
JB
661 expect(
662 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
663 pool.workerChoiceStrategyContext.workerChoiceStrategy
664 ).defaultWorkerWeight
665 ).toBeGreaterThan(0)
666 expect(
667 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
668 pool.workerChoiceStrategyContext.workerChoiceStrategy
669 ).workerVirtualTaskRunTime
670 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
671 // We need to clean up the resources after our test
672 await pool.destroy()
673 })
674
010d7020
JB
675 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median run time statistic', async () => {
676 const pool = new DynamicThreadPool(
677 min,
678 max,
679 './tests/worker-files/thread/testWorker.js',
680 {
681 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
682 workerChoiceStrategyOptions: {
683 medRunTime: true
684 }
685 }
686 )
687 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
688 const promises = []
689 const maxMultiplier = 2
690 for (let i = 0; i < max * maxMultiplier; i++) {
691 promises.push(pool.execute())
692 }
693 await Promise.all(promises)
694 for (const workerNode of pool.workerNodes) {
695 expect(workerNode.tasksUsage.avgRunTime).toBeDefined()
696 expect(workerNode.tasksUsage.avgRunTime).toBe(0)
697 expect(workerNode.tasksUsage.medRunTime).toBeDefined()
698 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
699 }
08f3f44c
JB
700 expect(
701 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
702 pool.workerChoiceStrategyContext.workerChoiceStrategy
703 ).defaultWorkerWeight
704 ).toBeGreaterThan(0)
705 expect(
706 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
707 pool.workerChoiceStrategyContext.workerChoiceStrategy
708 ).workerVirtualTaskRunTime
709 ).toBeGreaterThanOrEqual(0)
010d7020
JB
710 // We need to clean up the resources after our test
711 await pool.destroy()
712 })
713
a6f7f1b4 714 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 715 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 716 let pool = new FixedThreadPool(
caeb9817
JB
717 max,
718 './tests/worker-files/thread/testWorker.js'
719 )
38f6e859 720 expect(
95c83464 721 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 722 workerChoiceStrategy
f06e48d8 723 ).currentWorkerNodeId
b529c323 724 ).toBeDefined()
38f6e859 725 expect(
95c83464 726 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 727 workerChoiceStrategy
b529c323
JB
728 ).defaultWorkerWeight
729 ).toBeDefined()
caeb9817 730 expect(
95c83464 731 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 732 workerChoiceStrategy
08f3f44c 733 ).workerVirtualTaskRunTime
b529c323 734 ).toBeDefined()
594bfb84 735 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 736 expect(
95c83464 737 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 738 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 739 ).currentWorkerNodeId
a6f7f1b4
JB
740 ).toBe(0)
741 expect(
95c83464 742 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 743 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 744 ).defaultWorkerWeight
a6f7f1b4 745 ).toBeGreaterThan(0)
08f3f44c
JB
746 expect(
747 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
748 workerChoiceStrategy
749 ).workerVirtualTaskRunTime
750 ).toBe(0)
f0829c53
JB
751 await pool.destroy()
752 pool = new DynamicThreadPool(
753 min,
754 max,
755 './tests/worker-files/thread/testWorker.js'
756 )
38f6e859 757 expect(
95c83464 758 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 759 workerChoiceStrategy
f06e48d8 760 ).currentWorkerNodeId
b529c323 761 ).toBeDefined()
38f6e859 762 expect(
95c83464 763 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 764 workerChoiceStrategy
b529c323
JB
765 ).defaultWorkerWeight
766 ).toBeDefined()
f0829c53 767 expect(
95c83464 768 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 769 workerChoiceStrategy
08f3f44c 770 ).workerVirtualTaskRunTime
b529c323 771 ).toBeDefined()
594bfb84 772 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 773 expect(
95c83464 774 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 775 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 776 ).currentWorkerNodeId
a6f7f1b4
JB
777 ).toBe(0)
778 expect(
95c83464 779 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 780 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 781 ).defaultWorkerWeight
a6f7f1b4 782 ).toBeGreaterThan(0)
08f3f44c
JB
783 expect(
784 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
785 workerChoiceStrategy
786 ).workerVirtualTaskRunTime
787 ).toBe(0)
caeb9817
JB
788 // We need to clean up the resources after our test
789 await pool.destroy()
790 })
791
89b09b26 792 it('Verify unknown strategy throw error', () => {
a35560ba
S
793 expect(
794 () =>
795 new DynamicThreadPool(
796 min,
797 max,
798 './tests/worker-files/thread/testWorker.js',
1927ee67 799 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 800 )
d4aeae5a 801 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
802 })
803})