1 import { expect } from 'expect'
2 import { createStubInstance, restore, stub } from 'sinon'
7 } from '../../../lib/index.js'
8 import { WorkerChoiceStrategyContext } from '../../../lib/pools/selection-strategies/worker-choice-strategy-context.js'
9 import { RoundRobinWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy.js'
10 import { LeastUsedWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/least-used-worker-choice-strategy.js'
11 import { LeastBusyWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/least-busy-worker-choice-strategy.js'
12 import { LeastEluWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/least-elu-worker-choice-strategy.js'
13 import { FairShareWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy.js'
14 import { WeightedRoundRobinWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.js'
15 import { InterleavedWeightedRoundRobinWorkerChoiceStrategy } from '../../../lib/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.js'
17 describe('Worker choice strategy context test suite', () => {
20 let fixedPool, dynamicPool
23 fixedPool = new FixedThreadPool(
25 './tests/worker-files/thread/testWorker.mjs'
27 dynamicPool = new DynamicThreadPool(
30 './tests/worker-files/thread/testWorker.mjs'
39 await fixedPool.destroy()
40 await dynamicPool.destroy()
43 it('Verify that constructor() initializes the context with all the available worker choice strategies', () => {
44 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
47 expect(workerChoiceStrategyContext.workerChoiceStrategies.size).toBe(
48 Object.keys(WorkerChoiceStrategies).length
52 it('Verify that execute() return the worker chosen by the strategy with fixed pool', () => {
53 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
56 const workerChoiceStrategyStub = createStubInstance(
57 RoundRobinWorkerChoiceStrategy,
59 choose: stub().returns(0)
62 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
63 WorkerChoiceStrategies.ROUND_ROBIN
65 workerChoiceStrategyContext.workerChoiceStrategies.set(
66 workerChoiceStrategyContext.workerChoiceStrategy,
67 workerChoiceStrategyStub
69 const chosenWorkerKey = workerChoiceStrategyContext.execute()
71 workerChoiceStrategyContext.workerChoiceStrategies.get(
72 workerChoiceStrategyContext.workerChoiceStrategy
75 expect(chosenWorkerKey).toBe(0)
78 it('Verify that execute() throws error if null or undefined is returned after retries', () => {
79 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
82 const workerChoiceStrategyUndefinedStub = createStubInstance(
83 RoundRobinWorkerChoiceStrategy,
85 choose: stub().returns(undefined)
88 const workerChoiceStrategyNullStub = createStubInstance(
89 RoundRobinWorkerChoiceStrategy,
91 choose: stub().returns(null)
94 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
95 WorkerChoiceStrategies.ROUND_ROBIN
97 workerChoiceStrategyContext.workerChoiceStrategies.set(
98 workerChoiceStrategyContext.workerChoiceStrategy,
99 workerChoiceStrategyUndefinedStub
101 expect(() => workerChoiceStrategyContext.execute()).toThrowError(
102 new Error('Worker node key chosen is null or undefined after 6 retries')
104 workerChoiceStrategyContext.workerChoiceStrategies.set(
105 workerChoiceStrategyContext.workerChoiceStrategy,
106 workerChoiceStrategyNullStub
108 expect(() => workerChoiceStrategyContext.execute()).toThrowError(
109 new Error('Worker node key chosen is null or undefined after 6 retries')
113 it('Verify that execute() return the worker chosen by the strategy with dynamic pool', () => {
114 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
117 const workerChoiceStrategyStub = createStubInstance(
118 RoundRobinWorkerChoiceStrategy,
120 choose: stub().returns(0)
123 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
124 WorkerChoiceStrategies.ROUND_ROBIN
126 workerChoiceStrategyContext.workerChoiceStrategies.set(
127 workerChoiceStrategyContext.workerChoiceStrategy,
128 workerChoiceStrategyStub
130 const chosenWorkerKey = workerChoiceStrategyContext.execute()
132 workerChoiceStrategyContext.workerChoiceStrategies.get(
133 workerChoiceStrategyContext.workerChoiceStrategy
136 expect(chosenWorkerKey).toBe(0)
139 it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => {
140 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
141 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
145 workerChoiceStrategyContext.workerChoiceStrategies.get(
148 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
149 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
152 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
154 workerChoiceStrategyContext.workerChoiceStrategies.get(
157 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
158 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
163 it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and dynamic pool', () => {
164 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
165 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
169 workerChoiceStrategyContext.workerChoiceStrategies.get(
172 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
173 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
176 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
178 workerChoiceStrategyContext.workerChoiceStrategies.get(
181 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
182 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
187 it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and fixed pool', () => {
188 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
189 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
192 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
194 workerChoiceStrategyContext.workerChoiceStrategies.get(
197 ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
198 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
203 it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and dynamic pool', () => {
204 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
205 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
208 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
210 workerChoiceStrategyContext.workerChoiceStrategies.get(
213 ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
214 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
219 it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and fixed pool', () => {
220 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
221 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
224 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
226 workerChoiceStrategyContext.workerChoiceStrategies.get(
229 ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
230 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
235 it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and dynamic pool', () => {
236 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
237 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
240 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
242 workerChoiceStrategyContext.workerChoiceStrategies.get(
245 ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
246 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
251 it('Verify that setWorkerChoiceStrategy() works with LEAST_ELU and fixed pool', () => {
252 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
253 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
256 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
258 workerChoiceStrategyContext.workerChoiceStrategies.get(
261 ).toBeInstanceOf(LeastEluWorkerChoiceStrategy)
262 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
267 it('Verify that setWorkerChoiceStrategy() works with LEAST_ELU and dynamic pool', () => {
268 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
269 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
272 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
274 workerChoiceStrategyContext.workerChoiceStrategies.get(
277 ).toBeInstanceOf(LeastEluWorkerChoiceStrategy)
278 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
283 it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and fixed pool', () => {
284 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
285 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
288 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
290 workerChoiceStrategyContext.workerChoiceStrategies.get(
293 ).toBeInstanceOf(FairShareWorkerChoiceStrategy)
294 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
299 it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and dynamic pool', () => {
300 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
301 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
304 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
306 workerChoiceStrategyContext.workerChoiceStrategies.get(
309 ).toBeInstanceOf(FairShareWorkerChoiceStrategy)
310 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
315 it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and fixed pool', () => {
316 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
317 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
320 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
322 workerChoiceStrategyContext.workerChoiceStrategies.get(
325 ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy)
326 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
331 it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and dynamic pool', () => {
332 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
333 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
336 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
338 workerChoiceStrategyContext.workerChoiceStrategies.get(
341 ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy)
342 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
347 it('Verify that setWorkerChoiceStrategy() works with INTERLEAVED_WEIGHTED_ROUND_ROBIN and fixed pool', () => {
348 const workerChoiceStrategy =
349 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
350 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
353 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
355 workerChoiceStrategyContext.workerChoiceStrategies.get(
358 ).toBeInstanceOf(InterleavedWeightedRoundRobinWorkerChoiceStrategy)
359 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
364 it('Verify that setWorkerChoiceStrategy() works with INTERLEAVED_WEIGHTED_ROUND_ROBIN and dynamic pool', () => {
365 const workerChoiceStrategy =
366 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
367 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
370 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
372 workerChoiceStrategyContext.workerChoiceStrategies.get(
375 ).toBeInstanceOf(InterleavedWeightedRoundRobinWorkerChoiceStrategy)
376 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
381 it('Verify that worker choice strategy options enable median runtime pool statistics', () => {
382 const wwrWorkerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
383 let workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
385 wwrWorkerChoiceStrategy,
387 runTime: { median: true }
391 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
395 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median
397 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
399 wwrWorkerChoiceStrategy,
401 runTime: { median: true }
405 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
409 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median
411 const fsWorkerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
412 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
414 fsWorkerChoiceStrategy,
416 runTime: { median: true }
420 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
424 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median
426 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
428 fsWorkerChoiceStrategy,
430 runTime: { median: true }
434 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime
438 workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median