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
}
126 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
145 pool
= new DynamicThreadPool(
148 './tests/worker-files/thread/testWorker.js',
149 { workerChoiceStrategy
}
152 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
170 // We need to clean up the resources after our test
174 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
175 const pool
= new FixedThreadPool(
177 './tests/worker-files/thread/testWorker.js',
178 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
180 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
181 const promises
= new Set()
182 const maxMultiplier
= 2
183 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
184 promises
.add(pool
.execute())
186 await Promise
.all(promises
)
187 for (const workerNode
of pool
.workerNodes
) {
188 expect(workerNode
.workerUsage
).toStrictEqual({
190 executed
: maxMultiplier
,
199 history
: expect
.any(CircularArray
)
205 history
: expect
.any(CircularArray
)
212 history
: expect
.any(CircularArray
)
218 history
: expect
.any(CircularArray
)
225 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
226 WorkerChoiceStrategies
.ROUND_ROBIN
229 // We need to clean up the resources after our test
233 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
234 const pool
= new DynamicThreadPool(
237 './tests/worker-files/thread/testWorker.js',
238 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
240 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
241 const promises
= new Set()
242 const maxMultiplier
= 2
243 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
244 promises
.add(pool
.execute())
246 await Promise
.all(promises
)
247 for (const workerNode
of pool
.workerNodes
) {
248 expect(workerNode
.workerUsage
).toStrictEqual({
250 executed
: maxMultiplier
,
259 history
: expect
.any(CircularArray
)
265 history
: expect
.any(CircularArray
)
272 history
: expect
.any(CircularArray
)
278 history
: expect
.any(CircularArray
)
285 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
286 WorkerChoiceStrategies
.ROUND_ROBIN
289 // We need to clean up the resources after our test
293 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
294 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
295 let pool
= new FixedClusterPool(
297 './tests/worker-files/cluster/testWorker.js',
298 { workerChoiceStrategy
}
300 let results
= new Set()
301 for (let i
= 0; i
< max
; i
++) {
302 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
304 expect(results
.size
).toBe(max
)
306 pool
= new FixedThreadPool(
308 './tests/worker-files/thread/testWorker.js',
309 { workerChoiceStrategy
}
312 for (let i
= 0; i
< max
; i
++) {
313 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
315 expect(results
.size
).toBe(max
)
319 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
320 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
321 let pool
= new FixedThreadPool(
323 './tests/worker-files/thread/testWorker.js',
324 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
327 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
331 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
333 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
334 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
338 pool
= new DynamicThreadPool(
341 './tests/worker-files/thread/testWorker.js',
342 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
345 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
349 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
351 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
352 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
355 // We need to clean up the resources after our test
359 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
360 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
361 let pool
= new FixedThreadPool(
363 './tests/worker-files/thread/testWorker.js',
364 { workerChoiceStrategy
}
367 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
386 pool
= new DynamicThreadPool(
389 './tests/worker-files/thread/testWorker.js',
390 { workerChoiceStrategy
}
393 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
411 // We need to clean up the resources after our test
415 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
416 const pool
= new FixedThreadPool(
418 './tests/worker-files/thread/testWorker.js',
419 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
421 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
422 const promises
= new Set()
423 const maxMultiplier
= 2
424 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
425 promises
.add(pool
.execute())
427 await Promise
.all(promises
)
428 for (const workerNode
of pool
.workerNodes
) {
429 expect(workerNode
.workerUsage
).toStrictEqual({
431 executed
: maxMultiplier
,
440 history
: expect
.any(CircularArray
)
446 history
: expect
.any(CircularArray
)
453 history
: expect
.any(CircularArray
)
459 history
: expect
.any(CircularArray
)
465 // We need to clean up the resources after our test
469 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
470 const pool
= new DynamicThreadPool(
473 './tests/worker-files/thread/testWorker.js',
474 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
476 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
477 const promises
= new Set()
478 const maxMultiplier
= 2
479 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
480 promises
.add(pool
.execute())
482 await Promise
.all(promises
)
483 for (const workerNode
of pool
.workerNodes
) {
484 expect(workerNode
.workerUsage
).toStrictEqual({
486 executed
: maxMultiplier
,
495 history
: expect
.any(CircularArray
)
501 history
: expect
.any(CircularArray
)
508 history
: expect
.any(CircularArray
)
514 history
: expect
.any(CircularArray
)
520 // We need to clean up the resources after our test
524 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
525 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
526 let pool
= new FixedThreadPool(
528 './tests/worker-files/thread/testWorker.js',
529 { workerChoiceStrategy
}
532 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
551 pool
= new DynamicThreadPool(
554 './tests/worker-files/thread/testWorker.js',
555 { workerChoiceStrategy
}
558 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
576 // We need to clean up the resources after our test
580 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
581 const pool
= new FixedThreadPool(
583 './tests/worker-files/thread/testWorker.js',
584 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
586 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
587 const promises
= new Set()
588 const maxMultiplier
= 2
589 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
590 promises
.add(pool
.execute())
592 await Promise
.all(promises
)
593 for (const workerNode
of pool
.workerNodes
) {
594 expect(workerNode
.workerUsage
).toStrictEqual({
596 executed
: expect
.any(Number
),
602 aggregate
: expect
.any(Number
),
605 history
: expect
.any(CircularArray
)
608 aggregate
: expect
.any(Number
),
611 history
: expect
.any(CircularArray
)
618 history
: expect
.any(CircularArray
)
624 history
: expect
.any(CircularArray
)
629 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
630 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
633 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
634 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThanOrEqual(
638 // We need to clean up the resources after our test
642 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
643 const pool
= new DynamicThreadPool(
646 './tests/worker-files/thread/testWorker.js',
647 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
649 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
650 const promises
= new Set()
651 const maxMultiplier
= 2
652 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
653 promises
.add(pool
.execute())
655 await Promise
.all(promises
)
656 for (const workerNode
of pool
.workerNodes
) {
657 expect(workerNode
.workerUsage
).toStrictEqual({
659 executed
: expect
.any(Number
),
665 aggregate
: expect
.any(Number
),
668 history
: expect
.any(CircularArray
)
671 aggregate
: expect
.any(Number
),
674 history
: expect
.any(CircularArray
)
681 history
: expect
.any(CircularArray
)
687 history
: expect
.any(CircularArray
)
692 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
693 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
696 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
697 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThan(0)
699 // We need to clean up the resources after our test
703 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
704 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
705 let pool
= new FixedThreadPool(
707 './tests/worker-files/thread/testWorker.js',
708 { workerChoiceStrategy
}
711 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
730 pool
= new DynamicThreadPool(
733 './tests/worker-files/thread/testWorker.js',
734 { workerChoiceStrategy
}
737 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
755 // We need to clean up the resources after our test
759 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
760 const pool
= new FixedThreadPool(
762 './tests/worker-files/thread/testWorker.js',
763 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
765 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
766 const promises
= new Set()
767 const maxMultiplier
= 2
768 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
769 promises
.add(pool
.execute())
771 await Promise
.all(promises
)
772 for (const workerNode
of pool
.workerNodes
) {
773 expect(workerNode
.workerUsage
).toStrictEqual({
775 executed
: expect
.any(Number
),
784 history
: expect
.any(CircularArray
)
790 history
: expect
.any(CircularArray
)
797 history
: expect
.any(CircularArray
)
800 aggregate
: expect
.any(Number
),
803 history
: expect
.any(CircularArray
)
805 utilization
: expect
.any(Number
)
808 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
809 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
812 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
813 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
815 // We need to clean up the resources after our test
819 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
820 const pool
= new DynamicThreadPool(
823 './tests/worker-files/thread/testWorker.js',
824 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
826 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
827 const promises
= new Set()
828 const maxMultiplier
= 2
829 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
830 promises
.add(pool
.execute())
832 await Promise
.all(promises
)
833 for (const workerNode
of pool
.workerNodes
) {
834 expect(workerNode
.workerUsage
).toStrictEqual({
836 executed
: expect
.any(Number
),
845 history
: expect
.any(CircularArray
)
851 history
: expect
.any(CircularArray
)
858 history
: expect
.any(CircularArray
)
861 aggregate
: expect
.any(Number
),
864 history
: expect
.any(CircularArray
)
866 utilization
: expect
.any(Number
)
869 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
870 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
873 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
874 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
876 // We need to clean up the resources after our test
880 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
881 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
882 let pool
= new FixedThreadPool(
884 './tests/worker-files/thread/testWorker.js',
885 { workerChoiceStrategy
}
888 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
907 pool
= new DynamicThreadPool(
910 './tests/worker-files/thread/testWorker.js',
911 { workerChoiceStrategy
}
914 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
932 // We need to clean up the resources after our test
936 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
937 const pool
= new FixedThreadPool(
939 './tests/worker-files/thread/testWorker.js',
940 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
942 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
943 const promises
= new Set()
944 const maxMultiplier
= 2
945 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
946 promises
.add(pool
.execute())
948 await Promise
.all(promises
)
949 for (const workerNode
of pool
.workerNodes
) {
950 expect(workerNode
.workerUsage
).toStrictEqual({
952 executed
: maxMultiplier
,
958 aggregate
: expect
.any(Number
),
959 average
: expect
.any(Number
),
961 history
: expect
.any(CircularArray
)
967 history
: expect
.any(CircularArray
)
974 history
: expect
.any(CircularArray
)
977 aggregate
: expect
.any(Number
),
978 average
: expect
.any(Number
),
980 history
: expect
.any(CircularArray
)
982 utilization
: expect
.any(Number
)
985 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
986 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
987 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
988 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
991 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
992 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
993 ).workersVirtualTaskEndTimestamp
.length
994 ).toBe(pool
.workerNodes
.length
)
995 // We need to clean up the resources after our test
999 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1000 const pool
= new DynamicThreadPool(
1003 './tests/worker-files/thread/testWorker.js',
1004 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1006 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1007 const promises
= new Set()
1008 const maxMultiplier
= 2
1009 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1010 promises
.add(pool
.execute())
1012 await Promise
.all(promises
)
1013 for (const workerNode
of pool
.workerNodes
) {
1014 expect(workerNode
.workerUsage
).toStrictEqual({
1016 executed
: maxMultiplier
,
1022 aggregate
: expect
.any(Number
),
1023 average
: expect
.any(Number
),
1025 history
: expect
.any(CircularArray
)
1031 history
: expect
.any(CircularArray
)
1038 history
: expect
.any(CircularArray
)
1041 aggregate
: expect
.any(Number
),
1042 average
: expect
.any(Number
),
1044 history
: expect
.any(CircularArray
)
1046 utilization
: expect
.any(Number
)
1049 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1050 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1051 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1052 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
1055 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1056 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1057 ).workersVirtualTaskEndTimestamp
.length
1058 ).toBe(pool
.workerNodes
.length
)
1059 // We need to clean up the resources after our test
1060 await pool
.destroy()
1063 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1064 const pool
= new DynamicThreadPool(
1067 './tests/worker-files/thread/testWorker.js',
1069 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
1070 workerChoiceStrategyOptions
: {
1071 runTime
: { median
: true }
1075 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1076 const promises
= new Set()
1077 const maxMultiplier
= 2
1078 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1079 promises
.add(pool
.execute())
1081 await Promise
.all(promises
)
1082 for (const workerNode
of pool
.workerNodes
) {
1083 expect(workerNode
.workerUsage
).toStrictEqual({
1085 executed
: maxMultiplier
,
1091 aggregate
: expect
.any(Number
),
1093 median
: expect
.any(Number
),
1094 history
: expect
.any(CircularArray
)
1100 history
: expect
.any(CircularArray
)
1107 history
: expect
.any(CircularArray
)
1110 aggregate
: expect
.any(Number
),
1111 average
: expect
.any(Number
),
1113 history
: expect
.any(CircularArray
)
1115 utilization
: expect
.any(Number
)
1118 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1119 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1120 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1121 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
1124 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1125 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1126 ).workersVirtualTaskEndTimestamp
.length
1127 ).toBe(pool
.workerNodes
.length
)
1128 // We need to clean up the resources after our test
1129 await pool
.destroy()
1132 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1133 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1134 let pool
= new FixedThreadPool(
1136 './tests/worker-files/thread/testWorker.js'
1139 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1140 workerChoiceStrategy
1141 ).workersVirtualTaskEndTimestamp
1142 ).toBeInstanceOf(Array
)
1144 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1145 workerChoiceStrategy
1146 ).workersVirtualTaskEndTimestamp
.length
1148 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1149 workerChoiceStrategy
1150 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1152 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1153 workerChoiceStrategy
1154 ).workersVirtualTaskEndTimestamp
.length
1156 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1158 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1159 workerChoiceStrategy
1160 ).workersVirtualTaskEndTimestamp
1161 ).toBeInstanceOf(Array
)
1163 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1164 workerChoiceStrategy
1165 ).workersVirtualTaskEndTimestamp
.length
1167 await pool
.destroy()
1168 pool
= new DynamicThreadPool(
1171 './tests/worker-files/thread/testWorker.js'
1174 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1175 workerChoiceStrategy
1176 ).workersVirtualTaskEndTimestamp
1177 ).toBeInstanceOf(Array
)
1179 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1180 workerChoiceStrategy
1181 ).workersVirtualTaskEndTimestamp
.length
1183 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1184 workerChoiceStrategy
1185 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1187 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1188 workerChoiceStrategy
1189 ).workersVirtualTaskEndTimestamp
.length
1191 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1193 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1194 workerChoiceStrategy
1195 ).workersVirtualTaskEndTimestamp
1196 ).toBeInstanceOf(Array
)
1198 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1199 workerChoiceStrategy
1200 ).workersVirtualTaskEndTimestamp
.length
1202 // We need to clean up the resources after our test
1203 await pool
.destroy()
1206 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1207 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1208 let pool
= new FixedThreadPool(
1210 './tests/worker-files/thread/testWorker.js',
1211 { workerChoiceStrategy
}
1214 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1232 await pool
.destroy()
1233 pool
= new DynamicThreadPool(
1236 './tests/worker-files/thread/testWorker.js',
1237 { workerChoiceStrategy
}
1240 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1258 // We need to clean up the resources after our test
1259 await pool
.destroy()
1262 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1263 const pool
= new FixedThreadPool(
1265 './tests/worker-files/thread/testWorker.js',
1266 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1268 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1269 const promises
= new Set()
1270 const maxMultiplier
= 2
1271 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1272 promises
.add(pool
.execute())
1274 await Promise
.all(promises
)
1275 for (const workerNode
of pool
.workerNodes
) {
1276 expect(workerNode
.workerUsage
).toStrictEqual({
1278 executed
: expect
.any(Number
),
1284 aggregate
: expect
.any(Number
),
1285 average
: expect
.any(Number
),
1287 history
: expect
.any(CircularArray
)
1293 history
: expect
.any(CircularArray
)
1300 history
: expect
.any(CircularArray
)
1306 history
: expect
.any(CircularArray
)
1311 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1312 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1315 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
1316 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
1319 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1320 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1321 ).defaultWorkerWeight
1322 ).toBeGreaterThan(0)
1324 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1325 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1326 ).workerVirtualTaskRunTime
1327 ).toBeGreaterThanOrEqual(0)
1328 // We need to clean up the resources after our test
1329 await pool
.destroy()
1332 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1333 const pool
= new DynamicThreadPool(
1336 './tests/worker-files/thread/testWorker.js',
1337 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1339 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1340 const promises
= new Set()
1341 const maxMultiplier
= 2
1342 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1343 promises
.add(pool
.execute())
1345 await Promise
.all(promises
)
1346 for (const workerNode
of pool
.workerNodes
) {
1347 expect(workerNode
.workerUsage
).toStrictEqual({
1349 executed
: expect
.any(Number
),
1355 aggregate
: expect
.any(Number
),
1356 average
: expect
.any(Number
),
1358 history
: expect
.any(CircularArray
)
1364 history
: expect
.any(CircularArray
)
1371 history
: expect
.any(CircularArray
)
1377 history
: expect
.any(CircularArray
)
1382 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1383 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1386 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1387 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1390 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1391 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1392 ).defaultWorkerWeight
1393 ).toBeGreaterThan(0)
1395 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1396 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1397 ).workerVirtualTaskRunTime
1398 ).toBeGreaterThanOrEqual(0)
1399 // We need to clean up the resources after our test
1400 await pool
.destroy()
1403 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1404 const pool
= new DynamicThreadPool(
1407 './tests/worker-files/thread/testWorker.js',
1409 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1410 workerChoiceStrategyOptions
: {
1411 runTime
: { median
: true }
1415 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1416 const promises
= new Set()
1417 const maxMultiplier
= 2
1418 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1419 promises
.add(pool
.execute())
1421 await Promise
.all(promises
)
1422 for (const workerNode
of pool
.workerNodes
) {
1423 expect(workerNode
.workerUsage
).toStrictEqual({
1425 executed
: expect
.any(Number
),
1431 aggregate
: expect
.any(Number
),
1433 median
: expect
.any(Number
),
1434 history
: expect
.any(CircularArray
)
1440 history
: expect
.any(CircularArray
)
1447 history
: expect
.any(CircularArray
)
1453 history
: expect
.any(CircularArray
)
1458 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1459 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1462 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1463 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1466 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1467 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1468 ).defaultWorkerWeight
1469 ).toBeGreaterThan(0)
1471 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1472 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1473 ).workerVirtualTaskRunTime
1474 ).toBeGreaterThanOrEqual(0)
1475 // We need to clean up the resources after our test
1476 await pool
.destroy()
1479 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1480 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1481 let pool
= new FixedThreadPool(
1483 './tests/worker-files/thread/testWorker.js'
1486 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1487 workerChoiceStrategy
1488 ).currentWorkerNodeId
1491 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1492 workerChoiceStrategy
1493 ).defaultWorkerWeight
1496 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1497 workerChoiceStrategy
1498 ).workerVirtualTaskRunTime
1500 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1502 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1503 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1504 ).currentWorkerNodeId
1507 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1508 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1509 ).defaultWorkerWeight
1510 ).toBeGreaterThan(0)
1512 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1513 workerChoiceStrategy
1514 ).workerVirtualTaskRunTime
1516 await pool
.destroy()
1517 pool
= new DynamicThreadPool(
1520 './tests/worker-files/thread/testWorker.js'
1523 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1524 workerChoiceStrategy
1525 ).currentWorkerNodeId
1528 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1529 workerChoiceStrategy
1530 ).defaultWorkerWeight
1533 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1534 workerChoiceStrategy
1535 ).workerVirtualTaskRunTime
1537 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1539 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1540 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1541 ).currentWorkerNodeId
1544 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1545 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1546 ).defaultWorkerWeight
1547 ).toBeGreaterThan(0)
1549 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1550 workerChoiceStrategy
1551 ).workerVirtualTaskRunTime
1553 // We need to clean up the resources after our test
1554 await pool
.destroy()
1557 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1558 const workerChoiceStrategy
=
1559 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1560 let pool
= new FixedThreadPool(
1562 './tests/worker-files/thread/testWorker.js',
1563 { workerChoiceStrategy
}
1566 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1584 await pool
.destroy()
1585 pool
= new DynamicThreadPool(
1588 './tests/worker-files/thread/testWorker.js',
1589 { workerChoiceStrategy
}
1592 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1610 // We need to clean up the resources after our test
1611 await pool
.destroy()
1614 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1615 const pool
= new FixedThreadPool(
1617 './tests/worker-files/thread/testWorker.js',
1619 workerChoiceStrategy
:
1620 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1623 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1624 const promises
= new Set()
1625 const maxMultiplier
= 2
1626 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1627 promises
.add(pool
.execute())
1629 await Promise
.all(promises
)
1630 for (const workerNode
of pool
.workerNodes
) {
1631 expect(workerNode
.workerUsage
).toStrictEqual({
1633 executed
: maxMultiplier
,
1642 history
: expect
.any(CircularArray
)
1648 history
: expect
.any(CircularArray
)
1655 history
: expect
.any(CircularArray
)
1661 history
: expect
.any(CircularArray
)
1668 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1669 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1670 ).defaultWorkerWeight
1671 ).toBeGreaterThan(0)
1673 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1674 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1678 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1679 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1680 ).currentWorkerNodeId
1683 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1684 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1687 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1688 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1689 ).defaultWorkerWeight
1691 // We need to clean up the resources after our test
1692 await pool
.destroy()
1695 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1696 const pool
= new DynamicThreadPool(
1699 './tests/worker-files/thread/testWorker.js',
1701 workerChoiceStrategy
:
1702 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1705 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1706 const promises
= new Set()
1707 const maxMultiplier
= 2
1708 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1709 promises
.add(pool
.execute())
1711 await Promise
.all(promises
)
1712 for (const workerNode
of pool
.workerNodes
) {
1713 expect(workerNode
.workerUsage
).toStrictEqual({
1715 executed
: maxMultiplier
,
1724 history
: expect
.any(CircularArray
)
1730 history
: expect
.any(CircularArray
)
1737 history
: expect
.any(CircularArray
)
1743 history
: expect
.any(CircularArray
)
1750 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1751 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1752 ).defaultWorkerWeight
1753 ).toBeGreaterThan(0)
1755 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1756 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1760 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1761 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1762 ).currentWorkerNodeId
1765 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1766 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1769 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1770 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1771 ).defaultWorkerWeight
1773 // We need to clean up the resources after our test
1774 await pool
.destroy()
1777 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1778 const workerChoiceStrategy
=
1779 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1780 let pool
= new FixedThreadPool(
1782 './tests/worker-files/thread/testWorker.js'
1785 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1786 workerChoiceStrategy
1790 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1791 workerChoiceStrategy
1792 ).currentWorkerNodeId
1795 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1796 workerChoiceStrategy
1797 ).defaultWorkerWeight
1800 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1801 workerChoiceStrategy
1804 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1806 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1807 workerChoiceStrategy
1811 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1812 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1813 ).currentWorkerNodeId
1816 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1817 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1818 ).defaultWorkerWeight
1819 ).toBeGreaterThan(0)
1821 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1822 workerChoiceStrategy
1825 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1826 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1827 ).defaultWorkerWeight
1829 await pool
.destroy()
1830 pool
= new DynamicThreadPool(
1833 './tests/worker-files/thread/testWorker.js'
1836 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1837 workerChoiceStrategy
1841 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1842 workerChoiceStrategy
1843 ).currentWorkerNodeId
1846 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1847 workerChoiceStrategy
1848 ).defaultWorkerWeight
1851 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1852 workerChoiceStrategy
1855 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1857 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1858 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1859 ).currentWorkerNodeId
1862 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1863 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1864 ).defaultWorkerWeight
1865 ).toBeGreaterThan(0)
1867 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1868 workerChoiceStrategy
1871 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1872 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1873 ).defaultWorkerWeight
1875 // We need to clean up the resources after our test
1876 await pool
.destroy()
1879 it('Verify unknown strategy throw error', () => {
1882 new DynamicThreadPool(
1885 './tests/worker-files/thread/testWorker.js',
1886 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1888 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")