test: test for wait node readiness in dynamic pool
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.mjs
CommitLineData
a074ffee
JB
1import { expect } from 'expect'
2import {
999ef664 3 DynamicClusterPool,
a35560ba 4 DynamicThreadPool,
3d6dd312 5 FixedClusterPool,
2ced693a 6 FixedThreadPool,
3d6dd312 7 WorkerChoiceStrategies
a074ffee
JB
8} from '../../../lib/index.js'
9import { CircularArray } from '../../../lib/circular-array.js'
722d55a0 10import { sleep } from '../../test-utils.js'
a35560ba
S
11
12describe('Selection strategies test suite', () => {
e1ffb94f
JB
13 const min = 0
14 const max = 3
15
a35560ba
S
16 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
17 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
e4543b14
JB
18 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
19 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
a7bbf44a 20 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
23ff945a 21 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
22 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
23 'WEIGHTED_ROUND_ROBIN'
24 )
feec6e8c
JB
25 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
26 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
27 )
a35560ba
S
28 })
29
e843b904 30 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
31 const pool = new DynamicThreadPool(
32 min,
33 max,
b2fd3f4a 34 './tests/worker-files/thread/testWorker.mjs'
e843b904
JB
35 )
36 expect(pool.opts.workerChoiceStrategy).toBe(
37 WorkerChoiceStrategies.ROUND_ROBIN
38 )
39 // We need to clean up the resources after our test
40 await pool.destroy()
41 })
42
594bfb84
JB
43 it('Verify available strategies are taken at pool creation', async () => {
44 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
45 const pool = new FixedThreadPool(
46 max,
b2fd3f4a 47 './tests/worker-files/thread/testWorker.mjs',
594bfb84
JB
48 { workerChoiceStrategy }
49 )
50 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
51 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
52 workerChoiceStrategy
53 )
54 await pool.destroy()
55 }
d2f7b7a2
JB
56 })
57
594bfb84
JB
58 it('Verify available strategies can be set after pool creation', async () => {
59 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
60 const pool = new DynamicThreadPool(
61 min,
62 max,
b2fd3f4a 63 './tests/worker-files/thread/testWorker.mjs'
594bfb84
JB
64 )
65 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
66 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
67 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
68 workerChoiceStrategy
69 )
999ef664
JB
70 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
71 retries: 6,
72 runTime: { median: false },
73 waitTime: { median: false },
74 elu: { median: false }
75 })
76 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
77 retries: 6,
78 runTime: { median: false },
79 waitTime: { median: false },
80 elu: { median: false }
81 })
82 await pool.destroy()
83 }
84 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
85 const pool = new DynamicClusterPool(
86 min,
87 max,
88 './tests/worker-files/cluster/testWorker.js'
89 )
90 pool.setWorkerChoiceStrategy(workerChoiceStrategy, { retries: 3 })
91 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
92 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
93 workerChoiceStrategy
94 )
95 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
96 retries: 3,
97 runTime: { median: false },
98 waitTime: { median: false },
99 elu: { median: false }
100 })
101 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
102 retries: 3,
103 runTime: { median: false },
104 waitTime: { median: false },
105 elu: { median: false }
106 })
594bfb84
JB
107 await pool.destroy()
108 }
109 })
110
111 it('Verify available strategies default internals at pool creation', async () => {
112 const pool = new FixedThreadPool(
e843b904 113 max,
b2fd3f4a 114 './tests/worker-files/thread/testWorker.mjs'
e843b904 115 )
594bfb84 116 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
54f4e726
JB
117 expect(
118 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
119 workerChoiceStrategy
120 ).nextWorkerNodeKey
121 ).toBe(0)
122 expect(
123 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
124 workerChoiceStrategy
125 ).previousWorkerNodeKey
126 ).toBe(0)
f3a91bac 127 if (
594bfb84
JB
128 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
129 ) {
130 expect(
131 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
132 workerChoiceStrategy
54f4e726
JB
133 ).defaultWorkerWeight
134 ).toBeGreaterThan(0)
135 expect(
136 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
137 workerChoiceStrategy
f3a91bac 138 ).workerNodeVirtualTaskRunTime
594bfb84 139 ).toBe(0)
54f4e726
JB
140 } else if (
141 workerChoiceStrategy ===
142 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
143 ) {
594bfb84
JB
144 expect(
145 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
146 workerChoiceStrategy
147 ).defaultWorkerWeight
148 ).toBeGreaterThan(0)
08f3f44c
JB
149 expect(
150 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
151 workerChoiceStrategy
f3a91bac 152 ).workerNodeVirtualTaskRunTime
08f3f44c 153 ).toBe(0)
54f4e726
JB
154 expect(
155 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
156 workerChoiceStrategy
157 ).roundId
158 ).toBe(0)
159 expect(
160 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
161 workerChoiceStrategy
162 ).workerNodeId
163 ).toBe(0)
164 expect(
165 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
166 workerChoiceStrategy
167 ).roundWeights
168 ).toStrictEqual([
169 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
170 workerChoiceStrategy
171 ).defaultWorkerWeight
172 ])
594bfb84
JB
173 }
174 }
e843b904
JB
175 await pool.destroy()
176 })
177
722d55a0
JB
178 it('Verify strategies wait for worker node readiness in dynamic pool', async () => {
179 const pool = new DynamicThreadPool(
180 min,
181 max,
182 './tests/worker-files/thread/testWorker.mjs'
183 )
184 await sleep(600)
185 expect(pool.starting).toBe(false)
186 expect(pool.workerNodes.length).toBe(min)
187 const maxMultiplier = 10000
188 const promises = new Set()
189 for (let i = 0; i < max * maxMultiplier; i++) {
190 promises.add(pool.execute())
191 }
192 await Promise.all(promises)
193 expect(pool.workerNodes.length).toBe(max)
194 // We need to clean up the resources after our test
195 await pool.destroy()
196 })
197
6c6afb84
JB
198 it('Verify ROUND_ROBIN strategy default policy', async () => {
199 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
200 let pool = new FixedThreadPool(
201 max,
b2fd3f4a 202 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
203 { workerChoiceStrategy }
204 )
205 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
94407def 206 dynamicWorkerUsage: false,
b1aae695 207 dynamicWorkerReady: true
6c6afb84
JB
208 })
209 await pool.destroy()
210 pool = new DynamicThreadPool(
211 min,
212 max,
b2fd3f4a 213 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
214 { workerChoiceStrategy }
215 )
216 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
94407def 217 dynamicWorkerUsage: false,
b1aae695 218 dynamicWorkerReady: true
6c6afb84
JB
219 })
220 // We need to clean up the resources after our test
221 await pool.destroy()
222 })
223
224 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
594bfb84 225 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
226 let pool = new FixedThreadPool(
227 max,
b2fd3f4a 228 './tests/worker-files/thread/testWorker.mjs',
594bfb84 229 { workerChoiceStrategy }
10fcfaf4 230 )
87de9ff5
JB
231 expect(
232 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
233 ).toStrictEqual({
932fc8be
JB
234 runTime: {
235 aggregate: false,
236 average: false,
237 median: false
238 },
239 waitTime: {
240 aggregate: false,
241 average: false,
242 median: false
243 },
5df69fab
JB
244 elu: {
245 aggregate: false,
246 average: false,
247 median: false
248 }
86bf340d 249 })
fd7ebd49 250 await pool.destroy()
10fcfaf4
JB
251 pool = new DynamicThreadPool(
252 min,
253 max,
b2fd3f4a 254 './tests/worker-files/thread/testWorker.mjs',
594bfb84 255 { workerChoiceStrategy }
10fcfaf4 256 )
87de9ff5
JB
257 expect(
258 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
259 ).toStrictEqual({
932fc8be
JB
260 runTime: {
261 aggregate: false,
262 average: false,
263 median: false
264 },
265 waitTime: {
266 aggregate: false,
267 average: false,
268 median: false
269 },
5df69fab
JB
270 elu: {
271 aggregate: false,
272 average: false,
273 median: false
274 }
86bf340d 275 })
10fcfaf4
JB
276 // We need to clean up the resources after our test
277 await pool.destroy()
278 })
279
bdaf31cd 280 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
516dcb0d 281 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
bdaf31cd
JB
282 const pool = new FixedThreadPool(
283 max,
b2fd3f4a 284 './tests/worker-files/thread/testWorker.mjs',
516dcb0d 285 { workerChoiceStrategy }
bdaf31cd 286 )
bdaf31cd 287 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 288 const promises = new Set()
a20f0ba5
JB
289 const maxMultiplier = 2
290 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 291 promises.add(pool.execute())
e211bc18
JB
292 }
293 await Promise.all(promises)
294 for (const workerNode of pool.workerNodes) {
465b2940 295 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
296 tasks: {
297 executed: maxMultiplier,
298 executing: 0,
299 queued: 0,
df593701 300 maxQueued: 0,
463226a4 301 sequentiallyStolen: 0,
5ad42e34 302 stolen: 0,
a4e07f72
JB
303 failed: 0
304 },
305 runTime: {
4ba4c7f9 306 history: new CircularArray()
a4e07f72
JB
307 },
308 waitTime: {
4ba4c7f9 309 history: new CircularArray()
a4e07f72 310 },
5df69fab
JB
311 elu: {
312 idle: {
4ba4c7f9 313 history: new CircularArray()
5df69fab
JB
314 },
315 active: {
4ba4c7f9 316 history: new CircularArray()
71514351 317 }
5df69fab 318 }
e211bc18 319 })
bdaf31cd 320 }
9458090a
JB
321 expect(
322 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
516dcb0d 323 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 324 ).nextWorkerNodeKey
9458090a 325 ).toBe(0)
086fd843
JB
326 expect(
327 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
516dcb0d 328 pool.workerChoiceStrategyContext.workerChoiceStrategy
086fd843
JB
329 ).previousWorkerNodeKey
330 ).toBe(pool.workerNodes.length - 1)
bdaf31cd
JB
331 // We need to clean up the resources after our test
332 await pool.destroy()
333 })
334
335 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
516dcb0d 336 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
bdaf31cd
JB
337 const pool = new DynamicThreadPool(
338 min,
339 max,
b2fd3f4a 340 './tests/worker-files/thread/testWorker.mjs',
516dcb0d 341 { workerChoiceStrategy }
bdaf31cd 342 )
bdaf31cd 343 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 344 const promises = new Set()
a20f0ba5
JB
345 const maxMultiplier = 2
346 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 347 promises.add(pool.execute())
e211bc18
JB
348 }
349 await Promise.all(promises)
350 for (const workerNode of pool.workerNodes) {
465b2940 351 expect(workerNode.usage).toStrictEqual({
a4e07f72 352 tasks: {
94407def 353 executed: expect.any(Number),
a4e07f72
JB
354 executing: 0,
355 queued: 0,
df593701 356 maxQueued: 0,
463226a4 357 sequentiallyStolen: 0,
5ad42e34 358 stolen: 0,
a4e07f72
JB
359 failed: 0
360 },
361 runTime: {
4ba4c7f9 362 history: new CircularArray()
a4e07f72
JB
363 },
364 waitTime: {
4ba4c7f9 365 history: new CircularArray()
a4e07f72 366 },
5df69fab
JB
367 elu: {
368 idle: {
4ba4c7f9 369 history: new CircularArray()
5df69fab
JB
370 },
371 active: {
4ba4c7f9 372 history: new CircularArray()
71514351 373 }
5df69fab 374 }
e211bc18 375 })
94407def
JB
376 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
377 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
378 max * maxMultiplier
379 )
bdaf31cd 380 }
9458090a
JB
381 expect(
382 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
516dcb0d 383 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 384 ).nextWorkerNodeKey
9458090a 385 ).toBe(0)
086fd843
JB
386 expect(
387 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
516dcb0d 388 pool.workerChoiceStrategyContext.workerChoiceStrategy
086fd843
JB
389 ).previousWorkerNodeKey
390 ).toBe(pool.workerNodes.length - 1)
bdaf31cd
JB
391 // We need to clean up the resources after our test
392 await pool.destroy()
393 })
394
2ced693a 395 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 396 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
397 let pool = new FixedClusterPool(
398 max,
594bfb84
JB
399 './tests/worker-files/cluster/testWorker.js',
400 { workerChoiceStrategy }
2ced693a
JB
401 )
402 let results = new Set()
403 for (let i = 0; i < max; i++) {
51a8af40 404 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
2ced693a
JB
405 }
406 expect(results.size).toBe(max)
407 await pool.destroy()
594bfb84
JB
408 pool = new FixedThreadPool(
409 max,
b2fd3f4a 410 './tests/worker-files/thread/testWorker.mjs',
594bfb84
JB
411 { workerChoiceStrategy }
412 )
2ced693a
JB
413 results = new Set()
414 for (let i = 0; i < max; i++) {
51a8af40 415 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
2ced693a
JB
416 }
417 expect(results.size).toBe(max)
418 await pool.destroy()
419 })
420
a6f7f1b4 421 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 422 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
423 let pool = new FixedThreadPool(
424 max,
b2fd3f4a 425 './tests/worker-files/thread/testWorker.mjs',
a6f7f1b4
JB
426 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
427 )
86ed0598
JB
428 expect(
429 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
430 pool.workerChoiceStrategyContext.workerChoiceStrategy
431 ).nextWorkerNodeKey
432 ).toBeDefined()
433 expect(
434 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
435 pool.workerChoiceStrategyContext.workerChoiceStrategy
436 ).previousWorkerNodeKey
437 ).toBeDefined()
086fd843 438 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
38f6e859 439 expect(
95c83464 440 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 441 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 442 ).nextWorkerNodeKey
086fd843 443 ).toBe(0)
a6f7f1b4 444 expect(
95c83464 445 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 446 pool.workerChoiceStrategyContext.workerChoiceStrategy
086fd843 447 ).previousWorkerNodeKey
a6f7f1b4
JB
448 ).toBe(0)
449 await pool.destroy()
450 pool = new DynamicThreadPool(
451 min,
452 max,
b2fd3f4a 453 './tests/worker-files/thread/testWorker.mjs',
a6f7f1b4
JB
454 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
455 )
86ed0598
JB
456 expect(
457 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
458 pool.workerChoiceStrategyContext.workerChoiceStrategy
459 ).nextWorkerNodeKey
460 ).toBeDefined()
461 expect(
462 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
463 pool.workerChoiceStrategyContext.workerChoiceStrategy
464 ).previousWorkerNodeKey
465 ).toBeDefined()
086fd843 466 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
38f6e859 467 expect(
95c83464 468 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 469 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 470 ).nextWorkerNodeKey
086fd843 471 ).toBe(0)
a6f7f1b4 472 expect(
95c83464 473 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 474 pool.workerChoiceStrategyContext.workerChoiceStrategy
086fd843 475 ).previousWorkerNodeKey
a6f7f1b4
JB
476 ).toBe(0)
477 // We need to clean up the resources after our test
478 await pool.destroy()
479 })
480
6c6afb84
JB
481 it('Verify LEAST_USED strategy default policy', async () => {
482 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
483 let pool = new FixedThreadPool(
484 max,
b2fd3f4a 485 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
486 { workerChoiceStrategy }
487 )
488 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
489 dynamicWorkerUsage: false,
490 dynamicWorkerReady: true
6c6afb84
JB
491 })
492 await pool.destroy()
493 pool = new DynamicThreadPool(
494 min,
495 max,
b2fd3f4a 496 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
497 { workerChoiceStrategy }
498 )
499 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
500 dynamicWorkerUsage: false,
501 dynamicWorkerReady: true
6c6afb84
JB
502 })
503 // We need to clean up the resources after our test
504 await pool.destroy()
505 })
506
507 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
e4543b14 508 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
10fcfaf4
JB
509 let pool = new FixedThreadPool(
510 max,
b2fd3f4a 511 './tests/worker-files/thread/testWorker.mjs',
594bfb84 512 { workerChoiceStrategy }
10fcfaf4 513 )
87de9ff5
JB
514 expect(
515 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
516 ).toStrictEqual({
932fc8be
JB
517 runTime: {
518 aggregate: false,
519 average: false,
520 median: false
521 },
522 waitTime: {
523 aggregate: false,
524 average: false,
525 median: false
526 },
5df69fab
JB
527 elu: {
528 aggregate: false,
529 average: false,
530 median: false
531 }
86bf340d 532 })
fd7ebd49 533 await pool.destroy()
10fcfaf4
JB
534 pool = new DynamicThreadPool(
535 min,
536 max,
b2fd3f4a 537 './tests/worker-files/thread/testWorker.mjs',
594bfb84 538 { workerChoiceStrategy }
10fcfaf4 539 )
87de9ff5
JB
540 expect(
541 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
542 ).toStrictEqual({
932fc8be
JB
543 runTime: {
544 aggregate: false,
545 average: false,
546 median: false
547 },
548 waitTime: {
549 aggregate: false,
550 average: false,
551 median: false
552 },
5df69fab
JB
553 elu: {
554 aggregate: false,
555 average: false,
556 median: false
557 }
86bf340d 558 })
10fcfaf4
JB
559 // We need to clean up the resources after our test
560 await pool.destroy()
561 })
562
e4543b14 563 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
564 const pool = new FixedThreadPool(
565 max,
b2fd3f4a 566 './tests/worker-files/thread/testWorker.mjs',
e4543b14 567 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
b98ec2e6 568 )
e4543b14 569 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 570 const promises = new Set()
a20f0ba5
JB
571 const maxMultiplier = 2
572 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 573 promises.add(pool.execute())
e211bc18
JB
574 }
575 await Promise.all(promises)
576 for (const workerNode of pool.workerNodes) {
465b2940 577 expect(workerNode.usage).toStrictEqual({
a4e07f72 578 tasks: {
76407b8e 579 executed: expect.any(Number),
a4e07f72
JB
580 executing: 0,
581 queued: 0,
df593701 582 maxQueued: 0,
463226a4 583 sequentiallyStolen: 0,
5ad42e34 584 stolen: 0,
a4e07f72
JB
585 failed: 0
586 },
587 runTime: {
4ba4c7f9 588 history: new CircularArray()
a4e07f72
JB
589 },
590 waitTime: {
4ba4c7f9 591 history: new CircularArray()
a4e07f72 592 },
5df69fab
JB
593 elu: {
594 idle: {
4ba4c7f9 595 history: new CircularArray()
5df69fab
JB
596 },
597 active: {
4ba4c7f9 598 history: new CircularArray()
71514351 599 }
5df69fab 600 }
e211bc18 601 })
465b2940
JB
602 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
603 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
76407b8e
JB
604 max * maxMultiplier
605 )
a35560ba 606 }
e5c68e12
JB
607 expect(
608 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
609 pool.workerChoiceStrategyContext.workerChoiceStrategy
610 ).nextWorkerNodeKey
611 ).toEqual(expect.any(Number))
612 expect(
613 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
614 pool.workerChoiceStrategyContext.workerChoiceStrategy
615 ).previousWorkerNodeKey
616 ).toEqual(expect.any(Number))
a35560ba
S
617 // We need to clean up the resources after our test
618 await pool.destroy()
619 })
620
e4543b14 621 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
622 const pool = new DynamicThreadPool(
623 min,
624 max,
b2fd3f4a 625 './tests/worker-files/thread/testWorker.mjs',
e4543b14 626 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
ff5e76e1 627 )
e4543b14 628 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 629 const promises = new Set()
a20f0ba5
JB
630 const maxMultiplier = 2
631 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 632 promises.add(pool.execute())
e211bc18
JB
633 }
634 await Promise.all(promises)
635 for (const workerNode of pool.workerNodes) {
465b2940 636 expect(workerNode.usage).toStrictEqual({
a4e07f72 637 tasks: {
76407b8e 638 executed: expect.any(Number),
a4e07f72
JB
639 executing: 0,
640 queued: 0,
df593701 641 maxQueued: 0,
463226a4 642 sequentiallyStolen: 0,
5ad42e34 643 stolen: 0,
a4e07f72
JB
644 failed: 0
645 },
646 runTime: {
4ba4c7f9 647 history: new CircularArray()
a4e07f72
JB
648 },
649 waitTime: {
4ba4c7f9 650 history: new CircularArray()
a4e07f72 651 },
5df69fab
JB
652 elu: {
653 idle: {
4ba4c7f9 654 history: new CircularArray()
5df69fab
JB
655 },
656 active: {
4ba4c7f9 657 history: new CircularArray()
71514351 658 }
5df69fab 659 }
e211bc18 660 })
465b2940
JB
661 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
662 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
76407b8e
JB
663 max * maxMultiplier
664 )
168c526f 665 }
e5c68e12
JB
666 expect(
667 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
668 pool.workerChoiceStrategyContext.workerChoiceStrategy
669 ).nextWorkerNodeKey
670 ).toEqual(expect.any(Number))
671 expect(
672 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
673 pool.workerChoiceStrategyContext.workerChoiceStrategy
674 ).previousWorkerNodeKey
675 ).toEqual(expect.any(Number))
168c526f
JB
676 // We need to clean up the resources after our test
677 await pool.destroy()
678 })
679
6c6afb84
JB
680 it('Verify LEAST_BUSY strategy default policy', async () => {
681 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
682 let pool = new FixedThreadPool(
683 max,
b2fd3f4a 684 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
685 { workerChoiceStrategy }
686 )
687 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
688 dynamicWorkerUsage: false,
689 dynamicWorkerReady: true
6c6afb84
JB
690 })
691 await pool.destroy()
692 pool = new DynamicThreadPool(
693 min,
694 max,
b2fd3f4a 695 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
696 { workerChoiceStrategy }
697 )
698 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
699 dynamicWorkerUsage: false,
700 dynamicWorkerReady: true
6c6afb84
JB
701 })
702 // We need to clean up the resources after our test
703 await pool.destroy()
704 })
705
706 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
e4543b14 707 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
168c526f
JB
708 let pool = new FixedThreadPool(
709 max,
b2fd3f4a 710 './tests/worker-files/thread/testWorker.mjs',
594bfb84 711 { workerChoiceStrategy }
168c526f 712 )
87de9ff5
JB
713 expect(
714 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
715 ).toStrictEqual({
932fc8be
JB
716 runTime: {
717 aggregate: true,
718 average: false,
719 median: false
720 },
721 waitTime: {
722 aggregate: true,
723 average: false,
724 median: false
725 },
5df69fab
JB
726 elu: {
727 aggregate: false,
728 average: false,
729 median: false
730 }
86bf340d 731 })
168c526f
JB
732 await pool.destroy()
733 pool = new DynamicThreadPool(
734 min,
735 max,
b2fd3f4a 736 './tests/worker-files/thread/testWorker.mjs',
594bfb84 737 { workerChoiceStrategy }
168c526f 738 )
87de9ff5
JB
739 expect(
740 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
741 ).toStrictEqual({
932fc8be
JB
742 runTime: {
743 aggregate: true,
744 average: false,
745 median: false
746 },
747 waitTime: {
748 aggregate: true,
749 average: false,
750 median: false
751 },
5df69fab
JB
752 elu: {
753 aggregate: false,
754 average: false,
755 median: false
756 }
86bf340d 757 })
168c526f
JB
758 // We need to clean up the resources after our test
759 await pool.destroy()
760 })
761
e4543b14 762 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
168c526f
JB
763 const pool = new FixedThreadPool(
764 max,
b2fd3f4a 765 './tests/worker-files/thread/testWorker.mjs',
e4543b14 766 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 767 )
e4543b14 768 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 769 const promises = new Set()
a20f0ba5
JB
770 const maxMultiplier = 2
771 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 772 promises.add(pool.execute())
e211bc18
JB
773 }
774 await Promise.all(promises)
775 for (const workerNode of pool.workerNodes) {
619f403b 776 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
777 tasks: {
778 executed: expect.any(Number),
779 executing: 0,
780 queued: 0,
df593701 781 maxQueued: 0,
463226a4 782 sequentiallyStolen: 0,
5ad42e34 783 stolen: 0,
a4e07f72
JB
784 failed: 0
785 },
619f403b 786 runTime: expect.objectContaining({
a4e07f72 787 history: expect.any(CircularArray)
619f403b
JB
788 }),
789 waitTime: expect.objectContaining({
a4e07f72 790 history: expect.any(CircularArray)
619f403b 791 }),
5df69fab
JB
792 elu: {
793 idle: {
619f403b 794 history: new CircularArray()
5df69fab
JB
795 },
796 active: {
619f403b 797 history: new CircularArray()
71514351 798 }
5df69fab 799 }
e211bc18 800 })
465b2940
JB
801 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
802 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
803 max * maxMultiplier
804 )
19dbc45b
JB
805 if (workerNode.usage.runTime.aggregate == null) {
806 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
807 } else {
808 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
809 }
810 if (workerNode.usage.waitTime.aggregate == null) {
811 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
812 } else {
813 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
814 }
168c526f 815 }
e5c68e12
JB
816 expect(
817 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
818 pool.workerChoiceStrategyContext.workerChoiceStrategy
819 ).nextWorkerNodeKey
820 ).toEqual(expect.any(Number))
821 expect(
822 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
823 pool.workerChoiceStrategyContext.workerChoiceStrategy
824 ).previousWorkerNodeKey
825 ).toEqual(expect.any(Number))
168c526f
JB
826 // We need to clean up the resources after our test
827 await pool.destroy()
828 })
829
e4543b14 830 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
168c526f
JB
831 const pool = new DynamicThreadPool(
832 min,
833 max,
b2fd3f4a 834 './tests/worker-files/thread/testWorker.mjs',
e4543b14 835 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 836 )
e4543b14 837 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 838 const promises = new Set()
a20f0ba5
JB
839 const maxMultiplier = 2
840 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 841 promises.add(pool.execute())
e211bc18
JB
842 }
843 await Promise.all(promises)
844 for (const workerNode of pool.workerNodes) {
619f403b 845 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
846 tasks: {
847 executed: expect.any(Number),
848 executing: 0,
849 queued: 0,
df593701 850 maxQueued: 0,
463226a4 851 sequentiallyStolen: 0,
5ad42e34 852 stolen: 0,
a4e07f72
JB
853 failed: 0
854 },
619f403b 855 runTime: expect.objectContaining({
a4e07f72 856 history: expect.any(CircularArray)
619f403b
JB
857 }),
858 waitTime: expect.objectContaining({
a4e07f72 859 history: expect.any(CircularArray)
619f403b 860 }),
5df69fab
JB
861 elu: {
862 idle: {
619f403b 863 history: new CircularArray()
5df69fab
JB
864 },
865 active: {
619f403b 866 history: new CircularArray()
71514351 867 }
5df69fab 868 }
e211bc18 869 })
465b2940
JB
870 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
871 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
872 max * maxMultiplier
873 )
19dbc45b
JB
874 if (workerNode.usage.runTime.aggregate == null) {
875 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
876 } else {
877 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
878 }
879 if (workerNode.usage.waitTime.aggregate == null) {
880 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
881 } else {
882 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
883 }
ff5e76e1 884 }
e5c68e12
JB
885 expect(
886 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
887 pool.workerChoiceStrategyContext.workerChoiceStrategy
888 ).nextWorkerNodeKey
889 ).toEqual(expect.any(Number))
890 expect(
891 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
892 pool.workerChoiceStrategyContext.workerChoiceStrategy
893 ).previousWorkerNodeKey
894 ).toEqual(expect.any(Number))
ff5e76e1
JB
895 // We need to clean up the resources after our test
896 await pool.destroy()
897 })
898
6c6afb84
JB
899 it('Verify LEAST_ELU strategy default policy', async () => {
900 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
901 let pool = new FixedThreadPool(
902 max,
b2fd3f4a 903 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
904 { workerChoiceStrategy }
905 )
906 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
907 dynamicWorkerUsage: false,
908 dynamicWorkerReady: true
6c6afb84
JB
909 })
910 await pool.destroy()
911 pool = new DynamicThreadPool(
912 min,
913 max,
b2fd3f4a 914 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
915 { workerChoiceStrategy }
916 )
917 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
918 dynamicWorkerUsage: false,
919 dynamicWorkerReady: true
6c6afb84
JB
920 })
921 // We need to clean up the resources after our test
922 await pool.destroy()
923 })
924
925 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
a7bbf44a
JB
926 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
927 let pool = new FixedThreadPool(
928 max,
b2fd3f4a 929 './tests/worker-files/thread/testWorker.mjs',
a7bbf44a
JB
930 { workerChoiceStrategy }
931 )
05302647
JB
932 expect(
933 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
934 ).toStrictEqual({
e460940e
JB
935 runTime: {
936 aggregate: false,
937 average: false,
938 median: false
939 },
940 waitTime: {
941 aggregate: false,
942 average: false,
943 median: false
944 },
5df69fab
JB
945 elu: {
946 aggregate: true,
947 average: false,
948 median: false
949 }
a7bbf44a
JB
950 })
951 await pool.destroy()
952 pool = new DynamicThreadPool(
953 min,
954 max,
b2fd3f4a 955 './tests/worker-files/thread/testWorker.mjs',
a7bbf44a
JB
956 { workerChoiceStrategy }
957 )
05302647
JB
958 expect(
959 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
960 ).toStrictEqual({
e460940e
JB
961 runTime: {
962 aggregate: false,
963 average: false,
964 median: false
965 },
966 waitTime: {
967 aggregate: false,
968 average: false,
969 median: false
970 },
5df69fab
JB
971 elu: {
972 aggregate: true,
973 average: false,
974 median: false
975 }
a7bbf44a
JB
976 })
977 // We need to clean up the resources after our test
978 await pool.destroy()
979 })
980
ae9cf3c8 981 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
c5ad42cd
JB
982 const pool = new FixedThreadPool(
983 max,
b2fd3f4a 984 './tests/worker-files/thread/testWorker.mjs',
c5ad42cd
JB
985 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
986 )
987 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
dd38581f 988 const promises = new Set()
c5ad42cd
JB
989 const maxMultiplier = 2
990 for (let i = 0; i < max * maxMultiplier; i++) {
dd38581f 991 promises.add(pool.execute())
c5ad42cd 992 }
dd38581f 993 await Promise.all(promises)
c5ad42cd 994 for (const workerNode of pool.workerNodes) {
619f403b 995 expect(workerNode.usage).toStrictEqual({
c5ad42cd
JB
996 tasks: {
997 executed: expect.any(Number),
998 executing: 0,
999 queued: 0,
df593701 1000 maxQueued: 0,
463226a4 1001 sequentiallyStolen: 0,
5ad42e34 1002 stolen: 0,
c5ad42cd
JB
1003 failed: 0
1004 },
1005 runTime: {
619f403b 1006 history: new CircularArray()
a1347286
JB
1007 },
1008 waitTime: {
619f403b 1009 history: new CircularArray()
5df69fab 1010 },
619f403b
JB
1011 elu: expect.objectContaining({
1012 idle: expect.objectContaining({
5df69fab 1013 history: expect.any(CircularArray)
619f403b
JB
1014 }),
1015 active: expect.objectContaining({
5df69fab 1016 history: expect.any(CircularArray)
619f403b
JB
1017 })
1018 })
5df69fab 1019 })
465b2940
JB
1020 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1021 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a1347286
JB
1022 max * maxMultiplier
1023 )
7db63069
JB
1024 if (workerNode.usage.elu.active.aggregate == null) {
1025 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1026 } else {
1027 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1028 }
1029 if (workerNode.usage.elu.idle.aggregate == null) {
1030 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1031 } else {
1032 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1033 }
71514351
JB
1034 if (workerNode.usage.elu.utilization == null) {
1035 expect(workerNode.usage.elu.utilization).toBeUndefined()
1036 } else {
1037 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1038 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1039 }
a1347286 1040 }
e5c68e12
JB
1041 expect(
1042 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1043 pool.workerChoiceStrategyContext.workerChoiceStrategy
1044 ).nextWorkerNodeKey
1045 ).toEqual(expect.any(Number))
1046 expect(
1047 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1048 pool.workerChoiceStrategyContext.workerChoiceStrategy
1049 ).previousWorkerNodeKey
1050 ).toEqual(expect.any(Number))
a1347286
JB
1051 // We need to clean up the resources after our test
1052 await pool.destroy()
1053 })
1054
1055 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1056 const pool = new DynamicThreadPool(
1057 min,
1058 max,
b2fd3f4a 1059 './tests/worker-files/thread/testWorker.mjs',
a1347286
JB
1060 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
1061 )
1062 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
dd38581f 1063 const promises = new Set()
a1347286
JB
1064 const maxMultiplier = 2
1065 for (let i = 0; i < max * maxMultiplier; i++) {
dd38581f 1066 promises.add(pool.execute())
a1347286 1067 }
dd38581f 1068 await Promise.all(promises)
a1347286 1069 for (const workerNode of pool.workerNodes) {
619f403b 1070 expect(workerNode.usage).toStrictEqual({
a1347286
JB
1071 tasks: {
1072 executed: expect.any(Number),
1073 executing: 0,
1074 queued: 0,
df593701 1075 maxQueued: 0,
463226a4 1076 sequentiallyStolen: 0,
5ad42e34 1077 stolen: 0,
a1347286
JB
1078 failed: 0
1079 },
1080 runTime: {
619f403b 1081 history: new CircularArray()
c5ad42cd
JB
1082 },
1083 waitTime: {
619f403b 1084 history: new CircularArray()
5df69fab 1085 },
619f403b
JB
1086 elu: expect.objectContaining({
1087 idle: expect.objectContaining({
5df69fab 1088 history: expect.any(CircularArray)
619f403b
JB
1089 }),
1090 active: expect.objectContaining({
5df69fab 1091 history: expect.any(CircularArray)
619f403b
JB
1092 })
1093 })
5df69fab 1094 })
465b2940
JB
1095 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1096 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
c5ad42cd
JB
1097 max * maxMultiplier
1098 )
7db63069
JB
1099 if (workerNode.usage.elu.active.aggregate == null) {
1100 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1101 } else {
1102 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1103 }
1104 if (workerNode.usage.elu.idle.aggregate == null) {
1105 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1106 } else {
1107 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1108 }
71514351
JB
1109 if (workerNode.usage.elu.utilization == null) {
1110 expect(workerNode.usage.elu.utilization).toBeUndefined()
1111 } else {
1112 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1113 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1114 }
c5ad42cd 1115 }
e5c68e12
JB
1116 expect(
1117 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1118 pool.workerChoiceStrategyContext.workerChoiceStrategy
1119 ).nextWorkerNodeKey
1120 ).toEqual(expect.any(Number))
1121 expect(
1122 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1123 pool.workerChoiceStrategyContext.workerChoiceStrategy
1124 ).previousWorkerNodeKey
1125 ).toEqual(expect.any(Number))
c5ad42cd
JB
1126 // We need to clean up the resources after our test
1127 await pool.destroy()
1128 })
1129
6c6afb84
JB
1130 it('Verify FAIR_SHARE strategy default policy', async () => {
1131 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1132 let pool = new FixedThreadPool(
1133 max,
b2fd3f4a 1134 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1135 { workerChoiceStrategy }
1136 )
1137 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1138 dynamicWorkerUsage: false,
1139 dynamicWorkerReady: true
6c6afb84
JB
1140 })
1141 await pool.destroy()
1142 pool = new DynamicThreadPool(
1143 min,
1144 max,
b2fd3f4a 1145 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1146 { workerChoiceStrategy }
1147 )
1148 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1149 dynamicWorkerUsage: false,
1150 dynamicWorkerReady: true
6c6afb84
JB
1151 })
1152 // We need to clean up the resources after our test
1153 await pool.destroy()
1154 })
1155
1156 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
594bfb84 1157 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
1158 let pool = new FixedThreadPool(
1159 max,
b2fd3f4a 1160 './tests/worker-files/thread/testWorker.mjs',
594bfb84 1161 { workerChoiceStrategy }
10fcfaf4 1162 )
87de9ff5
JB
1163 expect(
1164 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1165 ).toStrictEqual({
932fc8be
JB
1166 runTime: {
1167 aggregate: true,
1168 average: true,
1169 median: false
1170 },
1171 waitTime: {
1172 aggregate: false,
1173 average: false,
1174 median: false
1175 },
5df69fab 1176 elu: {
9adcefab
JB
1177 aggregate: true,
1178 average: true,
5df69fab
JB
1179 median: false
1180 }
86bf340d 1181 })
fd7ebd49 1182 await pool.destroy()
10fcfaf4
JB
1183 pool = new DynamicThreadPool(
1184 min,
1185 max,
b2fd3f4a 1186 './tests/worker-files/thread/testWorker.mjs',
594bfb84 1187 { workerChoiceStrategy }
10fcfaf4 1188 )
87de9ff5
JB
1189 expect(
1190 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1191 ).toStrictEqual({
932fc8be
JB
1192 runTime: {
1193 aggregate: true,
1194 average: true,
1195 median: false
1196 },
1197 waitTime: {
1198 aggregate: false,
1199 average: false,
1200 median: false
1201 },
5df69fab 1202 elu: {
9adcefab
JB
1203 aggregate: true,
1204 average: true,
5df69fab
JB
1205 median: false
1206 }
86bf340d 1207 })
10fcfaf4
JB
1208 // We need to clean up the resources after our test
1209 await pool.destroy()
1210 })
1211
23ff945a 1212 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
1213 const pool = new FixedThreadPool(
1214 max,
b2fd3f4a 1215 './tests/worker-files/thread/testWorker.mjs',
23ff945a
JB
1216 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1217 )
1218 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1219 const promises = new Set()
a20f0ba5
JB
1220 const maxMultiplier = 2
1221 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1222 promises.add(pool.execute())
23ff945a 1223 }
e211bc18 1224 await Promise.all(promises)
138d29a8 1225 for (const workerNode of pool.workerNodes) {
619f403b 1226 expect(workerNode.usage).toStrictEqual({
a4e07f72 1227 tasks: {
d33be430 1228 executed: expect.any(Number),
a4e07f72
JB
1229 executing: 0,
1230 queued: 0,
df593701 1231 maxQueued: 0,
463226a4 1232 sequentiallyStolen: 0,
5ad42e34 1233 stolen: 0,
a4e07f72
JB
1234 failed: 0
1235 },
619f403b 1236 runTime: expect.objectContaining({
a4e07f72 1237 history: expect.any(CircularArray)
619f403b 1238 }),
a4e07f72 1239 waitTime: {
619f403b 1240 history: new CircularArray()
a4e07f72 1241 },
619f403b
JB
1242 elu: expect.objectContaining({
1243 idle: expect.objectContaining({
5df69fab 1244 history: expect.any(CircularArray)
619f403b
JB
1245 }),
1246 active: expect.objectContaining({
5df69fab 1247 history: expect.any(CircularArray)
619f403b
JB
1248 })
1249 })
86bf340d 1250 })
465b2940
JB
1251 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1252 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
d33be430
JB
1253 max * maxMultiplier
1254 )
71514351
JB
1255 if (workerNode.usage.runTime.aggregate == null) {
1256 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1257 } else {
1258 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1259 }
1260 if (workerNode.usage.runTime.average == null) {
1261 expect(workerNode.usage.runTime.average).toBeUndefined()
1262 } else {
1263 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1264 }
7db63069
JB
1265 if (workerNode.usage.elu.active.aggregate == null) {
1266 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1267 } else {
1268 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1269 }
1270 if (workerNode.usage.elu.idle.aggregate == null) {
1271 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1272 } else {
1273 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1274 }
71514351
JB
1275 if (workerNode.usage.elu.utilization == null) {
1276 expect(workerNode.usage.elu.utilization).toBeUndefined()
1277 } else {
1278 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1279 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1280 }
946b809b 1281 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
138d29a8 1282 }
e5c68e12
JB
1283 expect(
1284 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1285 pool.workerChoiceStrategyContext.workerChoiceStrategy
1286 ).nextWorkerNodeKey
1287 ).toEqual(expect.any(Number))
1288 expect(
1289 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1290 pool.workerChoiceStrategyContext.workerChoiceStrategy
1291 ).previousWorkerNodeKey
1292 ).toEqual(expect.any(Number))
23ff945a
JB
1293 // We need to clean up the resources after our test
1294 await pool.destroy()
1295 })
1296
1297 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
1298 const pool = new DynamicThreadPool(
1299 min,
1300 max,
b2fd3f4a 1301 './tests/worker-files/thread/testWorker.mjs',
23ff945a
JB
1302 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1303 )
1304 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1305 const promises = new Set()
f7070eee 1306 const maxMultiplier = 2
804a889e 1307 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1308 promises.add(pool.execute())
23ff945a 1309 }
e211bc18 1310 await Promise.all(promises)
138d29a8 1311 for (const workerNode of pool.workerNodes) {
619f403b 1312 expect(workerNode.usage).toStrictEqual({
a4e07f72 1313 tasks: {
6c6afb84 1314 executed: expect.any(Number),
a4e07f72
JB
1315 executing: 0,
1316 queued: 0,
df593701 1317 maxQueued: 0,
463226a4 1318 sequentiallyStolen: 0,
5ad42e34 1319 stolen: 0,
a4e07f72
JB
1320 failed: 0
1321 },
619f403b 1322 runTime: expect.objectContaining({
a4e07f72 1323 history: expect.any(CircularArray)
619f403b 1324 }),
a4e07f72 1325 waitTime: {
619f403b 1326 history: new CircularArray()
a4e07f72 1327 },
619f403b
JB
1328 elu: expect.objectContaining({
1329 idle: expect.objectContaining({
5df69fab 1330 history: expect.any(CircularArray)
619f403b
JB
1331 }),
1332 active: expect.objectContaining({
5df69fab 1333 history: expect.any(CircularArray)
619f403b
JB
1334 })
1335 })
86bf340d 1336 })
465b2940
JB
1337 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1338 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
6c6afb84
JB
1339 max * maxMultiplier
1340 )
71514351
JB
1341 if (workerNode.usage.runTime.aggregate == null) {
1342 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1343 } else {
1344 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1345 }
1346 if (workerNode.usage.runTime.average == null) {
1347 expect(workerNode.usage.runTime.average).toBeUndefined()
1348 } else {
1349 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1350 }
7db63069
JB
1351 if (workerNode.usage.elu.active.aggregate == null) {
1352 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1353 } else {
1354 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1355 }
1356 if (workerNode.usage.elu.idle.aggregate == null) {
1357 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1358 } else {
1359 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1360 }
71514351
JB
1361 if (workerNode.usage.elu.utilization == null) {
1362 expect(workerNode.usage.elu.utilization).toBeUndefined()
1363 } else {
1364 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1365 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1366 }
946b809b 1367 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
138d29a8 1368 }
e5c68e12
JB
1369 expect(
1370 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1371 pool.workerChoiceStrategyContext.workerChoiceStrategy
1372 ).nextWorkerNodeKey
1373 ).toEqual(expect.any(Number))
1374 expect(
1375 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1376 pool.workerChoiceStrategyContext.workerChoiceStrategy
1377 ).previousWorkerNodeKey
1378 ).toEqual(expect.any(Number))
23ff945a
JB
1379 // We need to clean up the resources after our test
1380 await pool.destroy()
1381 })
1382
9e775f96 1383 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
1384 const pool = new DynamicThreadPool(
1385 min,
1386 max,
b2fd3f4a 1387 './tests/worker-files/thread/testWorker.mjs',
010d7020
JB
1388 {
1389 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1390 workerChoiceStrategyOptions: {
932fc8be 1391 runTime: { median: true }
010d7020
JB
1392 }
1393 }
1394 )
1395 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 1396 const promises = new Set()
010d7020
JB
1397 const maxMultiplier = 2
1398 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1399 promises.add(pool.execute())
010d7020 1400 }
e211bc18 1401 await Promise.all(promises)
010d7020 1402 for (const workerNode of pool.workerNodes) {
619f403b 1403 expect(workerNode.usage).toStrictEqual({
a4e07f72 1404 tasks: {
6c6afb84 1405 executed: expect.any(Number),
a4e07f72
JB
1406 executing: 0,
1407 queued: 0,
df593701 1408 maxQueued: 0,
463226a4 1409 sequentiallyStolen: 0,
5ad42e34 1410 stolen: 0,
a4e07f72
JB
1411 failed: 0
1412 },
619f403b 1413 runTime: expect.objectContaining({
a4e07f72 1414 history: expect.any(CircularArray)
619f403b 1415 }),
a4e07f72 1416 waitTime: {
619f403b 1417 history: new CircularArray()
a4e07f72 1418 },
619f403b
JB
1419 elu: expect.objectContaining({
1420 idle: expect.objectContaining({
5df69fab 1421 history: expect.any(CircularArray)
619f403b
JB
1422 }),
1423 active: expect.objectContaining({
5df69fab 1424 history: expect.any(CircularArray)
619f403b
JB
1425 })
1426 })
86bf340d 1427 })
465b2940
JB
1428 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1429 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
6c6afb84
JB
1430 max * maxMultiplier
1431 )
71514351
JB
1432 if (workerNode.usage.runTime.aggregate == null) {
1433 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1434 } else {
1435 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1436 }
1437 if (workerNode.usage.runTime.median == null) {
1438 expect(workerNode.usage.runTime.median).toBeUndefined()
1439 } else {
1440 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1441 }
7db63069
JB
1442 if (workerNode.usage.elu.active.aggregate == null) {
1443 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1444 } else {
1445 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1446 }
1447 if (workerNode.usage.elu.idle.aggregate == null) {
1448 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1449 } else {
1450 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1451 }
71514351
JB
1452 if (workerNode.usage.elu.utilization == null) {
1453 expect(workerNode.usage.elu.utilization).toBeUndefined()
1454 } else {
1455 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1456 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1457 }
946b809b 1458 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
010d7020 1459 }
2b4fddb8
JB
1460 expect(
1461 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1462 pool.workerChoiceStrategyContext.workerChoiceStrategy
e5c68e12
JB
1463 ).nextWorkerNodeKey
1464 ).toEqual(expect.any(Number))
1465 expect(
1466 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1467 pool.workerChoiceStrategyContext.workerChoiceStrategy
1468 ).previousWorkerNodeKey
1469 ).toEqual(expect.any(Number))
010d7020
JB
1470 // We need to clean up the resources after our test
1471 await pool.destroy()
1472 })
1473
a6f7f1b4 1474 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 1475 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 1476 let pool = new FixedThreadPool(
caeb9817 1477 max,
b2fd3f4a 1478 './tests/worker-files/thread/testWorker.mjs'
caeb9817 1479 )
f3a91bac
JB
1480 for (const workerNode of pool.workerNodes) {
1481 workerNode.strategyData = {
1482 virtualTaskEndTimestamp: performance.now()
1483 }
1484 }
594bfb84 1485 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
f3a91bac
JB
1486 for (const workerNode of pool.workerNodes) {
1487 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1488 }
f0829c53
JB
1489 await pool.destroy()
1490 pool = new DynamicThreadPool(
1491 min,
1492 max,
b2fd3f4a 1493 './tests/worker-files/thread/testWorker.mjs'
f0829c53 1494 )
f3a91bac
JB
1495 for (const workerNode of pool.workerNodes) {
1496 workerNode.strategyData = {
1497 virtualTaskEndTimestamp: performance.now()
1498 }
1499 }
594bfb84 1500 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
f3a91bac
JB
1501 for (const workerNode of pool.workerNodes) {
1502 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1503 }
caeb9817
JB
1504 // We need to clean up the resources after our test
1505 await pool.destroy()
1506 })
1507
6c6afb84
JB
1508 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1509 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1510 let pool = new FixedThreadPool(
1511 max,
b2fd3f4a 1512 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1513 { workerChoiceStrategy }
1514 )
1515 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1516 dynamicWorkerUsage: false,
1517 dynamicWorkerReady: true
6c6afb84
JB
1518 })
1519 await pool.destroy()
1520 pool = new DynamicThreadPool(
1521 min,
1522 max,
b2fd3f4a 1523 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1524 { workerChoiceStrategy }
1525 )
1526 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1527 dynamicWorkerUsage: false,
1528 dynamicWorkerReady: true
6c6afb84
JB
1529 })
1530 // We need to clean up the resources after our test
1531 await pool.destroy()
1532 })
1533
1534 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
594bfb84 1535 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
1536 let pool = new FixedThreadPool(
1537 max,
b2fd3f4a 1538 './tests/worker-files/thread/testWorker.mjs',
594bfb84 1539 { workerChoiceStrategy }
10fcfaf4 1540 )
87de9ff5
JB
1541 expect(
1542 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1543 ).toStrictEqual({
932fc8be
JB
1544 runTime: {
1545 aggregate: true,
1546 average: true,
1547 median: false
1548 },
1549 waitTime: {
1550 aggregate: false,
1551 average: false,
1552 median: false
1553 },
5df69fab
JB
1554 elu: {
1555 aggregate: false,
1556 average: false,
1557 median: false
1558 }
86bf340d 1559 })
fd7ebd49 1560 await pool.destroy()
10fcfaf4
JB
1561 pool = new DynamicThreadPool(
1562 min,
1563 max,
b2fd3f4a 1564 './tests/worker-files/thread/testWorker.mjs',
594bfb84 1565 { workerChoiceStrategy }
10fcfaf4 1566 )
87de9ff5
JB
1567 expect(
1568 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1569 ).toStrictEqual({
932fc8be
JB
1570 runTime: {
1571 aggregate: true,
1572 average: true,
1573 median: false
1574 },
1575 waitTime: {
1576 aggregate: false,
1577 average: false,
1578 median: false
1579 },
5df69fab
JB
1580 elu: {
1581 aggregate: false,
1582 average: false,
1583 median: false
1584 }
86bf340d 1585 })
10fcfaf4
JB
1586 // We need to clean up the resources after our test
1587 await pool.destroy()
1588 })
1589
b3432a63 1590 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
1591 const pool = new FixedThreadPool(
1592 max,
b2fd3f4a 1593 './tests/worker-files/thread/testWorker.mjs',
b3432a63
JB
1594 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1595 )
1596 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1597 const promises = new Set()
a20f0ba5
JB
1598 const maxMultiplier = 2
1599 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1600 promises.add(pool.execute())
b3432a63 1601 }
e211bc18 1602 await Promise.all(promises)
138d29a8 1603 for (const workerNode of pool.workerNodes) {
465b2940 1604 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1605 tasks: {
1606 executed: expect.any(Number),
1607 executing: 0,
1608 queued: 0,
df593701 1609 maxQueued: 0,
463226a4 1610 sequentiallyStolen: 0,
5ad42e34 1611 stolen: 0,
a4e07f72
JB
1612 failed: 0
1613 },
71514351 1614 runTime: expect.objectContaining({
a4e07f72 1615 history: expect.any(CircularArray)
71514351 1616 }),
a4e07f72 1617 waitTime: {
619f403b 1618 history: new CircularArray()
a4e07f72 1619 },
5df69fab
JB
1620 elu: {
1621 idle: {
619f403b 1622 history: new CircularArray()
5df69fab
JB
1623 },
1624 active: {
619f403b 1625 history: new CircularArray()
71514351 1626 }
5df69fab 1627 }
86bf340d 1628 })
465b2940
JB
1629 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1630 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1631 max * maxMultiplier
1632 )
71514351
JB
1633 if (workerNode.usage.runTime.aggregate == null) {
1634 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1635 } else {
1636 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1637 }
1638 if (workerNode.usage.runTime.average == null) {
1639 expect(workerNode.usage.runTime.average).toBeUndefined()
1640 } else {
1641 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1642 }
138d29a8 1643 }
516dcb0d
JB
1644 expect(
1645 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1646 pool.workerChoiceStrategyContext.workerChoiceStrategy
1647 ).nextWorkerNodeKey
1648 ).toBe(0)
1649 expect(
1650 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1651 pool.workerChoiceStrategyContext.workerChoiceStrategy
1652 ).previousWorkerNodeKey
1653 ).toBe(0)
97a2abc3 1654 expect(
95c83464 1655 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1656 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
1657 ).defaultWorkerWeight
1658 ).toBeGreaterThan(0)
1659 expect(
1660 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1661 pool.workerChoiceStrategyContext.workerChoiceStrategy
f3a91bac 1662 ).workerNodeVirtualTaskRunTime
08f3f44c 1663 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
1664 // We need to clean up the resources after our test
1665 await pool.destroy()
1666 })
1667
1668 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
1669 const pool = new DynamicThreadPool(
1670 min,
1671 max,
b2fd3f4a 1672 './tests/worker-files/thread/testWorker.mjs',
b3432a63
JB
1673 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1674 )
1675 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1676 const promises = new Set()
138d29a8 1677 const maxMultiplier = 2
5502c07c 1678 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1679 promises.add(pool.execute())
b3432a63 1680 }
e211bc18 1681 await Promise.all(promises)
138d29a8 1682 for (const workerNode of pool.workerNodes) {
465b2940 1683 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1684 tasks: {
1685 executed: expect.any(Number),
1686 executing: 0,
1687 queued: 0,
df593701 1688 maxQueued: 0,
463226a4 1689 sequentiallyStolen: 0,
5ad42e34 1690 stolen: 0,
a4e07f72
JB
1691 failed: 0
1692 },
b1aae695 1693 runTime: expect.objectContaining({
a4e07f72 1694 history: expect.any(CircularArray)
b1aae695 1695 }),
a4e07f72 1696 waitTime: {
619f403b 1697 history: new CircularArray()
a4e07f72 1698 },
5df69fab
JB
1699 elu: {
1700 idle: {
619f403b 1701 history: new CircularArray()
5df69fab
JB
1702 },
1703 active: {
619f403b 1704 history: new CircularArray()
71514351 1705 }
5df69fab 1706 }
86bf340d 1707 })
465b2940
JB
1708 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1709 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1710 max * maxMultiplier
1711 )
b1aae695
JB
1712 if (workerNode.usage.runTime.aggregate == null) {
1713 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1714 } else {
1715 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1716 }
1717 if (workerNode.usage.runTime.average == null) {
1718 expect(workerNode.usage.runTime.average).toBeUndefined()
1719 } else {
1720 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1721 }
138d29a8 1722 }
516dcb0d
JB
1723 expect(
1724 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1725 pool.workerChoiceStrategyContext.workerChoiceStrategy
1726 ).nextWorkerNodeKey
1727 ).toBe(0)
1728 expect(
1729 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1730 pool.workerChoiceStrategyContext.workerChoiceStrategy
1731 ).previousWorkerNodeKey
1732 ).toBe(0)
2b4fddb8
JB
1733 expect(
1734 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1735 pool.workerChoiceStrategyContext.workerChoiceStrategy
1736 ).defaultWorkerWeight
1737 ).toBeGreaterThan(0)
1738 expect(
1739 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1740 pool.workerChoiceStrategyContext.workerChoiceStrategy
f3a91bac 1741 ).workerNodeVirtualTaskRunTime
2b4fddb8 1742 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
1743 // We need to clean up the resources after our test
1744 await pool.destroy()
1745 })
1746
9e775f96 1747 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
1748 const pool = new DynamicThreadPool(
1749 min,
1750 max,
b2fd3f4a 1751 './tests/worker-files/thread/testWorker.mjs',
010d7020
JB
1752 {
1753 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1754 workerChoiceStrategyOptions: {
932fc8be 1755 runTime: { median: true }
010d7020
JB
1756 }
1757 }
1758 )
1759 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 1760 const promises = new Set()
010d7020
JB
1761 const maxMultiplier = 2
1762 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 1763 promises.add(pool.execute())
010d7020 1764 }
e211bc18 1765 await Promise.all(promises)
010d7020 1766 for (const workerNode of pool.workerNodes) {
465b2940 1767 expect(workerNode.usage).toStrictEqual({
a4e07f72
JB
1768 tasks: {
1769 executed: expect.any(Number),
1770 executing: 0,
1771 queued: 0,
df593701 1772 maxQueued: 0,
463226a4 1773 sequentiallyStolen: 0,
5ad42e34 1774 stolen: 0,
a4e07f72
JB
1775 failed: 0
1776 },
b1aae695 1777 runTime: expect.objectContaining({
a4e07f72 1778 history: expect.any(CircularArray)
b1aae695 1779 }),
a4e07f72 1780 waitTime: {
619f403b 1781 history: new CircularArray()
a4e07f72 1782 },
5df69fab
JB
1783 elu: {
1784 idle: {
619f403b 1785 history: new CircularArray()
5df69fab
JB
1786 },
1787 active: {
619f403b 1788 history: new CircularArray()
71514351 1789 }
5df69fab 1790 }
86bf340d 1791 })
465b2940
JB
1792 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1793 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
a4e07f72
JB
1794 max * maxMultiplier
1795 )
b1aae695
JB
1796 if (workerNode.usage.runTime.aggregate == null) {
1797 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1798 } else {
1799 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1800 }
1801 if (workerNode.usage.runTime.median == null) {
1802 expect(workerNode.usage.runTime.median).toBeUndefined()
1803 } else {
1804 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1805 }
010d7020 1806 }
516dcb0d
JB
1807 expect(
1808 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1809 pool.workerChoiceStrategyContext.workerChoiceStrategy
1810 ).nextWorkerNodeKey
1811 ).toBe(0)
1812 expect(
1813 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1814 pool.workerChoiceStrategyContext.workerChoiceStrategy
1815 ).previousWorkerNodeKey
1816 ).toBe(0)
08f3f44c
JB
1817 expect(
1818 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1819 pool.workerChoiceStrategyContext.workerChoiceStrategy
1820 ).defaultWorkerWeight
1821 ).toBeGreaterThan(0)
1822 expect(
1823 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1824 pool.workerChoiceStrategyContext.workerChoiceStrategy
f3a91bac 1825 ).workerNodeVirtualTaskRunTime
08f3f44c 1826 ).toBeGreaterThanOrEqual(0)
010d7020
JB
1827 // We need to clean up the resources after our test
1828 await pool.destroy()
1829 })
1830
a6f7f1b4 1831 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 1832 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 1833 let pool = new FixedThreadPool(
caeb9817 1834 max,
b2fd3f4a 1835 './tests/worker-files/thread/testWorker.mjs'
caeb9817 1836 )
38f6e859 1837 expect(
95c83464 1838 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1839 workerChoiceStrategy
9b106837 1840 ).nextWorkerNodeKey
b529c323 1841 ).toBeDefined()
086fd843
JB
1842 expect(
1843 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1844 workerChoiceStrategy
1845 ).previousWorkerNodeKey
1846 ).toBeDefined()
38f6e859 1847 expect(
95c83464 1848 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1849 workerChoiceStrategy
b529c323
JB
1850 ).defaultWorkerWeight
1851 ).toBeDefined()
caeb9817 1852 expect(
95c83464 1853 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1854 workerChoiceStrategy
f3a91bac 1855 ).workerNodeVirtualTaskRunTime
b529c323 1856 ).toBeDefined()
594bfb84 1857 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1858 expect(
95c83464 1859 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1860 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 1861 ).nextWorkerNodeKey
a6f7f1b4 1862 ).toBe(0)
086fd843
JB
1863 expect(
1864 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1865 pool.workerChoiceStrategyContext.workerChoiceStrategy
1866 ).previousWorkerNodeKey
1867 ).toBe(0)
a6f7f1b4 1868 expect(
95c83464 1869 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1870 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1871 ).defaultWorkerWeight
a6f7f1b4 1872 ).toBeGreaterThan(0)
08f3f44c
JB
1873 expect(
1874 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 1875 pool.workerChoiceStrategyContext.workerChoiceStrategy
f3a91bac 1876 ).workerNodeVirtualTaskRunTime
08f3f44c 1877 ).toBe(0)
f0829c53
JB
1878 await pool.destroy()
1879 pool = new DynamicThreadPool(
1880 min,
1881 max,
b2fd3f4a 1882 './tests/worker-files/thread/testWorker.mjs'
f0829c53 1883 )
38f6e859 1884 expect(
95c83464 1885 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1886 workerChoiceStrategy
9b106837 1887 ).nextWorkerNodeKey
b529c323 1888 ).toBeDefined()
086fd843
JB
1889 expect(
1890 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1891 workerChoiceStrategy
1892 ).previousWorkerNodeKey
1893 ).toBeDefined()
38f6e859 1894 expect(
95c83464 1895 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1896 workerChoiceStrategy
b529c323
JB
1897 ).defaultWorkerWeight
1898 ).toBeDefined()
f0829c53 1899 expect(
95c83464 1900 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 1901 workerChoiceStrategy
f3a91bac 1902 ).workerNodeVirtualTaskRunTime
b529c323 1903 ).toBeDefined()
594bfb84 1904 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 1905 expect(
95c83464 1906 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1907 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 1908 ).nextWorkerNodeKey
a6f7f1b4 1909 ).toBe(0)
086fd843
JB
1910 expect(
1911 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1912 pool.workerChoiceStrategyContext.workerChoiceStrategy
1913 ).previousWorkerNodeKey
1914 ).toBe(0)
a6f7f1b4 1915 expect(
95c83464 1916 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 1917 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 1918 ).defaultWorkerWeight
a6f7f1b4 1919 ).toBeGreaterThan(0)
08f3f44c
JB
1920 expect(
1921 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 1922 pool.workerChoiceStrategyContext.workerChoiceStrategy
f3a91bac 1923 ).workerNodeVirtualTaskRunTime
08f3f44c 1924 ).toBe(0)
caeb9817
JB
1925 // We need to clean up the resources after our test
1926 await pool.destroy()
1927 })
1928
6c6afb84
JB
1929 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1930 const workerChoiceStrategy =
1931 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1932 let pool = new FixedThreadPool(
1933 max,
b2fd3f4a 1934 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1935 { workerChoiceStrategy }
1936 )
1937 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1938 dynamicWorkerUsage: false,
1939 dynamicWorkerReady: true
6c6afb84
JB
1940 })
1941 await pool.destroy()
1942 pool = new DynamicThreadPool(
1943 min,
1944 max,
b2fd3f4a 1945 './tests/worker-files/thread/testWorker.mjs',
6c6afb84
JB
1946 { workerChoiceStrategy }
1947 )
1948 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
b1aae695
JB
1949 dynamicWorkerUsage: false,
1950 dynamicWorkerReady: true
6c6afb84
JB
1951 })
1952 // We need to clean up the resources after our test
1953 await pool.destroy()
1954 })
1955
1956 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
e52fb978
JB
1957 const workerChoiceStrategy =
1958 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1959 let pool = new FixedThreadPool(
1960 max,
b2fd3f4a 1961 './tests/worker-files/thread/testWorker.mjs',
e52fb978
JB
1962 { workerChoiceStrategy }
1963 )
87de9ff5
JB
1964 expect(
1965 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1966 ).toStrictEqual({
932fc8be 1967 runTime: {
619f403b
JB
1968 aggregate: true,
1969 average: true,
932fc8be
JB
1970 median: false
1971 },
1972 waitTime: {
1973 aggregate: false,
1974 average: false,
1975 median: false
1976 },
5df69fab
JB
1977 elu: {
1978 aggregate: false,
1979 average: false,
1980 median: false
1981 }
e52fb978
JB
1982 })
1983 await pool.destroy()
1984 pool = new DynamicThreadPool(
1985 min,
1986 max,
b2fd3f4a 1987 './tests/worker-files/thread/testWorker.mjs',
e52fb978
JB
1988 { workerChoiceStrategy }
1989 )
87de9ff5
JB
1990 expect(
1991 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1992 ).toStrictEqual({
932fc8be 1993 runTime: {
619f403b
JB
1994 aggregate: true,
1995 average: true,
932fc8be
JB
1996 median: false
1997 },
1998 waitTime: {
1999 aggregate: false,
2000 average: false,
2001 median: false
2002 },
5df69fab
JB
2003 elu: {
2004 aggregate: false,
2005 average: false,
2006 median: false
2007 }
e52fb978
JB
2008 })
2009 // We need to clean up the resources after our test
2010 await pool.destroy()
2011 })
2012
e62e7646
JB
2013 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
2014 const pool = new FixedThreadPool(
2015 max,
b2fd3f4a 2016 './tests/worker-files/thread/testWorker.mjs',
e62e7646
JB
2017 {
2018 workerChoiceStrategy:
2019 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2020 }
2021 )
2022 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2023 const promises = new Set()
2024 const maxMultiplier = 2
2025 for (let i = 0; i < max * maxMultiplier; i++) {
2026 promises.add(pool.execute())
2027 }
2028 await Promise.all(promises)
2029 for (const workerNode of pool.workerNodes) {
465b2940 2030 expect(workerNode.usage).toStrictEqual({
a4e07f72 2031 tasks: {
619f403b 2032 executed: expect.any(Number),
a4e07f72
JB
2033 executing: 0,
2034 queued: 0,
df593701 2035 maxQueued: 0,
463226a4 2036 sequentiallyStolen: 0,
5ad42e34 2037 stolen: 0,
a4e07f72
JB
2038 failed: 0
2039 },
619f403b
JB
2040 runTime: expect.objectContaining({
2041 history: expect.any(CircularArray)
2042 }),
a4e07f72 2043 waitTime: {
4ba4c7f9 2044 history: new CircularArray()
a4e07f72 2045 },
5df69fab
JB
2046 elu: {
2047 idle: {
4ba4c7f9 2048 history: new CircularArray()
5df69fab
JB
2049 },
2050 active: {
4ba4c7f9 2051 history: new CircularArray()
71514351 2052 }
5df69fab 2053 }
e62e7646 2054 })
619f403b
JB
2055 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2056 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2057 max * maxMultiplier
2058 )
e62e7646
JB
2059 }
2060 expect(
2061 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2062 pool.workerChoiceStrategyContext.workerChoiceStrategy
2063 ).defaultWorkerWeight
2064 ).toBeGreaterThan(0)
2065 expect(
2066 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2067 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 2068 ).roundId
e62e7646 2069 ).toBe(0)
619f403b
JB
2070 expect(
2071 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2072 pool.workerChoiceStrategyContext.workerChoiceStrategy
2073 ).workerNodeId
2074 ).toBe(0)
e62e7646
JB
2075 expect(
2076 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2077 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 2078 ).nextWorkerNodeKey
e62e7646 2079 ).toBe(0)
086fd843
JB
2080 expect(
2081 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2082 pool.workerChoiceStrategyContext.workerChoiceStrategy
2083 ).previousWorkerNodeKey
2084 ).toEqual(expect.any(Number))
e62e7646
JB
2085 expect(
2086 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2087 pool.workerChoiceStrategyContext.workerChoiceStrategy
2088 ).roundWeights
2089 ).toStrictEqual([
2090 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2091 pool.workerChoiceStrategyContext.workerChoiceStrategy
2092 ).defaultWorkerWeight
2093 ])
2094 // We need to clean up the resources after our test
2095 await pool.destroy()
2096 })
2097
2098 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2099 const pool = new DynamicThreadPool(
2100 min,
2101 max,
b2fd3f4a 2102 './tests/worker-files/thread/testWorker.mjs',
e62e7646
JB
2103 {
2104 workerChoiceStrategy:
2105 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2106 }
2107 )
2108 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2109 const promises = new Set()
2110 const maxMultiplier = 2
2111 for (let i = 0; i < max * maxMultiplier; i++) {
2112 promises.add(pool.execute())
2113 }
2114 await Promise.all(promises)
2115 for (const workerNode of pool.workerNodes) {
465b2940 2116 expect(workerNode.usage).toStrictEqual({
a4e07f72 2117 tasks: {
b1aae695 2118 executed: expect.any(Number),
a4e07f72
JB
2119 executing: 0,
2120 queued: 0,
df593701 2121 maxQueued: 0,
463226a4 2122 sequentiallyStolen: 0,
5ad42e34 2123 stolen: 0,
a4e07f72
JB
2124 failed: 0
2125 },
619f403b
JB
2126 runTime: expect.objectContaining({
2127 history: expect.any(CircularArray)
2128 }),
a4e07f72 2129 waitTime: {
4ba4c7f9 2130 history: new CircularArray()
a4e07f72 2131 },
5df69fab
JB
2132 elu: {
2133 idle: {
4ba4c7f9 2134 history: new CircularArray()
5df69fab
JB
2135 },
2136 active: {
4ba4c7f9 2137 history: new CircularArray()
71514351 2138 }
5df69fab 2139 }
e62e7646 2140 })
e43b8c2d
JB
2141 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2142 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2143 max * maxMultiplier
2144 )
e62e7646
JB
2145 }
2146 expect(
2147 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2148 pool.workerChoiceStrategyContext.workerChoiceStrategy
2149 ).defaultWorkerWeight
2150 ).toBeGreaterThan(0)
2151 expect(
2152 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2153 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 2154 ).roundId
e62e7646 2155 ).toBe(0)
619f403b
JB
2156 expect(
2157 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2158 pool.workerChoiceStrategyContext.workerChoiceStrategy
2159 ).workerNodeId
2160 ).toBe(0)
e62e7646
JB
2161 expect(
2162 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2163 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 2164 ).nextWorkerNodeKey
d2c73f82 2165 ).toBe(0)
086fd843
JB
2166 expect(
2167 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2168 pool.workerChoiceStrategyContext.workerChoiceStrategy
2169 ).previousWorkerNodeKey
2170 ).toEqual(expect.any(Number))
e62e7646
JB
2171 expect(
2172 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2173 pool.workerChoiceStrategyContext.workerChoiceStrategy
2174 ).roundWeights
2175 ).toStrictEqual([
2176 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2177 pool.workerChoiceStrategyContext.workerChoiceStrategy
2178 ).defaultWorkerWeight
2179 ])
2180 // We need to clean up the resources after our test
2181 await pool.destroy()
2182 })
2183
8c3ec188
JB
2184 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2185 const workerChoiceStrategy =
2186 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2187 let pool = new FixedThreadPool(
2188 max,
b2fd3f4a 2189 './tests/worker-files/thread/testWorker.mjs'
8c3ec188
JB
2190 )
2191 expect(
2192 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2193 workerChoiceStrategy
d33be430 2194 ).roundId
8c3ec188 2195 ).toBeDefined()
086fd843
JB
2196 expect(
2197 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2198 workerChoiceStrategy
2199 ).workerNodeId
2200 ).toBeDefined()
8c3ec188
JB
2201 expect(
2202 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2203 workerChoiceStrategy
9b106837 2204 ).nextWorkerNodeKey
8c3ec188 2205 ).toBeDefined()
086fd843
JB
2206 expect(
2207 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2208 workerChoiceStrategy
2209 ).previousWorkerNodeKey
2210 ).toBeDefined()
8c3ec188
JB
2211 expect(
2212 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2213 workerChoiceStrategy
2214 ).defaultWorkerWeight
2215 ).toBeDefined()
2216 expect(
2217 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2218 workerChoiceStrategy
2219 ).roundWeights
2220 ).toBeDefined()
2221 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2222 expect(
2223 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 2224 pool.workerChoiceStrategyContext.workerChoiceStrategy
d33be430 2225 ).roundId
8c3ec188 2226 ).toBe(0)
086fd843
JB
2227 expect(
2228 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2229 pool.workerChoiceStrategyContext.workerChoiceStrategy
2230 ).workerNodeId
2231 ).toBe(0)
8c3ec188
JB
2232 expect(
2233 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2234 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 2235 ).nextWorkerNodeKey
8c3ec188 2236 ).toBe(0)
086fd843
JB
2237 expect(
2238 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2239 pool.workerChoiceStrategyContext.workerChoiceStrategy
2240 ).previousWorkerNodeKey
2241 ).toBe(0)
8c3ec188
JB
2242 expect(
2243 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2244 pool.workerChoiceStrategyContext.workerChoiceStrategy
2245 ).defaultWorkerWeight
2246 ).toBeGreaterThan(0)
2247 expect(
2248 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 2249 pool.workerChoiceStrategyContext.workerChoiceStrategy
8c3ec188
JB
2250 ).roundWeights
2251 ).toStrictEqual([
2252 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2253 pool.workerChoiceStrategyContext.workerChoiceStrategy
2254 ).defaultWorkerWeight
2255 ])
2256 await pool.destroy()
2257 pool = new DynamicThreadPool(
2258 min,
2259 max,
b2fd3f4a 2260 './tests/worker-files/thread/testWorker.mjs'
8c3ec188
JB
2261 )
2262 expect(
2263 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2264 workerChoiceStrategy
d33be430 2265 ).roundId
8c3ec188 2266 ).toBeDefined()
086fd843
JB
2267 expect(
2268 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2269 workerChoiceStrategy
2270 ).workerNodeId
2271 ).toBeDefined()
8c3ec188
JB
2272 expect(
2273 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2274 workerChoiceStrategy
9b106837 2275 ).nextWorkerNodeKey
8c3ec188 2276 ).toBeDefined()
086fd843
JB
2277 expect(
2278 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2279 workerChoiceStrategy
2280 ).previousWorkerNodeKey
2281 ).toBeDefined()
8c3ec188
JB
2282 expect(
2283 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2284 workerChoiceStrategy
2285 ).defaultWorkerWeight
2286 ).toBeDefined()
2287 expect(
2288 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2289 workerChoiceStrategy
2290 ).roundWeights
2291 ).toBeDefined()
2292 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
086fd843
JB
2293 expect(
2294 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2295 pool.workerChoiceStrategyContext.workerChoiceStrategy
2296 ).roundId
2297 ).toBe(0)
2298 expect(
2299 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2300 pool.workerChoiceStrategyContext.workerChoiceStrategy
2301 ).workerNodeId
2302 ).toBe(0)
8c3ec188
JB
2303 expect(
2304 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2305 pool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 2306 ).nextWorkerNodeKey
8c3ec188 2307 ).toBe(0)
086fd843
JB
2308 expect(
2309 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2310 pool.workerChoiceStrategyContext.workerChoiceStrategy
2311 ).previousWorkerNodeKey
2312 ).toBe(0)
8c3ec188
JB
2313 expect(
2314 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2315 pool.workerChoiceStrategyContext.workerChoiceStrategy
2316 ).defaultWorkerWeight
2317 ).toBeGreaterThan(0)
2318 expect(
2319 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
086fd843 2320 pool.workerChoiceStrategyContext.workerChoiceStrategy
8c3ec188
JB
2321 ).roundWeights
2322 ).toStrictEqual([
2323 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2324 pool.workerChoiceStrategyContext.workerChoiceStrategy
2325 ).defaultWorkerWeight
2326 ])
2327 // We need to clean up the resources after our test
2328 await pool.destroy()
2329 })
2330
89b09b26 2331 it('Verify unknown strategy throw error', () => {
a35560ba
S
2332 expect(
2333 () =>
2334 new DynamicThreadPool(
2335 min,
2336 max,
b2fd3f4a 2337 './tests/worker-files/thread/testWorker.mjs',
1927ee67 2338 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 2339 )
948faff7 2340 ).toThrow("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
2341 })
2342})