refactor: cleanup worker usage properties namespace
[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')
86bf340d 8const { CircularArray } = require('../../../lib/circular-array')
a35560ba
S
9
10describe('Selection strategies test suite', () => {
e1ffb94f
JB
11 const min = 0
12 const max = 3
13
a35560ba
S
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
e4543b14
JB
16 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
a7bbf44a 18 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
23ff945a 19 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
20 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
21 'WEIGHTED_ROUND_ROBIN'
22 )
feec6e8c
JB
23 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
24 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
25 )
a35560ba
S
26 })
27
e843b904 28 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
29 const pool = new DynamicThreadPool(
30 min,
31 max,
32 './tests/worker-files/thread/testWorker.js'
33 )
34 expect(pool.opts.workerChoiceStrategy).toBe(
35 WorkerChoiceStrategies.ROUND_ROBIN
36 )
37 // We need to clean up the resources after our test
38 await pool.destroy()
39 })
40
594bfb84
JB
41 it('Verify available strategies are taken at pool creation', async () => {
42 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
43 const pool = new FixedThreadPool(
44 max,
45 './tests/worker-files/thread/testWorker.js',
46 { workerChoiceStrategy }
47 )
48 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
49 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
50 workerChoiceStrategy
51 )
52 await pool.destroy()
53 }
d2f7b7a2
JB
54 })
55
594bfb84
JB
56 it('Verify available strategies can be set after pool creation', async () => {
57 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
58 const pool = new DynamicThreadPool(
59 min,
60 max,
ec82cfa1 61 './tests/worker-files/thread/testWorker.js'
594bfb84
JB
62 )
63 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
64 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
65 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
66 workerChoiceStrategy
67 )
68 await pool.destroy()
69 }
70 })
71
72 it('Verify available strategies default internals at pool creation', async () => {
73 const pool = new FixedThreadPool(
e843b904
JB
74 max,
75 './tests/worker-files/thread/testWorker.js'
76 )
594bfb84
JB
77 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
78 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
79 expect(
80 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
81 workerChoiceStrategy
82 ).nextWorkerNodeId
83 ).toBe(0)
84 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
08f3f44c
JB
85 expect(
86 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
87 workerChoiceStrategy
b0d6ed8f 88 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
89 ).toBeInstanceOf(Array)
90 expect(
91 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
92 workerChoiceStrategy
b0d6ed8f 93 ).workersVirtualTaskEndTimestamp.length
08f3f44c 94 ).toBe(0)
594bfb84
JB
95 } else if (
96 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
97 ) {
98 expect(
99 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
100 workerChoiceStrategy
d33be430 101 ).nextWorkerNodeId
594bfb84
JB
102 ).toBe(0)
103 expect(
104 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
105 workerChoiceStrategy
106 ).defaultWorkerWeight
107 ).toBeGreaterThan(0)
08f3f44c
JB
108 expect(
109 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
110 workerChoiceStrategy
111 ).workerVirtualTaskRunTime
112 ).toBe(0)
594bfb84
JB
113 }
114 }
e843b904
JB
115 await pool.destroy()
116 })
117
6c6afb84
JB
118 it('Verify ROUND_ROBIN strategy default policy', async () => {
119 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
120 let pool = new FixedThreadPool(
121 max,
122 './tests/worker-files/thread/testWorker.js',
123 { workerChoiceStrategy }
124 )
125 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
126 useDynamicWorker: true
127 })
128 await pool.destroy()
129 pool = new DynamicThreadPool(
130 min,
131 max,
132 './tests/worker-files/thread/testWorker.js',
133 { workerChoiceStrategy }
134 )
135 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
136 useDynamicWorker: true
137 })
138 // We need to clean up the resources after our test
139 await pool.destroy()
140 })
141
142 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
594bfb84 143 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
144 let pool = new FixedThreadPool(
145 max,
d710242d 146 './tests/worker-files/thread/testWorker.js',
594bfb84 147 { workerChoiceStrategy }
10fcfaf4 148 )
87de9ff5
JB
149 expect(
150 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
151 ).toStrictEqual({
932fc8be
JB
152 runTime: {
153 aggregate: false,
154 average: false,
155 median: false
156 },
157 waitTime: {
158 aggregate: false,
159 average: false,
160 median: false
161 },
5df69fab
JB
162 elu: {
163 aggregate: false,
164 average: false,
165 median: false
166 }
86bf340d 167 })
fd7ebd49 168 await pool.destroy()
10fcfaf4
JB
169 pool = new DynamicThreadPool(
170 min,
171 max,
d710242d 172 './tests/worker-files/thread/testWorker.js',
594bfb84 173 { workerChoiceStrategy }
10fcfaf4 174 )
87de9ff5
JB
175 expect(
176 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
177 ).toStrictEqual({
932fc8be
JB
178 runTime: {
179 aggregate: false,
180 average: false,
181 median: false
182 },
183 waitTime: {
184 aggregate: false,
185 average: false,
186 median: false
187 },
5df69fab
JB
188 elu: {
189 aggregate: false,
190 average: false,
191 median: false
192 }
86bf340d 193 })
10fcfaf4
JB
194 // We need to clean up the resources after our test
195 await pool.destroy()
196 })
197
bdaf31cd 198 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
bdaf31cd
JB
199 const pool = new FixedThreadPool(
200 max,
201 './tests/worker-files/thread/testWorker.js',
202 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
203 )
bdaf31cd 204 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 205 const promises = new Set()
a20f0ba5
JB
206 const maxMultiplier = 2
207 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 208 promises.add(pool.execute())
e211bc18
JB
209 }
210 await Promise.all(promises)
211 for (const workerNode of pool.workerNodes) {
465b2940 212 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
213 tasks: {
214 executed: maxMultiplier,
215 executing: 0,
216 queued: 0,
df593701 217 maxQueued: 0,
a4e07f72
JB
218 failed: 0
219 },
220 runTime: {
932fc8be 221 aggregate: 0,
a4e07f72
JB
222 average: 0,
223 median: 0,
224 history: expect.any(CircularArray)
225 },
226 waitTime: {
932fc8be 227 aggregate: 0,
a4e07f72
JB
228 average: 0,
229 median: 0,
230 history: expect.any(CircularArray)
231 },
5df69fab
JB
232 elu: {
233 idle: {
234 aggregate: 0,
235 average: 0,
236 median: 0,
237 history: expect.any(CircularArray)
238 },
239 active: {
240 aggregate: 0,
241 average: 0,
242 median: 0,
243 history: expect.any(CircularArray)
244 },
245 utilization: 0
246 }
e211bc18 247 })
bdaf31cd 248 }
9458090a
JB
249 expect(
250 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
251 WorkerChoiceStrategies.ROUND_ROBIN
252 ).nextWorkerNodeId
253 ).toBe(0)
bdaf31cd
JB
254 // We need to clean up the resources after our test
255 await pool.destroy()
256 })
257
258 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
bdaf31cd
JB
259 const pool = new DynamicThreadPool(
260 min,
261 max,
262 './tests/worker-files/thread/testWorker.js',
263 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
264 )
bdaf31cd 265 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 266 const promises = new Set()
a20f0ba5
JB
267 const maxMultiplier = 2
268 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 269 promises.add(pool.execute())
e211bc18
JB
270 }
271 await Promise.all(promises)
272 for (const workerNode of pool.workerNodes) {
465b2940 273 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
274 tasks: {
275 executed: maxMultiplier,
276 executing: 0,
277 queued: 0,
df593701 278 maxQueued: 0,
a4e07f72
JB
279 failed: 0
280 },
281 runTime: {
932fc8be 282 aggregate: 0,
a4e07f72
JB
283 average: 0,
284 median: 0,
285 history: expect.any(CircularArray)
286 },
287 waitTime: {
932fc8be 288 aggregate: 0,
a4e07f72
JB
289 average: 0,
290 median: 0,
291 history: expect.any(CircularArray)
292 },
5df69fab
JB
293 elu: {
294 idle: {
295 aggregate: 0,
296 average: 0,
297 median: 0,
298 history: expect.any(CircularArray)
299 },
300 active: {
301 aggregate: 0,
302 average: 0,
303 median: 0,
304 history: expect.any(CircularArray)
305 },
306 utilization: 0
307 }
e211bc18 308 })
bdaf31cd 309 }
9458090a
JB
310 expect(
311 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
312 WorkerChoiceStrategies.ROUND_ROBIN
313 ).nextWorkerNodeId
314 ).toBe(0)
bdaf31cd
JB
315 // We need to clean up the resources after our test
316 await pool.destroy()
317 })
318
2ced693a 319 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 320 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
321 let pool = new FixedClusterPool(
322 max,
594bfb84
JB
323 './tests/worker-files/cluster/testWorker.js',
324 { workerChoiceStrategy }
2ced693a
JB
325 )
326 let results = new Set()
327 for (let i = 0; i < max; i++) {
20dcad1a 328 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
2ced693a
JB
329 }
330 expect(results.size).toBe(max)
331 await pool.destroy()
594bfb84
JB
332 pool = new FixedThreadPool(
333 max,
334 './tests/worker-files/thread/testWorker.js',
335 { workerChoiceStrategy }
336 )
2ced693a
JB
337 results = new Set()
338 for (let i = 0; i < max; i++) {
20dcad1a 339 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
2ced693a
JB
340 }
341 expect(results.size).toBe(max)
342 await pool.destroy()
343 })
344
a6f7f1b4 345 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 346 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
347 let pool = new FixedThreadPool(
348 max,
349 './tests/worker-files/thread/testWorker.js',
350 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
351 )
38f6e859 352 expect(
95c83464 353 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 354 workerChoiceStrategy
f06e48d8 355 ).nextWorkerNodeId
b529c323 356 ).toBeDefined()
594bfb84 357 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 358 expect(
95c83464 359 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 360 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 361 ).nextWorkerNodeId
a6f7f1b4
JB
362 ).toBe(0)
363 await pool.destroy()
364 pool = new DynamicThreadPool(
365 min,
366 max,
367 './tests/worker-files/thread/testWorker.js',
368 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
369 )
38f6e859 370 expect(
95c83464 371 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 372 workerChoiceStrategy
f06e48d8 373 ).nextWorkerNodeId
b529c323 374 ).toBeDefined()
594bfb84 375 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 376 expect(
95c83464 377 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 378 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 379 ).nextWorkerNodeId
a6f7f1b4
JB
380 ).toBe(0)
381 // We need to clean up the resources after our test
382 await pool.destroy()
383 })
384
6c6afb84
JB
385 it('Verify LEAST_USED strategy default policy', async () => {
386 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
387 let pool = new FixedThreadPool(
388 max,
389 './tests/worker-files/thread/testWorker.js',
390 { workerChoiceStrategy }
391 )
392 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
393 useDynamicWorker: false
394 })
395 await pool.destroy()
396 pool = new DynamicThreadPool(
397 min,
398 max,
399 './tests/worker-files/thread/testWorker.js',
400 { workerChoiceStrategy }
401 )
402 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
403 useDynamicWorker: false
404 })
405 // We need to clean up the resources after our test
406 await pool.destroy()
407 })
408
409 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
e4543b14 410 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
10fcfaf4
JB
411 let pool = new FixedThreadPool(
412 max,
d710242d 413 './tests/worker-files/thread/testWorker.js',
594bfb84 414 { workerChoiceStrategy }
10fcfaf4 415 )
87de9ff5
JB
416 expect(
417 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
418 ).toStrictEqual({
932fc8be
JB
419 runTime: {
420 aggregate: false,
421 average: false,
422 median: false
423 },
424 waitTime: {
425 aggregate: false,
426 average: false,
427 median: false
428 },
5df69fab
JB
429 elu: {
430 aggregate: false,
431 average: false,
432 median: false
433 }
86bf340d 434 })
fd7ebd49 435 await pool.destroy()
10fcfaf4
JB
436 pool = new DynamicThreadPool(
437 min,
438 max,
d710242d 439 './tests/worker-files/thread/testWorker.js',
594bfb84 440 { workerChoiceStrategy }
10fcfaf4 441 )
87de9ff5
JB
442 expect(
443 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
444 ).toStrictEqual({
932fc8be
JB
445 runTime: {
446 aggregate: false,
447 average: false,
448 median: false
449 },
450 waitTime: {
451 aggregate: false,
452 average: false,
453 median: false
454 },
5df69fab
JB
455 elu: {
456 aggregate: false,
457 average: false,
458 median: false
459 }
86bf340d 460 })
10fcfaf4
JB
461 // We need to clean up the resources after our test
462 await pool.destroy()
463 })
464
e4543b14 465 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
466 const pool = new FixedThreadPool(
467 max,
468 './tests/worker-files/thread/testWorker.js',
e4543b14 469 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
b98ec2e6 470 )
e4543b14 471 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 472 const promises = new Set()
a20f0ba5
JB
473 const maxMultiplier = 2
474 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 475 promises.add(pool.execute())
e211bc18
JB
476 }
477 await Promise.all(promises)
478 for (const workerNode of pool.workerNodes) {
465b2940 479 expect(workerNode.usage).toStrictEqual({
a4e07f72 480 tasks: {
76407b8e 481 executed: expect.any(Number),
a4e07f72
JB
482 executing: 0,
483 queued: 0,
df593701 484 maxQueued: 0,
a4e07f72
JB
485 failed: 0
486 },
487 runTime: {
932fc8be 488 aggregate: 0,
a4e07f72
JB
489 average: 0,
490 median: 0,
491 history: expect.any(CircularArray)
492 },
493 waitTime: {
932fc8be 494 aggregate: 0,
a4e07f72
JB
495 average: 0,
496 median: 0,
497 history: expect.any(CircularArray)
498 },
5df69fab
JB
499 elu: {
500 idle: {
501 aggregate: 0,
502 average: 0,
503 median: 0,
504 history: expect.any(CircularArray)
505 },
506 active: {
507 aggregate: 0,
508 average: 0,
509 median: 0,
510 history: expect.any(CircularArray)
511 },
512 utilization: 0
513 }
e211bc18 514 })
465b2940
JB
515 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
516 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
76407b8e
JB
517 max * maxMultiplier
518 )
a35560ba 519 }
a35560ba
S
520 // We need to clean up the resources after our test
521 await pool.destroy()
522 })
523
e4543b14 524 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
525 const pool = new DynamicThreadPool(
526 min,
527 max,
528 './tests/worker-files/thread/testWorker.js',
e4543b14 529 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
ff5e76e1 530 )
e4543b14 531 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 532 const promises = new Set()
a20f0ba5
JB
533 const maxMultiplier = 2
534 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 535 promises.add(pool.execute())
e211bc18
JB
536 }
537 await Promise.all(promises)
538 for (const workerNode of pool.workerNodes) {
465b2940 539 expect(workerNode.usage).toStrictEqual({
a4e07f72 540 tasks: {
76407b8e 541 executed: expect.any(Number),
a4e07f72
JB
542 executing: 0,
543 queued: 0,
df593701 544 maxQueued: 0,
a4e07f72
JB
545 failed: 0
546 },
547 runTime: {
932fc8be 548 aggregate: 0,
a4e07f72
JB
549 average: 0,
550 median: 0,
551 history: expect.any(CircularArray)
552 },
553 waitTime: {
932fc8be 554 aggregate: 0,
a4e07f72
JB
555 average: 0,
556 median: 0,
557 history: expect.any(CircularArray)
558 },
5df69fab
JB
559 elu: {
560 idle: {
561 aggregate: 0,
562 average: 0,
563 median: 0,
564 history: expect.any(CircularArray)
565 },
566 active: {
567 aggregate: 0,
568 average: 0,
569 median: 0,
570 history: expect.any(CircularArray)
571 },
572 utilization: 0
573 }
e211bc18 574 })
465b2940
JB
575 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
576 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
76407b8e
JB
577 max * maxMultiplier
578 )
168c526f 579 }
168c526f
JB
580 // We need to clean up the resources after our test
581 await pool.destroy()
582 })
583
6c6afb84
JB
584 it('Verify LEAST_BUSY strategy default policy', async () => {
585 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
586 let pool = new FixedThreadPool(
587 max,
588 './tests/worker-files/thread/testWorker.js',
589 { workerChoiceStrategy }
590 )
591 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
592 useDynamicWorker: false
593 })
594 await pool.destroy()
595 pool = new DynamicThreadPool(
596 min,
597 max,
598 './tests/worker-files/thread/testWorker.js',
599 { workerChoiceStrategy }
600 )
601 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
602 useDynamicWorker: false
603 })
604 // We need to clean up the resources after our test
605 await pool.destroy()
606 })
607
608 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
e4543b14 609 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
168c526f
JB
610 let pool = new FixedThreadPool(
611 max,
d710242d 612 './tests/worker-files/thread/testWorker.js',
594bfb84 613 { workerChoiceStrategy }
168c526f 614 )
87de9ff5
JB
615 expect(
616 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
617 ).toStrictEqual({
932fc8be
JB
618 runTime: {
619 aggregate: true,
620 average: false,
621 median: false
622 },
623 waitTime: {
624 aggregate: true,
625 average: false,
626 median: false
627 },
5df69fab
JB
628 elu: {
629 aggregate: false,
630 average: false,
631 median: false
632 }
86bf340d 633 })
168c526f
JB
634 await pool.destroy()
635 pool = new DynamicThreadPool(
636 min,
637 max,
d710242d 638 './tests/worker-files/thread/testWorker.js',
594bfb84 639 { workerChoiceStrategy }
168c526f 640 )
87de9ff5
JB
641 expect(
642 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
643 ).toStrictEqual({
932fc8be
JB
644 runTime: {
645 aggregate: true,
646 average: false,
647 median: false
648 },
649 waitTime: {
650 aggregate: true,
651 average: false,
652 median: false
653 },
5df69fab
JB
654 elu: {
655 aggregate: false,
656 average: false,
657 median: false
658 }
86bf340d 659 })
168c526f
JB
660 // We need to clean up the resources after our test
661 await pool.destroy()
662 })
663
e4543b14 664 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
168c526f
JB
665 const pool = new FixedThreadPool(
666 max,
667 './tests/worker-files/thread/testWorker.js',
e4543b14 668 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 669 )
e4543b14 670 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 671 const promises = new Set()
a20f0ba5
JB
672 const maxMultiplier = 2
673 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 674 promises.add(pool.execute())
e211bc18
JB
675 }
676 await Promise.all(promises)
677 for (const workerNode of pool.workerNodes) {
465b2940 678 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
679 tasks: {
680 executed: expect.any(Number),
681 executing: 0,
682 queued: 0,
df593701 683 maxQueued: 0,
a4e07f72
JB
684 failed: 0
685 },
686 runTime: {
932fc8be 687 aggregate: expect.any(Number),
a4e07f72
JB
688 average: 0,
689 median: 0,
690 history: expect.any(CircularArray)
691 },
692 waitTime: {
932fc8be 693 aggregate: expect.any(Number),
a4e07f72
JB
694 average: 0,
695 median: 0,
696 history: expect.any(CircularArray)
697 },
5df69fab
JB
698 elu: {
699 idle: {
700 aggregate: 0,
701 average: 0,
702 median: 0,
703 history: expect.any(CircularArray)
704 },
705 active: {
706 aggregate: 0,
707 average: 0,
708 median: 0,
709 history: expect.any(CircularArray)
710 },
711 utilization: 0
712 }
e211bc18 713 })
465b2940
JB
714 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
715 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
716 max * maxMultiplier
717 )
465b2940
JB
718 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
719 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThanOrEqual(0)
168c526f 720 }
168c526f
JB
721 // We need to clean up the resources after our test
722 await pool.destroy()
723 })
724
e4543b14 725 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
168c526f
JB
726 const pool = new DynamicThreadPool(
727 min,
728 max,
729 './tests/worker-files/thread/testWorker.js',
e4543b14 730 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 731 )
e4543b14 732 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 733 const promises = new Set()
a20f0ba5
JB
734 const maxMultiplier = 2
735 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 736 promises.add(pool.execute())
e211bc18
JB
737 }
738 await Promise.all(promises)
739 for (const workerNode of pool.workerNodes) {
465b2940 740 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
741 tasks: {
742 executed: expect.any(Number),
743 executing: 0,
744 queued: 0,
df593701 745 maxQueued: 0,
a4e07f72
JB
746 failed: 0
747 },
748 runTime: {
932fc8be 749 aggregate: expect.any(Number),
a4e07f72
JB
750 average: 0,
751 median: 0,
752 history: expect.any(CircularArray)
753 },
754 waitTime: {
932fc8be 755 aggregate: expect.any(Number),
a4e07f72
JB
756 average: 0,
757 median: 0,
758 history: expect.any(CircularArray)
759 },
5df69fab
JB
760 elu: {
761 idle: {
762 aggregate: 0,
763 average: 0,
764 median: 0,
765 history: expect.any(CircularArray)
766 },
767 active: {
768 aggregate: 0,
769 average: 0,
770 median: 0,
771 history: expect.any(CircularArray)
772 },
773 utilization: 0
774 }
e211bc18 775 })
465b2940
JB
776 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
777 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
778 max * maxMultiplier
779 )
465b2940
JB
780 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
781 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThanOrEqual(0)
ff5e76e1 782 }
ff5e76e1
JB
783 // We need to clean up the resources after our test
784 await pool.destroy()
785 })
786
6c6afb84
JB
787 it('Verify LEAST_ELU strategy default policy', async () => {
788 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
789 let pool = new FixedThreadPool(
790 max,
791 './tests/worker-files/thread/testWorker.js',
792 { workerChoiceStrategy }
793 )
794 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
795 useDynamicWorker: false
796 })
797 await pool.destroy()
798 pool = new DynamicThreadPool(
799 min,
800 max,
801 './tests/worker-files/thread/testWorker.js',
802 { workerChoiceStrategy }
803 )
804 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
805 useDynamicWorker: false
806 })
807 // We need to clean up the resources after our test
808 await pool.destroy()
809 })
810
811 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
a7bbf44a
JB
812 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
813 let pool = new FixedThreadPool(
814 max,
815 './tests/worker-files/thread/testWorker.js',
816 { workerChoiceStrategy }
817 )
05302647
JB
818 expect(
819 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
820 ).toStrictEqual({
e460940e
JB
821 runTime: {
822 aggregate: false,
823 average: false,
824 median: false
825 },
826 waitTime: {
827 aggregate: false,
828 average: false,
829 median: false
830 },
5df69fab
JB
831 elu: {
832 aggregate: true,
833 average: false,
834 median: false
835 }
a7bbf44a
JB
836 })
837 await pool.destroy()
838 pool = new DynamicThreadPool(
839 min,
840 max,
841 './tests/worker-files/thread/testWorker.js',
842 { workerChoiceStrategy }
843 )
05302647
JB
844 expect(
845 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
846 ).toStrictEqual({
e460940e
JB
847 runTime: {
848 aggregate: false,
849 average: false,
850 median: false
851 },
852 waitTime: {
853 aggregate: false,
854 average: false,
855 median: false
856 },
5df69fab
JB
857 elu: {
858 aggregate: true,
859 average: false,
860 median: false
861 }
a7bbf44a
JB
862 })
863 // We need to clean up the resources after our test
864 await pool.destroy()
865 })
866
ae9cf3c8 867 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
c5ad42cd
JB
868 const pool = new FixedThreadPool(
869 max,
870 './tests/worker-files/thread/testWorker.js',
871 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
872 )
873 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
dd38581f 874 const promises = new Set()
c5ad42cd
JB
875 const maxMultiplier = 2
876 for (let i = 0; i < max * maxMultiplier; i++) {
dd38581f 877 promises.add(pool.execute())
c5ad42cd 878 }
dd38581f 879 await Promise.all(promises)
c5ad42cd 880 for (const workerNode of pool.workerNodes) {
465b2940 881 expect(workerNode.usage).toStrictEqual({
c5ad42cd
JB
882 tasks: {
883 executed: expect.any(Number),
884 executing: 0,
885 queued: 0,
df593701 886 maxQueued: 0,
c5ad42cd
JB
887 failed: 0
888 },
889 runTime: {
e460940e 890 aggregate: 0,
c5ad42cd
JB
891 average: 0,
892 median: 0,
893 history: expect.any(CircularArray)
a1347286
JB
894 },
895 waitTime: {
896 aggregate: 0,
897 average: 0,
898 median: 0,
899 history: expect.any(CircularArray)
5df69fab
JB
900 },
901 elu: {
902 idle: {
903 aggregate: 0,
904 average: 0,
905 median: 0,
906 history: expect.any(CircularArray)
907 },
908 active: {
909 aggregate: expect.any(Number),
910 average: 0,
911 median: 0,
912 history: expect.any(CircularArray)
913 },
914 utilization: expect.any(Number)
a1347286 915 }
5df69fab 916 })
465b2940
JB
917 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
918 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a1347286
JB
919 max * maxMultiplier
920 )
465b2940
JB
921 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
922 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
a1347286
JB
923 }
924 // We need to clean up the resources after our test
925 await pool.destroy()
926 })
927
928 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
929 const pool = new DynamicThreadPool(
930 min,
931 max,
932 './tests/worker-files/thread/testWorker.js',
933 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
934 )
935 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
dd38581f 936 const promises = new Set()
a1347286
JB
937 const maxMultiplier = 2
938 for (let i = 0; i < max * maxMultiplier; i++) {
dd38581f 939 promises.add(pool.execute())
a1347286 940 }
dd38581f 941 await Promise.all(promises)
a1347286 942 for (const workerNode of pool.workerNodes) {
465b2940 943 expect(workerNode.usage).toStrictEqual({
a1347286
JB
944 tasks: {
945 executed: expect.any(Number),
946 executing: 0,
947 queued: 0,
df593701 948 maxQueued: 0,
a1347286
JB
949 failed: 0
950 },
951 runTime: {
952 aggregate: 0,
953 average: 0,
954 median: 0,
955 history: expect.any(CircularArray)
c5ad42cd
JB
956 },
957 waitTime: {
e460940e 958 aggregate: 0,
c5ad42cd
JB
959 average: 0,
960 median: 0,
961 history: expect.any(CircularArray)
5df69fab
JB
962 },
963 elu: {
964 idle: {
965 aggregate: 0,
966 average: 0,
967 median: 0,
968 history: expect.any(CircularArray)
969 },
970 active: {
971 aggregate: expect.any(Number),
972 average: 0,
973 median: 0,
974 history: expect.any(CircularArray)
975 },
976 utilization: expect.any(Number)
c5ad42cd 977 }
5df69fab 978 })
465b2940
JB
979 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
980 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
c5ad42cd
JB
981 max * maxMultiplier
982 )
465b2940
JB
983 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
984 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
c5ad42cd
JB
985 }
986 // We need to clean up the resources after our test
987 await pool.destroy()
988 })
989
6c6afb84
JB
990 it('Verify FAIR_SHARE strategy default policy', async () => {
991 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
992 let pool = new FixedThreadPool(
993 max,
994 './tests/worker-files/thread/testWorker.js',
995 { workerChoiceStrategy }
996 )
997 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
998 useDynamicWorker: false
999 })
1000 await pool.destroy()
1001 pool = new DynamicThreadPool(
1002 min,
1003 max,
1004 './tests/worker-files/thread/testWorker.js',
1005 { workerChoiceStrategy }
1006 )
1007 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1008 useDynamicWorker: false
1009 })
1010 // We need to clean up the resources after our test
1011 await pool.destroy()
1012 })
1013
1014 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
594bfb84 1015 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
1016 let pool = new FixedThreadPool(
1017 max,
d710242d 1018 './tests/worker-files/thread/testWorker.js',
594bfb84 1019 { workerChoiceStrategy }
10fcfaf4 1020 )
87de9ff5
JB
1021 expect(
1022 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1023 ).toStrictEqual({
932fc8be
JB
1024 runTime: {
1025 aggregate: true,
1026 average: true,
1027 median: false
1028 },
1029 waitTime: {
1030 aggregate: false,
1031 average: false,
1032 median: false
1033 },
5df69fab 1034 elu: {
9adcefab
JB
1035 aggregate: true,
1036 average: true,
5df69fab
JB
1037 median: false
1038 }
86bf340d 1039 })
fd7ebd49 1040 await pool.destroy()
10fcfaf4
JB
1041 pool = new DynamicThreadPool(
1042 min,
1043 max,
d710242d 1044 './tests/worker-files/thread/testWorker.js',
594bfb84 1045 { workerChoiceStrategy }
10fcfaf4 1046 )
87de9ff5
JB
1047 expect(
1048 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1049 ).toStrictEqual({
932fc8be
JB
1050 runTime: {
1051 aggregate: true,
1052 average: true,
1053 median: false
1054 },
1055 waitTime: {
1056 aggregate: false,
1057 average: false,
1058 median: false
1059 },
5df69fab 1060 elu: {
9adcefab
JB
1061 aggregate: true,
1062 average: true,
5df69fab
JB
1063 median: false
1064 }
86bf340d 1065 })
10fcfaf4
JB
1066 // We need to clean up the resources after our test
1067 await pool.destroy()
1068 })
1069
23ff945a 1070 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
1071 const pool = new FixedThreadPool(
1072 max,
1073 './tests/worker-files/thread/testWorker.js',
1074 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1075 )
1076 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1077 const promises = new Set()
a20f0ba5
JB
1078 const maxMultiplier = 2
1079 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1080 promises.add(pool.execute())
23ff945a 1081 }
e211bc18 1082 await Promise.all(promises)
138d29a8 1083 for (const workerNode of pool.workerNodes) {
465b2940 1084 expect(workerNode.usage).toStrictEqual({
a4e07f72 1085 tasks: {
d33be430 1086 executed: expect.any(Number),
a4e07f72
JB
1087 executing: 0,
1088 queued: 0,
df593701 1089 maxQueued: 0,
a4e07f72
JB
1090 failed: 0
1091 },
1092 runTime: {
932fc8be 1093 aggregate: expect.any(Number),
a4e07f72
JB
1094 average: expect.any(Number),
1095 median: 0,
1096 history: expect.any(CircularArray)
1097 },
1098 waitTime: {
932fc8be 1099 aggregate: 0,
a4e07f72
JB
1100 average: 0,
1101 median: 0,
1102 history: expect.any(CircularArray)
1103 },
5df69fab
JB
1104 elu: {
1105 idle: {
1106 aggregate: 0,
1107 average: 0,
1108 median: 0,
1109 history: expect.any(CircularArray)
1110 },
1111 active: {
9adcefab
JB
1112 aggregate: expect.any(Number),
1113 average: expect.any(Number),
5df69fab
JB
1114 median: 0,
1115 history: expect.any(CircularArray)
1116 },
9adcefab 1117 utilization: expect.any(Number)
5df69fab 1118 }
86bf340d 1119 })
465b2940
JB
1120 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1121 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
d33be430
JB
1122 max * maxMultiplier
1123 )
465b2940
JB
1124 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1125 expect(workerNode.usage.runTime.average).toBeGreaterThanOrEqual(0)
1126 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1127 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
138d29a8 1128 }
97a2abc3 1129 expect(
95c83464 1130 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1131 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 1132 ).workersVirtualTaskEndTimestamp.length
f06e48d8 1133 ).toBe(pool.workerNodes.length)
23ff945a
JB
1134 // We need to clean up the resources after our test
1135 await pool.destroy()
1136 })
1137
1138 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
1139 const pool = new DynamicThreadPool(
1140 min,
1141 max,
1142 './tests/worker-files/thread/testWorker.js',
1143 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1144 )
1145 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1146 const promises = new Set()
f7070eee 1147 const maxMultiplier = 2
804a889e 1148 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1149 promises.add(pool.execute())
23ff945a 1150 }
e211bc18 1151 await Promise.all(promises)
138d29a8 1152 for (const workerNode of pool.workerNodes) {
465b2940 1153 expect(workerNode.usage).toStrictEqual({
a4e07f72 1154 tasks: {
6c6afb84 1155 executed: expect.any(Number),
a4e07f72
JB
1156 executing: 0,
1157 queued: 0,
df593701 1158 maxQueued: 0,
a4e07f72
JB
1159 failed: 0
1160 },
1161 runTime: {
932fc8be 1162 aggregate: expect.any(Number),
a4e07f72
JB
1163 average: expect.any(Number),
1164 median: 0,
1165 history: expect.any(CircularArray)
1166 },
1167 waitTime: {
932fc8be 1168 aggregate: 0,
a4e07f72
JB
1169 average: 0,
1170 median: 0,
1171 history: expect.any(CircularArray)
1172 },
5df69fab
JB
1173 elu: {
1174 idle: {
1175 aggregate: 0,
1176 average: 0,
1177 median: 0,
1178 history: expect.any(CircularArray)
1179 },
1180 active: {
9adcefab
JB
1181 aggregate: expect.any(Number),
1182 average: expect.any(Number),
5df69fab
JB
1183 median: 0,
1184 history: expect.any(CircularArray)
1185 },
9adcefab 1186 utilization: expect.any(Number)
5df69fab 1187 }
86bf340d 1188 })
465b2940
JB
1189 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1190 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
6c6afb84
JB
1191 max * maxMultiplier
1192 )
465b2940
JB
1193 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1194 expect(workerNode.usage.runTime.average).toBeGreaterThanOrEqual(0)
1195 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1196 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
138d29a8 1197 }
2b4fddb8
JB
1198 expect(
1199 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1200 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 1201 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 1202 ).toBe(pool.workerNodes.length)
23ff945a
JB
1203 // We need to clean up the resources after our test
1204 await pool.destroy()
1205 })
1206
9e775f96 1207 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
1208 const pool = new DynamicThreadPool(
1209 min,
1210 max,
1211 './tests/worker-files/thread/testWorker.js',
1212 {
1213 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1214 workerChoiceStrategyOptions: {
932fc8be 1215 runTime: { median: true }
010d7020
JB
1216 }
1217 }
1218 )
1219 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1220 const promises = new Set()
010d7020
JB
1221 const maxMultiplier = 2
1222 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1223 promises.add(pool.execute())
010d7020 1224 }
e211bc18 1225 await Promise.all(promises)
010d7020 1226 for (const workerNode of pool.workerNodes) {
465b2940 1227 expect(workerNode.usage).toStrictEqual({
a4e07f72 1228 tasks: {
6c6afb84 1229 executed: expect.any(Number),
a4e07f72
JB
1230 executing: 0,
1231 queued: 0,
df593701 1232 maxQueued: 0,
a4e07f72
JB
1233 failed: 0
1234 },
1235 runTime: {
932fc8be 1236 aggregate: expect.any(Number),
a4e07f72
JB
1237 average: 0,
1238 median: expect.any(Number),
1239 history: expect.any(CircularArray)
1240 },
1241 waitTime: {
932fc8be 1242 aggregate: 0,
a4e07f72
JB
1243 average: 0,
1244 median: 0,
1245 history: expect.any(CircularArray)
1246 },
5df69fab
JB
1247 elu: {
1248 idle: {
1249 aggregate: 0,
1250 average: 0,
1251 median: 0,
1252 history: expect.any(CircularArray)
1253 },
1254 active: {
9adcefab
JB
1255 aggregate: expect.any(Number),
1256 average: expect.any(Number),
5df69fab
JB
1257 median: 0,
1258 history: expect.any(CircularArray)
1259 },
9adcefab 1260 utilization: expect.any(Number)
5df69fab 1261 }
86bf340d 1262 })
465b2940
JB
1263 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1264 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
6c6afb84
JB
1265 max * maxMultiplier
1266 )
465b2940
JB
1267 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1268 expect(workerNode.usage.runTime.median).toBeGreaterThanOrEqual(0)
1269 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1270 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
010d7020 1271 }
2b4fddb8
JB
1272 expect(
1273 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1274 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 1275 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 1276 ).toBe(pool.workerNodes.length)
010d7020
JB
1277 // We need to clean up the resources after our test
1278 await pool.destroy()
1279 })
1280
a6f7f1b4 1281 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 1282 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 1283 let pool = new FixedThreadPool(
caeb9817
JB
1284 max,
1285 './tests/worker-files/thread/testWorker.js'
1286 )
1287 expect(
95c83464 1288 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1289 workerChoiceStrategy
b0d6ed8f 1290 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
1291 ).toBeInstanceOf(Array)
1292 expect(
1293 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1294 workerChoiceStrategy
b0d6ed8f 1295 ).workersVirtualTaskEndTimestamp.length
08f3f44c 1296 ).toBe(0)
2b4fddb8
JB
1297 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1298 workerChoiceStrategy
b0d6ed8f 1299 ).workersVirtualTaskEndTimestamp[0] = performance.now()
2b4fddb8
JB
1300 expect(
1301 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1302 workerChoiceStrategy
b0d6ed8f 1303 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 1304 ).toBe(1)
594bfb84 1305 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
1306 expect(
1307 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1308 workerChoiceStrategy
b0d6ed8f 1309 ).workersVirtualTaskEndTimestamp
08f3f44c 1310 ).toBeInstanceOf(Array)
08f3f44c
JB
1311 expect(
1312 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1313 workerChoiceStrategy
b0d6ed8f 1314 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 1315 ).toBe(0)
f0829c53
JB
1316 await pool.destroy()
1317 pool = new DynamicThreadPool(
1318 min,
1319 max,
1320 './tests/worker-files/thread/testWorker.js'
1321 )
1322 expect(
95c83464 1323 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1324 workerChoiceStrategy
b0d6ed8f 1325 ).workersVirtualTaskEndTimestamp
08f3f44c 1326 ).toBeInstanceOf(Array)
2b4fddb8
JB
1327 expect(
1328 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1329 workerChoiceStrategy
b0d6ed8f 1330 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 1331 ).toBe(0)
08f3f44c
JB
1332 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1333 workerChoiceStrategy
b0d6ed8f 1334 ).workersVirtualTaskEndTimestamp[0] = performance.now()
08f3f44c
JB
1335 expect(
1336 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1337 workerChoiceStrategy
b0d6ed8f 1338 ).workersVirtualTaskEndTimestamp.length
08f3f44c 1339 ).toBe(1)
594bfb84 1340 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
1341 expect(
1342 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1343 workerChoiceStrategy
b0d6ed8f 1344 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
1345 ).toBeInstanceOf(Array)
1346 expect(
1347 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1348 workerChoiceStrategy
b0d6ed8f 1349 ).workersVirtualTaskEndTimestamp.length
08f3f44c 1350 ).toBe(0)
caeb9817
JB
1351 // We need to clean up the resources after our test
1352 await pool.destroy()
1353 })
1354
6c6afb84
JB
1355 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1356 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1357 let pool = new FixedThreadPool(
1358 max,
1359 './tests/worker-files/thread/testWorker.js',
1360 { workerChoiceStrategy }
1361 )
1362 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1363 useDynamicWorker: true
1364 })
1365 await pool.destroy()
1366 pool = new DynamicThreadPool(
1367 min,
1368 max,
1369 './tests/worker-files/thread/testWorker.js',
1370 { workerChoiceStrategy }
1371 )
1372 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1373 useDynamicWorker: true
1374 })
1375 // We need to clean up the resources after our test
1376 await pool.destroy()
1377 })
1378
1379 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
594bfb84 1380 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
1381 let pool = new FixedThreadPool(
1382 max,
d710242d 1383 './tests/worker-files/thread/testWorker.js',
594bfb84 1384 { workerChoiceStrategy }
10fcfaf4 1385 )
87de9ff5
JB
1386 expect(
1387 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1388 ).toStrictEqual({
932fc8be
JB
1389 runTime: {
1390 aggregate: true,
1391 average: true,
1392 median: false
1393 },
1394 waitTime: {
1395 aggregate: false,
1396 average: false,
1397 median: false
1398 },
5df69fab
JB
1399 elu: {
1400 aggregate: false,
1401 average: false,
1402 median: false
1403 }
86bf340d 1404 })
fd7ebd49 1405 await pool.destroy()
10fcfaf4
JB
1406 pool = new DynamicThreadPool(
1407 min,
1408 max,
d710242d 1409 './tests/worker-files/thread/testWorker.js',
594bfb84 1410 { workerChoiceStrategy }
10fcfaf4 1411 )
87de9ff5
JB
1412 expect(
1413 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1414 ).toStrictEqual({
932fc8be
JB
1415 runTime: {
1416 aggregate: true,
1417 average: true,
1418 median: false
1419 },
1420 waitTime: {
1421 aggregate: false,
1422 average: false,
1423 median: false
1424 },
5df69fab
JB
1425 elu: {
1426 aggregate: false,
1427 average: false,
1428 median: false
1429 }
86bf340d 1430 })
10fcfaf4
JB
1431 // We need to clean up the resources after our test
1432 await pool.destroy()
1433 })
1434
b3432a63 1435 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
1436 const pool = new FixedThreadPool(
1437 max,
1438 './tests/worker-files/thread/testWorker.js',
1439 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1440 )
1441 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1442 const promises = new Set()
a20f0ba5
JB
1443 const maxMultiplier = 2
1444 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1445 promises.add(pool.execute())
b3432a63 1446 }
e211bc18 1447 await Promise.all(promises)
138d29a8 1448 for (const workerNode of pool.workerNodes) {
465b2940 1449 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1450 tasks: {
1451 executed: expect.any(Number),
1452 executing: 0,
1453 queued: 0,
df593701 1454 maxQueued: 0,
a4e07f72
JB
1455 failed: 0
1456 },
1457 runTime: {
932fc8be 1458 aggregate: expect.any(Number),
a4e07f72
JB
1459 average: expect.any(Number),
1460 median: 0,
1461 history: expect.any(CircularArray)
1462 },
1463 waitTime: {
932fc8be 1464 aggregate: 0,
a4e07f72
JB
1465 average: 0,
1466 median: 0,
1467 history: expect.any(CircularArray)
1468 },
5df69fab
JB
1469 elu: {
1470 idle: {
1471 aggregate: 0,
1472 average: 0,
1473 median: 0,
1474 history: expect.any(CircularArray)
1475 },
1476 active: {
1477 aggregate: 0,
1478 average: 0,
1479 median: 0,
1480 history: expect.any(CircularArray)
1481 },
1482 utilization: 0
1483 }
86bf340d 1484 })
465b2940
JB
1485 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1486 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1487 max * maxMultiplier
1488 )
465b2940
JB
1489 expect(workerNode.usage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1490 expect(workerNode.usage.runTime.average).toBeGreaterThanOrEqual(0)
138d29a8 1491 }
97a2abc3 1492 expect(
95c83464 1493 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1494 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
1495 ).defaultWorkerWeight
1496 ).toBeGreaterThan(0)
1497 expect(
1498 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1499 pool.workerChoiceStrategyContext.workerChoiceStrategy
1500 ).workerVirtualTaskRunTime
1501 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
1502 // We need to clean up the resources after our test
1503 await pool.destroy()
1504 })
1505
1506 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
1507 const pool = new DynamicThreadPool(
1508 min,
1509 max,
1510 './tests/worker-files/thread/testWorker.js',
1511 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1512 )
1513 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1514 const promises = new Set()
138d29a8 1515 const maxMultiplier = 2
5502c07c 1516 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1517 promises.add(pool.execute())
b3432a63 1518 }
e211bc18 1519 await Promise.all(promises)
138d29a8 1520 for (const workerNode of pool.workerNodes) {
465b2940 1521 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1522 tasks: {
1523 executed: expect.any(Number),
1524 executing: 0,
1525 queued: 0,
df593701 1526 maxQueued: 0,
a4e07f72
JB
1527 failed: 0
1528 },
1529 runTime: {
932fc8be 1530 aggregate: expect.any(Number),
a4e07f72
JB
1531 average: expect.any(Number),
1532 median: 0,
1533 history: expect.any(CircularArray)
1534 },
1535 waitTime: {
932fc8be 1536 aggregate: 0,
a4e07f72
JB
1537 average: 0,
1538 median: 0,
1539 history: expect.any(CircularArray)
1540 },
5df69fab
JB
1541 elu: {
1542 idle: {
1543 aggregate: 0,
1544 average: 0,
1545 median: 0,
1546 history: expect.any(CircularArray)
1547 },
1548 active: {
1549 aggregate: 0,
1550 average: 0,
1551 median: 0,
1552 history: expect.any(CircularArray)
1553 },
1554 utilization: 0
1555 }
86bf340d 1556 })
465b2940
JB
1557 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1558 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1559 max * maxMultiplier
1560 )
465b2940
JB
1561 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1562 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
138d29a8 1563 }
2b4fddb8
JB
1564 expect(
1565 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1566 pool.workerChoiceStrategyContext.workerChoiceStrategy
1567 ).defaultWorkerWeight
1568 ).toBeGreaterThan(0)
1569 expect(
1570 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1571 pool.workerChoiceStrategyContext.workerChoiceStrategy
1572 ).workerVirtualTaskRunTime
1573 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
1574 // We need to clean up the resources after our test
1575 await pool.destroy()
1576 })
1577
9e775f96 1578 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
1579 const pool = new DynamicThreadPool(
1580 min,
1581 max,
1582 './tests/worker-files/thread/testWorker.js',
1583 {
1584 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1585 workerChoiceStrategyOptions: {
932fc8be 1586 runTime: { median: true }
010d7020
JB
1587 }
1588 }
1589 )
1590 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1591 const promises = new Set()
010d7020
JB
1592 const maxMultiplier = 2
1593 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1594 promises.add(pool.execute())
010d7020 1595 }
e211bc18 1596 await Promise.all(promises)
010d7020 1597 for (const workerNode of pool.workerNodes) {
465b2940 1598 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1599 tasks: {
1600 executed: expect.any(Number),
1601 executing: 0,
1602 queued: 0,
df593701 1603 maxQueued: 0,
a4e07f72
JB
1604 failed: 0
1605 },
1606 runTime: {
932fc8be 1607 aggregate: expect.any(Number),
a4e07f72
JB
1608 average: 0,
1609 median: expect.any(Number),
1610 history: expect.any(CircularArray)
1611 },
1612 waitTime: {
932fc8be 1613 aggregate: 0,
a4e07f72
JB
1614 average: 0,
1615 median: 0,
1616 history: expect.any(CircularArray)
1617 },
5df69fab
JB
1618 elu: {
1619 idle: {
1620 aggregate: 0,
1621 average: 0,
1622 median: 0,
1623 history: expect.any(CircularArray)
1624 },
1625 active: {
1626 aggregate: 0,
1627 average: 0,
1628 median: 0,
1629 history: expect.any(CircularArray)
1630 },
1631 utilization: 0
1632 }
86bf340d 1633 })
465b2940
JB
1634 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1635 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1636 max * maxMultiplier
1637 )
465b2940
JB
1638 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1639 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
010d7020 1640 }
08f3f44c
JB
1641 expect(
1642 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1643 pool.workerChoiceStrategyContext.workerChoiceStrategy
1644 ).defaultWorkerWeight
1645 ).toBeGreaterThan(0)
1646 expect(
1647 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1648 pool.workerChoiceStrategyContext.workerChoiceStrategy
1649 ).workerVirtualTaskRunTime
1650 ).toBeGreaterThanOrEqual(0)
010d7020
JB
1651 // We need to clean up the resources after our test
1652 await pool.destroy()
1653 })
1654
a6f7f1b4 1655 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 1656 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 1657 let pool = new FixedThreadPool(
caeb9817
JB
1658 max,
1659 './tests/worker-files/thread/testWorker.js'
1660 )
38f6e859 1661 expect(
95c83464 1662 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1663 workerChoiceStrategy
d33be430 1664 ).nextWorkerNodeId
b529c323 1665 ).toBeDefined()
38f6e859 1666 expect(
95c83464 1667 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1668 workerChoiceStrategy
b529c323
JB
1669 ).defaultWorkerWeight
1670 ).toBeDefined()
caeb9817 1671 expect(
95c83464 1672 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1673 workerChoiceStrategy
08f3f44c 1674 ).workerVirtualTaskRunTime
b529c323 1675 ).toBeDefined()
594bfb84 1676 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1677 expect(
95c83464 1678 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1679 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1680 ).nextWorkerNodeId
a6f7f1b4
JB
1681 ).toBe(0)
1682 expect(
95c83464 1683 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1684 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1685 ).defaultWorkerWeight
a6f7f1b4 1686 ).toBeGreaterThan(0)
08f3f44c
JB
1687 expect(
1688 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1689 workerChoiceStrategy
1690 ).workerVirtualTaskRunTime
1691 ).toBe(0)
f0829c53
JB
1692 await pool.destroy()
1693 pool = new DynamicThreadPool(
1694 min,
1695 max,
1696 './tests/worker-files/thread/testWorker.js'
1697 )
38f6e859 1698 expect(
95c83464 1699 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1700 workerChoiceStrategy
d33be430 1701 ).nextWorkerNodeId
b529c323 1702 ).toBeDefined()
38f6e859 1703 expect(
95c83464 1704 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1705 workerChoiceStrategy
b529c323
JB
1706 ).defaultWorkerWeight
1707 ).toBeDefined()
f0829c53 1708 expect(
95c83464 1709 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1710 workerChoiceStrategy
08f3f44c 1711 ).workerVirtualTaskRunTime
b529c323 1712 ).toBeDefined()
594bfb84 1713 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1714 expect(
95c83464 1715 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1716 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1717 ).nextWorkerNodeId
a6f7f1b4
JB
1718 ).toBe(0)
1719 expect(
95c83464 1720 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1721 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1722 ).defaultWorkerWeight
a6f7f1b4 1723 ).toBeGreaterThan(0)
08f3f44c
JB
1724 expect(
1725 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1726 workerChoiceStrategy
1727 ).workerVirtualTaskRunTime
1728 ).toBe(0)
caeb9817
JB
1729 // We need to clean up the resources after our test
1730 await pool.destroy()
1731 })
1732
6c6afb84
JB
1733 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1734 const workerChoiceStrategy =
1735 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1736 let pool = new FixedThreadPool(
1737 max,
1738 './tests/worker-files/thread/testWorker.js',
1739 { workerChoiceStrategy }
1740 )
1741 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1742 useDynamicWorker: true
1743 })
1744 await pool.destroy()
1745 pool = new DynamicThreadPool(
1746 min,
1747 max,
1748 './tests/worker-files/thread/testWorker.js',
1749 { workerChoiceStrategy }
1750 )
1751 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1752 useDynamicWorker: true
1753 })
1754 // We need to clean up the resources after our test
1755 await pool.destroy()
1756 })
1757
1758 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
e52fb978
JB
1759 const workerChoiceStrategy =
1760 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1761 let pool = new FixedThreadPool(
1762 max,
1763 './tests/worker-files/thread/testWorker.js',
1764 { workerChoiceStrategy }
1765 )
87de9ff5
JB
1766 expect(
1767 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1768 ).toStrictEqual({
932fc8be
JB
1769 runTime: {
1770 aggregate: false,
1771 average: false,
1772 median: false
1773 },
1774 waitTime: {
1775 aggregate: false,
1776 average: false,
1777 median: false
1778 },
5df69fab
JB
1779 elu: {
1780 aggregate: false,
1781 average: false,
1782 median: false
1783 }
e52fb978
JB
1784 })
1785 await pool.destroy()
1786 pool = new DynamicThreadPool(
1787 min,
1788 max,
1789 './tests/worker-files/thread/testWorker.js',
1790 { workerChoiceStrategy }
1791 )
87de9ff5
JB
1792 expect(
1793 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1794 ).toStrictEqual({
932fc8be
JB
1795 runTime: {
1796 aggregate: false,
1797 average: false,
1798 median: false
1799 },
1800 waitTime: {
1801 aggregate: false,
1802 average: false,
1803 median: false
1804 },
5df69fab
JB
1805 elu: {
1806 aggregate: false,
1807 average: false,
1808 median: false
1809 }
e52fb978
JB
1810 })
1811 // We need to clean up the resources after our test
1812 await pool.destroy()
1813 })
1814
e62e7646
JB
1815 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1816 const pool = new FixedThreadPool(
1817 max,
1818 './tests/worker-files/thread/testWorker.js',
1819 {
1820 workerChoiceStrategy:
1821 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1822 }
1823 )
1824 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1825 const promises = new Set()
1826 const maxMultiplier = 2
1827 for (let i = 0; i < max * maxMultiplier; i++) {
1828 promises.add(pool.execute())
1829 }
1830 await Promise.all(promises)
1831 for (const workerNode of pool.workerNodes) {
465b2940 1832 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1833 tasks: {
1834 executed: maxMultiplier,
1835 executing: 0,
1836 queued: 0,
df593701 1837 maxQueued: 0,
a4e07f72
JB
1838 failed: 0
1839 },
1840 runTime: {
932fc8be 1841 aggregate: 0,
a4e07f72
JB
1842 average: 0,
1843 median: 0,
1844 history: expect.any(CircularArray)
1845 },
1846 waitTime: {
932fc8be 1847 aggregate: 0,
a4e07f72
JB
1848 average: 0,
1849 median: 0,
1850 history: expect.any(CircularArray)
1851 },
5df69fab
JB
1852 elu: {
1853 idle: {
1854 aggregate: 0,
1855 average: 0,
1856 median: 0,
1857 history: expect.any(CircularArray)
1858 },
1859 active: {
1860 aggregate: 0,
1861 average: 0,
1862 median: 0,
1863 history: expect.any(CircularArray)
1864 },
1865 utilization: 0
1866 }
e62e7646
JB
1867 })
1868 }
1869 expect(
1870 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1871 pool.workerChoiceStrategyContext.workerChoiceStrategy
1872 ).defaultWorkerWeight
1873 ).toBeGreaterThan(0)
1874 expect(
1875 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1876 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1877 ).roundId
e62e7646
JB
1878 ).toBe(0)
1879 expect(
1880 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1881 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1882 ).nextWorkerNodeId
e62e7646
JB
1883 ).toBe(0)
1884 expect(
1885 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1886 pool.workerChoiceStrategyContext.workerChoiceStrategy
1887 ).roundWeights
1888 ).toStrictEqual([
1889 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1890 pool.workerChoiceStrategyContext.workerChoiceStrategy
1891 ).defaultWorkerWeight
1892 ])
1893 // We need to clean up the resources after our test
1894 await pool.destroy()
1895 })
1896
1897 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1898 const pool = new DynamicThreadPool(
1899 min,
1900 max,
1901 './tests/worker-files/thread/testWorker.js',
1902 {
1903 workerChoiceStrategy:
1904 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1905 }
1906 )
1907 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1908 const promises = new Set()
1909 const maxMultiplier = 2
1910 for (let i = 0; i < max * maxMultiplier; i++) {
1911 promises.add(pool.execute())
1912 }
1913 await Promise.all(promises)
1914 for (const workerNode of pool.workerNodes) {
465b2940 1915 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1916 tasks: {
1917 executed: maxMultiplier,
1918 executing: 0,
1919 queued: 0,
df593701 1920 maxQueued: 0,
a4e07f72
JB
1921 failed: 0
1922 },
1923 runTime: {
932fc8be 1924 aggregate: 0,
a4e07f72
JB
1925 average: 0,
1926 median: 0,
1927 history: expect.any(CircularArray)
1928 },
1929 waitTime: {
932fc8be 1930 aggregate: 0,
a4e07f72
JB
1931 average: 0,
1932 median: 0,
1933 history: expect.any(CircularArray)
1934 },
5df69fab
JB
1935 elu: {
1936 idle: {
1937 aggregate: 0,
1938 average: 0,
1939 median: 0,
1940 history: expect.any(CircularArray)
1941 },
1942 active: {
1943 aggregate: 0,
1944 average: 0,
1945 median: 0,
1946 history: expect.any(CircularArray)
1947 },
1948 utilization: 0
1949 }
e62e7646
JB
1950 })
1951 }
1952 expect(
1953 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1954 pool.workerChoiceStrategyContext.workerChoiceStrategy
1955 ).defaultWorkerWeight
1956 ).toBeGreaterThan(0)
1957 expect(
1958 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1959 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1960 ).roundId
e62e7646
JB
1961 ).toBe(0)
1962 expect(
1963 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1964 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 1965 ).nextWorkerNodeId
e62e7646
JB
1966 ).toBe(0)
1967 expect(
1968 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1969 pool.workerChoiceStrategyContext.workerChoiceStrategy
1970 ).roundWeights
1971 ).toStrictEqual([
1972 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1973 pool.workerChoiceStrategyContext.workerChoiceStrategy
1974 ).defaultWorkerWeight
1975 ])
1976 // We need to clean up the resources after our test
1977 await pool.destroy()
1978 })
1979
8c3ec188
JB
1980 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1981 const workerChoiceStrategy =
1982 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1983 let pool = new FixedThreadPool(
1984 max,
1985 './tests/worker-files/thread/testWorker.js'
1986 )
1987 expect(
1988 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1989 workerChoiceStrategy
d33be430 1990 ).roundId
8c3ec188
JB
1991 ).toBeDefined()
1992 expect(
1993 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1994 workerChoiceStrategy
d33be430 1995 ).nextWorkerNodeId
8c3ec188
JB
1996 ).toBeDefined()
1997 expect(
1998 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1999 workerChoiceStrategy
2000 ).defaultWorkerWeight
2001 ).toBeDefined()
2002 expect(
2003 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2004 workerChoiceStrategy
2005 ).roundWeights
2006 ).toBeDefined()
2007 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2008 expect(
2009 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2010 workerChoiceStrategy
d33be430 2011 ).roundId
8c3ec188
JB
2012 ).toBe(0)
2013 expect(
2014 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2015 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 2016 ).nextWorkerNodeId
8c3ec188
JB
2017 ).toBe(0)
2018 expect(
2019 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2020 pool.workerChoiceStrategyContext.workerChoiceStrategy
2021 ).defaultWorkerWeight
2022 ).toBeGreaterThan(0)
2023 expect(
2024 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2025 workerChoiceStrategy
2026 ).roundWeights
2027 ).toStrictEqual([
2028 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2029 pool.workerChoiceStrategyContext.workerChoiceStrategy
2030 ).defaultWorkerWeight
2031 ])
2032 await pool.destroy()
2033 pool = new DynamicThreadPool(
2034 min,
2035 max,
2036 './tests/worker-files/thread/testWorker.js'
2037 )
2038 expect(
2039 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2040 workerChoiceStrategy
d33be430 2041 ).roundId
8c3ec188
JB
2042 ).toBeDefined()
2043 expect(
2044 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2045 workerChoiceStrategy
d33be430 2046 ).nextWorkerNodeId
8c3ec188
JB
2047 ).toBeDefined()
2048 expect(
2049 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2050 workerChoiceStrategy
2051 ).defaultWorkerWeight
2052 ).toBeDefined()
2053 expect(
2054 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2055 workerChoiceStrategy
2056 ).roundWeights
2057 ).toBeDefined()
2058 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2059 expect(
2060 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2061 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 2062 ).nextWorkerNodeId
8c3ec188
JB
2063 ).toBe(0)
2064 expect(
2065 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2066 pool.workerChoiceStrategyContext.workerChoiceStrategy
2067 ).defaultWorkerWeight
2068 ).toBeGreaterThan(0)
2069 expect(
2070 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2071 workerChoiceStrategy
2072 ).roundWeights
2073 ).toStrictEqual([
2074 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2075 pool.workerChoiceStrategyContext.workerChoiceStrategy
2076 ).defaultWorkerWeight
2077 ])
2078 // We need to clean up the resources after our test
2079 await pool.destroy()
2080 })
2081
89b09b26 2082 it('Verify unknown strategy throw error', () => {
a35560ba
S
2083 expect(
2084 () =>
2085 new DynamicThreadPool(
2086 min,
2087 max,
2088 './tests/worker-files/thread/testWorker.js',
1927ee67 2089 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 2090 )
d4aeae5a 2091 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
2092 })
2093})