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