9cd4e72c57b1098256b9c2f356fcfc0ded6da730
[poolifier.git] / tests / pools / thread / dynamic.test.js
1 const { expect } = require('expect')
2 const { DynamicThreadPool } = require('../../../lib/index')
3 const { WorkerFunctions } = require('../../test-types')
4 const TestUtils = require('../../test-utils')
5
6 describe('Dynamic thread pool test suite', () => {
7 const min = 1
8 const max = 3
9 const pool = new DynamicThreadPool(
10 min,
11 max,
12 './tests/worker-files/thread/testWorker.js',
13 {
14 errorHandler: e => console.error(e)
15 }
16 )
17
18 it('Verify that the function is executed in a worker thread', async () => {
19 let result = await pool.execute({
20 function: WorkerFunctions.fibonacci
21 })
22 expect(result).toBe(false)
23 result = await pool.execute({
24 function: WorkerFunctions.factorial
25 })
26 expect(result).toBe(false)
27 })
28
29 it('Verify that new workers are created when required, max size is not exceeded and that after a while new workers will die', async () => {
30 const promises = []
31 let poolBusy = 0
32 pool.emitter.on('busy', () => poolBusy++)
33 for (let i = 0; i < max * 2; i++) {
34 promises.push(pool.execute())
35 }
36 expect(pool.workers.length).toBeLessThanOrEqual(max)
37 expect(pool.workers.length).toBeGreaterThan(min)
38 // The `busy` event is triggered when the number of submitted tasks at once reach the max number of workers in the dynamic pool.
39 // So in total numberOfWorkers + 1 times for a loop submitting up to numberOfWorkers * 2 tasks to the dynamic pool.
40 expect(poolBusy).toBe(max + 1)
41 const numberOfExitEvents = await TestUtils.waitExits(pool, max - min)
42 expect(numberOfExitEvents).toBe(max - min)
43 })
44
45 it('Verify scale thread up and down is working', async () => {
46 expect(pool.workers.length).toBe(min)
47 for (let i = 0; i < max * 10; i++) {
48 pool.execute()
49 }
50 expect(pool.workers.length).toBe(max)
51 await TestUtils.waitExits(pool, max - min)
52 expect(pool.workers.length).toBe(min)
53 for (let i = 0; i < max * 10; i++) {
54 pool.execute()
55 }
56 expect(pool.workers.length).toBe(max)
57 await TestUtils.waitExits(pool, max - min)
58 expect(pool.workers.length).toBe(min)
59 })
60
61 it('Shutdown test', async () => {
62 const exitPromise = TestUtils.waitExits(pool, min)
63 await pool.destroy()
64 const numberOfExitEvents = await exitPromise
65 expect(numberOfExitEvents).toBe(min)
66 })
67
68 it('Validation of inputs test', () => {
69 expect(() => new DynamicThreadPool(min)).toThrowError(
70 new Error('Please specify a file with a worker implementation')
71 )
72 })
73
74 it('Should work even without opts in input', async () => {
75 const pool1 = new DynamicThreadPool(
76 min,
77 max,
78 './tests/worker-files/thread/testWorker.js'
79 )
80 const res = await pool1.execute()
81 expect(res).toBe(false)
82 // We need to clean up the resources after our test
83 await pool1.destroy()
84 })
85
86 it('Verify scale thread up and down is working when long running task is used:hard', async () => {
87 const longRunningPool = new DynamicThreadPool(
88 min,
89 max,
90 './tests/worker-files/thread/longRunningWorkerHardBehavior.js',
91 {
92 errorHandler: e => console.error(e),
93 onlineHandler: () => console.log('long running worker is online'),
94 exitHandler: () => console.log('long running worker exited')
95 }
96 )
97 expect(longRunningPool.workers.length).toBe(min)
98 for (let i = 0; i < max * 10; i++) {
99 longRunningPool.execute()
100 }
101 expect(longRunningPool.workers.length).toBe(max)
102 await TestUtils.waitExits(longRunningPool, max - min)
103 expect(longRunningPool.workers.length).toBe(min)
104 // We need to clean up the resources after our test
105 await longRunningPool.destroy()
106 })
107
108 it('Verify scale thread up and down is working when long running task is used:soft', async () => {
109 const longRunningPool = new DynamicThreadPool(
110 min,
111 max,
112 './tests/worker-files/thread/longRunningWorkerSoftBehavior.js',
113 {
114 errorHandler: e => console.error(e),
115 onlineHandler: () => console.log('long running worker is online'),
116 exitHandler: () => console.log('long running worker exited')
117 }
118 )
119 expect(longRunningPool.workers.length).toBe(min)
120 for (let i = 0; i < max * 10; i++) {
121 longRunningPool.execute()
122 }
123 expect(longRunningPool.workers.length).toBe(max)
124 await TestUtils.sleep(1500)
125 // Here we expect the workers to be at the max size since that the task is still running
126 expect(longRunningPool.workers.length).toBe(max)
127 // We need to clean up the resources after our test
128 await longRunningPool.destroy()
129 })
130
131 it('Verify that a pool with zero worker can be instantiated', async () => {
132 const pool = new DynamicThreadPool(
133 0,
134 max,
135 './tests/worker-files/thread/testWorker.js'
136 )
137 expect(pool).toBeInstanceOf(DynamicThreadPool)
138 // We need to clean up the resources after our test
139 await pool.destroy()
140 })
141 })