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