Merge branch 'master' into elu-strategy
[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
cdace0e5 7} = require('../../../lib')
86bf340d 8const { CircularArray } = require('../../../lib/circular-array')
a35560ba
S
9
10describe('Selection strategies test suite', () => {
e1ffb94f
JB
11 const min = 0
12 const max = 3
13
a35560ba
S
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
e4543b14
JB
16 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
23ff945a 18 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
19 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
20 'WEIGHTED_ROUND_ROBIN'
21 )
feec6e8c
JB
22 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
23 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
24 )
a35560ba
S
25 })
26
e843b904 27 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
28 const pool = new DynamicThreadPool(
29 min,
30 max,
31 './tests/worker-files/thread/testWorker.js'
32 )
33 expect(pool.opts.workerChoiceStrategy).toBe(
34 WorkerChoiceStrategies.ROUND_ROBIN
35 )
36 // We need to clean up the resources after our test
37 await pool.destroy()
38 })
39
594bfb84
JB
40 it('Verify available strategies are taken at pool creation', async () => {
41 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
42 const pool = new FixedThreadPool(
43 max,
44 './tests/worker-files/thread/testWorker.js',
45 { workerChoiceStrategy }
46 )
47 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
48 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
49 workerChoiceStrategy
50 )
51 await pool.destroy()
52 }
d2f7b7a2
JB
53 })
54
594bfb84
JB
55 it('Verify available strategies can be set after pool creation', async () => {
56 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
57 const pool = new DynamicThreadPool(
58 min,
59 max,
ec82cfa1 60 './tests/worker-files/thread/testWorker.js'
594bfb84
JB
61 )
62 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
63 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
64 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
65 workerChoiceStrategy
66 )
67 await pool.destroy()
68 }
69 })
70
71 it('Verify available strategies default internals at pool creation', async () => {
72 const pool = new FixedThreadPool(
e843b904
JB
73 max,
74 './tests/worker-files/thread/testWorker.js'
75 )
594bfb84
JB
76 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
77 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
78 expect(
79 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
80 workerChoiceStrategy
81 ).nextWorkerNodeId
82 ).toBe(0)
83 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
08f3f44c
JB
84 expect(
85 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
86 workerChoiceStrategy
b0d6ed8f 87 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
88 ).toBeInstanceOf(Array)
89 expect(
90 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
91 workerChoiceStrategy
b0d6ed8f 92 ).workersVirtualTaskEndTimestamp.length
08f3f44c 93 ).toBe(0)
594bfb84
JB
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)
08f3f44c
JB
107 expect(
108 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
109 workerChoiceStrategy
110 ).workerVirtualTaskRunTime
111 ).toBe(0)
594bfb84
JB
112 }
113 }
e843b904
JB
114 await pool.destroy()
115 })
116
10fcfaf4 117 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 118 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
119 let pool = new FixedThreadPool(
120 max,
d710242d 121 './tests/worker-files/thread/testWorker.js',
594bfb84 122 { workerChoiceStrategy }
10fcfaf4 123 )
10fcfaf4 124 expect(
86bf340d
JB
125 pool.workerChoiceStrategyContext.getRequiredStatistics()
126 ).toStrictEqual({
127 runTime: false,
128 avgRunTime: false,
129 medRunTime: false,
130 waitTime: false,
131 avgWaitTime: false,
d44d5953
JB
132 medWaitTime: false,
133 elu: false
86bf340d 134 })
fd7ebd49 135 await pool.destroy()
10fcfaf4
JB
136 pool = new DynamicThreadPool(
137 min,
138 max,
d710242d 139 './tests/worker-files/thread/testWorker.js',
594bfb84 140 { workerChoiceStrategy }
10fcfaf4 141 )
10fcfaf4 142 expect(
86bf340d
JB
143 pool.workerChoiceStrategyContext.getRequiredStatistics()
144 ).toStrictEqual({
145 runTime: false,
146 avgRunTime: false,
147 medRunTime: false,
148 waitTime: false,
149 avgWaitTime: false,
d44d5953
JB
150 medWaitTime: false,
151 elu: false
86bf340d 152 })
10fcfaf4
JB
153 // We need to clean up the resources after our test
154 await pool.destroy()
155 })
156
bdaf31cd 157 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
bdaf31cd
JB
158 const pool = new FixedThreadPool(
159 max,
160 './tests/worker-files/thread/testWorker.js',
161 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
162 )
bdaf31cd 163 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 164 const promises = new Set()
a20f0ba5
JB
165 const maxMultiplier = 2
166 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 167 promises.add(pool.execute())
e211bc18
JB
168 }
169 await Promise.all(promises)
170 for (const workerNode of pool.workerNodes) {
171 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 172 ran: maxMultiplier,
e211bc18
JB
173 running: 0,
174 runTime: 0,
175 runTimeHistory: expect.any(CircularArray),
176 avgRunTime: 0,
177 medRunTime: 0,
178 waitTime: 0,
179 waitTimeHistory: expect.any(CircularArray),
180 avgWaitTime: 0,
181 medWaitTime: 0,
d44d5953
JB
182 error: 0,
183 elu: undefined
e211bc18 184 })
bdaf31cd 185 }
9458090a
JB
186 expect(
187 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
188 WorkerChoiceStrategies.ROUND_ROBIN
189 ).nextWorkerNodeId
190 ).toBe(0)
bdaf31cd
JB
191 // We need to clean up the resources after our test
192 await pool.destroy()
193 })
194
195 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
bdaf31cd
JB
196 const pool = new DynamicThreadPool(
197 min,
198 max,
199 './tests/worker-files/thread/testWorker.js',
200 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
201 )
bdaf31cd 202 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 203 const promises = new Set()
a20f0ba5
JB
204 const maxMultiplier = 2
205 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 206 promises.add(pool.execute())
e211bc18
JB
207 }
208 await Promise.all(promises)
209 for (const workerNode of pool.workerNodes) {
210 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 211 ran: maxMultiplier,
e211bc18
JB
212 running: 0,
213 runTime: 0,
214 runTimeHistory: expect.any(CircularArray),
215 avgRunTime: 0,
216 medRunTime: 0,
217 waitTime: 0,
218 waitTimeHistory: expect.any(CircularArray),
219 avgWaitTime: 0,
220 medWaitTime: 0,
d44d5953
JB
221 error: 0,
222 elu: undefined
e211bc18 223 })
bdaf31cd 224 }
9458090a
JB
225 expect(
226 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
227 WorkerChoiceStrategies.ROUND_ROBIN
228 ).nextWorkerNodeId
229 ).toBe(0)
bdaf31cd
JB
230 // We need to clean up the resources after our test
231 await pool.destroy()
232 })
233
2ced693a 234 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 235 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
236 let pool = new FixedClusterPool(
237 max,
594bfb84
JB
238 './tests/worker-files/cluster/testWorker.js',
239 { workerChoiceStrategy }
2ced693a
JB
240 )
241 let results = new Set()
242 for (let i = 0; i < max; i++) {
20dcad1a 243 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
2ced693a
JB
244 }
245 expect(results.size).toBe(max)
246 await pool.destroy()
594bfb84
JB
247 pool = new FixedThreadPool(
248 max,
249 './tests/worker-files/thread/testWorker.js',
250 { workerChoiceStrategy }
251 )
2ced693a
JB
252 results = new Set()
253 for (let i = 0; i < max; i++) {
20dcad1a 254 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
2ced693a
JB
255 }
256 expect(results.size).toBe(max)
257 await pool.destroy()
258 })
259
a6f7f1b4 260 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 261 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
262 let pool = new FixedThreadPool(
263 max,
264 './tests/worker-files/thread/testWorker.js',
265 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
266 )
38f6e859 267 expect(
95c83464 268 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 269 workerChoiceStrategy
f06e48d8 270 ).nextWorkerNodeId
b529c323 271 ).toBeDefined()
594bfb84 272 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 273 expect(
95c83464 274 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 275 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 276 ).nextWorkerNodeId
a6f7f1b4
JB
277 ).toBe(0)
278 await pool.destroy()
279 pool = new DynamicThreadPool(
280 min,
281 max,
282 './tests/worker-files/thread/testWorker.js',
283 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
284 )
38f6e859 285 expect(
95c83464 286 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 287 workerChoiceStrategy
f06e48d8 288 ).nextWorkerNodeId
b529c323 289 ).toBeDefined()
594bfb84 290 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 291 expect(
95c83464 292 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 293 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 294 ).nextWorkerNodeId
a6f7f1b4
JB
295 ).toBe(0)
296 // We need to clean up the resources after our test
297 await pool.destroy()
298 })
299
e4543b14
JB
300 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
301 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
10fcfaf4
JB
302 let pool = new FixedThreadPool(
303 max,
d710242d 304 './tests/worker-files/thread/testWorker.js',
594bfb84 305 { workerChoiceStrategy }
10fcfaf4 306 )
10fcfaf4 307 expect(
86bf340d
JB
308 pool.workerChoiceStrategyContext.getRequiredStatistics()
309 ).toStrictEqual({
310 runTime: false,
311 avgRunTime: false,
312 medRunTime: false,
313 waitTime: false,
314 avgWaitTime: false,
d44d5953
JB
315 medWaitTime: false,
316 elu: false
86bf340d 317 })
fd7ebd49 318 await pool.destroy()
10fcfaf4
JB
319 pool = new DynamicThreadPool(
320 min,
321 max,
d710242d 322 './tests/worker-files/thread/testWorker.js',
594bfb84 323 { workerChoiceStrategy }
10fcfaf4 324 )
10fcfaf4 325 expect(
86bf340d
JB
326 pool.workerChoiceStrategyContext.getRequiredStatistics()
327 ).toStrictEqual({
328 runTime: false,
329 avgRunTime: false,
330 medRunTime: false,
331 waitTime: false,
332 avgWaitTime: false,
d44d5953
JB
333 medWaitTime: false,
334 elu: false
86bf340d 335 })
10fcfaf4
JB
336 // We need to clean up the resources after our test
337 await pool.destroy()
338 })
339
e4543b14 340 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
341 const pool = new FixedThreadPool(
342 max,
343 './tests/worker-files/thread/testWorker.js',
e4543b14 344 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
b98ec2e6 345 )
e4543b14 346 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 347 const promises = new Set()
a20f0ba5
JB
348 const maxMultiplier = 2
349 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 350 promises.add(pool.execute())
e211bc18
JB
351 }
352 await Promise.all(promises)
353 for (const workerNode of pool.workerNodes) {
354 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 355 ran: maxMultiplier,
e211bc18
JB
356 running: 0,
357 runTime: 0,
358 runTimeHistory: expect.any(CircularArray),
359 avgRunTime: 0,
360 medRunTime: 0,
361 waitTime: 0,
362 waitTimeHistory: expect.any(CircularArray),
363 avgWaitTime: 0,
364 medWaitTime: 0,
d44d5953
JB
365 error: 0,
366 elu: undefined
e211bc18 367 })
a35560ba 368 }
a35560ba
S
369 // We need to clean up the resources after our test
370 await pool.destroy()
371 })
372
e4543b14 373 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
374 const pool = new DynamicThreadPool(
375 min,
376 max,
377 './tests/worker-files/thread/testWorker.js',
e4543b14 378 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
ff5e76e1 379 )
e4543b14 380 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 381 const promises = new Set()
a20f0ba5
JB
382 const maxMultiplier = 2
383 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 384 promises.add(pool.execute())
e211bc18
JB
385 }
386 await Promise.all(promises)
387 for (const workerNode of pool.workerNodes) {
388 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 389 ran: maxMultiplier,
e211bc18
JB
390 running: 0,
391 runTime: 0,
392 runTimeHistory: expect.any(CircularArray),
393 avgRunTime: 0,
394 medRunTime: 0,
395 waitTime: 0,
396 waitTimeHistory: expect.any(CircularArray),
397 avgWaitTime: 0,
398 medWaitTime: 0,
d44d5953
JB
399 error: 0,
400 elu: undefined
e211bc18 401 })
168c526f 402 }
168c526f
JB
403 // We need to clean up the resources after our test
404 await pool.destroy()
405 })
406
e4543b14
JB
407 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
408 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
168c526f
JB
409 let pool = new FixedThreadPool(
410 max,
d710242d 411 './tests/worker-files/thread/testWorker.js',
594bfb84 412 { workerChoiceStrategy }
168c526f 413 )
168c526f 414 expect(
86bf340d
JB
415 pool.workerChoiceStrategyContext.getRequiredStatistics()
416 ).toStrictEqual({
417 runTime: true,
418 avgRunTime: false,
419 medRunTime: false,
420 waitTime: false,
421 avgWaitTime: false,
d44d5953
JB
422 medWaitTime: false,
423 elu: false
86bf340d 424 })
168c526f
JB
425 await pool.destroy()
426 pool = new DynamicThreadPool(
427 min,
428 max,
d710242d 429 './tests/worker-files/thread/testWorker.js',
594bfb84 430 { workerChoiceStrategy }
168c526f 431 )
168c526f 432 expect(
86bf340d
JB
433 pool.workerChoiceStrategyContext.getRequiredStatistics()
434 ).toStrictEqual({
435 runTime: true,
436 avgRunTime: false,
437 medRunTime: false,
438 waitTime: false,
439 avgWaitTime: false,
d44d5953
JB
440 medWaitTime: false,
441 elu: false
86bf340d 442 })
168c526f
JB
443 // We need to clean up the resources after our test
444 await pool.destroy()
445 })
446
e4543b14 447 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
168c526f
JB
448 const pool = new FixedThreadPool(
449 max,
450 './tests/worker-files/thread/testWorker.js',
e4543b14 451 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 452 )
e4543b14 453 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 454 const promises = new Set()
a20f0ba5
JB
455 const maxMultiplier = 2
456 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 457 promises.add(pool.execute())
e211bc18
JB
458 }
459 await Promise.all(promises)
460 for (const workerNode of pool.workerNodes) {
461 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 462 ran: expect.any(Number),
e211bc18
JB
463 running: 0,
464 runTime: expect.any(Number),
465 runTimeHistory: expect.any(CircularArray),
466 avgRunTime: 0,
467 medRunTime: 0,
468 waitTime: 0,
469 waitTimeHistory: expect.any(CircularArray),
470 avgWaitTime: 0,
471 medWaitTime: 0,
d44d5953
JB
472 error: 0,
473 elu: undefined
e211bc18 474 })
1ab50fe5
JB
475 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
476 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18 477 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
168c526f 478 }
168c526f
JB
479 // We need to clean up the resources after our test
480 await pool.destroy()
481 })
482
e4543b14 483 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
168c526f
JB
484 const pool = new DynamicThreadPool(
485 min,
486 max,
487 './tests/worker-files/thread/testWorker.js',
e4543b14 488 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 489 )
e4543b14 490 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 491 const promises = new Set()
a20f0ba5
JB
492 const maxMultiplier = 2
493 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 494 promises.add(pool.execute())
e211bc18
JB
495 }
496 await Promise.all(promises)
497 for (const workerNode of pool.workerNodes) {
498 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 499 ran: expect.any(Number),
e211bc18
JB
500 running: 0,
501 runTime: expect.any(Number),
502 runTimeHistory: expect.any(CircularArray),
503 avgRunTime: 0,
504 medRunTime: 0,
505 waitTime: 0,
506 waitTimeHistory: expect.any(CircularArray),
507 avgWaitTime: 0,
508 medWaitTime: 0,
d44d5953
JB
509 error: 0,
510 elu: undefined
e211bc18 511 })
1ab50fe5
JB
512 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
513 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18 514 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
ff5e76e1 515 }
ff5e76e1
JB
516 // We need to clean up the resources after our test
517 await pool.destroy()
518 })
519
10fcfaf4 520 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
594bfb84 521 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
522 let pool = new FixedThreadPool(
523 max,
d710242d 524 './tests/worker-files/thread/testWorker.js',
594bfb84 525 { workerChoiceStrategy }
10fcfaf4 526 )
10fcfaf4 527 expect(
86bf340d
JB
528 pool.workerChoiceStrategyContext.getRequiredStatistics()
529 ).toStrictEqual({
530 runTime: true,
531 avgRunTime: true,
532 medRunTime: false,
533 waitTime: false,
534 avgWaitTime: false,
d44d5953
JB
535 medWaitTime: false,
536 elu: false
86bf340d 537 })
fd7ebd49 538 await pool.destroy()
10fcfaf4
JB
539 pool = new DynamicThreadPool(
540 min,
541 max,
d710242d 542 './tests/worker-files/thread/testWorker.js',
594bfb84 543 { workerChoiceStrategy }
10fcfaf4 544 )
10fcfaf4 545 expect(
86bf340d
JB
546 pool.workerChoiceStrategyContext.getRequiredStatistics()
547 ).toStrictEqual({
548 runTime: true,
549 avgRunTime: true,
550 medRunTime: false,
551 waitTime: false,
552 avgWaitTime: false,
d44d5953
JB
553 medWaitTime: false,
554 elu: false
86bf340d 555 })
10fcfaf4
JB
556 // We need to clean up the resources after our test
557 await pool.destroy()
558 })
559
23ff945a 560 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
561 const pool = new FixedThreadPool(
562 max,
563 './tests/worker-files/thread/testWorker.js',
564 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
565 )
566 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 567 const promises = new Set()
a20f0ba5
JB
568 const maxMultiplier = 2
569 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 570 promises.add(pool.execute())
23ff945a 571 }
e211bc18 572 await Promise.all(promises)
138d29a8 573 for (const workerNode of pool.workerNodes) {
86bf340d 574 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 575 ran: maxMultiplier,
86bf340d
JB
576 running: 0,
577 runTime: expect.any(Number),
578 runTimeHistory: expect.any(CircularArray),
579 avgRunTime: expect.any(Number),
580 medRunTime: 0,
581 waitTime: 0,
582 waitTimeHistory: expect.any(CircularArray),
583 avgWaitTime: 0,
584 medWaitTime: 0,
d44d5953
JB
585 error: 0,
586 elu: undefined
86bf340d 587 })
e211bc18
JB
588 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
589 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 590 }
97a2abc3 591 expect(
95c83464 592 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 593 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 594 ).workersVirtualTaskEndTimestamp.length
f06e48d8 595 ).toBe(pool.workerNodes.length)
23ff945a
JB
596 // We need to clean up the resources after our test
597 await pool.destroy()
598 })
599
600 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
601 const pool = new DynamicThreadPool(
602 min,
603 max,
604 './tests/worker-files/thread/testWorker.js',
605 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
606 )
607 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 608 const promises = new Set()
f7070eee 609 const maxMultiplier = 2
804a889e 610 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 611 promises.add(pool.execute())
23ff945a 612 }
e211bc18 613 await Promise.all(promises)
138d29a8 614 for (const workerNode of pool.workerNodes) {
86bf340d 615 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 616 ran: maxMultiplier,
86bf340d
JB
617 running: 0,
618 runTime: expect.any(Number),
619 runTimeHistory: expect.any(CircularArray),
620 avgRunTime: expect.any(Number),
621 medRunTime: 0,
622 waitTime: 0,
623 waitTimeHistory: expect.any(CircularArray),
624 avgWaitTime: 0,
625 medWaitTime: 0,
d44d5953
JB
626 error: 0,
627 elu: undefined
86bf340d 628 })
e211bc18
JB
629 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
630 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 631 }
2b4fddb8
JB
632 expect(
633 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
634 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 635 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 636 ).toBe(pool.workerNodes.length)
23ff945a
JB
637 // We need to clean up the resources after our test
638 await pool.destroy()
639 })
640
9e775f96 641 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
642 const pool = new DynamicThreadPool(
643 min,
644 max,
645 './tests/worker-files/thread/testWorker.js',
646 {
647 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
648 workerChoiceStrategyOptions: {
649 medRunTime: true
650 }
651 }
652 )
653 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 654 const promises = new Set()
010d7020
JB
655 const maxMultiplier = 2
656 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 657 promises.add(pool.execute())
010d7020 658 }
e211bc18 659 await Promise.all(promises)
010d7020 660 for (const workerNode of pool.workerNodes) {
86bf340d 661 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 662 ran: maxMultiplier,
86bf340d
JB
663 running: 0,
664 runTime: expect.any(Number),
665 runTimeHistory: expect.any(CircularArray),
666 avgRunTime: 0,
667 medRunTime: expect.any(Number),
668 waitTime: 0,
669 waitTimeHistory: expect.any(CircularArray),
670 avgWaitTime: 0,
671 medWaitTime: 0,
d44d5953
JB
672 error: 0,
673 elu: undefined
86bf340d 674 })
e211bc18
JB
675 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
676 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
010d7020 677 }
2b4fddb8
JB
678 expect(
679 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
680 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 681 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 682 ).toBe(pool.workerNodes.length)
010d7020
JB
683 // We need to clean up the resources after our test
684 await pool.destroy()
685 })
686
a6f7f1b4 687 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 688 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 689 let pool = new FixedThreadPool(
caeb9817
JB
690 max,
691 './tests/worker-files/thread/testWorker.js'
692 )
693 expect(
95c83464 694 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 695 workerChoiceStrategy
b0d6ed8f 696 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
697 ).toBeInstanceOf(Array)
698 expect(
699 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
700 workerChoiceStrategy
b0d6ed8f 701 ).workersVirtualTaskEndTimestamp.length
08f3f44c 702 ).toBe(0)
2b4fddb8
JB
703 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
704 workerChoiceStrategy
b0d6ed8f 705 ).workersVirtualTaskEndTimestamp[0] = performance.now()
2b4fddb8
JB
706 expect(
707 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
708 workerChoiceStrategy
b0d6ed8f 709 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 710 ).toBe(1)
594bfb84 711 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
712 expect(
713 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
714 workerChoiceStrategy
b0d6ed8f 715 ).workersVirtualTaskEndTimestamp
08f3f44c 716 ).toBeInstanceOf(Array)
08f3f44c
JB
717 expect(
718 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
719 workerChoiceStrategy
b0d6ed8f 720 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 721 ).toBe(0)
f0829c53
JB
722 await pool.destroy()
723 pool = new DynamicThreadPool(
724 min,
725 max,
726 './tests/worker-files/thread/testWorker.js'
727 )
728 expect(
95c83464 729 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 730 workerChoiceStrategy
b0d6ed8f 731 ).workersVirtualTaskEndTimestamp
08f3f44c 732 ).toBeInstanceOf(Array)
2b4fddb8
JB
733 expect(
734 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
735 workerChoiceStrategy
b0d6ed8f 736 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 737 ).toBe(0)
08f3f44c
JB
738 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
739 workerChoiceStrategy
b0d6ed8f 740 ).workersVirtualTaskEndTimestamp[0] = performance.now()
08f3f44c
JB
741 expect(
742 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
743 workerChoiceStrategy
b0d6ed8f 744 ).workersVirtualTaskEndTimestamp.length
08f3f44c 745 ).toBe(1)
594bfb84 746 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
747 expect(
748 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
749 workerChoiceStrategy
b0d6ed8f 750 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
751 ).toBeInstanceOf(Array)
752 expect(
753 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
754 workerChoiceStrategy
b0d6ed8f 755 ).workersVirtualTaskEndTimestamp.length
08f3f44c 756 ).toBe(0)
caeb9817
JB
757 // We need to clean up the resources after our test
758 await pool.destroy()
759 })
760
10fcfaf4 761 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 762 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
763 let pool = new FixedThreadPool(
764 max,
d710242d 765 './tests/worker-files/thread/testWorker.js',
594bfb84 766 { workerChoiceStrategy }
10fcfaf4 767 )
10fcfaf4 768 expect(
86bf340d
JB
769 pool.workerChoiceStrategyContext.getRequiredStatistics()
770 ).toStrictEqual({
771 runTime: true,
772 avgRunTime: true,
773 medRunTime: false,
774 waitTime: false,
775 avgWaitTime: false,
d44d5953
JB
776 medWaitTime: false,
777 elu: false
86bf340d 778 })
fd7ebd49 779 await pool.destroy()
10fcfaf4
JB
780 pool = new DynamicThreadPool(
781 min,
782 max,
d710242d 783 './tests/worker-files/thread/testWorker.js',
594bfb84 784 { workerChoiceStrategy }
10fcfaf4 785 )
10fcfaf4 786 expect(
86bf340d
JB
787 pool.workerChoiceStrategyContext.getRequiredStatistics()
788 ).toStrictEqual({
789 runTime: true,
790 avgRunTime: true,
791 medRunTime: false,
792 waitTime: false,
793 avgWaitTime: false,
d44d5953
JB
794 medWaitTime: false,
795 elu: false
86bf340d 796 })
10fcfaf4
JB
797 // We need to clean up the resources after our test
798 await pool.destroy()
799 })
800
b3432a63 801 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
802 const pool = new FixedThreadPool(
803 max,
804 './tests/worker-files/thread/testWorker.js',
805 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
806 )
807 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 808 const promises = new Set()
a20f0ba5
JB
809 const maxMultiplier = 2
810 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 811 promises.add(pool.execute())
b3432a63 812 }
e211bc18 813 await Promise.all(promises)
138d29a8 814 for (const workerNode of pool.workerNodes) {
86bf340d 815 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 816 ran: expect.any(Number),
86bf340d
JB
817 running: 0,
818 runTime: expect.any(Number),
819 runTimeHistory: expect.any(CircularArray),
820 avgRunTime: expect.any(Number),
821 medRunTime: 0,
822 waitTime: 0,
823 waitTimeHistory: expect.any(CircularArray),
824 avgWaitTime: 0,
825 medWaitTime: 0,
d44d5953
JB
826 error: 0,
827 elu: undefined
86bf340d 828 })
1ab50fe5
JB
829 expect(workerNode.tasksUsage.ran).toBeGreaterThanOrEqual(0)
830 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
ee9f5295 831 expect(workerNode.tasksUsage.runTime).toBeGreaterThanOrEqual(0)
138d29a8 832 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0)
138d29a8 833 }
97a2abc3 834 expect(
95c83464 835 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 836 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
837 ).defaultWorkerWeight
838 ).toBeGreaterThan(0)
839 expect(
840 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
841 pool.workerChoiceStrategyContext.workerChoiceStrategy
842 ).workerVirtualTaskRunTime
843 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
844 // We need to clean up the resources after our test
845 await pool.destroy()
846 })
847
848 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
849 const pool = new DynamicThreadPool(
850 min,
851 max,
852 './tests/worker-files/thread/testWorker.js',
853 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
854 )
855 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 856 const promises = new Set()
138d29a8 857 const maxMultiplier = 2
5502c07c 858 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 859 promises.add(pool.execute())
b3432a63 860 }
e211bc18 861 await Promise.all(promises)
138d29a8 862 for (const workerNode of pool.workerNodes) {
86bf340d 863 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 864 ran: expect.any(Number),
86bf340d
JB
865 running: 0,
866 runTime: expect.any(Number),
867 runTimeHistory: expect.any(CircularArray),
868 avgRunTime: expect.any(Number),
869 medRunTime: 0,
870 waitTime: 0,
871 waitTimeHistory: expect.any(CircularArray),
872 avgWaitTime: 0,
873 medWaitTime: 0,
d44d5953
JB
874 error: 0,
875 elu: undefined
86bf340d 876 })
1ab50fe5
JB
877 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
878 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18
JB
879 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
880 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 881 }
2b4fddb8
JB
882 expect(
883 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
884 pool.workerChoiceStrategyContext.workerChoiceStrategy
885 ).defaultWorkerWeight
886 ).toBeGreaterThan(0)
887 expect(
888 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
889 pool.workerChoiceStrategyContext.workerChoiceStrategy
890 ).workerVirtualTaskRunTime
891 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
892 // We need to clean up the resources after our test
893 await pool.destroy()
894 })
895
9e775f96 896 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
897 const pool = new DynamicThreadPool(
898 min,
899 max,
900 './tests/worker-files/thread/testWorker.js',
901 {
902 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
903 workerChoiceStrategyOptions: {
904 medRunTime: true
905 }
906 }
907 )
908 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 909 const promises = new Set()
010d7020
JB
910 const maxMultiplier = 2
911 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 912 promises.add(pool.execute())
010d7020 913 }
e211bc18 914 await Promise.all(promises)
010d7020 915 for (const workerNode of pool.workerNodes) {
86bf340d 916 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 917 ran: expect.any(Number),
86bf340d
JB
918 running: 0,
919 runTime: expect.any(Number),
920 runTimeHistory: expect.any(CircularArray),
921 avgRunTime: 0,
922 medRunTime: expect.any(Number),
923 waitTime: 0,
924 waitTimeHistory: expect.any(CircularArray),
925 avgWaitTime: 0,
926 medWaitTime: 0,
d44d5953
JB
927 error: 0,
928 elu: undefined
86bf340d 929 })
1ab50fe5
JB
930 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
931 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18
JB
932 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
933 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
010d7020 934 }
08f3f44c
JB
935 expect(
936 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
937 pool.workerChoiceStrategyContext.workerChoiceStrategy
938 ).defaultWorkerWeight
939 ).toBeGreaterThan(0)
940 expect(
941 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
942 pool.workerChoiceStrategyContext.workerChoiceStrategy
943 ).workerVirtualTaskRunTime
944 ).toBeGreaterThanOrEqual(0)
010d7020
JB
945 // We need to clean up the resources after our test
946 await pool.destroy()
947 })
948
a6f7f1b4 949 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 950 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 951 let pool = new FixedThreadPool(
caeb9817
JB
952 max,
953 './tests/worker-files/thread/testWorker.js'
954 )
38f6e859 955 expect(
95c83464 956 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 957 workerChoiceStrategy
f06e48d8 958 ).currentWorkerNodeId
b529c323 959 ).toBeDefined()
38f6e859 960 expect(
95c83464 961 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 962 workerChoiceStrategy
b529c323
JB
963 ).defaultWorkerWeight
964 ).toBeDefined()
caeb9817 965 expect(
95c83464 966 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 967 workerChoiceStrategy
08f3f44c 968 ).workerVirtualTaskRunTime
b529c323 969 ).toBeDefined()
594bfb84 970 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 971 expect(
95c83464 972 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 973 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 974 ).currentWorkerNodeId
a6f7f1b4
JB
975 ).toBe(0)
976 expect(
95c83464 977 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 978 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 979 ).defaultWorkerWeight
a6f7f1b4 980 ).toBeGreaterThan(0)
08f3f44c
JB
981 expect(
982 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
983 workerChoiceStrategy
984 ).workerVirtualTaskRunTime
985 ).toBe(0)
f0829c53
JB
986 await pool.destroy()
987 pool = new DynamicThreadPool(
988 min,
989 max,
990 './tests/worker-files/thread/testWorker.js'
991 )
38f6e859 992 expect(
95c83464 993 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 994 workerChoiceStrategy
f06e48d8 995 ).currentWorkerNodeId
b529c323 996 ).toBeDefined()
38f6e859 997 expect(
95c83464 998 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 999 workerChoiceStrategy
b529c323
JB
1000 ).defaultWorkerWeight
1001 ).toBeDefined()
f0829c53 1002 expect(
95c83464 1003 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1004 workerChoiceStrategy
08f3f44c 1005 ).workerVirtualTaskRunTime
b529c323 1006 ).toBeDefined()
594bfb84 1007 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1008 expect(
95c83464 1009 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1010 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 1011 ).currentWorkerNodeId
a6f7f1b4
JB
1012 ).toBe(0)
1013 expect(
95c83464 1014 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1015 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1016 ).defaultWorkerWeight
a6f7f1b4 1017 ).toBeGreaterThan(0)
08f3f44c
JB
1018 expect(
1019 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1020 workerChoiceStrategy
1021 ).workerVirtualTaskRunTime
1022 ).toBe(0)
caeb9817
JB
1023 // We need to clean up the resources after our test
1024 await pool.destroy()
1025 })
1026
e52fb978
JB
1027 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1028 const workerChoiceStrategy =
1029 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1030 let pool = new FixedThreadPool(
1031 max,
1032 './tests/worker-files/thread/testWorker.js',
1033 { workerChoiceStrategy }
1034 )
1035 expect(
1036 pool.workerChoiceStrategyContext.getRequiredStatistics()
1037 ).toStrictEqual({
1038 runTime: false,
1039 avgRunTime: false,
1040 medRunTime: false,
1041 waitTime: false,
1042 avgWaitTime: false,
d44d5953
JB
1043 medWaitTime: false,
1044 elu: false
e52fb978
JB
1045 })
1046 await pool.destroy()
1047 pool = new DynamicThreadPool(
1048 min,
1049 max,
1050 './tests/worker-files/thread/testWorker.js',
1051 { workerChoiceStrategy }
1052 )
1053 expect(
1054 pool.workerChoiceStrategyContext.getRequiredStatistics()
1055 ).toStrictEqual({
1056 runTime: false,
1057 avgRunTime: false,
1058 medRunTime: false,
1059 waitTime: false,
1060 avgWaitTime: false,
d44d5953
JB
1061 medWaitTime: false,
1062 elu: false
e52fb978
JB
1063 })
1064 // We need to clean up the resources after our test
1065 await pool.destroy()
1066 })
1067
e62e7646
JB
1068 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1069 const pool = new FixedThreadPool(
1070 max,
1071 './tests/worker-files/thread/testWorker.js',
1072 {
1073 workerChoiceStrategy:
1074 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1075 }
1076 )
1077 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1078 const promises = new Set()
1079 const maxMultiplier = 2
1080 for (let i = 0; i < max * maxMultiplier; i++) {
1081 promises.add(pool.execute())
1082 }
1083 await Promise.all(promises)
1084 for (const workerNode of pool.workerNodes) {
1085 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 1086 ran: maxMultiplier,
e62e7646
JB
1087 running: 0,
1088 runTime: 0,
1089 runTimeHistory: expect.any(CircularArray),
1090 avgRunTime: 0,
1091 medRunTime: 0,
1092 waitTime: 0,
1093 waitTimeHistory: expect.any(CircularArray),
1094 avgWaitTime: 0,
1095 medWaitTime: 0,
d44d5953
JB
1096 error: 0,
1097 elu: undefined
e62e7646
JB
1098 })
1099 }
1100 expect(
1101 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1102 pool.workerChoiceStrategyContext.workerChoiceStrategy
1103 ).defaultWorkerWeight
1104 ).toBeGreaterThan(0)
1105 expect(
1106 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1107 pool.workerChoiceStrategyContext.workerChoiceStrategy
1108 ).currentRoundId
1109 ).toBe(0)
1110 expect(
1111 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1112 pool.workerChoiceStrategyContext.workerChoiceStrategy
1113 ).currentWorkerNodeId
1114 ).toBe(0)
1115 expect(
1116 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1117 pool.workerChoiceStrategyContext.workerChoiceStrategy
1118 ).roundWeights
1119 ).toStrictEqual([
1120 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1121 pool.workerChoiceStrategyContext.workerChoiceStrategy
1122 ).defaultWorkerWeight
1123 ])
1124 // We need to clean up the resources after our test
1125 await pool.destroy()
1126 })
1127
1128 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1129 const pool = new DynamicThreadPool(
1130 min,
1131 max,
1132 './tests/worker-files/thread/testWorker.js',
1133 {
1134 workerChoiceStrategy:
1135 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1136 }
1137 )
1138 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1139 const promises = new Set()
1140 const maxMultiplier = 2
1141 for (let i = 0; i < max * maxMultiplier; i++) {
1142 promises.add(pool.execute())
1143 }
1144 await Promise.all(promises)
1145 for (const workerNode of pool.workerNodes) {
1146 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 1147 ran: maxMultiplier,
e62e7646
JB
1148 running: 0,
1149 runTime: 0,
1150 runTimeHistory: expect.any(CircularArray),
1151 avgRunTime: 0,
1152 medRunTime: 0,
1153 waitTime: 0,
1154 waitTimeHistory: expect.any(CircularArray),
1155 avgWaitTime: 0,
1156 medWaitTime: 0,
d44d5953
JB
1157 error: 0,
1158 elu: undefined
e62e7646
JB
1159 })
1160 }
1161 expect(
1162 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1163 pool.workerChoiceStrategyContext.workerChoiceStrategy
1164 ).defaultWorkerWeight
1165 ).toBeGreaterThan(0)
1166 expect(
1167 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1168 pool.workerChoiceStrategyContext.workerChoiceStrategy
1169 ).currentRoundId
1170 ).toBe(0)
1171 expect(
1172 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1173 pool.workerChoiceStrategyContext.workerChoiceStrategy
1174 ).currentWorkerNodeId
1175 ).toBe(0)
1176 expect(
1177 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1178 pool.workerChoiceStrategyContext.workerChoiceStrategy
1179 ).roundWeights
1180 ).toStrictEqual([
1181 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1182 pool.workerChoiceStrategyContext.workerChoiceStrategy
1183 ).defaultWorkerWeight
1184 ])
1185 // We need to clean up the resources after our test
1186 await pool.destroy()
1187 })
1188
8c3ec188
JB
1189 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1190 const workerChoiceStrategy =
1191 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1192 let pool = new FixedThreadPool(
1193 max,
1194 './tests/worker-files/thread/testWorker.js'
1195 )
1196 expect(
1197 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1198 workerChoiceStrategy
1199 ).currentRoundId
1200 ).toBeDefined()
1201 expect(
1202 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1203 workerChoiceStrategy
1204 ).currentWorkerNodeId
1205 ).toBeDefined()
1206 expect(
1207 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1208 workerChoiceStrategy
1209 ).defaultWorkerWeight
1210 ).toBeDefined()
1211 expect(
1212 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1213 workerChoiceStrategy
1214 ).roundWeights
1215 ).toBeDefined()
1216 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1217 expect(
1218 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1219 workerChoiceStrategy
1220 ).currentRoundId
1221 ).toBe(0)
1222 expect(
1223 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1224 pool.workerChoiceStrategyContext.workerChoiceStrategy
1225 ).currentWorkerNodeId
1226 ).toBe(0)
1227 expect(
1228 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1229 pool.workerChoiceStrategyContext.workerChoiceStrategy
1230 ).defaultWorkerWeight
1231 ).toBeGreaterThan(0)
1232 expect(
1233 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1234 workerChoiceStrategy
1235 ).roundWeights
1236 ).toStrictEqual([
1237 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1238 pool.workerChoiceStrategyContext.workerChoiceStrategy
1239 ).defaultWorkerWeight
1240 ])
1241 await pool.destroy()
1242 pool = new DynamicThreadPool(
1243 min,
1244 max,
1245 './tests/worker-files/thread/testWorker.js'
1246 )
1247 expect(
1248 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1249 workerChoiceStrategy
1250 ).currentRoundId
1251 ).toBeDefined()
1252 expect(
1253 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1254 workerChoiceStrategy
1255 ).currentWorkerNodeId
1256 ).toBeDefined()
1257 expect(
1258 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1259 workerChoiceStrategy
1260 ).defaultWorkerWeight
1261 ).toBeDefined()
1262 expect(
1263 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1264 workerChoiceStrategy
1265 ).roundWeights
1266 ).toBeDefined()
1267 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1268 expect(
1269 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1270 pool.workerChoiceStrategyContext.workerChoiceStrategy
1271 ).currentWorkerNodeId
1272 ).toBe(0)
1273 expect(
1274 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1275 pool.workerChoiceStrategyContext.workerChoiceStrategy
1276 ).defaultWorkerWeight
1277 ).toBeGreaterThan(0)
1278 expect(
1279 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1280 workerChoiceStrategy
1281 ).roundWeights
1282 ).toStrictEqual([
1283 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1284 pool.workerChoiceStrategyContext.workerChoiceStrategy
1285 ).defaultWorkerWeight
1286 ])
1287 // We need to clean up the resources after our test
1288 await pool.destroy()
1289 })
1290
89b09b26 1291 it('Verify unknown strategy throw error', () => {
a35560ba
S
1292 expect(
1293 () =>
1294 new DynamicThreadPool(
1295 min,
1296 max,
1297 './tests/worker-files/thread/testWorker.js',
1927ee67 1298 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 1299 )
d4aeae5a 1300 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
1301 })
1302})