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