refactor: rename worker choice strategies to sensible names
[poolifier.git] / tests / pools / selection-strategies / worker-choice-strategy-context.test.js
1 const { expect } = require('expect')
2 const sinon = require('sinon')
3 const {
4 FixedThreadPool,
5 DynamicThreadPool,
6 WorkerChoiceStrategies
7 } = require('../../../lib')
8 const {
9 WorkerChoiceStrategyContext
10 } = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context')
11 const {
12 RoundRobinWorkerChoiceStrategy
13 } = require('../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy')
14 const {
15 LeastUsedWorkerChoiceStrategy
16 } = require('../../../lib/pools/selection-strategies/least-used-worker-choice-strategy')
17 const {
18 LeastBusyWorkerChoiceStrategy
19 } = require('../../../lib/pools/selection-strategies/least-busy-worker-choice-strategy')
20 const {
21 FairShareWorkerChoiceStrategy
22 } = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy')
23 const {
24 WeightedRoundRobinWorkerChoiceStrategy
25 } = require('../../../lib/pools/selection-strategies/weighted-round-robin-worker-choice-strategy')
26
27 describe('Worker choice strategy context test suite', () => {
28 const min = 1
29 const max = 3
30 let fixedPool, dynamicPool
31
32 before(() => {
33 fixedPool = new FixedThreadPool(
34 max,
35 './tests/worker-files/thread/testWorker.js'
36 )
37 dynamicPool = new DynamicThreadPool(
38 min,
39 max,
40 './tests/worker-files/thread/testWorker.js'
41 )
42 })
43
44 afterEach(() => {
45 sinon.restore()
46 })
47
48 after(async () => {
49 await fixedPool.destroy()
50 await dynamicPool.destroy()
51 })
52
53 it('Verify that constructor() initializes the context with all the available worker choice strategies', () => {
54 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
55 fixedPool
56 )
57 expect(workerChoiceStrategyContext.workerChoiceStrategies.size).toBe(
58 Object.keys(WorkerChoiceStrategies).length
59 )
60 })
61
62 it('Verify that execute() return the worker chosen by the strategy with fixed pool', () => {
63 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
64 fixedPool
65 )
66 const WorkerChoiceStrategyStub = sinon.createStubInstance(
67 RoundRobinWorkerChoiceStrategy,
68 {
69 choose: sinon.stub().returns(0)
70 }
71 )
72 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
73 WorkerChoiceStrategies.ROUND_ROBIN
74 )
75 workerChoiceStrategyContext.workerChoiceStrategies.set(
76 workerChoiceStrategyContext.workerChoiceStrategy,
77 WorkerChoiceStrategyStub
78 )
79 const chosenWorkerKey = workerChoiceStrategyContext.execute()
80 expect(
81 workerChoiceStrategyContext.workerChoiceStrategies.get(
82 workerChoiceStrategyContext.workerChoiceStrategy
83 ).choose.calledOnce
84 ).toBe(true)
85 expect(chosenWorkerKey).toBe(0)
86 })
87
88 it('Verify that execute() throws error if null or undefined is returned', () => {
89 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
90 fixedPool
91 )
92 const WorkerChoiceStrategyUndefinedStub = sinon.createStubInstance(
93 RoundRobinWorkerChoiceStrategy,
94 {
95 choose: sinon.stub().returns(undefined)
96 }
97 )
98 const WorkerChoiceStrategyNullStub = sinon.createStubInstance(
99 RoundRobinWorkerChoiceStrategy,
100 {
101 choose: sinon.stub().returns(null)
102 }
103 )
104 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
105 WorkerChoiceStrategies.ROUND_ROBIN
106 )
107 workerChoiceStrategyContext.workerChoiceStrategies.set(
108 workerChoiceStrategyContext.workerChoiceStrategy,
109 WorkerChoiceStrategyUndefinedStub
110 )
111 expect(() => workerChoiceStrategyContext.execute()).toThrowError(
112 new Error('Worker node key chosen is null or undefined')
113 )
114 workerChoiceStrategyContext.workerChoiceStrategies.set(
115 workerChoiceStrategyContext.workerChoiceStrategy,
116 WorkerChoiceStrategyNullStub
117 )
118 expect(() => workerChoiceStrategyContext.execute()).toThrowError(
119 new Error('Worker node key chosen is null or undefined')
120 )
121 })
122
123 it('Verify that execute() return the worker chosen by the strategy with dynamic pool', () => {
124 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
125 dynamicPool
126 )
127 const WorkerChoiceStrategyStub = sinon.createStubInstance(
128 RoundRobinWorkerChoiceStrategy,
129 {
130 choose: sinon.stub().returns(0)
131 }
132 )
133 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
134 WorkerChoiceStrategies.ROUND_ROBIN
135 )
136 workerChoiceStrategyContext.workerChoiceStrategies.set(
137 workerChoiceStrategyContext.workerChoiceStrategy,
138 WorkerChoiceStrategyStub
139 )
140 const chosenWorkerKey = workerChoiceStrategyContext.execute()
141 expect(
142 workerChoiceStrategyContext.workerChoiceStrategies.get(
143 workerChoiceStrategyContext.workerChoiceStrategy
144 ).choose.calledOnce
145 ).toBe(true)
146 expect(chosenWorkerKey).toBe(0)
147 })
148
149 it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => {
150 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
151 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
152 fixedPool
153 )
154 expect(
155 workerChoiceStrategyContext.workerChoiceStrategies.get(
156 workerChoiceStrategy
157 )
158 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
159 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
160 workerChoiceStrategy
161 )
162 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
163 expect(
164 workerChoiceStrategyContext.workerChoiceStrategies.get(
165 workerChoiceStrategy
166 )
167 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
168 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
169 workerChoiceStrategy
170 )
171 })
172
173 it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and dynamic pool', () => {
174 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
175 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
176 dynamicPool
177 )
178 expect(
179 workerChoiceStrategyContext.workerChoiceStrategies.get(
180 workerChoiceStrategy
181 )
182 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
183 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
184 workerChoiceStrategy
185 )
186 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
187 expect(
188 workerChoiceStrategyContext.workerChoiceStrategies.get(
189 workerChoiceStrategy
190 )
191 ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy)
192 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
193 workerChoiceStrategy
194 )
195 })
196
197 it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and fixed pool', () => {
198 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
199 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
200 fixedPool
201 )
202 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
203 expect(
204 workerChoiceStrategyContext.workerChoiceStrategies.get(
205 workerChoiceStrategy
206 )
207 ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
208 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
209 workerChoiceStrategy
210 )
211 })
212
213 it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and dynamic pool', () => {
214 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
215 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
216 dynamicPool
217 )
218 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
219 expect(
220 workerChoiceStrategyContext.workerChoiceStrategies.get(
221 workerChoiceStrategy
222 )
223 ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
224 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
225 workerChoiceStrategy
226 )
227 })
228
229 it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and fixed pool', () => {
230 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
231 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
232 fixedPool
233 )
234 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
235 expect(
236 workerChoiceStrategyContext.workerChoiceStrategies.get(
237 workerChoiceStrategy
238 )
239 ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
240 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
241 workerChoiceStrategy
242 )
243 })
244
245 it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and dynamic pool', () => {
246 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
247 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
248 dynamicPool
249 )
250 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
251 expect(
252 workerChoiceStrategyContext.workerChoiceStrategies.get(
253 workerChoiceStrategy
254 )
255 ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
256 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
257 workerChoiceStrategy
258 )
259 })
260
261 it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and fixed pool', () => {
262 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
263 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
264 fixedPool
265 )
266 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
267 expect(
268 workerChoiceStrategyContext.workerChoiceStrategies.get(
269 workerChoiceStrategy
270 )
271 ).toBeInstanceOf(FairShareWorkerChoiceStrategy)
272 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
273 workerChoiceStrategy
274 )
275 })
276
277 it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and dynamic pool', () => {
278 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
279 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
280 dynamicPool
281 )
282 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
283 expect(
284 workerChoiceStrategyContext.workerChoiceStrategies.get(
285 workerChoiceStrategy
286 )
287 ).toBeInstanceOf(FairShareWorkerChoiceStrategy)
288 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
289 workerChoiceStrategy
290 )
291 })
292
293 it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and fixed pool', () => {
294 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
295 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
296 fixedPool
297 )
298 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
299 expect(
300 workerChoiceStrategyContext.workerChoiceStrategies.get(
301 workerChoiceStrategy
302 )
303 ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy)
304 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
305 workerChoiceStrategy
306 )
307 })
308
309 it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and dynamic pool', () => {
310 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
311 const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
312 dynamicPool
313 )
314 workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy)
315 expect(
316 workerChoiceStrategyContext.workerChoiceStrategies.get(
317 workerChoiceStrategy
318 )
319 ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy)
320 expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
321 workerChoiceStrategy
322 )
323 })
324
325 it('Verify that worker choice strategy options enable median runtime pool statistics', () => {
326 const wwrWorkerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
327 let workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
328 fixedPool,
329 wwrWorkerChoiceStrategy,
330 {
331 medRunTime: true
332 }
333 )
334 expect(workerChoiceStrategyContext.getRequiredStatistics().avgRunTime).toBe(
335 false
336 )
337 expect(workerChoiceStrategyContext.getRequiredStatistics().medRunTime).toBe(
338 true
339 )
340 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
341 dynamicPool,
342 wwrWorkerChoiceStrategy,
343 {
344 medRunTime: true
345 }
346 )
347 expect(workerChoiceStrategyContext.getRequiredStatistics().avgRunTime).toBe(
348 false
349 )
350 expect(workerChoiceStrategyContext.getRequiredStatistics().medRunTime).toBe(
351 true
352 )
353 const fsWorkerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
354 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
355 fixedPool,
356 fsWorkerChoiceStrategy,
357 {
358 medRunTime: true
359 }
360 )
361 expect(workerChoiceStrategyContext.getRequiredStatistics().avgRunTime).toBe(
362 false
363 )
364 expect(workerChoiceStrategyContext.getRequiredStatistics().medRunTime).toBe(
365 true
366 )
367 workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
368 dynamicPool,
369 fsWorkerChoiceStrategy,
370 {
371 medRunTime: true
372 }
373 )
374 expect(workerChoiceStrategyContext.getRequiredStatistics().avgRunTime).toBe(
375 false
376 )
377 expect(workerChoiceStrategyContext.getRequiredStatistics().medRunTime).toBe(
378 true
379 )
380 })
381 })