test: adapt for tasks usage wait time introduction
[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
JB
664 expect(workerNode.tasksUsage).toStrictEqual({
665 run: max * maxMultiplier,
666 running: 0,
667 runTime: expect.any(Number),
668 runTimeHistory: expect.any(CircularArray),
669 avgRunTime: expect.any(Number),
670 medRunTime: 0,
671 waitTime: 0,
672 waitTimeHistory: expect.any(CircularArray),
673 avgWaitTime: 0,
674 medWaitTime: 0,
675 error: 0
676 })
138d29a8 677 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0)
138d29a8 678 }
97a2abc3 679 expect(
95c83464 680 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 681 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
682 ).defaultWorkerWeight
683 ).toBeGreaterThan(0)
684 expect(
685 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
686 pool.workerChoiceStrategyContext.workerChoiceStrategy
687 ).workerVirtualTaskRunTime
688 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
689 // We need to clean up the resources after our test
690 await pool.destroy()
691 })
692
693 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
694 const pool = new DynamicThreadPool(
695 min,
696 max,
697 './tests/worker-files/thread/testWorker.js',
698 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
699 )
700 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
138d29a8 701 const maxMultiplier = 2
5502c07c 702 for (let i = 0; i < max * maxMultiplier; i++) {
a4958de2 703 await pool.execute()
b3432a63 704 }
138d29a8 705 for (const workerNode of pool.workerNodes) {
86bf340d
JB
706 expect(workerNode.tasksUsage).toStrictEqual({
707 run: max * maxMultiplier,
708 running: 0,
709 runTime: expect.any(Number),
710 runTimeHistory: expect.any(CircularArray),
711 avgRunTime: expect.any(Number),
712 medRunTime: 0,
713 waitTime: 0,
714 waitTimeHistory: expect.any(CircularArray),
715 avgWaitTime: 0,
716 medWaitTime: 0,
717 error: 0
718 })
138d29a8 719 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0)
138d29a8 720 }
2b4fddb8
JB
721 expect(
722 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
723 pool.workerChoiceStrategyContext.workerChoiceStrategy
724 ).defaultWorkerWeight
725 ).toBeGreaterThan(0)
726 expect(
727 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
728 pool.workerChoiceStrategyContext.workerChoiceStrategy
729 ).workerVirtualTaskRunTime
730 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
731 // We need to clean up the resources after our test
732 await pool.destroy()
733 })
734
9e775f96 735 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
736 const pool = new DynamicThreadPool(
737 min,
738 max,
739 './tests/worker-files/thread/testWorker.js',
740 {
741 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
742 workerChoiceStrategyOptions: {
743 medRunTime: true
744 }
745 }
746 )
747 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
010d7020
JB
748 const maxMultiplier = 2
749 for (let i = 0; i < max * maxMultiplier; i++) {
a4958de2 750 await pool.execute()
010d7020 751 }
010d7020 752 for (const workerNode of pool.workerNodes) {
86bf340d
JB
753 expect(workerNode.tasksUsage).toStrictEqual({
754 run: max * maxMultiplier,
755 running: 0,
756 runTime: expect.any(Number),
757 runTimeHistory: expect.any(CircularArray),
758 avgRunTime: 0,
759 medRunTime: expect.any(Number),
760 waitTime: 0,
761 waitTimeHistory: expect.any(CircularArray),
762 avgWaitTime: 0,
763 medWaitTime: 0,
764 error: 0
765 })
138d29a8 766 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThanOrEqual(0)
010d7020 767 }
08f3f44c
JB
768 expect(
769 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
770 pool.workerChoiceStrategyContext.workerChoiceStrategy
771 ).defaultWorkerWeight
772 ).toBeGreaterThan(0)
773 expect(
774 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
775 pool.workerChoiceStrategyContext.workerChoiceStrategy
776 ).workerVirtualTaskRunTime
777 ).toBeGreaterThanOrEqual(0)
010d7020
JB
778 // We need to clean up the resources after our test
779 await pool.destroy()
780 })
781
a6f7f1b4 782 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 783 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 784 let pool = new FixedThreadPool(
caeb9817
JB
785 max,
786 './tests/worker-files/thread/testWorker.js'
787 )
38f6e859 788 expect(
95c83464 789 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 790 workerChoiceStrategy
f06e48d8 791 ).currentWorkerNodeId
b529c323 792 ).toBeDefined()
38f6e859 793 expect(
95c83464 794 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 795 workerChoiceStrategy
b529c323
JB
796 ).defaultWorkerWeight
797 ).toBeDefined()
caeb9817 798 expect(
95c83464 799 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 800 workerChoiceStrategy
08f3f44c 801 ).workerVirtualTaskRunTime
b529c323 802 ).toBeDefined()
594bfb84 803 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 804 expect(
95c83464 805 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 806 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 807 ).currentWorkerNodeId
a6f7f1b4
JB
808 ).toBe(0)
809 expect(
95c83464 810 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 811 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 812 ).defaultWorkerWeight
a6f7f1b4 813 ).toBeGreaterThan(0)
08f3f44c
JB
814 expect(
815 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
816 workerChoiceStrategy
817 ).workerVirtualTaskRunTime
818 ).toBe(0)
f0829c53
JB
819 await pool.destroy()
820 pool = new DynamicThreadPool(
821 min,
822 max,
823 './tests/worker-files/thread/testWorker.js'
824 )
38f6e859 825 expect(
95c83464 826 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 827 workerChoiceStrategy
f06e48d8 828 ).currentWorkerNodeId
b529c323 829 ).toBeDefined()
38f6e859 830 expect(
95c83464 831 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 832 workerChoiceStrategy
b529c323
JB
833 ).defaultWorkerWeight
834 ).toBeDefined()
f0829c53 835 expect(
95c83464 836 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 837 workerChoiceStrategy
08f3f44c 838 ).workerVirtualTaskRunTime
b529c323 839 ).toBeDefined()
594bfb84 840 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 841 expect(
95c83464 842 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 843 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 844 ).currentWorkerNodeId
a6f7f1b4
JB
845 ).toBe(0)
846 expect(
95c83464 847 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 848 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 849 ).defaultWorkerWeight
a6f7f1b4 850 ).toBeGreaterThan(0)
08f3f44c
JB
851 expect(
852 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
853 workerChoiceStrategy
854 ).workerVirtualTaskRunTime
855 ).toBe(0)
caeb9817
JB
856 // We need to clean up the resources after our test
857 await pool.destroy()
858 })
859
89b09b26 860 it('Verify unknown strategy throw error', () => {
a35560ba
S
861 expect(
862 () =>
863 new DynamicThreadPool(
864 min,
865 max,
866 './tests/worker-files/thread/testWorker.js',
1927ee67 867 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 868 )
d4aeae5a 869 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
870 })
871})