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