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