1 import { expect } from 'expect'
8 } from '../../../lib/index.js'
9 import { CircularArray } from '../../../lib/circular-array.js'
11 describe('Selection strategies test suite', () => {
15 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
16 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
17 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
18 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
19 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
20 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
21 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
22 'WEIGHTED_ROUND_ROBIN'
24 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
25 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
29 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
30 const pool = new DynamicThreadPool(
33 './tests/worker-files/thread/testWorker.mjs'
35 expect(pool.opts.workerChoiceStrategy).toBe(
36 WorkerChoiceStrategies.ROUND_ROBIN
38 // We need to clean up the resources after our test
42 it('Verify available strategies are taken at pool creation', async () => {
43 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
44 const pool = new FixedThreadPool(
46 './tests/worker-files/thread/testWorker.mjs',
47 { workerChoiceStrategy }
49 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
50 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
57 it('Verify available strategies can be set after pool creation', async () => {
58 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
59 const pool = new DynamicThreadPool(
62 './tests/worker-files/thread/testWorker.mjs'
64 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
65 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
66 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
69 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
71 runTime: { median: false },
72 waitTime: { median: false },
73 elu: { median: false }
75 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
77 runTime: { median: false },
78 waitTime: { median: false },
79 elu: { median: false }
83 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
84 const pool = new DynamicClusterPool(
87 './tests/worker-files/cluster/testWorker.js'
89 pool.setWorkerChoiceStrategy(workerChoiceStrategy, { retries: 3 })
90 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
91 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
94 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
96 runTime: { median: false },
97 waitTime: { median: false },
98 elu: { median: false }
100 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
102 runTime: { median: false },
103 waitTime: { median: false },
104 elu: { median: false }
110 it('Verify available strategies default internals at pool creation', async () => {
111 const pool = new FixedThreadPool(
113 './tests/worker-files/thread/testWorker.mjs'
115 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
117 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
122 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
124 ).previousWorkerNodeKey
127 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
130 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
132 ).defaultWorkerWeight
135 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
137 ).workerNodeVirtualTaskRunTime
140 workerChoiceStrategy ===
141 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
144 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
146 ).defaultWorkerWeight
149 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
151 ).workerNodeVirtualTaskRunTime
154 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
159 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
164 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
168 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
170 ).defaultWorkerWeight
177 it('Verify ROUND_ROBIN strategy default policy', async () => {
178 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
179 let pool = new FixedThreadPool(
181 './tests/worker-files/thread/testWorker.mjs',
182 { workerChoiceStrategy }
184 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
185 dynamicWorkerUsage: false,
186 dynamicWorkerReady: true
189 pool = new DynamicThreadPool(
192 './tests/worker-files/thread/testWorker.mjs',
193 { workerChoiceStrategy }
195 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
196 dynamicWorkerUsage: false,
197 dynamicWorkerReady: true
199 // We need to clean up the resources after our test
203 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
204 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
205 let pool = new FixedThreadPool(
207 './tests/worker-files/thread/testWorker.mjs',
208 { workerChoiceStrategy }
211 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
230 pool = new DynamicThreadPool(
233 './tests/worker-files/thread/testWorker.mjs',
234 { workerChoiceStrategy }
237 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
255 // We need to clean up the resources after our test
259 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
260 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
261 const pool = new FixedThreadPool(
263 './tests/worker-files/thread/testWorker.mjs',
264 { workerChoiceStrategy }
266 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
267 const promises = new Set()
268 const maxMultiplier = 2
269 for (let i = 0; i < max * maxMultiplier; i++) {
270 promises.add(pool.execute())
272 await Promise.all(promises)
273 for (const workerNode of pool.workerNodes) {
274 expect(workerNode.usage).toStrictEqual({
276 executed: maxMultiplier,
280 sequentiallyStolen: 0,
285 history: new CircularArray()
288 history: new CircularArray()
292 history: new CircularArray()
295 history: new CircularArray()
301 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
302 pool.workerChoiceStrategyContext.workerChoiceStrategy
306 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
307 pool.workerChoiceStrategyContext.workerChoiceStrategy
308 ).previousWorkerNodeKey
309 ).toBe(pool.workerNodes.length - 1)
310 // We need to clean up the resources after our test
314 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
315 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
316 const pool = new DynamicThreadPool(
319 './tests/worker-files/thread/testWorker.mjs',
320 { workerChoiceStrategy }
322 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
323 const promises = new Set()
324 const maxMultiplier = 2
325 for (let i = 0; i < max * maxMultiplier; i++) {
326 promises.add(pool.execute())
328 await Promise.all(promises)
329 for (const workerNode of pool.workerNodes) {
330 expect(workerNode.usage).toStrictEqual({
332 executed: expect.any(Number),
336 sequentiallyStolen: 0,
341 history: new CircularArray()
344 history: new CircularArray()
348 history: new CircularArray()
351 history: new CircularArray()
355 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
356 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
361 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
362 pool.workerChoiceStrategyContext.workerChoiceStrategy
366 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
367 pool.workerChoiceStrategyContext.workerChoiceStrategy
368 ).previousWorkerNodeKey
369 ).toBe(pool.workerNodes.length - 1)
370 // We need to clean up the resources after our test
374 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
375 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
376 let pool = new FixedClusterPool(
378 './tests/worker-files/cluster/testWorker.js',
379 { workerChoiceStrategy }
381 let results = new Set()
382 for (let i = 0; i < max; i++) {
383 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
385 expect(results.size).toBe(max)
387 pool = new FixedThreadPool(
389 './tests/worker-files/thread/testWorker.mjs',
390 { workerChoiceStrategy }
393 for (let i = 0; i < max; i++) {
394 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
396 expect(results.size).toBe(max)
400 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
401 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
402 let pool = new FixedThreadPool(
404 './tests/worker-files/thread/testWorker.mjs',
405 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
408 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
409 pool.workerChoiceStrategyContext.workerChoiceStrategy
413 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
414 pool.workerChoiceStrategyContext.workerChoiceStrategy
415 ).previousWorkerNodeKey
417 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
419 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
420 pool.workerChoiceStrategyContext.workerChoiceStrategy
424 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
425 pool.workerChoiceStrategyContext.workerChoiceStrategy
426 ).previousWorkerNodeKey
429 pool = new DynamicThreadPool(
432 './tests/worker-files/thread/testWorker.mjs',
433 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
436 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
437 pool.workerChoiceStrategyContext.workerChoiceStrategy
441 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
442 pool.workerChoiceStrategyContext.workerChoiceStrategy
443 ).previousWorkerNodeKey
445 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
447 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
448 pool.workerChoiceStrategyContext.workerChoiceStrategy
452 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
453 pool.workerChoiceStrategyContext.workerChoiceStrategy
454 ).previousWorkerNodeKey
456 // We need to clean up the resources after our test
460 it('Verify LEAST_USED strategy default policy', async () => {
461 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
462 let pool = new FixedThreadPool(
464 './tests/worker-files/thread/testWorker.mjs',
465 { workerChoiceStrategy }
467 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
468 dynamicWorkerUsage: false,
469 dynamicWorkerReady: true
472 pool = new DynamicThreadPool(
475 './tests/worker-files/thread/testWorker.mjs',
476 { workerChoiceStrategy }
478 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
479 dynamicWorkerUsage: false,
480 dynamicWorkerReady: true
482 // We need to clean up the resources after our test
486 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
487 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
488 let pool = new FixedThreadPool(
490 './tests/worker-files/thread/testWorker.mjs',
491 { workerChoiceStrategy }
494 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
513 pool = new DynamicThreadPool(
516 './tests/worker-files/thread/testWorker.mjs',
517 { workerChoiceStrategy }
520 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
538 // We need to clean up the resources after our test
542 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
543 const pool = new FixedThreadPool(
545 './tests/worker-files/thread/testWorker.mjs',
546 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
548 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
549 const promises = new Set()
550 const maxMultiplier = 2
551 for (let i = 0; i < max * maxMultiplier; i++) {
552 promises.add(pool.execute())
554 await Promise.all(promises)
555 for (const workerNode of pool.workerNodes) {
556 expect(workerNode.usage).toStrictEqual({
558 executed: expect.any(Number),
562 sequentiallyStolen: 0,
567 history: new CircularArray()
570 history: new CircularArray()
574 history: new CircularArray()
577 history: new CircularArray()
581 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
582 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
587 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
588 pool.workerChoiceStrategyContext.workerChoiceStrategy
590 ).toEqual(expect.any(Number))
592 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
593 pool.workerChoiceStrategyContext.workerChoiceStrategy
594 ).previousWorkerNodeKey
595 ).toEqual(expect.any(Number))
596 // We need to clean up the resources after our test
600 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
601 const pool = new DynamicThreadPool(
604 './tests/worker-files/thread/testWorker.mjs',
605 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
607 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
608 const promises = new Set()
609 const maxMultiplier = 2
610 for (let i = 0; i < max * maxMultiplier; i++) {
611 promises.add(pool.execute())
613 await Promise.all(promises)
614 for (const workerNode of pool.workerNodes) {
615 expect(workerNode.usage).toStrictEqual({
617 executed: expect.any(Number),
621 sequentiallyStolen: 0,
626 history: new CircularArray()
629 history: new CircularArray()
633 history: new CircularArray()
636 history: new CircularArray()
640 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
641 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
646 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
647 pool.workerChoiceStrategyContext.workerChoiceStrategy
649 ).toEqual(expect.any(Number))
651 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
652 pool.workerChoiceStrategyContext.workerChoiceStrategy
653 ).previousWorkerNodeKey
654 ).toEqual(expect.any(Number))
655 // We need to clean up the resources after our test
659 it('Verify LEAST_BUSY strategy default policy', async () => {
660 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
661 let pool = new FixedThreadPool(
663 './tests/worker-files/thread/testWorker.mjs',
664 { workerChoiceStrategy }
666 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
667 dynamicWorkerUsage: false,
668 dynamicWorkerReady: true
671 pool = new DynamicThreadPool(
674 './tests/worker-files/thread/testWorker.mjs',
675 { workerChoiceStrategy }
677 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
678 dynamicWorkerUsage: false,
679 dynamicWorkerReady: true
681 // We need to clean up the resources after our test
685 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
686 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
687 let pool = new FixedThreadPool(
689 './tests/worker-files/thread/testWorker.mjs',
690 { workerChoiceStrategy }
693 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
712 pool = new DynamicThreadPool(
715 './tests/worker-files/thread/testWorker.mjs',
716 { workerChoiceStrategy }
719 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
737 // We need to clean up the resources after our test
741 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
742 const pool = new FixedThreadPool(
744 './tests/worker-files/thread/testWorker.mjs',
745 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
747 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
748 const promises = new Set()
749 const maxMultiplier = 2
750 for (let i = 0; i < max * maxMultiplier; i++) {
751 promises.add(pool.execute())
753 await Promise.all(promises)
754 for (const workerNode of pool.workerNodes) {
755 expect(workerNode.usage).toStrictEqual({
757 executed: expect.any(Number),
761 sequentiallyStolen: 0,
765 runTime: expect.objectContaining({
766 history: expect.any(CircularArray)
768 waitTime: expect.objectContaining({
769 history: expect.any(CircularArray)
773 history: new CircularArray()
776 history: new CircularArray()
780 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
781 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
784 if (workerNode.usage.runTime.aggregate == null) {
785 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
787 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
789 if (workerNode.usage.waitTime.aggregate == null) {
790 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
792 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
796 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
797 pool.workerChoiceStrategyContext.workerChoiceStrategy
799 ).toEqual(expect.any(Number))
801 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
802 pool.workerChoiceStrategyContext.workerChoiceStrategy
803 ).previousWorkerNodeKey
804 ).toEqual(expect.any(Number))
805 // We need to clean up the resources after our test
809 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
810 const pool = new DynamicThreadPool(
813 './tests/worker-files/thread/testWorker.mjs',
814 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
816 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
817 const promises = new Set()
818 const maxMultiplier = 2
819 for (let i = 0; i < max * maxMultiplier; i++) {
820 promises.add(pool.execute())
822 await Promise.all(promises)
823 for (const workerNode of pool.workerNodes) {
824 expect(workerNode.usage).toStrictEqual({
826 executed: expect.any(Number),
830 sequentiallyStolen: 0,
834 runTime: expect.objectContaining({
835 history: expect.any(CircularArray)
837 waitTime: expect.objectContaining({
838 history: expect.any(CircularArray)
842 history: new CircularArray()
845 history: new CircularArray()
849 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
850 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
853 if (workerNode.usage.runTime.aggregate == null) {
854 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
856 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
858 if (workerNode.usage.waitTime.aggregate == null) {
859 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
861 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
865 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
866 pool.workerChoiceStrategyContext.workerChoiceStrategy
868 ).toEqual(expect.any(Number))
870 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
871 pool.workerChoiceStrategyContext.workerChoiceStrategy
872 ).previousWorkerNodeKey
873 ).toEqual(expect.any(Number))
874 // We need to clean up the resources after our test
878 it('Verify LEAST_ELU strategy default policy', async () => {
879 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
880 let pool = new FixedThreadPool(
882 './tests/worker-files/thread/testWorker.mjs',
883 { workerChoiceStrategy }
885 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
886 dynamicWorkerUsage: false,
887 dynamicWorkerReady: true
890 pool = new DynamicThreadPool(
893 './tests/worker-files/thread/testWorker.mjs',
894 { workerChoiceStrategy }
896 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
897 dynamicWorkerUsage: false,
898 dynamicWorkerReady: true
900 // We need to clean up the resources after our test
904 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
905 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
906 let pool = new FixedThreadPool(
908 './tests/worker-files/thread/testWorker.mjs',
909 { workerChoiceStrategy }
912 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
931 pool = new DynamicThreadPool(
934 './tests/worker-files/thread/testWorker.mjs',
935 { workerChoiceStrategy }
938 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
956 // We need to clean up the resources after our test
960 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
961 const pool = new FixedThreadPool(
963 './tests/worker-files/thread/testWorker.mjs',
964 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
966 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
967 const promises = new Set()
968 const maxMultiplier = 2
969 for (let i = 0; i < max * maxMultiplier; i++) {
970 promises.add(pool.execute())
972 await Promise.all(promises)
973 for (const workerNode of pool.workerNodes) {
974 expect(workerNode.usage).toStrictEqual({
976 executed: expect.any(Number),
980 sequentiallyStolen: 0,
985 history: new CircularArray()
988 history: new CircularArray()
990 elu: expect.objectContaining({
991 idle: expect.objectContaining({
992 history: expect.any(CircularArray)
994 active: expect.objectContaining({
995 history: expect.any(CircularArray)
999 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1000 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1003 if (workerNode.usage.elu.active.aggregate == null) {
1004 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1006 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1008 if (workerNode.usage.elu.idle.aggregate == null) {
1009 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1011 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1013 if (workerNode.usage.elu.utilization == null) {
1014 expect(workerNode.usage.elu.utilization).toBeUndefined()
1016 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1017 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1021 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1022 pool.workerChoiceStrategyContext.workerChoiceStrategy
1024 ).toEqual(expect.any(Number))
1026 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1027 pool.workerChoiceStrategyContext.workerChoiceStrategy
1028 ).previousWorkerNodeKey
1029 ).toEqual(expect.any(Number))
1030 // We need to clean up the resources after our test
1031 await pool.destroy()
1034 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1035 const pool = new DynamicThreadPool(
1038 './tests/worker-files/thread/testWorker.mjs',
1039 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
1041 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1042 const promises = new Set()
1043 const maxMultiplier = 2
1044 for (let i = 0; i < max * maxMultiplier; i++) {
1045 promises.add(pool.execute())
1047 await Promise.all(promises)
1048 for (const workerNode of pool.workerNodes) {
1049 expect(workerNode.usage).toStrictEqual({
1051 executed: expect.any(Number),
1055 sequentiallyStolen: 0,
1060 history: new CircularArray()
1063 history: new CircularArray()
1065 elu: expect.objectContaining({
1066 idle: expect.objectContaining({
1067 history: expect.any(CircularArray)
1069 active: expect.objectContaining({
1070 history: expect.any(CircularArray)
1074 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1075 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1078 if (workerNode.usage.elu.active.aggregate == null) {
1079 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1081 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1083 if (workerNode.usage.elu.idle.aggregate == null) {
1084 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1086 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1088 if (workerNode.usage.elu.utilization == null) {
1089 expect(workerNode.usage.elu.utilization).toBeUndefined()
1091 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1092 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1096 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1097 pool.workerChoiceStrategyContext.workerChoiceStrategy
1099 ).toEqual(expect.any(Number))
1101 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1102 pool.workerChoiceStrategyContext.workerChoiceStrategy
1103 ).previousWorkerNodeKey
1104 ).toEqual(expect.any(Number))
1105 // We need to clean up the resources after our test
1106 await pool.destroy()
1109 it('Verify FAIR_SHARE strategy default policy', async () => {
1110 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1111 let pool = new FixedThreadPool(
1113 './tests/worker-files/thread/testWorker.mjs',
1114 { workerChoiceStrategy }
1116 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1117 dynamicWorkerUsage: false,
1118 dynamicWorkerReady: true
1120 await pool.destroy()
1121 pool = new DynamicThreadPool(
1124 './tests/worker-files/thread/testWorker.mjs',
1125 { workerChoiceStrategy }
1127 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1128 dynamicWorkerUsage: false,
1129 dynamicWorkerReady: true
1131 // We need to clean up the resources after our test
1132 await pool.destroy()
1135 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1136 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1137 let pool = new FixedThreadPool(
1139 './tests/worker-files/thread/testWorker.mjs',
1140 { workerChoiceStrategy }
1143 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1161 await pool.destroy()
1162 pool = new DynamicThreadPool(
1165 './tests/worker-files/thread/testWorker.mjs',
1166 { workerChoiceStrategy }
1169 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1187 // We need to clean up the resources after our test
1188 await pool.destroy()
1191 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1192 const pool = new FixedThreadPool(
1194 './tests/worker-files/thread/testWorker.mjs',
1195 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1197 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1198 const promises = new Set()
1199 const maxMultiplier = 2
1200 for (let i = 0; i < max * maxMultiplier; i++) {
1201 promises.add(pool.execute())
1203 await Promise.all(promises)
1204 for (const workerNode of pool.workerNodes) {
1205 expect(workerNode.usage).toStrictEqual({
1207 executed: expect.any(Number),
1211 sequentiallyStolen: 0,
1215 runTime: expect.objectContaining({
1216 history: expect.any(CircularArray)
1219 history: new CircularArray()
1221 elu: expect.objectContaining({
1222 idle: expect.objectContaining({
1223 history: expect.any(CircularArray)
1225 active: expect.objectContaining({
1226 history: expect.any(CircularArray)
1230 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1231 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1234 if (workerNode.usage.runTime.aggregate == null) {
1235 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1237 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1239 if (workerNode.usage.runTime.average == null) {
1240 expect(workerNode.usage.runTime.average).toBeUndefined()
1242 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1244 if (workerNode.usage.elu.active.aggregate == null) {
1245 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1247 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1249 if (workerNode.usage.elu.idle.aggregate == null) {
1250 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1252 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1254 if (workerNode.usage.elu.utilization == null) {
1255 expect(workerNode.usage.elu.utilization).toBeUndefined()
1257 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1258 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1260 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1263 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1264 pool.workerChoiceStrategyContext.workerChoiceStrategy
1266 ).toEqual(expect.any(Number))
1268 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1269 pool.workerChoiceStrategyContext.workerChoiceStrategy
1270 ).previousWorkerNodeKey
1271 ).toEqual(expect.any(Number))
1272 // We need to clean up the resources after our test
1273 await pool.destroy()
1276 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1277 const pool = new DynamicThreadPool(
1280 './tests/worker-files/thread/testWorker.mjs',
1281 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1283 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1284 const promises = new Set()
1285 const maxMultiplier = 2
1286 for (let i = 0; i < max * maxMultiplier; i++) {
1287 promises.add(pool.execute())
1289 await Promise.all(promises)
1290 for (const workerNode of pool.workerNodes) {
1291 expect(workerNode.usage).toStrictEqual({
1293 executed: expect.any(Number),
1297 sequentiallyStolen: 0,
1301 runTime: expect.objectContaining({
1302 history: expect.any(CircularArray)
1305 history: new CircularArray()
1307 elu: expect.objectContaining({
1308 idle: expect.objectContaining({
1309 history: expect.any(CircularArray)
1311 active: expect.objectContaining({
1312 history: expect.any(CircularArray)
1316 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1317 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1320 if (workerNode.usage.runTime.aggregate == null) {
1321 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1323 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1325 if (workerNode.usage.runTime.average == null) {
1326 expect(workerNode.usage.runTime.average).toBeUndefined()
1328 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1330 if (workerNode.usage.elu.active.aggregate == null) {
1331 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1333 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1335 if (workerNode.usage.elu.idle.aggregate == null) {
1336 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1338 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1340 if (workerNode.usage.elu.utilization == null) {
1341 expect(workerNode.usage.elu.utilization).toBeUndefined()
1343 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1344 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1346 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1349 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1350 pool.workerChoiceStrategyContext.workerChoiceStrategy
1352 ).toEqual(expect.any(Number))
1354 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1355 pool.workerChoiceStrategyContext.workerChoiceStrategy
1356 ).previousWorkerNodeKey
1357 ).toEqual(expect.any(Number))
1358 // We need to clean up the resources after our test
1359 await pool.destroy()
1362 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1363 const pool = new DynamicThreadPool(
1366 './tests/worker-files/thread/testWorker.mjs',
1368 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1369 workerChoiceStrategyOptions: {
1370 runTime: { median: true }
1374 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1375 const promises = new Set()
1376 const maxMultiplier = 2
1377 for (let i = 0; i < max * maxMultiplier; i++) {
1378 promises.add(pool.execute())
1380 await Promise.all(promises)
1381 for (const workerNode of pool.workerNodes) {
1382 expect(workerNode.usage).toStrictEqual({
1384 executed: expect.any(Number),
1388 sequentiallyStolen: 0,
1392 runTime: expect.objectContaining({
1393 history: expect.any(CircularArray)
1396 history: new CircularArray()
1398 elu: expect.objectContaining({
1399 idle: expect.objectContaining({
1400 history: expect.any(CircularArray)
1402 active: expect.objectContaining({
1403 history: expect.any(CircularArray)
1407 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1408 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1411 if (workerNode.usage.runTime.aggregate == null) {
1412 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1414 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1416 if (workerNode.usage.runTime.median == null) {
1417 expect(workerNode.usage.runTime.median).toBeUndefined()
1419 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1421 if (workerNode.usage.elu.active.aggregate == null) {
1422 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1424 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1426 if (workerNode.usage.elu.idle.aggregate == null) {
1427 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1429 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1431 if (workerNode.usage.elu.utilization == null) {
1432 expect(workerNode.usage.elu.utilization).toBeUndefined()
1434 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1435 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1437 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1440 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1441 pool.workerChoiceStrategyContext.workerChoiceStrategy
1443 ).toEqual(expect.any(Number))
1445 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1446 pool.workerChoiceStrategyContext.workerChoiceStrategy
1447 ).previousWorkerNodeKey
1448 ).toEqual(expect.any(Number))
1449 // We need to clean up the resources after our test
1450 await pool.destroy()
1453 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1454 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1455 let pool = new FixedThreadPool(
1457 './tests/worker-files/thread/testWorker.mjs'
1459 for (const workerNode of pool.workerNodes) {
1460 workerNode.strategyData = {
1461 virtualTaskEndTimestamp: performance.now()
1464 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1465 for (const workerNode of pool.workerNodes) {
1466 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1468 await pool.destroy()
1469 pool = new DynamicThreadPool(
1472 './tests/worker-files/thread/testWorker.mjs'
1474 for (const workerNode of pool.workerNodes) {
1475 workerNode.strategyData = {
1476 virtualTaskEndTimestamp: performance.now()
1479 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1480 for (const workerNode of pool.workerNodes) {
1481 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1483 // We need to clean up the resources after our test
1484 await pool.destroy()
1487 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1488 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1489 let pool = new FixedThreadPool(
1491 './tests/worker-files/thread/testWorker.mjs',
1492 { workerChoiceStrategy }
1494 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1495 dynamicWorkerUsage: false,
1496 dynamicWorkerReady: true
1498 await pool.destroy()
1499 pool = new DynamicThreadPool(
1502 './tests/worker-files/thread/testWorker.mjs',
1503 { workerChoiceStrategy }
1505 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1506 dynamicWorkerUsage: false,
1507 dynamicWorkerReady: true
1509 // We need to clean up the resources after our test
1510 await pool.destroy()
1513 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1514 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1515 let pool = new FixedThreadPool(
1517 './tests/worker-files/thread/testWorker.mjs',
1518 { workerChoiceStrategy }
1521 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1539 await pool.destroy()
1540 pool = new DynamicThreadPool(
1543 './tests/worker-files/thread/testWorker.mjs',
1544 { workerChoiceStrategy }
1547 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1565 // We need to clean up the resources after our test
1566 await pool.destroy()
1569 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1570 const pool = new FixedThreadPool(
1572 './tests/worker-files/thread/testWorker.mjs',
1573 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1575 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1576 const promises = new Set()
1577 const maxMultiplier = 2
1578 for (let i = 0; i < max * maxMultiplier; i++) {
1579 promises.add(pool.execute())
1581 await Promise.all(promises)
1582 for (const workerNode of pool.workerNodes) {
1583 expect(workerNode.usage).toStrictEqual({
1585 executed: expect.any(Number),
1589 sequentiallyStolen: 0,
1593 runTime: expect.objectContaining({
1594 history: expect.any(CircularArray)
1597 history: new CircularArray()
1601 history: new CircularArray()
1604 history: new CircularArray()
1608 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1609 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1612 if (workerNode.usage.runTime.aggregate == null) {
1613 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1615 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1617 if (workerNode.usage.runTime.average == null) {
1618 expect(workerNode.usage.runTime.average).toBeUndefined()
1620 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1624 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1625 pool.workerChoiceStrategyContext.workerChoiceStrategy
1629 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1630 pool.workerChoiceStrategyContext.workerChoiceStrategy
1631 ).previousWorkerNodeKey
1634 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1635 pool.workerChoiceStrategyContext.workerChoiceStrategy
1636 ).defaultWorkerWeight
1637 ).toBeGreaterThan(0)
1639 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1640 pool.workerChoiceStrategyContext.workerChoiceStrategy
1641 ).workerNodeVirtualTaskRunTime
1642 ).toBeGreaterThanOrEqual(0)
1643 // We need to clean up the resources after our test
1644 await pool.destroy()
1647 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1648 const pool = new DynamicThreadPool(
1651 './tests/worker-files/thread/testWorker.mjs',
1652 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1654 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1655 const promises = new Set()
1656 const maxMultiplier = 2
1657 for (let i = 0; i < max * maxMultiplier; i++) {
1658 promises.add(pool.execute())
1660 await Promise.all(promises)
1661 for (const workerNode of pool.workerNodes) {
1662 expect(workerNode.usage).toStrictEqual({
1664 executed: expect.any(Number),
1668 sequentiallyStolen: 0,
1672 runTime: expect.objectContaining({
1673 history: expect.any(CircularArray)
1676 history: new CircularArray()
1680 history: new CircularArray()
1683 history: new CircularArray()
1687 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1688 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1691 if (workerNode.usage.runTime.aggregate == null) {
1692 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1694 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1696 if (workerNode.usage.runTime.average == null) {
1697 expect(workerNode.usage.runTime.average).toBeUndefined()
1699 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1703 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1704 pool.workerChoiceStrategyContext.workerChoiceStrategy
1708 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1709 pool.workerChoiceStrategyContext.workerChoiceStrategy
1710 ).previousWorkerNodeKey
1713 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1714 pool.workerChoiceStrategyContext.workerChoiceStrategy
1715 ).defaultWorkerWeight
1716 ).toBeGreaterThan(0)
1718 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1719 pool.workerChoiceStrategyContext.workerChoiceStrategy
1720 ).workerNodeVirtualTaskRunTime
1721 ).toBeGreaterThanOrEqual(0)
1722 // We need to clean up the resources after our test
1723 await pool.destroy()
1726 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1727 const pool = new DynamicThreadPool(
1730 './tests/worker-files/thread/testWorker.mjs',
1732 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1733 workerChoiceStrategyOptions: {
1734 runTime: { median: true }
1738 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1739 const promises = new Set()
1740 const maxMultiplier = 2
1741 for (let i = 0; i < max * maxMultiplier; i++) {
1742 promises.add(pool.execute())
1744 await Promise.all(promises)
1745 for (const workerNode of pool.workerNodes) {
1746 expect(workerNode.usage).toStrictEqual({
1748 executed: expect.any(Number),
1752 sequentiallyStolen: 0,
1756 runTime: expect.objectContaining({
1757 history: expect.any(CircularArray)
1760 history: new CircularArray()
1764 history: new CircularArray()
1767 history: new CircularArray()
1771 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1772 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1775 if (workerNode.usage.runTime.aggregate == null) {
1776 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1778 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1780 if (workerNode.usage.runTime.median == null) {
1781 expect(workerNode.usage.runTime.median).toBeUndefined()
1783 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1787 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1788 pool.workerChoiceStrategyContext.workerChoiceStrategy
1792 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1793 pool.workerChoiceStrategyContext.workerChoiceStrategy
1794 ).previousWorkerNodeKey
1797 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1798 pool.workerChoiceStrategyContext.workerChoiceStrategy
1799 ).defaultWorkerWeight
1800 ).toBeGreaterThan(0)
1802 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1803 pool.workerChoiceStrategyContext.workerChoiceStrategy
1804 ).workerNodeVirtualTaskRunTime
1805 ).toBeGreaterThanOrEqual(0)
1806 // We need to clean up the resources after our test
1807 await pool.destroy()
1810 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1811 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1812 let pool = new FixedThreadPool(
1814 './tests/worker-files/thread/testWorker.mjs'
1817 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1818 workerChoiceStrategy
1822 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1823 workerChoiceStrategy
1824 ).previousWorkerNodeKey
1827 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1828 workerChoiceStrategy
1829 ).defaultWorkerWeight
1832 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1833 workerChoiceStrategy
1834 ).workerNodeVirtualTaskRunTime
1836 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1838 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1839 pool.workerChoiceStrategyContext.workerChoiceStrategy
1843 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1844 pool.workerChoiceStrategyContext.workerChoiceStrategy
1845 ).previousWorkerNodeKey
1848 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1849 pool.workerChoiceStrategyContext.workerChoiceStrategy
1850 ).defaultWorkerWeight
1851 ).toBeGreaterThan(0)
1853 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1854 pool.workerChoiceStrategyContext.workerChoiceStrategy
1855 ).workerNodeVirtualTaskRunTime
1857 await pool.destroy()
1858 pool = new DynamicThreadPool(
1861 './tests/worker-files/thread/testWorker.mjs'
1864 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1865 workerChoiceStrategy
1869 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1870 workerChoiceStrategy
1871 ).previousWorkerNodeKey
1874 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1875 workerChoiceStrategy
1876 ).defaultWorkerWeight
1879 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1880 workerChoiceStrategy
1881 ).workerNodeVirtualTaskRunTime
1883 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1885 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1886 pool.workerChoiceStrategyContext.workerChoiceStrategy
1890 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1891 pool.workerChoiceStrategyContext.workerChoiceStrategy
1892 ).previousWorkerNodeKey
1895 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1896 pool.workerChoiceStrategyContext.workerChoiceStrategy
1897 ).defaultWorkerWeight
1898 ).toBeGreaterThan(0)
1900 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1901 pool.workerChoiceStrategyContext.workerChoiceStrategy
1902 ).workerNodeVirtualTaskRunTime
1904 // We need to clean up the resources after our test
1905 await pool.destroy()
1908 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1909 const workerChoiceStrategy =
1910 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1911 let pool = new FixedThreadPool(
1913 './tests/worker-files/thread/testWorker.mjs',
1914 { workerChoiceStrategy }
1916 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1917 dynamicWorkerUsage: false,
1918 dynamicWorkerReady: true
1920 await pool.destroy()
1921 pool = new DynamicThreadPool(
1924 './tests/worker-files/thread/testWorker.mjs',
1925 { workerChoiceStrategy }
1927 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1928 dynamicWorkerUsage: false,
1929 dynamicWorkerReady: true
1931 // We need to clean up the resources after our test
1932 await pool.destroy()
1935 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1936 const workerChoiceStrategy =
1937 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1938 let pool = new FixedThreadPool(
1940 './tests/worker-files/thread/testWorker.mjs',
1941 { workerChoiceStrategy }
1944 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1962 await pool.destroy()
1963 pool = new DynamicThreadPool(
1966 './tests/worker-files/thread/testWorker.mjs',
1967 { workerChoiceStrategy }
1970 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1988 // We need to clean up the resources after our test
1989 await pool.destroy()
1992 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1993 const pool = new FixedThreadPool(
1995 './tests/worker-files/thread/testWorker.mjs',
1997 workerChoiceStrategy:
1998 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2001 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2002 const promises = new Set()
2003 const maxMultiplier = 2
2004 for (let i = 0; i < max * maxMultiplier; i++) {
2005 promises.add(pool.execute())
2007 await Promise.all(promises)
2008 for (const workerNode of pool.workerNodes) {
2009 expect(workerNode.usage).toStrictEqual({
2011 executed: expect.any(Number),
2015 sequentiallyStolen: 0,
2019 runTime: expect.objectContaining({
2020 history: expect.any(CircularArray)
2023 history: new CircularArray()
2027 history: new CircularArray()
2030 history: new CircularArray()
2034 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2035 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2040 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2041 pool.workerChoiceStrategyContext.workerChoiceStrategy
2042 ).defaultWorkerWeight
2043 ).toBeGreaterThan(0)
2045 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2046 pool.workerChoiceStrategyContext.workerChoiceStrategy
2050 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2051 pool.workerChoiceStrategyContext.workerChoiceStrategy
2055 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2056 pool.workerChoiceStrategyContext.workerChoiceStrategy
2060 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2061 pool.workerChoiceStrategyContext.workerChoiceStrategy
2062 ).previousWorkerNodeKey
2063 ).toEqual(expect.any(Number))
2065 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2066 pool.workerChoiceStrategyContext.workerChoiceStrategy
2069 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2070 pool.workerChoiceStrategyContext.workerChoiceStrategy
2071 ).defaultWorkerWeight
2073 // We need to clean up the resources after our test
2074 await pool.destroy()
2077 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2078 const pool = new DynamicThreadPool(
2081 './tests/worker-files/thread/testWorker.mjs',
2083 workerChoiceStrategy:
2084 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2087 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2088 const promises = new Set()
2089 const maxMultiplier = 2
2090 for (let i = 0; i < max * maxMultiplier; i++) {
2091 promises.add(pool.execute())
2093 await Promise.all(promises)
2094 for (const workerNode of pool.workerNodes) {
2095 expect(workerNode.usage).toStrictEqual({
2097 executed: expect.any(Number),
2101 sequentiallyStolen: 0,
2105 runTime: expect.objectContaining({
2106 history: expect.any(CircularArray)
2109 history: new CircularArray()
2113 history: new CircularArray()
2116 history: new CircularArray()
2120 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2121 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2126 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2127 pool.workerChoiceStrategyContext.workerChoiceStrategy
2128 ).defaultWorkerWeight
2129 ).toBeGreaterThan(0)
2131 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2132 pool.workerChoiceStrategyContext.workerChoiceStrategy
2136 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2137 pool.workerChoiceStrategyContext.workerChoiceStrategy
2141 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2142 pool.workerChoiceStrategyContext.workerChoiceStrategy
2146 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2147 pool.workerChoiceStrategyContext.workerChoiceStrategy
2148 ).previousWorkerNodeKey
2149 ).toEqual(expect.any(Number))
2151 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2152 pool.workerChoiceStrategyContext.workerChoiceStrategy
2155 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2156 pool.workerChoiceStrategyContext.workerChoiceStrategy
2157 ).defaultWorkerWeight
2159 // We need to clean up the resources after our test
2160 await pool.destroy()
2163 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2164 const workerChoiceStrategy =
2165 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2166 let pool = new FixedThreadPool(
2168 './tests/worker-files/thread/testWorker.mjs'
2171 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2172 workerChoiceStrategy
2176 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2177 workerChoiceStrategy
2181 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2182 workerChoiceStrategy
2186 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2187 workerChoiceStrategy
2188 ).previousWorkerNodeKey
2191 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2192 workerChoiceStrategy
2193 ).defaultWorkerWeight
2196 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2197 workerChoiceStrategy
2200 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2202 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2203 pool.workerChoiceStrategyContext.workerChoiceStrategy
2207 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2208 pool.workerChoiceStrategyContext.workerChoiceStrategy
2212 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2213 pool.workerChoiceStrategyContext.workerChoiceStrategy
2217 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2218 pool.workerChoiceStrategyContext.workerChoiceStrategy
2219 ).previousWorkerNodeKey
2222 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2223 pool.workerChoiceStrategyContext.workerChoiceStrategy
2224 ).defaultWorkerWeight
2225 ).toBeGreaterThan(0)
2227 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2228 pool.workerChoiceStrategyContext.workerChoiceStrategy
2231 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2232 pool.workerChoiceStrategyContext.workerChoiceStrategy
2233 ).defaultWorkerWeight
2235 await pool.destroy()
2236 pool = new DynamicThreadPool(
2239 './tests/worker-files/thread/testWorker.mjs'
2242 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2243 workerChoiceStrategy
2247 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2248 workerChoiceStrategy
2252 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2253 workerChoiceStrategy
2257 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2258 workerChoiceStrategy
2259 ).previousWorkerNodeKey
2262 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2263 workerChoiceStrategy
2264 ).defaultWorkerWeight
2267 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2268 workerChoiceStrategy
2271 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2273 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2274 pool.workerChoiceStrategyContext.workerChoiceStrategy
2278 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2279 pool.workerChoiceStrategyContext.workerChoiceStrategy
2283 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2284 pool.workerChoiceStrategyContext.workerChoiceStrategy
2288 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2289 pool.workerChoiceStrategyContext.workerChoiceStrategy
2290 ).previousWorkerNodeKey
2293 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2294 pool.workerChoiceStrategyContext.workerChoiceStrategy
2295 ).defaultWorkerWeight
2296 ).toBeGreaterThan(0)
2298 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2299 pool.workerChoiceStrategyContext.workerChoiceStrategy
2302 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2303 pool.workerChoiceStrategyContext.workerChoiceStrategy
2304 ).defaultWorkerWeight
2306 // We need to clean up the resources after our test
2307 await pool.destroy()
2310 it('Verify unknown strategy throw error', () => {
2313 new DynamicThreadPool(
2316 './tests/worker-files/thread/testWorker.mjs',
2317 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
2319 ).toThrow("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")