Commit | Line | Data |
---|---|---|
a61a0724 | 1 | const { expect } = require('expect') |
a35560ba S |
2 | const { |
3 | WorkerChoiceStrategies, | |
4 | DynamicThreadPool, | |
2ced693a JB |
5 | FixedThreadPool, |
6 | FixedClusterPool | |
cdace0e5 | 7 | } = require('../../../lib') |
a35560ba S |
8 | |
9 | describe('Selection strategies test suite', () => { | |
e1ffb94f JB |
10 | const min = 0 |
11 | const max = 3 | |
12 | ||
a35560ba S |
13 | it('Verify that WorkerChoiceStrategies enumeration provides string values', () => { |
14 | expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN') | |
737c6d97 | 15 | expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED') |
168c526f | 16 | expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY') |
23ff945a | 17 | expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE') |
b3432a63 JB |
18 | expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe( |
19 | 'WEIGHTED_ROUND_ROBIN' | |
20 | ) | |
a35560ba S |
21 | }) |
22 | ||
e843b904 | 23 | it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => { |
e843b904 JB |
24 | const pool = new DynamicThreadPool( |
25 | min, | |
26 | max, | |
27 | './tests/worker-files/thread/testWorker.js' | |
28 | ) | |
29 | expect(pool.opts.workerChoiceStrategy).toBe( | |
30 | WorkerChoiceStrategies.ROUND_ROBIN | |
31 | ) | |
32 | // We need to clean up the resources after our test | |
33 | await pool.destroy() | |
34 | }) | |
35 | ||
594bfb84 JB |
36 | it('Verify available strategies are taken at pool creation', async () => { |
37 | for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { | |
38 | const pool = new FixedThreadPool( | |
39 | max, | |
40 | './tests/worker-files/thread/testWorker.js', | |
41 | { workerChoiceStrategy } | |
42 | ) | |
43 | expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy) | |
44 | expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe( | |
45 | workerChoiceStrategy | |
46 | ) | |
47 | await pool.destroy() | |
48 | } | |
d2f7b7a2 JB |
49 | }) |
50 | ||
594bfb84 JB |
51 | it('Verify available strategies can be set after pool creation', async () => { |
52 | for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { | |
53 | const pool = new DynamicThreadPool( | |
54 | min, | |
55 | max, | |
ec82cfa1 | 56 | './tests/worker-files/thread/testWorker.js' |
594bfb84 JB |
57 | ) |
58 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) | |
59 | expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy) | |
60 | expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe( | |
61 | workerChoiceStrategy | |
62 | ) | |
63 | await pool.destroy() | |
64 | } | |
65 | }) | |
66 | ||
67 | it('Verify available strategies default internals at pool creation', async () => { | |
68 | const pool = new FixedThreadPool( | |
e843b904 JB |
69 | max, |
70 | './tests/worker-files/thread/testWorker.js' | |
71 | ) | |
594bfb84 JB |
72 | for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { |
73 | if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) { | |
74 | expect( | |
75 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
76 | workerChoiceStrategy | |
77 | ).nextWorkerNodeId | |
78 | ).toBe(0) | |
79 | } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) { | |
08f3f44c JB |
80 | expect( |
81 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
82 | workerChoiceStrategy | |
83 | ).workersVirtualTaskTimestamp | |
84 | ).toBeInstanceOf(Array) | |
85 | expect( | |
86 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
87 | workerChoiceStrategy | |
88 | ).workersVirtualTaskTimestamp.length | |
89 | ).toBe(0) | |
594bfb84 JB |
90 | } else if ( |
91 | workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN | |
92 | ) { | |
93 | expect( | |
94 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
95 | workerChoiceStrategy | |
96 | ).currentWorkerNodeId | |
97 | ).toBe(0) | |
98 | expect( | |
99 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
100 | workerChoiceStrategy | |
101 | ).defaultWorkerWeight | |
102 | ).toBeGreaterThan(0) | |
08f3f44c JB |
103 | expect( |
104 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
105 | workerChoiceStrategy | |
106 | ).workerVirtualTaskRunTime | |
107 | ).toBe(0) | |
594bfb84 JB |
108 | } |
109 | } | |
e843b904 JB |
110 | await pool.destroy() |
111 | }) | |
112 | ||
10fcfaf4 | 113 | it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => { |
594bfb84 | 114 | const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN |
10fcfaf4 JB |
115 | let pool = new FixedThreadPool( |
116 | max, | |
d710242d | 117 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 118 | { workerChoiceStrategy } |
10fcfaf4 | 119 | ) |
10fcfaf4 | 120 | expect( |
97a2abc3 | 121 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 122 | ).toBe(false) |
c6bd2650 JB |
123 | expect( |
124 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
125 | ).toBe(false) | |
78099a15 JB |
126 | expect( |
127 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
128 | ).toBe(false) | |
fd7ebd49 | 129 | await pool.destroy() |
10fcfaf4 JB |
130 | pool = new DynamicThreadPool( |
131 | min, | |
132 | max, | |
d710242d | 133 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 134 | { workerChoiceStrategy } |
10fcfaf4 | 135 | ) |
10fcfaf4 | 136 | expect( |
97a2abc3 | 137 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 138 | ).toBe(false) |
c6bd2650 JB |
139 | expect( |
140 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
141 | ).toBe(false) | |
78099a15 JB |
142 | expect( |
143 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
144 | ).toBe(false) | |
10fcfaf4 JB |
145 | // We need to clean up the resources after our test |
146 | await pool.destroy() | |
147 | }) | |
148 | ||
bdaf31cd | 149 | it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => { |
bdaf31cd JB |
150 | const pool = new FixedThreadPool( |
151 | max, | |
152 | './tests/worker-files/thread/testWorker.js', | |
153 | { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN } | |
154 | ) | |
bdaf31cd JB |
155 | // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose` |
156 | const promises = [] | |
a20f0ba5 JB |
157 | const maxMultiplier = 2 |
158 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 159 | promises.push(pool.execute()) |
bdaf31cd JB |
160 | } |
161 | await Promise.all(promises) | |
162 | // We need to clean up the resources after our test | |
163 | await pool.destroy() | |
164 | }) | |
165 | ||
166 | it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => { | |
bdaf31cd JB |
167 | const pool = new DynamicThreadPool( |
168 | min, | |
169 | max, | |
170 | './tests/worker-files/thread/testWorker.js', | |
171 | { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN } | |
172 | ) | |
bdaf31cd JB |
173 | // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose` |
174 | const promises = [] | |
a20f0ba5 JB |
175 | const maxMultiplier = 2 |
176 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 177 | promises.push(pool.execute()) |
bdaf31cd JB |
178 | } |
179 | await Promise.all(promises) | |
180 | // We need to clean up the resources after our test | |
181 | await pool.destroy() | |
182 | }) | |
183 | ||
2ced693a | 184 | it('Verify ROUND_ROBIN strategy runtime behavior', async () => { |
594bfb84 | 185 | const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN |
2ced693a JB |
186 | let pool = new FixedClusterPool( |
187 | max, | |
594bfb84 JB |
188 | './tests/worker-files/cluster/testWorker.js', |
189 | { workerChoiceStrategy } | |
2ced693a JB |
190 | ) |
191 | let results = new Set() | |
192 | for (let i = 0; i < max; i++) { | |
adc3c320 | 193 | results.add(pool.chooseWorkerNode()[1].worker.id) |
2ced693a JB |
194 | } |
195 | expect(results.size).toBe(max) | |
196 | await pool.destroy() | |
594bfb84 JB |
197 | pool = new FixedThreadPool( |
198 | max, | |
199 | './tests/worker-files/thread/testWorker.js', | |
200 | { workerChoiceStrategy } | |
201 | ) | |
2ced693a JB |
202 | results = new Set() |
203 | for (let i = 0; i < max; i++) { | |
adc3c320 | 204 | results.add(pool.chooseWorkerNode()[1].worker.threadId) |
2ced693a JB |
205 | } |
206 | expect(results.size).toBe(max) | |
207 | await pool.destroy() | |
208 | }) | |
209 | ||
a6f7f1b4 | 210 | it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => { |
594bfb84 | 211 | const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN |
a6f7f1b4 JB |
212 | let pool = new FixedThreadPool( |
213 | max, | |
214 | './tests/worker-files/thread/testWorker.js', | |
215 | { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } | |
216 | ) | |
38f6e859 | 217 | expect( |
95c83464 | 218 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 219 | workerChoiceStrategy |
f06e48d8 | 220 | ).nextWorkerNodeId |
b529c323 | 221 | ).toBeDefined() |
594bfb84 | 222 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
a6f7f1b4 | 223 | expect( |
95c83464 | 224 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 225 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
f06e48d8 | 226 | ).nextWorkerNodeId |
a6f7f1b4 JB |
227 | ).toBe(0) |
228 | await pool.destroy() | |
229 | pool = new DynamicThreadPool( | |
230 | min, | |
231 | max, | |
232 | './tests/worker-files/thread/testWorker.js', | |
233 | { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } | |
234 | ) | |
38f6e859 | 235 | expect( |
95c83464 | 236 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 237 | workerChoiceStrategy |
f06e48d8 | 238 | ).nextWorkerNodeId |
b529c323 | 239 | ).toBeDefined() |
594bfb84 | 240 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
a6f7f1b4 | 241 | expect( |
95c83464 | 242 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 243 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
f06e48d8 | 244 | ).nextWorkerNodeId |
a6f7f1b4 JB |
245 | ).toBe(0) |
246 | // We need to clean up the resources after our test | |
247 | await pool.destroy() | |
248 | }) | |
249 | ||
737c6d97 | 250 | it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => { |
594bfb84 | 251 | const workerChoiceStrategy = WorkerChoiceStrategies.LESS_USED |
10fcfaf4 JB |
252 | let pool = new FixedThreadPool( |
253 | max, | |
d710242d | 254 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 255 | { workerChoiceStrategy } |
10fcfaf4 | 256 | ) |
10fcfaf4 | 257 | expect( |
97a2abc3 | 258 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 259 | ).toBe(false) |
c6bd2650 JB |
260 | expect( |
261 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
262 | ).toBe(false) | |
78099a15 JB |
263 | expect( |
264 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
265 | ).toBe(false) | |
fd7ebd49 | 266 | await pool.destroy() |
10fcfaf4 JB |
267 | pool = new DynamicThreadPool( |
268 | min, | |
269 | max, | |
d710242d | 270 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 271 | { workerChoiceStrategy } |
10fcfaf4 | 272 | ) |
10fcfaf4 | 273 | expect( |
97a2abc3 | 274 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 275 | ).toBe(false) |
c6bd2650 JB |
276 | expect( |
277 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
278 | ).toBe(false) | |
78099a15 JB |
279 | expect( |
280 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
281 | ).toBe(false) | |
10fcfaf4 JB |
282 | // We need to clean up the resources after our test |
283 | await pool.destroy() | |
284 | }) | |
285 | ||
737c6d97 | 286 | it('Verify LESS_USED strategy can be run in a fixed pool', async () => { |
b98ec2e6 JB |
287 | const pool = new FixedThreadPool( |
288 | max, | |
289 | './tests/worker-files/thread/testWorker.js', | |
737c6d97 | 290 | { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED } |
b98ec2e6 | 291 | ) |
168c526f | 292 | // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose` |
a35560ba | 293 | const promises = [] |
a20f0ba5 JB |
294 | const maxMultiplier = 2 |
295 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 296 | promises.push(pool.execute()) |
a35560ba S |
297 | } |
298 | await Promise.all(promises) | |
a35560ba S |
299 | // We need to clean up the resources after our test |
300 | await pool.destroy() | |
301 | }) | |
302 | ||
737c6d97 | 303 | it('Verify LESS_USED strategy can be run in a dynamic pool', async () => { |
ff5e76e1 JB |
304 | const pool = new DynamicThreadPool( |
305 | min, | |
306 | max, | |
307 | './tests/worker-files/thread/testWorker.js', | |
737c6d97 | 308 | { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED } |
ff5e76e1 | 309 | ) |
168c526f JB |
310 | // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose` |
311 | const promises = [] | |
a20f0ba5 JB |
312 | const maxMultiplier = 2 |
313 | for (let i = 0; i < max * maxMultiplier; i++) { | |
168c526f JB |
314 | promises.push(pool.execute()) |
315 | } | |
316 | await Promise.all(promises) | |
317 | // We need to clean up the resources after our test | |
318 | await pool.destroy() | |
319 | }) | |
320 | ||
168c526f | 321 | it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => { |
594bfb84 | 322 | const workerChoiceStrategy = WorkerChoiceStrategies.LESS_BUSY |
168c526f JB |
323 | let pool = new FixedThreadPool( |
324 | max, | |
d710242d | 325 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 326 | { workerChoiceStrategy } |
168c526f | 327 | ) |
168c526f | 328 | expect( |
97a2abc3 | 329 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
168c526f | 330 | ).toBe(true) |
c6bd2650 JB |
331 | expect( |
332 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
333 | ).toBe(false) | |
78099a15 JB |
334 | expect( |
335 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
336 | ).toBe(false) | |
168c526f JB |
337 | await pool.destroy() |
338 | pool = new DynamicThreadPool( | |
339 | min, | |
340 | max, | |
d710242d | 341 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 342 | { workerChoiceStrategy } |
168c526f | 343 | ) |
168c526f | 344 | expect( |
97a2abc3 | 345 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
168c526f | 346 | ).toBe(true) |
c6bd2650 JB |
347 | expect( |
348 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
349 | ).toBe(false) | |
78099a15 JB |
350 | expect( |
351 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
352 | ).toBe(false) | |
168c526f JB |
353 | // We need to clean up the resources after our test |
354 | await pool.destroy() | |
355 | }) | |
356 | ||
357 | it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => { | |
358 | const pool = new FixedThreadPool( | |
359 | max, | |
360 | './tests/worker-files/thread/testWorker.js', | |
361 | { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY } | |
362 | ) | |
363 | // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose` | |
364 | const promises = [] | |
a20f0ba5 JB |
365 | const maxMultiplier = 2 |
366 | for (let i = 0; i < max * maxMultiplier; i++) { | |
168c526f JB |
367 | promises.push(pool.execute()) |
368 | } | |
369 | await Promise.all(promises) | |
370 | // We need to clean up the resources after our test | |
371 | await pool.destroy() | |
372 | }) | |
373 | ||
374 | it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => { | |
375 | const pool = new DynamicThreadPool( | |
376 | min, | |
377 | max, | |
378 | './tests/worker-files/thread/testWorker.js', | |
379 | { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY } | |
380 | ) | |
381 | // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose` | |
ff5e76e1 | 382 | const promises = [] |
a20f0ba5 JB |
383 | const maxMultiplier = 2 |
384 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 385 | promises.push(pool.execute()) |
ff5e76e1 JB |
386 | } |
387 | await Promise.all(promises) | |
ff5e76e1 JB |
388 | // We need to clean up the resources after our test |
389 | await pool.destroy() | |
390 | }) | |
391 | ||
10fcfaf4 | 392 | it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => { |
594bfb84 | 393 | const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE |
10fcfaf4 JB |
394 | let pool = new FixedThreadPool( |
395 | max, | |
d710242d | 396 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 397 | { workerChoiceStrategy } |
10fcfaf4 | 398 | ) |
10fcfaf4 | 399 | expect( |
97a2abc3 | 400 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 401 | ).toBe(true) |
c6bd2650 JB |
402 | expect( |
403 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
404 | ).toBe(true) | |
78099a15 JB |
405 | expect( |
406 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
407 | ).toBe(false) | |
fd7ebd49 | 408 | await pool.destroy() |
10fcfaf4 JB |
409 | pool = new DynamicThreadPool( |
410 | min, | |
411 | max, | |
d710242d | 412 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 413 | { workerChoiceStrategy } |
10fcfaf4 | 414 | ) |
10fcfaf4 | 415 | expect( |
97a2abc3 | 416 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 417 | ).toBe(true) |
c6bd2650 JB |
418 | expect( |
419 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
420 | ).toBe(true) | |
78099a15 JB |
421 | expect( |
422 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
423 | ).toBe(false) | |
10fcfaf4 JB |
424 | // We need to clean up the resources after our test |
425 | await pool.destroy() | |
426 | }) | |
427 | ||
23ff945a | 428 | it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => { |
23ff945a JB |
429 | const pool = new FixedThreadPool( |
430 | max, | |
431 | './tests/worker-files/thread/testWorker.js', | |
432 | { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } | |
433 | ) | |
434 | // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` | |
435 | const promises = [] | |
a20f0ba5 JB |
436 | const maxMultiplier = 2 |
437 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 438 | promises.push(pool.execute()) |
23ff945a JB |
439 | } |
440 | await Promise.all(promises) | |
138d29a8 JB |
441 | for (const workerNode of pool.workerNodes) { |
442 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
443 | expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0) | |
444 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
445 | expect(workerNode.tasksUsage.medRunTime).toBe(0) | |
446 | } | |
97a2abc3 | 447 | expect( |
95c83464 | 448 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 449 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
08f3f44c | 450 | ).workersVirtualTaskTimestamp.length |
f06e48d8 | 451 | ).toBe(pool.workerNodes.length) |
23ff945a JB |
452 | // We need to clean up the resources after our test |
453 | await pool.destroy() | |
454 | }) | |
455 | ||
456 | it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => { | |
23ff945a JB |
457 | const pool = new DynamicThreadPool( |
458 | min, | |
459 | max, | |
460 | './tests/worker-files/thread/testWorker.js', | |
461 | { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } | |
462 | ) | |
463 | // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` | |
464 | const promises = [] | |
f7070eee | 465 | const maxMultiplier = 2 |
804a889e | 466 | for (let i = 0; i < max * maxMultiplier; i++) { |
6db75ad9 | 467 | promises.push(pool.execute()) |
23ff945a JB |
468 | } |
469 | await Promise.all(promises) | |
138d29a8 JB |
470 | for (const workerNode of pool.workerNodes) { |
471 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
472 | expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0) | |
473 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
474 | expect(workerNode.tasksUsage.medRunTime).toBe(0) | |
475 | } | |
2b4fddb8 JB |
476 | expect( |
477 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
478 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
479 | ).workersVirtualTaskTimestamp.length | |
480 | ).toBe(pool.workerNodes.length) | |
23ff945a JB |
481 | // We need to clean up the resources after our test |
482 | await pool.destroy() | |
483 | }) | |
484 | ||
010d7020 JB |
485 | it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median run time statistic', async () => { |
486 | const pool = new DynamicThreadPool( | |
487 | min, | |
488 | max, | |
489 | './tests/worker-files/thread/testWorker.js', | |
490 | { | |
491 | workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE, | |
492 | workerChoiceStrategyOptions: { | |
493 | medRunTime: true | |
494 | } | |
495 | } | |
496 | ) | |
497 | // TODO: Create a better test to cover `FairShareChoiceStrategy#choose` | |
498 | const promises = [] | |
499 | const maxMultiplier = 2 | |
500 | for (let i = 0; i < max * maxMultiplier; i++) { | |
501 | promises.push(pool.execute()) | |
502 | } | |
503 | await Promise.all(promises) | |
504 | for (const workerNode of pool.workerNodes) { | |
505 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
506 | expect(workerNode.tasksUsage.avgRunTime).toBe(0) | |
507 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
138d29a8 | 508 | expect(workerNode.tasksUsage.medRunTime).toBeGreaterThanOrEqual(0) |
010d7020 | 509 | } |
2b4fddb8 JB |
510 | expect( |
511 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
512 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
513 | ).workersVirtualTaskTimestamp.length | |
514 | ).toBe(pool.workerNodes.length) | |
010d7020 JB |
515 | // We need to clean up the resources after our test |
516 | await pool.destroy() | |
517 | }) | |
518 | ||
a6f7f1b4 | 519 | it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => { |
594bfb84 | 520 | const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE |
f0829c53 | 521 | let pool = new FixedThreadPool( |
caeb9817 JB |
522 | max, |
523 | './tests/worker-files/thread/testWorker.js' | |
524 | ) | |
525 | expect( | |
95c83464 | 526 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 527 | workerChoiceStrategy |
08f3f44c JB |
528 | ).workersVirtualTaskTimestamp |
529 | ).toBeInstanceOf(Array) | |
530 | expect( | |
531 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
532 | workerChoiceStrategy | |
533 | ).workersVirtualTaskTimestamp.length | |
534 | ).toBe(0) | |
2b4fddb8 JB |
535 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
536 | workerChoiceStrategy | |
537 | ).workersVirtualTaskTimestamp[0] = 0 | |
538 | expect( | |
539 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
540 | workerChoiceStrategy | |
541 | ).workersVirtualTaskTimestamp.length | |
542 | ).toBe(1) | |
594bfb84 | 543 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
08f3f44c JB |
544 | expect( |
545 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
546 | workerChoiceStrategy | |
547 | ).workersVirtualTaskTimestamp | |
548 | ).toBeInstanceOf(Array) | |
08f3f44c JB |
549 | expect( |
550 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
551 | workerChoiceStrategy | |
552 | ).workersVirtualTaskTimestamp.length | |
2b4fddb8 | 553 | ).toBe(0) |
f0829c53 JB |
554 | await pool.destroy() |
555 | pool = new DynamicThreadPool( | |
556 | min, | |
557 | max, | |
558 | './tests/worker-files/thread/testWorker.js' | |
559 | ) | |
560 | expect( | |
95c83464 | 561 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 562 | workerChoiceStrategy |
08f3f44c JB |
563 | ).workersVirtualTaskTimestamp |
564 | ).toBeInstanceOf(Array) | |
2b4fddb8 JB |
565 | expect( |
566 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
567 | workerChoiceStrategy | |
568 | ).workersVirtualTaskTimestamp.length | |
569 | ).toBe(0) | |
08f3f44c JB |
570 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
571 | workerChoiceStrategy | |
572 | ).workersVirtualTaskTimestamp[0] = 0 | |
573 | expect( | |
574 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
575 | workerChoiceStrategy | |
576 | ).workersVirtualTaskTimestamp.length | |
577 | ).toBe(1) | |
594bfb84 | 578 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
08f3f44c JB |
579 | expect( |
580 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
581 | workerChoiceStrategy | |
582 | ).workersVirtualTaskTimestamp | |
583 | ).toBeInstanceOf(Array) | |
584 | expect( | |
585 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
586 | workerChoiceStrategy | |
587 | ).workersVirtualTaskTimestamp.length | |
588 | ).toBe(0) | |
caeb9817 JB |
589 | // We need to clean up the resources after our test |
590 | await pool.destroy() | |
591 | }) | |
592 | ||
10fcfaf4 | 593 | it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => { |
594bfb84 | 594 | const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN |
10fcfaf4 JB |
595 | let pool = new FixedThreadPool( |
596 | max, | |
d710242d | 597 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 598 | { workerChoiceStrategy } |
10fcfaf4 | 599 | ) |
10fcfaf4 | 600 | expect( |
97a2abc3 | 601 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 602 | ).toBe(true) |
c6bd2650 JB |
603 | expect( |
604 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
605 | ).toBe(true) | |
78099a15 JB |
606 | expect( |
607 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
608 | ).toBe(false) | |
fd7ebd49 | 609 | await pool.destroy() |
10fcfaf4 JB |
610 | pool = new DynamicThreadPool( |
611 | min, | |
612 | max, | |
d710242d | 613 | './tests/worker-files/thread/testWorker.js', |
594bfb84 | 614 | { workerChoiceStrategy } |
10fcfaf4 | 615 | ) |
10fcfaf4 | 616 | expect( |
97a2abc3 | 617 | pool.workerChoiceStrategyContext.getRequiredStatistics().runTime |
10fcfaf4 | 618 | ).toBe(true) |
c6bd2650 JB |
619 | expect( |
620 | pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime | |
621 | ).toBe(true) | |
78099a15 JB |
622 | expect( |
623 | pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime | |
624 | ).toBe(false) | |
10fcfaf4 JB |
625 | // We need to clean up the resources after our test |
626 | await pool.destroy() | |
627 | }) | |
628 | ||
b3432a63 | 629 | it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => { |
b3432a63 JB |
630 | const pool = new FixedThreadPool( |
631 | max, | |
632 | './tests/worker-files/thread/testWorker.js', | |
633 | { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } | |
634 | ) | |
635 | // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` | |
636 | const promises = [] | |
a20f0ba5 JB |
637 | const maxMultiplier = 2 |
638 | for (let i = 0; i < max * maxMultiplier; i++) { | |
6db75ad9 | 639 | promises.push(pool.execute()) |
b3432a63 JB |
640 | } |
641 | await Promise.all(promises) | |
138d29a8 JB |
642 | for (const workerNode of pool.workerNodes) { |
643 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
644 | expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0) | |
645 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
646 | expect(workerNode.tasksUsage.medRunTime).toBe(0) | |
647 | } | |
97a2abc3 | 648 | expect( |
95c83464 | 649 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 650 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
08f3f44c JB |
651 | ).defaultWorkerWeight |
652 | ).toBeGreaterThan(0) | |
653 | expect( | |
654 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
655 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
656 | ).workerVirtualTaskRunTime | |
657 | ).toBeGreaterThanOrEqual(0) | |
b3432a63 JB |
658 | // We need to clean up the resources after our test |
659 | await pool.destroy() | |
660 | }) | |
661 | ||
662 | it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => { | |
b3432a63 JB |
663 | const pool = new DynamicThreadPool( |
664 | min, | |
665 | max, | |
666 | './tests/worker-files/thread/testWorker.js', | |
667 | { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN } | |
668 | ) | |
669 | // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` | |
670 | const promises = [] | |
138d29a8 | 671 | const maxMultiplier = 2 |
5502c07c | 672 | for (let i = 0; i < max * maxMultiplier; i++) { |
6db75ad9 | 673 | promises.push(pool.execute()) |
b3432a63 JB |
674 | } |
675 | await Promise.all(promises) | |
138d29a8 JB |
676 | for (const workerNode of pool.workerNodes) { |
677 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
678 | expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0) | |
679 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
680 | expect(workerNode.tasksUsage.medRunTime).toBe(0) | |
681 | } | |
2b4fddb8 JB |
682 | expect( |
683 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
684 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
685 | ).defaultWorkerWeight | |
686 | ).toBeGreaterThan(0) | |
687 | expect( | |
688 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
689 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
690 | ).workerVirtualTaskRunTime | |
691 | ).toBeGreaterThanOrEqual(0) | |
b3432a63 JB |
692 | // We need to clean up the resources after our test |
693 | await pool.destroy() | |
694 | }) | |
695 | ||
010d7020 JB |
696 | it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median run time statistic', async () => { |
697 | const pool = new DynamicThreadPool( | |
698 | min, | |
699 | max, | |
700 | './tests/worker-files/thread/testWorker.js', | |
701 | { | |
702 | workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN, | |
703 | workerChoiceStrategyOptions: { | |
704 | medRunTime: true | |
705 | } | |
706 | } | |
707 | ) | |
708 | // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose` | |
709 | const promises = [] | |
710 | const maxMultiplier = 2 | |
711 | for (let i = 0; i < max * maxMultiplier; i++) { | |
712 | promises.push(pool.execute()) | |
713 | } | |
714 | await Promise.all(promises) | |
715 | for (const workerNode of pool.workerNodes) { | |
716 | expect(workerNode.tasksUsage.avgRunTime).toBeDefined() | |
717 | expect(workerNode.tasksUsage.avgRunTime).toBe(0) | |
718 | expect(workerNode.tasksUsage.medRunTime).toBeDefined() | |
138d29a8 | 719 | expect(workerNode.tasksUsage.medRunTime).toBeGreaterThanOrEqual(0) |
010d7020 | 720 | } |
08f3f44c JB |
721 | expect( |
722 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
723 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
724 | ).defaultWorkerWeight | |
725 | ).toBeGreaterThan(0) | |
726 | expect( | |
727 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
728 | pool.workerChoiceStrategyContext.workerChoiceStrategy | |
729 | ).workerVirtualTaskRunTime | |
730 | ).toBeGreaterThanOrEqual(0) | |
010d7020 JB |
731 | // We need to clean up the resources after our test |
732 | await pool.destroy() | |
733 | }) | |
734 | ||
a6f7f1b4 | 735 | it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => { |
594bfb84 | 736 | const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN |
f0829c53 | 737 | let pool = new FixedThreadPool( |
caeb9817 JB |
738 | max, |
739 | './tests/worker-files/thread/testWorker.js' | |
740 | ) | |
38f6e859 | 741 | expect( |
95c83464 | 742 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 743 | workerChoiceStrategy |
f06e48d8 | 744 | ).currentWorkerNodeId |
b529c323 | 745 | ).toBeDefined() |
38f6e859 | 746 | expect( |
95c83464 | 747 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 748 | workerChoiceStrategy |
b529c323 JB |
749 | ).defaultWorkerWeight |
750 | ).toBeDefined() | |
caeb9817 | 751 | expect( |
95c83464 | 752 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 753 | workerChoiceStrategy |
08f3f44c | 754 | ).workerVirtualTaskRunTime |
b529c323 | 755 | ).toBeDefined() |
594bfb84 | 756 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
a6f7f1b4 | 757 | expect( |
95c83464 | 758 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 759 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
f06e48d8 | 760 | ).currentWorkerNodeId |
a6f7f1b4 JB |
761 | ).toBe(0) |
762 | expect( | |
95c83464 | 763 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 764 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
95c83464 | 765 | ).defaultWorkerWeight |
a6f7f1b4 | 766 | ).toBeGreaterThan(0) |
08f3f44c JB |
767 | expect( |
768 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
769 | workerChoiceStrategy | |
770 | ).workerVirtualTaskRunTime | |
771 | ).toBe(0) | |
f0829c53 JB |
772 | await pool.destroy() |
773 | pool = new DynamicThreadPool( | |
774 | min, | |
775 | max, | |
776 | './tests/worker-files/thread/testWorker.js' | |
777 | ) | |
38f6e859 | 778 | expect( |
95c83464 | 779 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 780 | workerChoiceStrategy |
f06e48d8 | 781 | ).currentWorkerNodeId |
b529c323 | 782 | ).toBeDefined() |
38f6e859 | 783 | expect( |
95c83464 | 784 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 785 | workerChoiceStrategy |
b529c323 JB |
786 | ).defaultWorkerWeight |
787 | ).toBeDefined() | |
f0829c53 | 788 | expect( |
95c83464 | 789 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
594bfb84 | 790 | workerChoiceStrategy |
08f3f44c | 791 | ).workerVirtualTaskRunTime |
b529c323 | 792 | ).toBeDefined() |
594bfb84 | 793 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) |
a6f7f1b4 | 794 | expect( |
95c83464 | 795 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 796 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
f06e48d8 | 797 | ).currentWorkerNodeId |
a6f7f1b4 JB |
798 | ).toBe(0) |
799 | expect( | |
95c83464 | 800 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( |
d710242d | 801 | pool.workerChoiceStrategyContext.workerChoiceStrategy |
95c83464 | 802 | ).defaultWorkerWeight |
a6f7f1b4 | 803 | ).toBeGreaterThan(0) |
08f3f44c JB |
804 | expect( |
805 | pool.workerChoiceStrategyContext.workerChoiceStrategies.get( | |
806 | workerChoiceStrategy | |
807 | ).workerVirtualTaskRunTime | |
808 | ).toBe(0) | |
caeb9817 JB |
809 | // We need to clean up the resources after our test |
810 | await pool.destroy() | |
811 | }) | |
812 | ||
89b09b26 | 813 | it('Verify unknown strategy throw error', () => { |
a35560ba S |
814 | expect( |
815 | () => | |
816 | new DynamicThreadPool( | |
817 | min, | |
818 | max, | |
819 | './tests/worker-files/thread/testWorker.js', | |
1927ee67 | 820 | { workerChoiceStrategy: 'UNKNOWN_STRATEGY' } |
a35560ba | 821 | ) |
d4aeae5a | 822 | ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'") |
a35560ba S |
823 | }) |
824 | }) |