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