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