49e87a92dcd1649878c7d5659c4aac1ed5928db7
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
1 const { expect } = require('expect')
2 const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
5 FixedThreadPool
6 } = require('../../../lib/index')
7
8 describe('Selection strategies test suite', () => {
9 const min = 0
10 const max = 3
11
12 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
13 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
14 expect(WorkerChoiceStrategies.LESS_RECENTLY_USED).toBe('LESS_RECENTLY_USED')
15 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
16 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
17 'WEIGHTED_ROUND_ROBIN'
18 )
19 })
20
21 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
22 const pool = new DynamicThreadPool(
23 min,
24 max,
25 './tests/worker-files/thread/testWorker.js'
26 )
27 expect(pool.opts.workerChoiceStrategy).toBe(
28 WorkerChoiceStrategies.ROUND_ROBIN
29 )
30 // We need to clean up the resources after our test
31 await pool.destroy()
32 })
33
34 it('Verify ROUND_ROBIN strategy can be set after pool creation', async () => {
35 const pool = new DynamicThreadPool(
36 min,
37 max,
38 './tests/worker-files/thread/testWorker.js'
39 )
40 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
41 expect(pool.opts.workerChoiceStrategy).toBe(
42 WorkerChoiceStrategies.ROUND_ROBIN
43 )
44 // We need to clean up the resources after our test
45 await pool.destroy()
46 })
47
48 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
49 let pool = new FixedThreadPool(
50 max,
51 './tests/worker-files/thread/testWorker.js'
52 )
53 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
54 expect(
55 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
56 .requiredStatistics.runTime
57 ).toBe(false)
58 await pool.destroy()
59 pool = new DynamicThreadPool(
60 min,
61 max,
62 './tests/worker-files/thread/testWorker.js'
63 )
64 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
65 expect(
66 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
67 .requiredStatistics.runTime
68 ).toBe(false)
69 // We need to clean up the resources after our test
70 await pool.destroy()
71 })
72
73 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
74 const pool = new FixedThreadPool(
75 max,
76 './tests/worker-files/thread/testWorker.js',
77 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
78 )
79 expect(pool.opts.workerChoiceStrategy).toBe(
80 WorkerChoiceStrategies.ROUND_ROBIN
81 )
82 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
83 const promises = []
84 for (let i = 0; i < max * 2; i++) {
85 promises.push(pool.execute())
86 }
87 await Promise.all(promises)
88 // We need to clean up the resources after our test
89 await pool.destroy()
90 })
91
92 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
93 const pool = new DynamicThreadPool(
94 min,
95 max,
96 './tests/worker-files/thread/testWorker.js',
97 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
98 )
99 expect(pool.opts.workerChoiceStrategy).toBe(
100 WorkerChoiceStrategies.ROUND_ROBIN
101 )
102 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
103 const promises = []
104 for (let i = 0; i < max * 2; i++) {
105 promises.push(pool.execute())
106 }
107 await Promise.all(promises)
108 // We need to clean up the resources after our test
109 await pool.destroy()
110 })
111
112 it('Verify LESS_RECENTLY_USED strategy is taken at pool creation', async () => {
113 const pool = new FixedThreadPool(
114 max,
115 './tests/worker-files/thread/testWorker.js',
116 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
117 )
118 expect(pool.opts.workerChoiceStrategy).toBe(
119 WorkerChoiceStrategies.LESS_RECENTLY_USED
120 )
121 // We need to clean up the resources after our test
122 await pool.destroy()
123 })
124
125 it('Verify LESS_RECENTLY_USED strategy can be set after pool creation', async () => {
126 const pool = new FixedThreadPool(
127 max,
128 './tests/worker-files/thread/testWorker.js'
129 )
130 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
131 expect(pool.opts.workerChoiceStrategy).toBe(
132 WorkerChoiceStrategies.LESS_RECENTLY_USED
133 )
134 // We need to clean up the resources after our test
135 await pool.destroy()
136 })
137
138 it('Verify LESS_RECENTLY_USED strategy default tasks usage statistics requirements', async () => {
139 let pool = new FixedThreadPool(
140 max,
141 './tests/worker-files/thread/testWorker.js'
142 )
143 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
144 expect(
145 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
146 .requiredStatistics.runTime
147 ).toBe(false)
148 await pool.destroy()
149 pool = new DynamicThreadPool(
150 min,
151 max,
152 './tests/worker-files/thread/testWorker.js'
153 )
154 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_RECENTLY_USED)
155 expect(
156 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
157 .requiredStatistics.runTime
158 ).toBe(false)
159 // We need to clean up the resources after our test
160 await pool.destroy()
161 })
162
163 it('Verify LESS_RECENTLY_USED strategy can be run in a fixed pool', async () => {
164 const pool = new FixedThreadPool(
165 max,
166 './tests/worker-files/thread/testWorker.js',
167 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
168 )
169 // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose`
170 const promises = []
171 for (let i = 0; i < max * 2; i++) {
172 promises.push(pool.execute())
173 }
174 await Promise.all(promises)
175 // We need to clean up the resources after our test
176 await pool.destroy()
177 })
178
179 it('Verify LESS_RECENTLY_USED strategy can be run in a dynamic pool', async () => {
180 const pool = new DynamicThreadPool(
181 min,
182 max,
183 './tests/worker-files/thread/testWorker.js',
184 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_RECENTLY_USED }
185 )
186 // TODO: Create a better test to cover `LessRecentlyUsedWorkerChoiceStrategy#choose`
187 const promises = []
188 for (let i = 0; i < max * 2; i++) {
189 promises.push(pool.execute())
190 }
191 await Promise.all(promises)
192 // We need to clean up the resources after our test
193 await pool.destroy()
194 })
195
196 it('Verify FAIR_SHARE strategy is taken at pool creation', async () => {
197 const pool = new FixedThreadPool(
198 max,
199 './tests/worker-files/thread/testWorker.js',
200 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
201 )
202 expect(pool.opts.workerChoiceStrategy).toBe(
203 WorkerChoiceStrategies.FAIR_SHARE
204 )
205 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
206 expect(
207 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
208 worker
209 ).start
210 ).toBe(0)
211 expect(
212 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
213 worker
214 ).end
215 ).toBe(0)
216 }
217 // We need to clean up the resources after our test
218 await pool.destroy()
219 })
220
221 it('Verify FAIR_SHARE strategy can be set after pool creation', async () => {
222 const pool = new FixedThreadPool(
223 max,
224 './tests/worker-files/thread/testWorker.js'
225 )
226 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
227 expect(pool.opts.workerChoiceStrategy).toBe(
228 WorkerChoiceStrategies.FAIR_SHARE
229 )
230 // We need to clean up the resources after our test
231 await pool.destroy()
232 })
233
234 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
235 let pool = new FixedThreadPool(
236 max,
237 './tests/worker-files/thread/testWorker.js'
238 )
239 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
240 expect(
241 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
242 .requiredStatistics.runTime
243 ).toBe(true)
244 await pool.destroy()
245 pool = new DynamicThreadPool(
246 min,
247 max,
248 './tests/worker-files/thread/testWorker.js'
249 )
250 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
251 expect(
252 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
253 .requiredStatistics.runTime
254 ).toBe(true)
255 // We need to clean up the resources after our test
256 await pool.destroy()
257 })
258
259 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
260 const pool = new FixedThreadPool(
261 max,
262 './tests/worker-files/thread/testWorker.js',
263 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
264 )
265 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
266 const promises = []
267 for (let i = 0; i < max * 2; i++) {
268 promises.push(pool.execute())
269 }
270 await Promise.all(promises)
271 // We need to clean up the resources after our test
272 await pool.destroy()
273 })
274
275 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
276 const pool = new DynamicThreadPool(
277 min,
278 max,
279 './tests/worker-files/thread/testWorker.js',
280 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
281 )
282 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
283 const promises = []
284 for (let i = 0; i < max * 2; i++) {
285 promises.push(pool.execute())
286 }
287 await Promise.all(promises)
288 // We need to clean up the resources after our test
289 await pool.destroy()
290 })
291
292 it('Verify FAIR_SHARE strategy statistics are resets after setting it', async () => {
293 let pool = new FixedThreadPool(
294 max,
295 './tests/worker-files/thread/testWorker.js'
296 )
297 expect(
298 pool.workerChoiceStrategyContext.workerChoiceStrategy
299 .workerLastVirtualTaskTimestamp
300 ).toBeUndefined()
301 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
302 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
303 expect(
304 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
305 worker
306 ).start
307 ).toBe(0)
308 expect(
309 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
310 worker
311 ).end
312 ).toBe(0)
313 }
314 await pool.destroy()
315 pool = new DynamicThreadPool(
316 min,
317 max,
318 './tests/worker-files/thread/testWorker.js'
319 )
320 expect(
321 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
322 .workerLastVirtualTaskTimestamp
323 ).toBeUndefined()
324 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
325 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
326 expect(
327 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
328 worker
329 ).start
330 ).toBe(0)
331 expect(
332 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
333 worker
334 ).end
335 ).toBe(0)
336 }
337 // We need to clean up the resources after our test
338 await pool.destroy()
339 })
340
341 it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => {
342 const pool = new FixedThreadPool(
343 max,
344 './tests/worker-files/thread/testWorker.js',
345 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
346 )
347 expect(pool.opts.workerChoiceStrategy).toBe(
348 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
349 )
350 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.keys()) {
351 expect(
352 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.get(
353 worker
354 ).runTime
355 ).toBe(0)
356 }
357 // We need to clean up the resources after our test
358 await pool.destroy()
359 })
360
361 it('Verify WEIGHTED_ROUND_ROBIN strategy can be set after pool creation', async () => {
362 const pool = new FixedThreadPool(
363 max,
364 './tests/worker-files/thread/testWorker.js'
365 )
366 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
367 expect(pool.opts.workerChoiceStrategy).toBe(
368 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
369 )
370 // We need to clean up the resources after our test
371 await pool.destroy()
372 })
373
374 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
375 let pool = new FixedThreadPool(
376 max,
377 './tests/worker-files/thread/testWorker.js'
378 )
379 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
380 expect(
381 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
382 .requiredStatistics.runTime
383 ).toBe(true)
384 await pool.destroy()
385 pool = new DynamicThreadPool(
386 min,
387 max,
388 './tests/worker-files/thread/testWorker.js'
389 )
390 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
391 expect(
392 pool.workerChoiceStrategyContext.getWorkerChoiceStrategy()
393 .requiredStatistics.runTime
394 ).toBe(true)
395 // We need to clean up the resources after our test
396 await pool.destroy()
397 })
398
399 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
400 const pool = new FixedThreadPool(
401 max,
402 './tests/worker-files/thread/testWorker.js',
403 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
404 )
405 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
406 const promises = []
407 for (let i = 0; i < max * 2; i++) {
408 promises.push(pool.execute())
409 }
410 await Promise.all(promises)
411 // We need to clean up the resources after our test
412 await pool.destroy()
413 })
414
415 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
416 const pool = new DynamicThreadPool(
417 min,
418 max,
419 './tests/worker-files/thread/testWorker.js',
420 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
421 )
422 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
423 const promises = []
424 for (let i = 0; i < max * 2; i++) {
425 promises.push(pool.execute())
426 }
427 await Promise.all(promises)
428 // We need to clean up the resources after our test
429 await pool.destroy()
430 })
431
432 it('Verify WEIGHTED_ROUND_ROBIN strategy statistics are resets after setting it', async () => {
433 let pool = new FixedThreadPool(
434 max,
435 './tests/worker-files/thread/testWorker.js'
436 )
437 expect(
438 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime
439 ).toBeUndefined()
440 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
441 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.keys()) {
442 expect(
443 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.get(
444 worker
445 ).runTime
446 ).toBe(0)
447 }
448 await pool.destroy()
449 pool = new DynamicThreadPool(
450 min,
451 max,
452 './tests/worker-files/thread/testWorker.js'
453 )
454 expect(
455 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
456 .workersTaskRunTime
457 ).toBeUndefined()
458 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
459 for (const worker of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workersTaskRunTime.keys()) {
460 expect(
461 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workersTaskRunTime.get(
462 worker
463 ).runTime
464 ).toBe(0)
465 }
466 // We need to clean up the resources after our test
467 await pool.destroy()
468 })
469
470 it('Verify unknown strategies throw error', () => {
471 expect(
472 () =>
473 new DynamicThreadPool(
474 min,
475 max,
476 './tests/worker-files/thread/testWorker.js',
477 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
478 )
479 ).toThrowError(
480 new Error("Worker choice strategy 'UNKNOWN_STRATEGY' not found")
481 )
482 })
483 })