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