Commit | Line | Data |
---|---|---|
40ad1d27 JB |
1 | const { expect } = require('expect') |
2 | const sinon = require('sinon') | |
3 | const { | |
4 | FixedThreadPool, | |
5 | DynamicThreadPool, | |
6 | WorkerChoiceStrategies | |
cdace0e5 | 7 | } = require('../../../lib') |
23ff945a JB |
8 | const { |
9 | WorkerChoiceStrategyContext | |
10 | } = require('../../../lib/pools/selection-strategies/worker-choice-strategy-context') | |
40ad1d27 JB |
11 | const { |
12 | RoundRobinWorkerChoiceStrategy | |
13 | } = require('../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy') | |
14 | const { | |
e4543b14 JB |
15 | LeastUsedWorkerChoiceStrategy |
16 | } = require('../../../lib/pools/selection-strategies/least-used-worker-choice-strategy') | |
168c526f | 17 | const { |
e4543b14 JB |
18 | LeastBusyWorkerChoiceStrategy |
19 | } = require('../../../lib/pools/selection-strategies/least-busy-worker-choice-strategy') | |
40ad1d27 | 20 | const { |
23ff945a JB |
21 | FairShareWorkerChoiceStrategy |
22 | } = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy') | |
c15273f2 JB |
23 | const { |
24 | WeightedRoundRobinWorkerChoiceStrategy | |
fa6f1296 | 25 | } = require('../../../lib/pools/selection-strategies/weighted-round-robin-worker-choice-strategy') |
40ad1d27 JB |
26 | |
27 | describe('Worker choice strategy context test suite', () => { | |
c15273f2 JB |
28 | const min = 1 |
29 | const max = 3 | |
40ad1d27 | 30 | let fixedPool, dynamicPool |
c15273f2 JB |
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 | ) | |
40ad1d27 JB |
42 | }) |
43 | ||
44 | afterEach(() => { | |
45 | sinon.restore() | |
46 | }) | |
47 | ||
fd7ebd49 JB |
48 | after(async () => { |
49 | await fixedPool.destroy() | |
50 | await dynamicPool.destroy() | |
c15273f2 JB |
51 | }) |
52 | ||
2285a040 JB |
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 | ||
40ad1d27 JB |
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 | { | |
c923ce56 | 69 | choose: sinon.stub().returns(0) |
40ad1d27 JB |
70 | } |
71 | ) | |
d710242d | 72 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
95c83464 JB |
73 | WorkerChoiceStrategies.ROUND_ROBIN |
74 | ) | |
75 | workerChoiceStrategyContext.workerChoiceStrategies.set( | |
d710242d | 76 | workerChoiceStrategyContext.workerChoiceStrategy, |
95c83464 JB |
77 | WorkerChoiceStrategyStub |
78 | ) | |
c923ce56 | 79 | const chosenWorkerKey = workerChoiceStrategyContext.execute() |
40ad1d27 | 80 | expect( |
95c83464 | 81 | workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 82 | workerChoiceStrategyContext.workerChoiceStrategy |
95c83464 | 83 | ).choose.calledOnce |
40ad1d27 | 84 | ).toBe(true) |
c923ce56 | 85 | expect(chosenWorkerKey).toBe(0) |
40ad1d27 JB |
86 | }) |
87 | ||
527e715f JB |
88 | it('Verify that execute() throws error if null or undefined is returned', () => { |
89 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( | |
90 | fixedPool | |
91 | ) | |
fa418e12 | 92 | const WorkerChoiceStrategyUndefinedStub = sinon.createStubInstance( |
527e715f JB |
93 | RoundRobinWorkerChoiceStrategy, |
94 | { | |
95 | choose: sinon.stub().returns(undefined) | |
96 | } | |
97 | ) | |
fa418e12 JB |
98 | const WorkerChoiceStrategyNullStub = sinon.createStubInstance( |
99 | RoundRobinWorkerChoiceStrategy, | |
100 | { | |
101 | choose: sinon.stub().returns(null) | |
102 | } | |
103 | ) | |
527e715f JB |
104 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
105 | WorkerChoiceStrategies.ROUND_ROBIN | |
106 | ) | |
107 | workerChoiceStrategyContext.workerChoiceStrategies.set( | |
108 | workerChoiceStrategyContext.workerChoiceStrategy, | |
fa418e12 JB |
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 | |
527e715f JB |
117 | ) |
118 | expect(() => workerChoiceStrategyContext.execute()).toThrowError( | |
119 | new Error('Worker node key chosen is null or undefined') | |
120 | ) | |
121 | }) | |
122 | ||
40ad1d27 JB |
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 | { | |
c923ce56 | 130 | choose: sinon.stub().returns(0) |
40ad1d27 JB |
131 | } |
132 | ) | |
d710242d | 133 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
95c83464 JB |
134 | WorkerChoiceStrategies.ROUND_ROBIN |
135 | ) | |
136 | workerChoiceStrategyContext.workerChoiceStrategies.set( | |
d710242d | 137 | workerChoiceStrategyContext.workerChoiceStrategy, |
95c83464 JB |
138 | WorkerChoiceStrategyStub |
139 | ) | |
c923ce56 | 140 | const chosenWorkerKey = workerChoiceStrategyContext.execute() |
40ad1d27 | 141 | expect( |
95c83464 | 142 | workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 143 | workerChoiceStrategyContext.workerChoiceStrategy |
95c83464 | 144 | ).choose.calledOnce |
40ad1d27 | 145 | ).toBe(true) |
c923ce56 | 146 | expect(chosenWorkerKey).toBe(0) |
40ad1d27 JB |
147 | }) |
148 | ||
149 | it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and fixed pool', () => { | |
594bfb84 | 150 | const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN |
40ad1d27 JB |
151 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
152 | fixedPool | |
153 | ) | |
95c83464 JB |
154 | expect( |
155 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 156 | workerChoiceStrategy |
95c83464 JB |
157 | ) |
158 | ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) | |
d710242d | 159 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 160 | workerChoiceStrategy |
40ad1d27 | 161 | ) |
594bfb84 | 162 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
163 | expect( |
164 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 165 | workerChoiceStrategy |
95c83464 JB |
166 | ) |
167 | ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) | |
d710242d | 168 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 169 | workerChoiceStrategy |
b2b1d84e | 170 | ) |
40ad1d27 JB |
171 | }) |
172 | ||
23ff945a | 173 | it('Verify that setWorkerChoiceStrategy() works with ROUND_ROBIN and dynamic pool', () => { |
594bfb84 | 174 | const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN |
40ad1d27 JB |
175 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
176 | dynamicPool | |
177 | ) | |
95c83464 JB |
178 | expect( |
179 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 180 | workerChoiceStrategy |
95c83464 JB |
181 | ) |
182 | ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) | |
d710242d | 183 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 184 | workerChoiceStrategy |
40ad1d27 | 185 | ) |
594bfb84 | 186 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
187 | expect( |
188 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 189 | workerChoiceStrategy |
95c83464 JB |
190 | ) |
191 | ).toBeInstanceOf(RoundRobinWorkerChoiceStrategy) | |
d710242d | 192 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 193 | workerChoiceStrategy |
b2b1d84e | 194 | ) |
40ad1d27 JB |
195 | }) |
196 | ||
e4543b14 JB |
197 | it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and fixed pool', () => { |
198 | const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED | |
40ad1d27 JB |
199 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
200 | fixedPool | |
201 | ) | |
594bfb84 | 202 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
203 | expect( |
204 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 205 | workerChoiceStrategy |
95c83464 | 206 | ) |
e4543b14 | 207 | ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy) |
d710242d | 208 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 209 | workerChoiceStrategy |
b2b1d84e | 210 | ) |
40ad1d27 JB |
211 | }) |
212 | ||
e4543b14 JB |
213 | it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and dynamic pool', () => { |
214 | const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED | |
40ad1d27 JB |
215 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
216 | dynamicPool | |
217 | ) | |
594bfb84 | 218 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
219 | expect( |
220 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 221 | workerChoiceStrategy |
95c83464 | 222 | ) |
e4543b14 | 223 | ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy) |
d710242d | 224 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 225 | workerChoiceStrategy |
b2b1d84e | 226 | ) |
168c526f JB |
227 | }) |
228 | ||
e4543b14 JB |
229 | it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and fixed pool', () => { |
230 | const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY | |
168c526f JB |
231 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
232 | fixedPool | |
233 | ) | |
594bfb84 | 234 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
235 | expect( |
236 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 237 | workerChoiceStrategy |
95c83464 | 238 | ) |
e4543b14 | 239 | ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy) |
d710242d | 240 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 241 | workerChoiceStrategy |
b2b1d84e | 242 | ) |
168c526f JB |
243 | }) |
244 | ||
e4543b14 JB |
245 | it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and dynamic pool', () => { |
246 | const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY | |
168c526f JB |
247 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
248 | dynamicPool | |
249 | ) | |
594bfb84 | 250 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
251 | expect( |
252 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 253 | workerChoiceStrategy |
95c83464 | 254 | ) |
e4543b14 | 255 | ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy) |
d710242d | 256 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 257 | workerChoiceStrategy |
b2b1d84e | 258 | ) |
40ad1d27 | 259 | }) |
23ff945a JB |
260 | |
261 | it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and fixed pool', () => { | |
594bfb84 | 262 | const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE |
23ff945a JB |
263 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
264 | fixedPool | |
265 | ) | |
594bfb84 | 266 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
267 | expect( |
268 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 269 | workerChoiceStrategy |
95c83464 JB |
270 | ) |
271 | ).toBeInstanceOf(FairShareWorkerChoiceStrategy) | |
d710242d | 272 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 273 | workerChoiceStrategy |
b2b1d84e | 274 | ) |
23ff945a JB |
275 | }) |
276 | ||
277 | it('Verify that setWorkerChoiceStrategy() works with FAIR_SHARE and dynamic pool', () => { | |
594bfb84 | 278 | const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE |
23ff945a JB |
279 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
280 | dynamicPool | |
281 | ) | |
594bfb84 | 282 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
283 | expect( |
284 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 285 | workerChoiceStrategy |
95c83464 JB |
286 | ) |
287 | ).toBeInstanceOf(FairShareWorkerChoiceStrategy) | |
d710242d | 288 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 289 | workerChoiceStrategy |
b2b1d84e | 290 | ) |
23ff945a JB |
291 | }) |
292 | ||
c15273f2 | 293 | it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and fixed pool', () => { |
594bfb84 | 294 | const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN |
c15273f2 JB |
295 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
296 | fixedPool | |
297 | ) | |
594bfb84 | 298 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
299 | expect( |
300 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 301 | workerChoiceStrategy |
95c83464 JB |
302 | ) |
303 | ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy) | |
d710242d | 304 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 305 | workerChoiceStrategy |
b2b1d84e | 306 | ) |
c15273f2 | 307 | }) |
23ff945a | 308 | |
c15273f2 | 309 | it('Verify that setWorkerChoiceStrategy() works with WEIGHTED_ROUND_ROBIN and dynamic pool', () => { |
594bfb84 | 310 | const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN |
c15273f2 JB |
311 | const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( |
312 | dynamicPool | |
313 | ) | |
594bfb84 | 314 | workerChoiceStrategyContext.setWorkerChoiceStrategy(workerChoiceStrategy) |
95c83464 JB |
315 | expect( |
316 | workerChoiceStrategyContext.workerChoiceStrategies.get( | |
594bfb84 | 317 | workerChoiceStrategy |
95c83464 JB |
318 | ) |
319 | ).toBeInstanceOf(WeightedRoundRobinWorkerChoiceStrategy) | |
d710242d | 320 | expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe( |
594bfb84 | 321 | workerChoiceStrategy |
b2b1d84e | 322 | ) |
c15273f2 | 323 | }) |
2fc5cae3 | 324 | |
9e45c2c4 | 325 | it('Verify that worker choice strategy options enable median runtime pool statistics', () => { |
2fc5cae3 JB |
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 | }) | |
40ad1d27 | 381 | }) |