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