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