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