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