X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=tests%2Fpools%2Fselection-strategies%2Fselection-strategies.test.js;h=254f02de7870e5c8da73ab6c260fa954a176283c;hb=95c83464bb1fab234d1c41204f98defcd01c789f;hp=b12a8df4b726438ba173f867ea59e19123f00fb1;hpb=23ff945ac0bc3b9bcf98c6491872cffaac805b73;p=poolifier.git diff --git a/tests/pools/selection-strategies/selection-strategies.test.js b/tests/pools/selection-strategies/selection-strategies.test.js index b12a8df4..254f02de 100644 --- a/tests/pools/selection-strategies/selection-strategies.test.js +++ b/tests/pools/selection-strategies/selection-strategies.test.js @@ -2,13 +2,18 @@ const { expect } = require('expect') const { WorkerChoiceStrategies, DynamicThreadPool, - FixedThreadPool + FixedThreadPool, + FixedClusterPool } = require('../../../lib/index') describe('Selection strategies test suite', () => { + const min = 0 + const max = 3 + it('Verify that WorkerChoiceStrategies enumeration provides string values', () => { expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN') - expect(WorkerChoiceStrategies.LESS_RECENTLY_USED).toBe('LESS_RECENTLY_USED') + expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED') + expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY') expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE') expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe( 'WEIGHTED_ROUND_ROBIN' @@ -16,8 +21,6 @@ describe('Selection strategies test suite', () => { }) it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => { - const min = 0 - const max = 3 const pool = new DynamicThreadPool( min, max, @@ -30,9 +33,25 @@ describe('Selection strategies test suite', () => { await pool.destroy() }) + it('Verify ROUND_ROBIN strategy is taken at pool creation', async () => { + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN } + ) + expect(pool.opts.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.ROUND_ROBIN + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.ROUND_ROBIN + ).nextWorkerId + ).toBe(0) + // We need to clean up the resources after our test + await pool.destroy() + }) + it('Verify ROUND_ROBIN strategy can be set after pool creation', async () => { - const min = 0 - const max = 3 const pool = new DynamicThreadPool( min, max, @@ -46,8 +65,36 @@ describe('Selection strategies test suite', () => { await pool.destroy() }) + it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(false) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(false) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + // We need to clean up the resources after our test + await pool.destroy() + }) + it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', @@ -59,7 +106,7 @@ describe('Selection strategies test suite', () => { // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) } await Promise.all(promises) // We need to clean up the resources after our test @@ -67,8 +114,6 @@ describe('Selection strategies test suite', () => { }) it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => { - const min = 0 - const max = 3 const pool = new DynamicThreadPool( min, max, @@ -81,71 +126,242 @@ describe('Selection strategies test suite', () => { // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) + } + await Promise.all(promises) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify ROUND_ROBIN strategy runtime behavior', async () => { + let pool = new FixedClusterPool( + max, + './tests/worker-files/cluster/testWorker.js' + ) + let results = new Set() + for (let i = 0; i < max; i++) { + results.add(pool.chooseWorker()[1].id) + } + expect(results.size).toBe(max) + await pool.destroy() + pool = new FixedThreadPool(max, './tests/worker-files/thread/testWorker.js') + results = new Set() + for (let i = 0; i < max; i++) { + results.add(pool.chooseWorker()[1].threadId) + } + expect(results.size).toBe(max) + await pool.destroy() + }) + + it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.ROUND_ROBIN + )?.nextWorkerId + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.ROUND_ROBIN + ).nextWorkerId + ).toBe(0) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.ROUND_ROBIN + )?.nextWorkerId + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.ROUND_ROBIN + ).nextWorkerId + ).toBe(0) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_USED strategy is taken at pool creation', async () => { + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED } + ) + expect(pool.opts.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.LESS_USED + ) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_USED strategy can be set after pool creation', async () => { + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED) + expect(pool.opts.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.LESS_USED + ) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(false) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(false) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_USED strategy can be run in a fixed pool', async () => { + const pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED } + ) + // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose` + const promises = [] + for (let i = 0; i < max * 2; i++) { + promises.push(pool.execute()) + } + await Promise.all(promises) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_USED strategy can be run in a dynamic pool', async () => { + const pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js', + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED } + ) + // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose` + const promises = [] + for (let i = 0; i < max * 2; i++) { + promises.push(pool.execute()) } await Promise.all(promises) // We need to clean up the resources after our test await pool.destroy() }) - it('Verify LESS_RECENTLY_USED strategy is taken at pool creation', async () => { - const max = 3 + it('Verify LESS_BUSY strategy is taken at pool creation', async () => { const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', - { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY } ) expect(pool.opts.workerChoiceStrategy).toBe( - WorkerChoiceStrategies.LESS_RECENTLY_USED + WorkerChoiceStrategies.LESS_BUSY ) // We need to clean up the resources after our test await pool.destroy() }) - it('Verify LESS_RECENTLY_USED strategy can be set after pool creation', async () => { - const max = 3 + it('Verify LESS_BUSY strategy can be set after pool creation', async () => { const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js' ) - pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY) expect(pool.opts.workerChoiceStrategy).toBe( - WorkerChoiceStrategies.LESS_RECENTLY_USED + WorkerChoiceStrategies.LESS_BUSY ) // We need to clean up the resources after our test await pool.destroy() }) - it('Verify LESS_RECENTLY_USED strategy can be run in a fixed pool', async () => { - const max = 3 + it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(false) + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => { const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', - { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY } ) - // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose` + // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) } await Promise.all(promises) // We need to clean up the resources after our test await pool.destroy() }) - it('Verify LESS_RECENTLY_USED strategy can be run in a dynamic pool', async () => { - const min = 0 - const max = 3 + it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => { const pool = new DynamicThreadPool( min, max, './tests/worker-files/thread/testWorker.js', - { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED } + { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY } ) - // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose` + // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) } await Promise.all(promises) // We need to clean up the resources after our test @@ -153,7 +369,6 @@ describe('Selection strategies test suite', () => { }) it('Verify FAIR_SHARE strategy is taken at pool creation', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', @@ -162,12 +377,25 @@ describe('Selection strategies test suite', () => { expect(pool.opts.workerChoiceStrategy).toBe( WorkerChoiceStrategies.FAIR_SHARE ) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).start + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).end + ).toBe(0) + } // We need to clean up the resources after our test await pool.destroy() }) it('Verify FAIR_SHARE strategy can be set after pool creation', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js' @@ -180,8 +408,36 @@ describe('Selection strategies test suite', () => { await pool.destroy() }) + it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(true) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(true) + // We need to clean up the resources after our test + await pool.destroy() + }) + it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', @@ -190,16 +446,19 @@ describe('Selection strategies test suite', () => { // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) } await Promise.all(promises) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.FAIR_SHARE + ).workerLastVirtualTaskTimestamp.size + ).toBe(pool.workers.length) // We need to clean up the resources after our test await pool.destroy() }) it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => { - const min = 0 - const max = 3 const pool = new DynamicThreadPool( min, max, @@ -208,16 +467,78 @@ describe('Selection strategies test suite', () => { ) // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` const promises = [] - for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + const maxMultiplier = 2 + for (let i = 0; i < max * maxMultiplier; i++) { + promises.push(pool.execute()) } await Promise.all(promises) + // if (process.platform !== 'win32') { + // expect( + // pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + // WorkerChoiceStrategies.FAIR_SHARE + // ).workerLastVirtualTaskTimestamp.size + // ).toBe(pool.workers.length) + // } + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.FAIR_SHARE + )?.workerLastVirtualTaskTimestamp + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).start + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).end + ).toBe(0) + } + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.FAIR_SHARE + )?.workerLastVirtualTaskTimestamp + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).start + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.FAIR_SHARE) + .workerLastVirtualTaskTimestamp.get(workerKey).end + ).toBe(0) + } // We need to clean up the resources after our test await pool.destroy() }) it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', @@ -226,12 +547,35 @@ describe('Selection strategies test suite', () => { expect(pool.opts.workerChoiceStrategy).toBe( WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).currentWorkerId + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).defaultWorkerWeight + ).toBeGreaterThan(0) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.get(workerKey).weight + ).toBeGreaterThan(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.get(workerKey).runTime + ).toBe(0) + } // We need to clean up the resources after our test await pool.destroy() }) it('Verify WEIGHTED_ROUND_ROBIN strategy can be set after pool creation', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js' @@ -244,8 +588,36 @@ describe('Selection strategies test suite', () => { await pool.destroy() }) + it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(true) + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().runTime + ).toBe(true) + expect( + pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime + ).toBe(true) + // We need to clean up the resources after our test + await pool.destroy() + }) + it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => { - const max = 3 const pool = new FixedThreadPool( max, './tests/worker-files/thread/testWorker.js', @@ -254,16 +626,19 @@ describe('Selection strategies test suite', () => { // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` const promises = [] for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + promises.push(pool.execute()) } await Promise.all(promises) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).workersTaskRunTime.size + ).toBe(pool.workers.length) // We need to clean up the resources after our test await pool.destroy() }) it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => { - const min = 0 - const max = 3 const pool = new DynamicThreadPool( min, max, @@ -272,17 +647,111 @@ describe('Selection strategies test suite', () => { ) // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` const promises = [] - for (let i = 0; i < max * 2; i++) { - promises.push(pool.execute({ test: 'test' })) + const maxMultiplier = + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).defaultWorkerWeight * 2 + for (let i = 0; i < max * maxMultiplier; i++) { + promises.push(pool.execute()) } await Promise.all(promises) + if (process.platform !== 'win32') { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).workersTaskRunTime.size + ).toBe(pool.workers.length) + } + // We need to clean up the resources after our test + await pool.destroy() + }) + + it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => { + let pool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.currentWorkerId + ).toBeUndefined() + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.defaultWorkerWeight + ).toBeUndefined() + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.workersTaskRunTime + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).currentWorkerId + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).defaultWorkerWeight + ).toBeGreaterThan(0) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.get(workerKey).runTime + ).toBe(0) + } + await pool.destroy() + pool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.currentWorkerId + ).toBeUndefined() + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.defaultWorkerWeight + ).toBeUndefined() + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + )?.workersTaskRunTime + ).toBeUndefined() + pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).currentWorkerId + ).toBe(0) + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies.get( + WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + ).defaultWorkerWeight + ).toBeGreaterThan(0) + for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.keys()) { + expect( + pool.workerChoiceStrategyContext.workerChoiceStrategies + .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN) + .workersTaskRunTime.get(workerKey).runTime + ).toBe(0) + } // We need to clean up the resources after our test await pool.destroy() }) it('Verify unknown strategies throw error', () => { - const min = 1 - const max = 3 expect( () => new DynamicThreadPool(