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