X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=tests%2Fpools%2Fselection-strategies%2Fworker-choice-strategy-context.test.js;h=df8cd25cb375a4aa50db889c7b014e4c17b22f9c;hb=086fd84368e031d54e321b3eab5cedb301ca3666;hp=75fcb9f25741e52d78f5b1ebcb11f65112233522;hpb=40ad1d27cb93fc21c700ed6ba96711104fd320c6;p=poolifier.git diff --git a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js index 75fcb9f2..df8cd25c 100644 --- a/tests/pools/selection-strategies/worker-choice-strategy-context.test.js +++ b/tests/pools/selection-strategies/worker-choice-strategy-context.test.js @@ -4,31 +4,67 @@ const { FixedThreadPool, DynamicThreadPool, WorkerChoiceStrategies -} = require('../../../lib/index') +} = require('../../../lib') +const { + WorkerChoiceStrategyContext +} = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context') const { RoundRobinWorkerChoiceStrategy } = require('../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy') const { - LessRecentlyUsedWorkerChoiceStrategy -} = require('../../../lib/pools/selection-strategies/less-recently-used-worker-choice-strategy') + LeastUsedWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/least-used-worker-choice-strategy') const { - WorkerChoiceStrategyContext -} = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context') + LeastBusyWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/least-busy-worker-choice-strategy') const { - DynamicPoolWorkerChoiceStrategy -} = require('../../../lib/pools/selection-strategies/dynamic-pool-worker-choice-strategy') + LeastEluWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/least-elu-worker-choice-strategy') +const { + FairShareWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy') +const { + WeightedRoundRobinWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/weighted-round-robin-worker-choice-strategy') +const { + InterleavedWeightedRoundRobinWorkerChoiceStrategy +} = require('../../../lib/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy') describe('Worker choice strategy context test suite', () => { + const min = 1 + const max = 3 let fixedPool, dynamicPool - beforeEach(() => { - fixedPool = sinon.createStubInstance(FixedThreadPool) - dynamicPool = sinon.createStubInstance(DynamicThreadPool) + + before(() => { + fixedPool = new FixedThreadPool( + max, + './tests/worker-files/thread/testWorker.js' + ) + dynamicPool = new DynamicThreadPool( + min, + max, + './tests/worker-files/thread/testWorker.js' + ) }) afterEach(() => { sinon.restore() }) + after(async () => { + await fixedPool.destroy() + await dynamicPool.destroy() + }) + + it('Verify that constructor() initializes the context with all the available worker choice strategies', () => { + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + expect(workerChoiceStrategyContext.workerChoiceStrategies.size).toBe( + Object.keys(WorkerChoiceStrategies).length + ) + }) + it('Verify that execute() return the worker chosen by the strategy with fixed pool', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool @@ -36,15 +72,58 @@ describe('Worker choice strategy context test suite', () => { const WorkerChoiceStrategyStub = sinon.createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: sinon.stub().returns('worker') + choose: sinon.stub().returns(0) } ) - workerChoiceStrategyContext.workerChoiceStrategy = WorkerChoiceStrategyStub - const worker = workerChoiceStrategyContext.execute() + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.ROUND_ROBIN + ) + workerChoiceStrategyContext.workerChoiceStrategies.set( + workerChoiceStrategyContext.workerChoiceStrategy, + WorkerChoiceStrategyStub + ) + const chosenWorkerKey = workerChoiceStrategyContext.execute() expect( - workerChoiceStrategyContext.workerChoiceStrategy.choose.calledOnce + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategyContext.workerChoiceStrategy + ).choose.calledOnce ).toBe(true) - expect(worker).toBe('worker') + expect(chosenWorkerKey).toBe(0) + }) + + it('Verify that execute() throws error if null or undefined is returned after retries', () => { + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + const WorkerChoiceStrategyUndefinedStub = sinon.createStubInstance( + RoundRobinWorkerChoiceStrategy, + { + choose: sinon.stub().returns(undefined) + } + ) + const WorkerChoiceStrategyNullStub = sinon.createStubInstance( + RoundRobinWorkerChoiceStrategy, + { + choose: sinon.stub().returns(null) + } + ) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.ROUND_ROBIN + ) + workerChoiceStrategyContext.workerChoiceStrategies.set( + workerChoiceStrategyContext.workerChoiceStrategy, + WorkerChoiceStrategyUndefinedStub + ) + expect(() => workerChoiceStrategyContext.execute()).toThrowError( + new Error('Worker node key chosen is null or undefined after 6 retries') + ) + workerChoiceStrategyContext.workerChoiceStrategies.set( + workerChoiceStrategyContext.workerChoiceStrategy, + WorkerChoiceStrategyNullStub + ) + expect(() => workerChoiceStrategyContext.execute()).toThrowError( + new Error('Worker node key chosen is null or undefined after 6 retries') + ) }) it('Verify that execute() return the worker chosen by the strategy with dynamic pool', () => { @@ -54,62 +133,325 @@ describe('Worker choice strategy context test suite', () => { const WorkerChoiceStrategyStub = sinon.createStubInstance( RoundRobinWorkerChoiceStrategy, { - choose: sinon.stub().returns('worker') + choose: sinon.stub().returns(0) } ) - workerChoiceStrategyContext.workerChoiceStrategy = WorkerChoiceStrategyStub - const worker = workerChoiceStrategyContext.execute() + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + WorkerChoiceStrategies.ROUND_ROBIN + ) + workerChoiceStrategyContext.workerChoiceStrategies.set( + workerChoiceStrategyContext.workerChoiceStrategy, + WorkerChoiceStrategyStub + ) + const chosenWorkerKey = workerChoiceStrategyContext.execute() expect( - workerChoiceStrategyContext.workerChoiceStrategy.choose.calledOnce + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategyContext.workerChoiceStrategy + ).choose.calledOnce ).toBe(true) - expect(worker).toBe('worker') + expect(chosenWorkerKey).toBe(0) }) it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - workerChoiceStrategyContext.setWorkerChoiceStrategy( - WorkerChoiceStrategies.ROUND_ROBIN + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) - expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( - RoundRobinWorkerChoiceStrategy + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) }) - it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => { + it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - workerChoiceStrategyContext.setWorkerChoiceStrategy( - WorkerChoiceStrategies.ROUND_ROBIN + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) - expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( - DynamicPoolWorkerChoiceStrategy + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) }) - it('Verify that setWorkerChoiceStrategy() works with LESS_RECENTLY_USED and fixed pool', () => { + it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool ) - workerChoiceStrategyContext.setWorkerChoiceStrategy( - WorkerChoiceStrategies.LESS_RECENTLY_USED + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) - expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( - LessRecentlyUsedWorkerChoiceStrategy + }) + + it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) }) - it('Verify that setWorkerChoiceStrategy() works with LESS_RECENTLY_USED and fixed pool', () => { + it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( dynamicPool ) - workerChoiceStrategyContext.setWorkerChoiceStrategy( - WorkerChoiceStrategies.LESS_RECENTLY_USED + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy ) - expect(workerChoiceStrategyContext.workerChoiceStrategy).toBeInstanceOf( - DynamicPoolWorkerChoiceStrategy + }) + + it('Verify that setWorkerChoiceStrategy() works with LEAST_ELU and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastEluWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with LEAST_ELU and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(LeastEluWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(FairShareWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(FairShareWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and fixed pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and dynamic pool', () => { + const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with INTERLEAVED_WEIGHTED_ROUND_ROBIN and fixed pool', () => { + const workerChoiceStrategy = + WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(InterleavedWeightedRoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that setWorkerChoiceStrategy() works with INTERLEAVED_WEIGHTED_ROUND_ROBIN and dynamic pool', () => { + const workerChoiceStrategy = + WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN + const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool + ) + workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) + expect( + workerChoiceStrategyContext.workerChoiceStrategies.get( + workerChoiceStrategy + ) + ).toBeInstanceOf(InterleavedWeightedRoundRobinWorkerChoiceStrategy) + expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( + workerChoiceStrategy + ) + }) + + it('Verify that worker choice strategy options enable median runtime pool statistics', () => { + const wwrWorkerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN + let workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool, + wwrWorkerChoiceStrategy, + { + runTime: { median: true } + } + ) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime + .average + ).toBe(false) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median + ).toBe(true) + workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool, + wwrWorkerChoiceStrategy, + { + runTime: { median: true } + } + ) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime + .average + ).toBe(false) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median + ).toBe(true) + const fsWorkerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE + workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + fixedPool, + fsWorkerChoiceStrategy, + { + runTime: { median: true } + } + ) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime + .average + ).toBe(false) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median + ).toBe(true) + workerChoiceStrategyContext = new WorkerChoiceStrategyContext( + dynamicPool, + fsWorkerChoiceStrategy, + { + runTime: { median: true } + } + ) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime + .average + ).toBe(false) + expect( + workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median + ).toBe(true) }) })