1 const { expect
} = require('expect')
3 WorkerChoiceStrategies
,
7 } = require('../../../lib')
8 const { CircularArray
} = require('../../../lib/circular-array')
10 describe('Selection strategies test suite', () => {
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies
.ROUND_ROBIN
).toBe('ROUND_ROBIN')
16 expect(WorkerChoiceStrategies
.LEAST_USED
).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies
.LEAST_BUSY
).toBe('LEAST_BUSY')
18 expect(WorkerChoiceStrategies
.LEAST_ELU
).toBe('LEAST_ELU')
19 expect(WorkerChoiceStrategies
.FAIR_SHARE
).toBe('FAIR_SHARE')
20 expect(WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
).toBe(
21 'WEIGHTED_ROUND_ROBIN'
23 expect(WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
).toBe(
24 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
28 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
29 const pool
= new DynamicThreadPool(
32 './tests/worker-files/thread/testWorker.js'
34 expect(pool
.opts
.workerChoiceStrategy
).toBe(
35 WorkerChoiceStrategies
.ROUND_ROBIN
37 // We need to clean up the resources after our test
41 it('Verify available strategies are taken at pool creation', async () => {
42 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
43 const pool
= new FixedThreadPool(
45 './tests/worker-files/thread/testWorker.js',
46 { workerChoiceStrategy
}
48 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
49 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
56 it('Verify available strategies can be set after pool creation', async () => {
57 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
58 const pool
= new DynamicThreadPool(
61 './tests/worker-files/thread/testWorker.js'
63 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
64 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
65 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
72 it('Verify available strategies default internals at pool creation', async () => {
73 const pool
= new FixedThreadPool(
75 './tests/worker-files/thread/testWorker.js'
77 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
78 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.ROUND_ROBIN
) {
80 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
84 } else if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
86 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
88 ).workersVirtualTaskEndTimestamp
89 ).toBeInstanceOf(Array
)
91 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
93 ).workersVirtualTaskEndTimestamp
.length
96 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
99 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
101 ).currentWorkerNodeId
104 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
106 ).defaultWorkerWeight
109 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
111 ).workerVirtualTaskRunTime
118 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
119 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
120 let pool
= new FixedThreadPool(
122 './tests/worker-files/thread/testWorker.js',
123 { workerChoiceStrategy
}
125 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
135 pool
= new DynamicThreadPool(
138 './tests/worker-files/thread/testWorker.js',
139 { workerChoiceStrategy
}
141 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
150 // We need to clean up the resources after our test
154 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
155 const pool
= new FixedThreadPool(
157 './tests/worker-files/thread/testWorker.js',
158 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
160 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
161 const promises
= new Set()
162 const maxMultiplier
= 2
163 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
164 promises
.add(pool
.execute())
166 await Promise
.all(promises
)
167 for (const workerNode
of pool
.workerNodes
) {
168 expect(workerNode
.workerUsage
).toStrictEqual({
170 executed
: maxMultiplier
,
179 history
: expect
.any(CircularArray
)
185 history
: expect
.any(CircularArray
)
191 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
192 WorkerChoiceStrategies
.ROUND_ROBIN
195 // We need to clean up the resources after our test
199 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
200 const pool
= new DynamicThreadPool(
203 './tests/worker-files/thread/testWorker.js',
204 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
206 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
207 const promises
= new Set()
208 const maxMultiplier
= 2
209 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
210 promises
.add(pool
.execute())
212 await Promise
.all(promises
)
213 for (const workerNode
of pool
.workerNodes
) {
214 expect(workerNode
.workerUsage
).toStrictEqual({
216 executed
: maxMultiplier
,
225 history
: expect
.any(CircularArray
)
231 history
: expect
.any(CircularArray
)
237 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
238 WorkerChoiceStrategies
.ROUND_ROBIN
241 // We need to clean up the resources after our test
245 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
246 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
247 let pool
= new FixedClusterPool(
249 './tests/worker-files/cluster/testWorker.js',
250 { workerChoiceStrategy
}
252 let results
= new Set()
253 for (let i
= 0; i
< max
; i
++) {
254 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
256 expect(results
.size
).toBe(max
)
258 pool
= new FixedThreadPool(
260 './tests/worker-files/thread/testWorker.js',
261 { workerChoiceStrategy
}
264 for (let i
= 0; i
< max
; i
++) {
265 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
267 expect(results
.size
).toBe(max
)
271 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
272 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
273 let pool
= new FixedThreadPool(
275 './tests/worker-files/thread/testWorker.js',
276 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
279 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
283 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
285 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
286 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
290 pool
= new DynamicThreadPool(
293 './tests/worker-files/thread/testWorker.js',
294 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
297 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
301 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
303 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
304 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
307 // We need to clean up the resources after our test
311 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
312 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
313 let pool
= new FixedThreadPool(
315 './tests/worker-files/thread/testWorker.js',
316 { workerChoiceStrategy
}
318 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
328 pool
= new DynamicThreadPool(
331 './tests/worker-files/thread/testWorker.js',
332 { workerChoiceStrategy
}
334 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
343 // We need to clean up the resources after our test
347 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
348 const pool
= new FixedThreadPool(
350 './tests/worker-files/thread/testWorker.js',
351 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
353 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
354 const promises
= new Set()
355 const maxMultiplier
= 2
356 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
357 promises
.add(pool
.execute())
359 await Promise
.all(promises
)
360 for (const workerNode
of pool
.workerNodes
) {
361 expect(workerNode
.workerUsage
).toStrictEqual({
363 executed
: maxMultiplier
,
372 history
: expect
.any(CircularArray
)
378 history
: expect
.any(CircularArray
)
383 // We need to clean up the resources after our test
387 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
388 const pool
= new DynamicThreadPool(
391 './tests/worker-files/thread/testWorker.js',
392 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
394 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
395 const promises
= new Set()
396 const maxMultiplier
= 2
397 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
398 promises
.add(pool
.execute())
400 await Promise
.all(promises
)
401 for (const workerNode
of pool
.workerNodes
) {
402 expect(workerNode
.workerUsage
).toStrictEqual({
404 executed
: maxMultiplier
,
413 history
: expect
.any(CircularArray
)
419 history
: expect
.any(CircularArray
)
425 // We need to clean up the resources after our test
429 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
430 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
431 let pool
= new FixedThreadPool(
433 './tests/worker-files/thread/testWorker.js',
434 { workerChoiceStrategy
}
436 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
446 pool
= new DynamicThreadPool(
449 './tests/worker-files/thread/testWorker.js',
450 { workerChoiceStrategy
}
452 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
461 // We need to clean up the resources after our test
465 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
466 const pool
= new FixedThreadPool(
468 './tests/worker-files/thread/testWorker.js',
469 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
471 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
472 const promises
= new Set()
473 const maxMultiplier
= 2
474 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
475 promises
.add(pool
.execute())
477 await Promise
.all(promises
)
478 for (const workerNode
of pool
.workerNodes
) {
479 expect(workerNode
.workerUsage
).toStrictEqual({
481 executed
: expect
.any(Number
),
487 aggregation
: expect
.any(Number
),
490 history
: expect
.any(CircularArray
)
496 history
: expect
.any(CircularArray
)
500 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
501 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
504 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
508 // We need to clean up the resources after our test
512 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
513 const pool
= new DynamicThreadPool(
516 './tests/worker-files/thread/testWorker.js',
517 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
519 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
520 const promises
= new Set()
521 const maxMultiplier
= 2
522 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
523 promises
.add(pool
.execute())
525 await Promise
.all(promises
)
526 for (const workerNode
of pool
.workerNodes
) {
527 expect(workerNode
.workerUsage
).toStrictEqual({
529 executed
: expect
.any(Number
),
535 aggregation
: expect
.any(Number
),
538 history
: expect
.any(CircularArray
)
544 history
: expect
.any(CircularArray
)
548 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
549 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
552 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
554 // We need to clean up the resources after our test
558 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
559 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
560 let pool
= new FixedThreadPool(
562 './tests/worker-files/thread/testWorker.js',
563 { workerChoiceStrategy
}
565 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
575 pool
= new DynamicThreadPool(
578 './tests/worker-files/thread/testWorker.js',
579 { workerChoiceStrategy
}
581 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
590 // We need to clean up the resources after our test
594 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
595 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
596 let pool
= new FixedThreadPool(
598 './tests/worker-files/thread/testWorker.js',
599 { workerChoiceStrategy
}
601 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
611 pool
= new DynamicThreadPool(
614 './tests/worker-files/thread/testWorker.js',
615 { workerChoiceStrategy
}
617 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
626 // We need to clean up the resources after our test
630 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
631 const pool
= new FixedThreadPool(
633 './tests/worker-files/thread/testWorker.js',
634 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
636 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
637 const promises
= new Set()
638 const maxMultiplier
= 2
639 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
640 promises
.add(pool
.execute())
642 await Promise
.all(promises
)
643 for (const workerNode
of pool
.workerNodes
) {
644 expect(workerNode
.workerUsage
).toStrictEqual({
646 executed
: maxMultiplier
,
652 aggregation
: expect
.any(Number
),
653 average
: expect
.any(Number
),
655 history
: expect
.any(CircularArray
)
661 history
: expect
.any(CircularArray
)
665 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
666 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
669 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
670 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
671 ).workersVirtualTaskEndTimestamp
.length
672 ).toBe(pool
.workerNodes
.length
)
673 // We need to clean up the resources after our test
677 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
678 const pool
= new DynamicThreadPool(
681 './tests/worker-files/thread/testWorker.js',
682 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
684 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
685 const promises
= new Set()
686 const maxMultiplier
= 2
687 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
688 promises
.add(pool
.execute())
690 await Promise
.all(promises
)
691 for (const workerNode
of pool
.workerNodes
) {
692 expect(workerNode
.workerUsage
).toStrictEqual({
694 executed
: maxMultiplier
,
700 aggregation
: expect
.any(Number
),
701 average
: expect
.any(Number
),
703 history
: expect
.any(CircularArray
)
709 history
: expect
.any(CircularArray
)
713 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
714 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
717 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
718 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
719 ).workersVirtualTaskEndTimestamp
.length
720 ).toBe(pool
.workerNodes
.length
)
721 // We need to clean up the resources after our test
725 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
726 const pool
= new DynamicThreadPool(
729 './tests/worker-files/thread/testWorker.js',
731 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
732 workerChoiceStrategyOptions
: {
737 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
738 const promises
= new Set()
739 const maxMultiplier
= 2
740 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
741 promises
.add(pool
.execute())
743 await Promise
.all(promises
)
744 for (const workerNode
of pool
.workerNodes
) {
745 expect(workerNode
.workerUsage
).toStrictEqual({
747 executed
: maxMultiplier
,
753 aggregation
: expect
.any(Number
),
755 median
: expect
.any(Number
),
756 history
: expect
.any(CircularArray
)
762 history
: expect
.any(CircularArray
)
766 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
767 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
770 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
771 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
772 ).workersVirtualTaskEndTimestamp
.length
773 ).toBe(pool
.workerNodes
.length
)
774 // We need to clean up the resources after our test
778 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
779 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
780 let pool
= new FixedThreadPool(
782 './tests/worker-files/thread/testWorker.js'
785 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
787 ).workersVirtualTaskEndTimestamp
788 ).toBeInstanceOf(Array
)
790 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
792 ).workersVirtualTaskEndTimestamp
.length
794 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
796 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
798 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
800 ).workersVirtualTaskEndTimestamp
.length
802 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
804 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
806 ).workersVirtualTaskEndTimestamp
807 ).toBeInstanceOf(Array
)
809 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
811 ).workersVirtualTaskEndTimestamp
.length
814 pool
= new DynamicThreadPool(
817 './tests/worker-files/thread/testWorker.js'
820 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
822 ).workersVirtualTaskEndTimestamp
823 ).toBeInstanceOf(Array
)
825 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
827 ).workersVirtualTaskEndTimestamp
.length
829 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
831 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
833 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
835 ).workersVirtualTaskEndTimestamp
.length
837 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
839 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
841 ).workersVirtualTaskEndTimestamp
842 ).toBeInstanceOf(Array
)
844 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
846 ).workersVirtualTaskEndTimestamp
.length
848 // We need to clean up the resources after our test
852 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
853 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
854 let pool
= new FixedThreadPool(
856 './tests/worker-files/thread/testWorker.js',
857 { workerChoiceStrategy
}
859 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
869 pool
= new DynamicThreadPool(
872 './tests/worker-files/thread/testWorker.js',
873 { workerChoiceStrategy
}
875 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
884 // We need to clean up the resources after our test
888 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
889 const pool
= new FixedThreadPool(
891 './tests/worker-files/thread/testWorker.js',
892 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
894 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
895 const promises
= new Set()
896 const maxMultiplier
= 2
897 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
898 promises
.add(pool
.execute())
900 await Promise
.all(promises
)
901 for (const workerNode
of pool
.workerNodes
) {
902 expect(workerNode
.workerUsage
).toStrictEqual({
904 executed
: expect
.any(Number
),
910 aggregation
: expect
.any(Number
),
911 average
: expect
.any(Number
),
913 history
: expect
.any(CircularArray
)
919 history
: expect
.any(CircularArray
)
923 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
924 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
927 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
930 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
933 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
934 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
935 ).defaultWorkerWeight
938 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
939 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
940 ).workerVirtualTaskRunTime
941 ).toBeGreaterThanOrEqual(0)
942 // We need to clean up the resources after our test
946 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
947 const pool
= new DynamicThreadPool(
950 './tests/worker-files/thread/testWorker.js',
951 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
953 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
954 const promises
= new Set()
955 const maxMultiplier
= 2
956 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
957 promises
.add(pool
.execute())
959 await Promise
.all(promises
)
960 for (const workerNode
of pool
.workerNodes
) {
961 expect(workerNode
.workerUsage
).toStrictEqual({
963 executed
: expect
.any(Number
),
969 aggregation
: expect
.any(Number
),
970 average
: expect
.any(Number
),
972 history
: expect
.any(CircularArray
)
978 history
: expect
.any(CircularArray
)
982 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
983 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
986 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
987 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
990 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
991 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
992 ).defaultWorkerWeight
995 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
996 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
997 ).workerVirtualTaskRunTime
998 ).toBeGreaterThanOrEqual(0)
999 // We need to clean up the resources after our test
1000 await pool
.destroy()
1003 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1004 const pool
= new DynamicThreadPool(
1007 './tests/worker-files/thread/testWorker.js',
1009 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1010 workerChoiceStrategyOptions
: {
1015 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1016 const promises
= new Set()
1017 const maxMultiplier
= 2
1018 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1019 promises
.add(pool
.execute())
1021 await Promise
.all(promises
)
1022 for (const workerNode
of pool
.workerNodes
) {
1023 expect(workerNode
.workerUsage
).toStrictEqual({
1025 executed
: expect
.any(Number
),
1031 aggregation
: expect
.any(Number
),
1033 median
: expect
.any(Number
),
1034 history
: expect
.any(CircularArray
)
1040 history
: expect
.any(CircularArray
)
1044 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1045 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1048 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
1049 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1052 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1053 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1054 ).defaultWorkerWeight
1055 ).toBeGreaterThan(0)
1057 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1058 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1059 ).workerVirtualTaskRunTime
1060 ).toBeGreaterThanOrEqual(0)
1061 // We need to clean up the resources after our test
1062 await pool
.destroy()
1065 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1066 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1067 let pool
= new FixedThreadPool(
1069 './tests/worker-files/thread/testWorker.js'
1072 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1073 workerChoiceStrategy
1074 ).currentWorkerNodeId
1077 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1078 workerChoiceStrategy
1079 ).defaultWorkerWeight
1082 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1083 workerChoiceStrategy
1084 ).workerVirtualTaskRunTime
1086 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1088 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1089 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1090 ).currentWorkerNodeId
1093 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1094 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1095 ).defaultWorkerWeight
1096 ).toBeGreaterThan(0)
1098 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1099 workerChoiceStrategy
1100 ).workerVirtualTaskRunTime
1102 await pool
.destroy()
1103 pool
= new DynamicThreadPool(
1106 './tests/worker-files/thread/testWorker.js'
1109 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1110 workerChoiceStrategy
1111 ).currentWorkerNodeId
1114 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1115 workerChoiceStrategy
1116 ).defaultWorkerWeight
1119 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1120 workerChoiceStrategy
1121 ).workerVirtualTaskRunTime
1123 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1125 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1126 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1127 ).currentWorkerNodeId
1130 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1131 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1132 ).defaultWorkerWeight
1133 ).toBeGreaterThan(0)
1135 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1136 workerChoiceStrategy
1137 ).workerVirtualTaskRunTime
1139 // We need to clean up the resources after our test
1140 await pool
.destroy()
1143 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1144 const workerChoiceStrategy
=
1145 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1146 let pool
= new FixedThreadPool(
1148 './tests/worker-files/thread/testWorker.js',
1149 { workerChoiceStrategy
}
1151 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
1160 await pool
.destroy()
1161 pool
= new DynamicThreadPool(
1164 './tests/worker-files/thread/testWorker.js',
1165 { workerChoiceStrategy
}
1167 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
1176 // We need to clean up the resources after our test
1177 await pool
.destroy()
1180 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1181 const pool
= new FixedThreadPool(
1183 './tests/worker-files/thread/testWorker.js',
1185 workerChoiceStrategy
:
1186 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1189 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1190 const promises
= new Set()
1191 const maxMultiplier
= 2
1192 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1193 promises
.add(pool
.execute())
1195 await Promise
.all(promises
)
1196 for (const workerNode
of pool
.workerNodes
) {
1197 expect(workerNode
.workerUsage
).toStrictEqual({
1199 executed
: maxMultiplier
,
1208 history
: expect
.any(CircularArray
)
1214 history
: expect
.any(CircularArray
)
1220 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1221 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1222 ).defaultWorkerWeight
1223 ).toBeGreaterThan(0)
1225 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1226 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1230 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1231 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1232 ).currentWorkerNodeId
1235 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1236 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1239 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1240 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1241 ).defaultWorkerWeight
1243 // We need to clean up the resources after our test
1244 await pool
.destroy()
1247 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1248 const pool
= new DynamicThreadPool(
1251 './tests/worker-files/thread/testWorker.js',
1253 workerChoiceStrategy
:
1254 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1257 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1258 const promises
= new Set()
1259 const maxMultiplier
= 2
1260 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1261 promises
.add(pool
.execute())
1263 await Promise
.all(promises
)
1264 for (const workerNode
of pool
.workerNodes
) {
1265 expect(workerNode
.workerUsage
).toStrictEqual({
1267 executed
: maxMultiplier
,
1276 history
: expect
.any(CircularArray
)
1282 history
: expect
.any(CircularArray
)
1288 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1289 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1290 ).defaultWorkerWeight
1291 ).toBeGreaterThan(0)
1293 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1294 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1298 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1299 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1300 ).currentWorkerNodeId
1303 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1304 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1307 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1308 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1309 ).defaultWorkerWeight
1311 // We need to clean up the resources after our test
1312 await pool
.destroy()
1315 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1316 const workerChoiceStrategy
=
1317 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1318 let pool
= new FixedThreadPool(
1320 './tests/worker-files/thread/testWorker.js'
1323 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1324 workerChoiceStrategy
1328 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1329 workerChoiceStrategy
1330 ).currentWorkerNodeId
1333 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1334 workerChoiceStrategy
1335 ).defaultWorkerWeight
1338 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1339 workerChoiceStrategy
1342 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1344 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1345 workerChoiceStrategy
1349 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1350 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1351 ).currentWorkerNodeId
1354 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1355 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1356 ).defaultWorkerWeight
1357 ).toBeGreaterThan(0)
1359 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1360 workerChoiceStrategy
1363 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1364 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1365 ).defaultWorkerWeight
1367 await pool
.destroy()
1368 pool
= new DynamicThreadPool(
1371 './tests/worker-files/thread/testWorker.js'
1374 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1375 workerChoiceStrategy
1379 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1380 workerChoiceStrategy
1381 ).currentWorkerNodeId
1384 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1385 workerChoiceStrategy
1386 ).defaultWorkerWeight
1389 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1390 workerChoiceStrategy
1393 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1395 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1396 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1397 ).currentWorkerNodeId
1400 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1401 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1402 ).defaultWorkerWeight
1403 ).toBeGreaterThan(0)
1405 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1406 workerChoiceStrategy
1409 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1410 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1411 ).defaultWorkerWeight
1413 // We need to clean up the resources after our test
1414 await pool
.destroy()
1417 it('Verify unknown strategy throw error', () => {
1420 new DynamicThreadPool(
1423 './tests/worker-files/thread/testWorker.js',
1424 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1426 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")