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