fix: fix build after merge with main
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
a35560ba
S
2const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
2ced693a
JB
5 FixedThreadPool,
6 FixedClusterPool
cdace0e5 7} = require('../../../lib')
86bf340d 8const { CircularArray } = require('../../../lib/circular-array')
a35560ba
S
9
10describe('Selection strategies test suite', () => {
e1ffb94f
JB
11 const min = 0
12 const max = 3
13
a35560ba
S
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
e4543b14 16 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
cdb517b3 17 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
e4543b14 18 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
23ff945a 19 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
20 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
21 'WEIGHTED_ROUND_ROBIN'
22 )
feec6e8c
JB
23 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
24 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
25 )
a35560ba
S
26 })
27
e843b904 28 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
29 const pool = new DynamicThreadPool(
30 min,
31 max,
32 './tests/worker-files/thread/testWorker.js'
33 )
34 expect(pool.opts.workerChoiceStrategy).toBe(
35 WorkerChoiceStrategies.ROUND_ROBIN
36 )
37 // We need to clean up the resources after our test
38 await pool.destroy()
39 })
40
594bfb84
JB
41 it('Verify available strategies are taken at pool creation', async () => {
42 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
43 const pool = new FixedThreadPool(
44 max,
45 './tests/worker-files/thread/testWorker.js',
46 { workerChoiceStrategy }
47 )
48 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
49 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
50 workerChoiceStrategy
51 )
52 await pool.destroy()
53 }
d2f7b7a2
JB
54 })
55
594bfb84
JB
56 it('Verify available strategies can be set after pool creation', async () => {
57 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
58 const pool = new DynamicThreadPool(
59 min,
60 max,
ec82cfa1 61 './tests/worker-files/thread/testWorker.js'
594bfb84
JB
62 )
63 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
64 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
65 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
66 workerChoiceStrategy
67 )
68 await pool.destroy()
69 }
70 })
71
72 it('Verify available strategies default internals at pool creation', async () => {
73 const pool = new FixedThreadPool(
e843b904
JB
74 max,
75 './tests/worker-files/thread/testWorker.js'
76 )
594bfb84
JB
77 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
78 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
79 expect(
80 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
81 workerChoiceStrategy
82 ).nextWorkerNodeId
83 ).toBe(0)
84 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
08f3f44c
JB
85 expect(
86 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
87 workerChoiceStrategy
b0d6ed8f 88 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
89 ).toBeInstanceOf(Array)
90 expect(
91 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
92 workerChoiceStrategy
b0d6ed8f 93 ).workersVirtualTaskEndTimestamp.length
08f3f44c 94 ).toBe(0)
594bfb84
JB
95 } else if (
96 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
97 ) {
98 expect(
99 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
100 workerChoiceStrategy
101 ).currentWorkerNodeId
102 ).toBe(0)
103 expect(
104 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
105 workerChoiceStrategy
106 ).defaultWorkerWeight
107 ).toBeGreaterThan(0)
08f3f44c
JB
108 expect(
109 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
110 workerChoiceStrategy
111 ).workerVirtualTaskRunTime
112 ).toBe(0)
594bfb84
JB
113 }
114 }
e843b904
JB
115 await pool.destroy()
116 })
117
10fcfaf4 118 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 119 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
120 let pool = new FixedThreadPool(
121 max,
d710242d 122 './tests/worker-files/thread/testWorker.js',
594bfb84 123 { workerChoiceStrategy }
10fcfaf4 124 )
b6b32453 125 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
126 runTime: false,
127 avgRunTime: false,
128 medRunTime: false,
129 waitTime: false,
130 avgWaitTime: false,
d44d5953
JB
131 medWaitTime: false,
132 elu: false
86bf340d 133 })
fd7ebd49 134 await pool.destroy()
10fcfaf4
JB
135 pool = new DynamicThreadPool(
136 min,
137 max,
d710242d 138 './tests/worker-files/thread/testWorker.js',
594bfb84 139 { workerChoiceStrategy }
10fcfaf4 140 )
b6b32453 141 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
142 runTime: false,
143 avgRunTime: false,
144 medRunTime: false,
145 waitTime: false,
146 avgWaitTime: false,
d44d5953
JB
147 medWaitTime: false,
148 elu: false
86bf340d 149 })
10fcfaf4
JB
150 // We need to clean up the resources after our test
151 await pool.destroy()
152 })
153
bdaf31cd 154 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
bdaf31cd
JB
155 const pool = new FixedThreadPool(
156 max,
157 './tests/worker-files/thread/testWorker.js',
158 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
159 )
bdaf31cd 160 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 161 const promises = new Set()
a20f0ba5
JB
162 const maxMultiplier = 2
163 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 164 promises.add(pool.execute())
e211bc18
JB
165 }
166 await Promise.all(promises)
167 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
168 expect(workerNode.workerUsage).toStrictEqual({
169 tasks: {
170 executed: maxMultiplier,
171 executing: 0,
172 queued: 0,
173 failed: 0
174 },
175 runTime: {
176 aggregation: 0,
177 average: 0,
178 median: 0,
179 history: expect.any(CircularArray)
180 },
181 waitTime: {
182 aggregation: 0,
183 average: 0,
184 median: 0,
185 history: expect.any(CircularArray)
186 },
d44d5953 187 elu: undefined
e211bc18 188 })
bdaf31cd 189 }
9458090a
JB
190 expect(
191 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
192 WorkerChoiceStrategies.ROUND_ROBIN
193 ).nextWorkerNodeId
194 ).toBe(0)
bdaf31cd
JB
195 // We need to clean up the resources after our test
196 await pool.destroy()
197 })
198
199 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
bdaf31cd
JB
200 const pool = new DynamicThreadPool(
201 min,
202 max,
203 './tests/worker-files/thread/testWorker.js',
204 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
205 )
bdaf31cd 206 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 207 const promises = new Set()
a20f0ba5
JB
208 const maxMultiplier = 2
209 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 210 promises.add(pool.execute())
e211bc18
JB
211 }
212 await Promise.all(promises)
213 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
214 expect(workerNode.workerUsage).toStrictEqual({
215 tasks: {
216 executed: maxMultiplier,
217 executing: 0,
218 queued: 0,
219 failed: 0
220 },
221 runTime: {
222 aggregation: 0,
223 average: 0,
224 median: 0,
225 history: expect.any(CircularArray)
226 },
227 waitTime: {
228 aggregation: 0,
229 average: 0,
230 median: 0,
231 history: expect.any(CircularArray)
232 },
d44d5953 233 elu: undefined
e211bc18 234 })
bdaf31cd 235 }
9458090a
JB
236 expect(
237 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
238 WorkerChoiceStrategies.ROUND_ROBIN
239 ).nextWorkerNodeId
240 ).toBe(0)
bdaf31cd
JB
241 // We need to clean up the resources after our test
242 await pool.destroy()
243 })
244
2ced693a 245 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 246 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
247 let pool = new FixedClusterPool(
248 max,
594bfb84
JB
249 './tests/worker-files/cluster/testWorker.js',
250 { workerChoiceStrategy }
2ced693a
JB
251 )
252 let results = new Set()
253 for (let i = 0; i < max; i++) {
20dcad1a 254 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
2ced693a
JB
255 }
256 expect(results.size).toBe(max)
257 await pool.destroy()
594bfb84
JB
258 pool = new FixedThreadPool(
259 max,
260 './tests/worker-files/thread/testWorker.js',
261 { workerChoiceStrategy }
262 )
2ced693a
JB
263 results = new Set()
264 for (let i = 0; i < max; i++) {
20dcad1a 265 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
2ced693a
JB
266 }
267 expect(results.size).toBe(max)
268 await pool.destroy()
269 })
270
a6f7f1b4 271 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 272 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
273 let pool = new FixedThreadPool(
274 max,
275 './tests/worker-files/thread/testWorker.js',
276 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
277 )
38f6e859 278 expect(
95c83464 279 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 280 workerChoiceStrategy
f06e48d8 281 ).nextWorkerNodeId
b529c323 282 ).toBeDefined()
594bfb84 283 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 284 expect(
95c83464 285 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 286 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 287 ).nextWorkerNodeId
a6f7f1b4
JB
288 ).toBe(0)
289 await pool.destroy()
290 pool = new DynamicThreadPool(
291 min,
292 max,
293 './tests/worker-files/thread/testWorker.js',
294 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
295 )
38f6e859 296 expect(
95c83464 297 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 298 workerChoiceStrategy
f06e48d8 299 ).nextWorkerNodeId
b529c323 300 ).toBeDefined()
594bfb84 301 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 302 expect(
95c83464 303 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 304 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 305 ).nextWorkerNodeId
a6f7f1b4
JB
306 ).toBe(0)
307 // We need to clean up the resources after our test
308 await pool.destroy()
309 })
310
e4543b14
JB
311 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
312 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
10fcfaf4
JB
313 let pool = new FixedThreadPool(
314 max,
d710242d 315 './tests/worker-files/thread/testWorker.js',
594bfb84 316 { workerChoiceStrategy }
10fcfaf4 317 )
b6b32453 318 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
319 runTime: false,
320 avgRunTime: false,
321 medRunTime: false,
322 waitTime: false,
323 avgWaitTime: false,
d44d5953
JB
324 medWaitTime: false,
325 elu: false
86bf340d 326 })
fd7ebd49 327 await pool.destroy()
10fcfaf4
JB
328 pool = new DynamicThreadPool(
329 min,
330 max,
d710242d 331 './tests/worker-files/thread/testWorker.js',
594bfb84 332 { workerChoiceStrategy }
10fcfaf4 333 )
b6b32453 334 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
335 runTime: false,
336 avgRunTime: false,
337 medRunTime: false,
338 waitTime: false,
339 avgWaitTime: false,
d44d5953
JB
340 medWaitTime: false,
341 elu: false
86bf340d 342 })
10fcfaf4
JB
343 // We need to clean up the resources after our test
344 await pool.destroy()
345 })
346
e4543b14 347 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
348 const pool = new FixedThreadPool(
349 max,
350 './tests/worker-files/thread/testWorker.js',
e4543b14 351 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
b98ec2e6 352 )
e4543b14 353 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 354 const promises = new Set()
a20f0ba5
JB
355 const maxMultiplier = 2
356 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 357 promises.add(pool.execute())
e211bc18
JB
358 }
359 await Promise.all(promises)
360 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
361 expect(workerNode.workerUsage).toStrictEqual({
362 tasks: {
363 executed: maxMultiplier,
364 executing: 0,
365 queued: 0,
366 failed: 0
367 },
368 runTime: {
369 aggregation: 0,
370 average: 0,
371 median: 0,
372 history: expect.any(CircularArray)
373 },
374 waitTime: {
375 aggregation: 0,
376 average: 0,
377 median: 0,
378 history: expect.any(CircularArray)
379 },
d44d5953 380 elu: undefined
e211bc18 381 })
a35560ba 382 }
a35560ba
S
383 // We need to clean up the resources after our test
384 await pool.destroy()
385 })
386
e4543b14 387 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
388 const pool = new DynamicThreadPool(
389 min,
390 max,
391 './tests/worker-files/thread/testWorker.js',
e4543b14 392 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
ff5e76e1 393 )
e4543b14 394 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 395 const promises = new Set()
a20f0ba5
JB
396 const maxMultiplier = 2
397 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 398 promises.add(pool.execute())
e211bc18
JB
399 }
400 await Promise.all(promises)
401 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
402 expect(workerNode.workerUsage).toStrictEqual({
403 tasks: {
404 executed: maxMultiplier,
405 executing: 0,
406 queued: 0,
407 failed: 0
408 },
409 runTime: {
410 aggregation: 0,
411 average: 0,
412 median: 0,
413 history: expect.any(CircularArray)
414 },
415 waitTime: {
416 aggregation: 0,
417 average: 0,
418 median: 0,
419 history: expect.any(CircularArray)
420 },
421
d44d5953 422 elu: undefined
e211bc18 423 })
168c526f 424 }
168c526f
JB
425 // We need to clean up the resources after our test
426 await pool.destroy()
427 })
428
e4543b14
JB
429 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
430 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
168c526f
JB
431 let pool = new FixedThreadPool(
432 max,
d710242d 433 './tests/worker-files/thread/testWorker.js',
594bfb84 434 { workerChoiceStrategy }
168c526f 435 )
b6b32453 436 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
437 runTime: true,
438 avgRunTime: false,
439 medRunTime: false,
440 waitTime: false,
441 avgWaitTime: false,
d44d5953
JB
442 medWaitTime: false,
443 elu: false
86bf340d 444 })
168c526f
JB
445 await pool.destroy()
446 pool = new DynamicThreadPool(
447 min,
448 max,
d710242d 449 './tests/worker-files/thread/testWorker.js',
594bfb84 450 { workerChoiceStrategy }
168c526f 451 )
b6b32453 452 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
453 runTime: true,
454 avgRunTime: false,
455 medRunTime: false,
456 waitTime: false,
457 avgWaitTime: false,
d44d5953
JB
458 medWaitTime: false,
459 elu: false
86bf340d 460 })
168c526f
JB
461 // We need to clean up the resources after our test
462 await pool.destroy()
463 })
464
e4543b14 465 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
168c526f
JB
466 const pool = new FixedThreadPool(
467 max,
468 './tests/worker-files/thread/testWorker.js',
e4543b14 469 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 470 )
e4543b14 471 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 472 const promises = new Set()
a20f0ba5
JB
473 const maxMultiplier = 2
474 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 475 promises.add(pool.execute())
e211bc18
JB
476 }
477 await Promise.all(promises)
478 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
479 expect(workerNode.workerUsage).toStrictEqual({
480 tasks: {
481 executed: expect.any(Number),
482 executing: 0,
483 queued: 0,
484 failed: 0
485 },
486 runTime: {
487 aggregation: expect.any(Number),
488 average: 0,
489 median: 0,
490 history: expect.any(CircularArray)
491 },
492 waitTime: {
493 aggregation: 0,
494 average: 0,
495 median: 0,
496 history: expect.any(CircularArray)
497 },
d44d5953 498 elu: undefined
e211bc18 499 })
a4e07f72
JB
500 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
501 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
502 max * maxMultiplier
503 )
504 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThanOrEqual(
505 0
506 )
168c526f 507 }
168c526f
JB
508 // We need to clean up the resources after our test
509 await pool.destroy()
510 })
511
e4543b14 512 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
168c526f
JB
513 const pool = new DynamicThreadPool(
514 min,
515 max,
516 './tests/worker-files/thread/testWorker.js',
e4543b14 517 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 518 )
e4543b14 519 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 520 const promises = new Set()
a20f0ba5
JB
521 const maxMultiplier = 2
522 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 523 promises.add(pool.execute())
e211bc18
JB
524 }
525 await Promise.all(promises)
526 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
527 expect(workerNode.workerUsage).toStrictEqual({
528 tasks: {
529 executed: expect.any(Number),
530 executing: 0,
531 queued: 0,
532 failed: 0
533 },
534 runTime: {
535 aggregation: expect.any(Number),
536 average: 0,
537 median: 0,
538 history: expect.any(CircularArray)
539 },
540 waitTime: {
541 aggregation: 0,
542 average: 0,
543 median: 0,
544 history: expect.any(CircularArray)
545 },
d44d5953 546 elu: undefined
e211bc18 547 })
a4e07f72
JB
548 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
549 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
550 max * maxMultiplier
551 )
552 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
ff5e76e1 553 }
ff5e76e1
JB
554 // We need to clean up the resources after our test
555 await pool.destroy()
556 })
557
10fcfaf4 558 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
594bfb84 559 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
560 let pool = new FixedThreadPool(
561 max,
d710242d 562 './tests/worker-files/thread/testWorker.js',
594bfb84 563 { workerChoiceStrategy }
10fcfaf4 564 )
b6b32453 565 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
566 runTime: true,
567 avgRunTime: true,
568 medRunTime: false,
569 waitTime: false,
570 avgWaitTime: false,
d44d5953
JB
571 medWaitTime: false,
572 elu: false
86bf340d 573 })
fd7ebd49 574 await pool.destroy()
10fcfaf4
JB
575 pool = new DynamicThreadPool(
576 min,
577 max,
d710242d 578 './tests/worker-files/thread/testWorker.js',
594bfb84 579 { workerChoiceStrategy }
10fcfaf4 580 )
b6b32453 581 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
582 runTime: true,
583 avgRunTime: true,
584 medRunTime: false,
585 waitTime: false,
586 avgWaitTime: false,
d44d5953
JB
587 medWaitTime: false,
588 elu: false
86bf340d 589 })
10fcfaf4
JB
590 // We need to clean up the resources after our test
591 await pool.destroy()
592 })
593
23ff945a 594 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
595 const pool = new FixedThreadPool(
596 max,
597 './tests/worker-files/thread/testWorker.js',
598 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
599 )
600 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 601 const promises = new Set()
a20f0ba5
JB
602 const maxMultiplier = 2
603 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 604 promises.add(pool.execute())
23ff945a 605 }
e211bc18 606 await Promise.all(promises)
138d29a8 607 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
608 expect(workerNode.workerUsage).toStrictEqual({
609 tasks: {
610 executed: maxMultiplier,
611 executing: 0,
612 queued: 0,
613 failed: 0
614 },
615 runTime: {
616 aggregation: expect.any(Number),
617 average: expect.any(Number),
618 median: 0,
619 history: expect.any(CircularArray)
620 },
621 waitTime: {
622 aggregation: 0,
623 average: 0,
624 median: 0,
625 history: expect.any(CircularArray)
626 },
d44d5953 627 elu: undefined
86bf340d 628 })
a4e07f72
JB
629 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
630 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
138d29a8 631 }
97a2abc3 632 expect(
95c83464 633 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 634 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 635 ).workersVirtualTaskEndTimestamp.length
f06e48d8 636 ).toBe(pool.workerNodes.length)
23ff945a
JB
637 // We need to clean up the resources after our test
638 await pool.destroy()
639 })
640
641 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
642 const pool = new DynamicThreadPool(
643 min,
644 max,
645 './tests/worker-files/thread/testWorker.js',
646 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
647 )
648 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 649 const promises = new Set()
f7070eee 650 const maxMultiplier = 2
804a889e 651 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 652 promises.add(pool.execute())
23ff945a 653 }
e211bc18 654 await Promise.all(promises)
138d29a8 655 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
656 expect(workerNode.workerUsage).toStrictEqual({
657 tasks: {
658 executed: maxMultiplier,
659 executing: 0,
660 queued: 0,
661 failed: 0
662 },
663 runTime: {
664 aggregation: expect.any(Number),
665 average: expect.any(Number),
666 median: 0,
667 history: expect.any(CircularArray)
668 },
669 waitTime: {
670 aggregation: 0,
671 average: 0,
672 median: 0,
673 history: expect.any(CircularArray)
674 },
d44d5953 675 elu: undefined
86bf340d 676 })
a4e07f72
JB
677 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
678 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
138d29a8 679 }
2b4fddb8
JB
680 expect(
681 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
682 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 683 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 684 ).toBe(pool.workerNodes.length)
23ff945a
JB
685 // We need to clean up the resources after our test
686 await pool.destroy()
687 })
688
9e775f96 689 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
690 const pool = new DynamicThreadPool(
691 min,
692 max,
693 './tests/worker-files/thread/testWorker.js',
694 {
695 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
696 workerChoiceStrategyOptions: {
697 medRunTime: true
698 }
699 }
700 )
701 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 702 const promises = new Set()
010d7020
JB
703 const maxMultiplier = 2
704 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 705 promises.add(pool.execute())
010d7020 706 }
e211bc18 707 await Promise.all(promises)
010d7020 708 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
709 expect(workerNode.workerUsage).toStrictEqual({
710 tasks: {
711 executed: maxMultiplier,
712 executing: 0,
713 queued: 0,
714 failed: 0
715 },
716 runTime: {
717 aggregation: expect.any(Number),
718 average: 0,
719 median: expect.any(Number),
720 history: expect.any(CircularArray)
721 },
722 waitTime: {
723 aggregation: 0,
724 average: 0,
725 median: 0,
726 history: expect.any(CircularArray)
727 },
d44d5953 728 elu: undefined
86bf340d 729 })
a4e07f72
JB
730 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
731 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
010d7020 732 }
2b4fddb8
JB
733 expect(
734 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
735 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 736 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 737 ).toBe(pool.workerNodes.length)
010d7020
JB
738 // We need to clean up the resources after our test
739 await pool.destroy()
740 })
741
a6f7f1b4 742 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 743 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 744 let pool = new FixedThreadPool(
caeb9817
JB
745 max,
746 './tests/worker-files/thread/testWorker.js'
747 )
748 expect(
95c83464 749 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 750 workerChoiceStrategy
b0d6ed8f 751 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
752 ).toBeInstanceOf(Array)
753 expect(
754 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
755 workerChoiceStrategy
b0d6ed8f 756 ).workersVirtualTaskEndTimestamp.length
08f3f44c 757 ).toBe(0)
2b4fddb8
JB
758 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
759 workerChoiceStrategy
b0d6ed8f 760 ).workersVirtualTaskEndTimestamp[0] = performance.now()
2b4fddb8
JB
761 expect(
762 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
763 workerChoiceStrategy
b0d6ed8f 764 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 765 ).toBe(1)
594bfb84 766 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
767 expect(
768 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
769 workerChoiceStrategy
b0d6ed8f 770 ).workersVirtualTaskEndTimestamp
08f3f44c 771 ).toBeInstanceOf(Array)
08f3f44c
JB
772 expect(
773 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
774 workerChoiceStrategy
b0d6ed8f 775 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 776 ).toBe(0)
f0829c53
JB
777 await pool.destroy()
778 pool = new DynamicThreadPool(
779 min,
780 max,
781 './tests/worker-files/thread/testWorker.js'
782 )
783 expect(
95c83464 784 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 785 workerChoiceStrategy
b0d6ed8f 786 ).workersVirtualTaskEndTimestamp
08f3f44c 787 ).toBeInstanceOf(Array)
2b4fddb8
JB
788 expect(
789 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
790 workerChoiceStrategy
b0d6ed8f 791 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 792 ).toBe(0)
08f3f44c
JB
793 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
794 workerChoiceStrategy
b0d6ed8f 795 ).workersVirtualTaskEndTimestamp[0] = performance.now()
08f3f44c
JB
796 expect(
797 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
798 workerChoiceStrategy
b0d6ed8f 799 ).workersVirtualTaskEndTimestamp.length
08f3f44c 800 ).toBe(1)
594bfb84 801 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
802 expect(
803 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
804 workerChoiceStrategy
b0d6ed8f 805 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
806 ).toBeInstanceOf(Array)
807 expect(
808 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
809 workerChoiceStrategy
b0d6ed8f 810 ).workersVirtualTaskEndTimestamp.length
08f3f44c 811 ).toBe(0)
caeb9817
JB
812 // We need to clean up the resources after our test
813 await pool.destroy()
814 })
815
10fcfaf4 816 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 817 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
818 let pool = new FixedThreadPool(
819 max,
d710242d 820 './tests/worker-files/thread/testWorker.js',
594bfb84 821 { workerChoiceStrategy }
10fcfaf4 822 )
b6b32453 823 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
824 runTime: true,
825 avgRunTime: true,
826 medRunTime: false,
827 waitTime: false,
828 avgWaitTime: false,
d44d5953
JB
829 medWaitTime: false,
830 elu: false
86bf340d 831 })
fd7ebd49 832 await pool.destroy()
10fcfaf4
JB
833 pool = new DynamicThreadPool(
834 min,
835 max,
d710242d 836 './tests/worker-files/thread/testWorker.js',
594bfb84 837 { workerChoiceStrategy }
10fcfaf4 838 )
b6b32453 839 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
840 runTime: true,
841 avgRunTime: true,
842 medRunTime: false,
843 waitTime: false,
844 avgWaitTime: false,
d44d5953
JB
845 medWaitTime: false,
846 elu: false
86bf340d 847 })
10fcfaf4
JB
848 // We need to clean up the resources after our test
849 await pool.destroy()
850 })
851
b3432a63 852 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
853 const pool = new FixedThreadPool(
854 max,
855 './tests/worker-files/thread/testWorker.js',
856 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
857 )
858 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 859 const promises = new Set()
a20f0ba5
JB
860 const maxMultiplier = 2
861 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 862 promises.add(pool.execute())
b3432a63 863 }
e211bc18 864 await Promise.all(promises)
138d29a8 865 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
866 expect(workerNode.workerUsage).toStrictEqual({
867 tasks: {
868 executed: expect.any(Number),
869 executing: 0,
870 queued: 0,
871 failed: 0
872 },
873 runTime: {
874 aggregation: expect.any(Number),
875 average: expect.any(Number),
876 median: 0,
877 history: expect.any(CircularArray)
878 },
879 waitTime: {
880 aggregation: 0,
881 average: 0,
882 median: 0,
883 history: expect.any(CircularArray)
884 },
d44d5953 885 elu: undefined
86bf340d 886 })
a4e07f72
JB
887 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
888 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
889 max * maxMultiplier
890 )
891 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThanOrEqual(
892 0
893 )
894 expect(workerNode.workerUsage.runTime.average).toBeGreaterThanOrEqual(0)
138d29a8 895 }
97a2abc3 896 expect(
95c83464 897 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 898 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
899 ).defaultWorkerWeight
900 ).toBeGreaterThan(0)
901 expect(
902 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
903 pool.workerChoiceStrategyContext.workerChoiceStrategy
904 ).workerVirtualTaskRunTime
905 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
906 // We need to clean up the resources after our test
907 await pool.destroy()
908 })
909
910 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
911 const pool = new DynamicThreadPool(
912 min,
913 max,
914 './tests/worker-files/thread/testWorker.js',
915 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
916 )
917 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 918 const promises = new Set()
138d29a8 919 const maxMultiplier = 2
5502c07c 920 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 921 promises.add(pool.execute())
b3432a63 922 }
e211bc18 923 await Promise.all(promises)
138d29a8 924 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
925 expect(workerNode.workerUsage).toStrictEqual({
926 tasks: {
927 executed: expect.any(Number),
928 executing: 0,
929 queued: 0,
930 failed: 0
931 },
932 runTime: {
933 aggregation: expect.any(Number),
934 average: expect.any(Number),
935 median: 0,
936 history: expect.any(CircularArray)
937 },
938 waitTime: {
939 aggregation: 0,
940 average: 0,
941 median: 0,
942 history: expect.any(CircularArray)
943 },
d44d5953 944 elu: undefined
86bf340d 945 })
a4e07f72
JB
946 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
947 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
948 max * maxMultiplier
949 )
950 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
951 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
138d29a8 952 }
2b4fddb8
JB
953 expect(
954 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
955 pool.workerChoiceStrategyContext.workerChoiceStrategy
956 ).defaultWorkerWeight
957 ).toBeGreaterThan(0)
958 expect(
959 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
960 pool.workerChoiceStrategyContext.workerChoiceStrategy
961 ).workerVirtualTaskRunTime
962 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
963 // We need to clean up the resources after our test
964 await pool.destroy()
965 })
966
9e775f96 967 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
968 const pool = new DynamicThreadPool(
969 min,
970 max,
971 './tests/worker-files/thread/testWorker.js',
972 {
973 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
974 workerChoiceStrategyOptions: {
975 medRunTime: true
976 }
977 }
978 )
979 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 980 const promises = new Set()
010d7020
JB
981 const maxMultiplier = 2
982 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 983 promises.add(pool.execute())
010d7020 984 }
e211bc18 985 await Promise.all(promises)
010d7020 986 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
987 expect(workerNode.workerUsage).toStrictEqual({
988 tasks: {
989 executed: expect.any(Number),
990 executing: 0,
991 queued: 0,
992 failed: 0
993 },
994 runTime: {
995 aggregation: expect.any(Number),
996 average: 0,
997 median: expect.any(Number),
998 history: expect.any(CircularArray)
999 },
1000 waitTime: {
1001 aggregation: 0,
1002 average: 0,
1003 median: 0,
1004 history: expect.any(CircularArray)
1005 },
d44d5953 1006 elu: undefined
86bf340d 1007 })
a4e07f72
JB
1008 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
1009 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1010 max * maxMultiplier
1011 )
1012 expect(workerNode.workerUsage.runTime.aggregation).toBeGreaterThan(0)
1013 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
010d7020 1014 }
08f3f44c
JB
1015 expect(
1016 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1017 pool.workerChoiceStrategyContext.workerChoiceStrategy
1018 ).defaultWorkerWeight
1019 ).toBeGreaterThan(0)
1020 expect(
1021 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1022 pool.workerChoiceStrategyContext.workerChoiceStrategy
1023 ).workerVirtualTaskRunTime
1024 ).toBeGreaterThanOrEqual(0)
010d7020
JB
1025 // We need to clean up the resources after our test
1026 await pool.destroy()
1027 })
1028
a6f7f1b4 1029 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 1030 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 1031 let pool = new FixedThreadPool(
caeb9817
JB
1032 max,
1033 './tests/worker-files/thread/testWorker.js'
1034 )
38f6e859 1035 expect(
95c83464 1036 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1037 workerChoiceStrategy
f06e48d8 1038 ).currentWorkerNodeId
b529c323 1039 ).toBeDefined()
38f6e859 1040 expect(
95c83464 1041 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1042 workerChoiceStrategy
b529c323
JB
1043 ).defaultWorkerWeight
1044 ).toBeDefined()
caeb9817 1045 expect(
95c83464 1046 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1047 workerChoiceStrategy
08f3f44c 1048 ).workerVirtualTaskRunTime
b529c323 1049 ).toBeDefined()
594bfb84 1050 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1051 expect(
95c83464 1052 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1053 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 1054 ).currentWorkerNodeId
a6f7f1b4
JB
1055 ).toBe(0)
1056 expect(
95c83464 1057 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1058 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1059 ).defaultWorkerWeight
a6f7f1b4 1060 ).toBeGreaterThan(0)
08f3f44c
JB
1061 expect(
1062 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1063 workerChoiceStrategy
1064 ).workerVirtualTaskRunTime
1065 ).toBe(0)
f0829c53
JB
1066 await pool.destroy()
1067 pool = new DynamicThreadPool(
1068 min,
1069 max,
1070 './tests/worker-files/thread/testWorker.js'
1071 )
38f6e859 1072 expect(
95c83464 1073 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1074 workerChoiceStrategy
f06e48d8 1075 ).currentWorkerNodeId
b529c323 1076 ).toBeDefined()
38f6e859 1077 expect(
95c83464 1078 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1079 workerChoiceStrategy
b529c323
JB
1080 ).defaultWorkerWeight
1081 ).toBeDefined()
f0829c53 1082 expect(
95c83464 1083 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1084 workerChoiceStrategy
08f3f44c 1085 ).workerVirtualTaskRunTime
b529c323 1086 ).toBeDefined()
594bfb84 1087 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1088 expect(
95c83464 1089 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1090 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 1091 ).currentWorkerNodeId
a6f7f1b4
JB
1092 ).toBe(0)
1093 expect(
95c83464 1094 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1095 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1096 ).defaultWorkerWeight
a6f7f1b4 1097 ).toBeGreaterThan(0)
08f3f44c
JB
1098 expect(
1099 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1100 workerChoiceStrategy
1101 ).workerVirtualTaskRunTime
1102 ).toBe(0)
caeb9817
JB
1103 // We need to clean up the resources after our test
1104 await pool.destroy()
1105 })
1106
e52fb978
JB
1107 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1108 const workerChoiceStrategy =
1109 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1110 let pool = new FixedThreadPool(
1111 max,
1112 './tests/worker-files/thread/testWorker.js',
1113 { workerChoiceStrategy }
1114 )
b6b32453 1115 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
e52fb978
JB
1116 runTime: false,
1117 avgRunTime: false,
1118 medRunTime: false,
1119 waitTime: false,
1120 avgWaitTime: false,
d44d5953
JB
1121 medWaitTime: false,
1122 elu: false
e52fb978
JB
1123 })
1124 await pool.destroy()
1125 pool = new DynamicThreadPool(
1126 min,
1127 max,
1128 './tests/worker-files/thread/testWorker.js',
1129 { workerChoiceStrategy }
1130 )
b6b32453 1131 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
e52fb978
JB
1132 runTime: false,
1133 avgRunTime: false,
1134 medRunTime: false,
1135 waitTime: false,
1136 avgWaitTime: false,
d44d5953
JB
1137 medWaitTime: false,
1138 elu: false
e52fb978
JB
1139 })
1140 // We need to clean up the resources after our test
1141 await pool.destroy()
1142 })
1143
e62e7646
JB
1144 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1145 const pool = new FixedThreadPool(
1146 max,
1147 './tests/worker-files/thread/testWorker.js',
1148 {
1149 workerChoiceStrategy:
1150 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1151 }
1152 )
1153 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1154 const promises = new Set()
1155 const maxMultiplier = 2
1156 for (let i = 0; i < max * maxMultiplier; i++) {
1157 promises.add(pool.execute())
1158 }
1159 await Promise.all(promises)
1160 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
1161 expect(workerNode.workerUsage).toStrictEqual({
1162 tasks: {
1163 executed: maxMultiplier,
1164 executing: 0,
1165 queued: 0,
1166 failed: 0
1167 },
1168 runTime: {
1169 aggregation: 0,
1170 average: 0,
1171 median: 0,
1172 history: expect.any(CircularArray)
1173 },
1174 waitTime: {
1175 aggregation: 0,
1176 average: 0,
1177 median: 0,
1178 history: expect.any(CircularArray)
1179 },
d44d5953 1180 elu: undefined
e62e7646
JB
1181 })
1182 }
1183 expect(
1184 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1185 pool.workerChoiceStrategyContext.workerChoiceStrategy
1186 ).defaultWorkerWeight
1187 ).toBeGreaterThan(0)
1188 expect(
1189 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1190 pool.workerChoiceStrategyContext.workerChoiceStrategy
1191 ).currentRoundId
1192 ).toBe(0)
1193 expect(
1194 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1195 pool.workerChoiceStrategyContext.workerChoiceStrategy
1196 ).currentWorkerNodeId
1197 ).toBe(0)
1198 expect(
1199 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1200 pool.workerChoiceStrategyContext.workerChoiceStrategy
1201 ).roundWeights
1202 ).toStrictEqual([
1203 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1204 pool.workerChoiceStrategyContext.workerChoiceStrategy
1205 ).defaultWorkerWeight
1206 ])
1207 // We need to clean up the resources after our test
1208 await pool.destroy()
1209 })
1210
1211 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1212 const pool = new DynamicThreadPool(
1213 min,
1214 max,
1215 './tests/worker-files/thread/testWorker.js',
1216 {
1217 workerChoiceStrategy:
1218 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1219 }
1220 )
1221 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1222 const promises = new Set()
1223 const maxMultiplier = 2
1224 for (let i = 0; i < max * maxMultiplier; i++) {
1225 promises.add(pool.execute())
1226 }
1227 await Promise.all(promises)
1228 for (const workerNode of pool.workerNodes) {
a4e07f72
JB
1229 expect(workerNode.workerUsage).toStrictEqual({
1230 tasks: {
1231 executed: maxMultiplier,
1232 executing: 0,
1233 queued: 0,
1234 failed: 0
1235 },
1236 runTime: {
1237 aggregation: 0,
1238 average: 0,
1239 median: 0,
1240 history: expect.any(CircularArray)
1241 },
1242 waitTime: {
1243 aggregation: 0,
1244 average: 0,
1245 median: 0,
1246 history: expect.any(CircularArray)
1247 },
d44d5953 1248 elu: undefined
e62e7646
JB
1249 })
1250 }
1251 expect(
1252 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1253 pool.workerChoiceStrategyContext.workerChoiceStrategy
1254 ).defaultWorkerWeight
1255 ).toBeGreaterThan(0)
1256 expect(
1257 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1258 pool.workerChoiceStrategyContext.workerChoiceStrategy
1259 ).currentRoundId
1260 ).toBe(0)
1261 expect(
1262 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1263 pool.workerChoiceStrategyContext.workerChoiceStrategy
1264 ).currentWorkerNodeId
1265 ).toBe(0)
1266 expect(
1267 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1268 pool.workerChoiceStrategyContext.workerChoiceStrategy
1269 ).roundWeights
1270 ).toStrictEqual([
1271 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1272 pool.workerChoiceStrategyContext.workerChoiceStrategy
1273 ).defaultWorkerWeight
1274 ])
1275 // We need to clean up the resources after our test
1276 await pool.destroy()
1277 })
1278
8c3ec188
JB
1279 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1280 const workerChoiceStrategy =
1281 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1282 let pool = new FixedThreadPool(
1283 max,
1284 './tests/worker-files/thread/testWorker.js'
1285 )
1286 expect(
1287 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1288 workerChoiceStrategy
1289 ).currentRoundId
1290 ).toBeDefined()
1291 expect(
1292 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1293 workerChoiceStrategy
1294 ).currentWorkerNodeId
1295 ).toBeDefined()
1296 expect(
1297 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1298 workerChoiceStrategy
1299 ).defaultWorkerWeight
1300 ).toBeDefined()
1301 expect(
1302 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1303 workerChoiceStrategy
1304 ).roundWeights
1305 ).toBeDefined()
1306 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1307 expect(
1308 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1309 workerChoiceStrategy
1310 ).currentRoundId
1311 ).toBe(0)
1312 expect(
1313 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1314 pool.workerChoiceStrategyContext.workerChoiceStrategy
1315 ).currentWorkerNodeId
1316 ).toBe(0)
1317 expect(
1318 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1319 pool.workerChoiceStrategyContext.workerChoiceStrategy
1320 ).defaultWorkerWeight
1321 ).toBeGreaterThan(0)
1322 expect(
1323 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1324 workerChoiceStrategy
1325 ).roundWeights
1326 ).toStrictEqual([
1327 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1328 pool.workerChoiceStrategyContext.workerChoiceStrategy
1329 ).defaultWorkerWeight
1330 ])
1331 await pool.destroy()
1332 pool = new DynamicThreadPool(
1333 min,
1334 max,
1335 './tests/worker-files/thread/testWorker.js'
1336 )
1337 expect(
1338 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1339 workerChoiceStrategy
1340 ).currentRoundId
1341 ).toBeDefined()
1342 expect(
1343 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1344 workerChoiceStrategy
1345 ).currentWorkerNodeId
1346 ).toBeDefined()
1347 expect(
1348 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1349 workerChoiceStrategy
1350 ).defaultWorkerWeight
1351 ).toBeDefined()
1352 expect(
1353 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1354 workerChoiceStrategy
1355 ).roundWeights
1356 ).toBeDefined()
1357 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1358 expect(
1359 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1360 pool.workerChoiceStrategyContext.workerChoiceStrategy
1361 ).currentWorkerNodeId
1362 ).toBe(0)
1363 expect(
1364 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1365 pool.workerChoiceStrategyContext.workerChoiceStrategy
1366 ).defaultWorkerWeight
1367 ).toBeGreaterThan(0)
1368 expect(
1369 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1370 workerChoiceStrategy
1371 ).roundWeights
1372 ).toStrictEqual([
1373 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1374 pool.workerChoiceStrategyContext.workerChoiceStrategy
1375 ).defaultWorkerWeight
1376 ])
1377 // We need to clean up the resources after our test
1378 await pool.destroy()
1379 })
1380
89b09b26 1381 it('Verify unknown strategy throw error', () => {
a35560ba
S
1382 expect(
1383 () =>
1384 new DynamicThreadPool(
1385 min,
1386 max,
1387 './tests/worker-files/thread/testWorker.js',
1927ee67 1388 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 1389 )
d4aeae5a 1390 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
1391 })
1392})