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