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