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