docs: update changelog entries
[poolifier.git] / tests / pools / cluster / fixed.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
cdace0e5 2const { FixedClusterPool, PoolEvents } = require('../../../lib')
2d2e32c2 3const { WorkerFunctions } = require('../../test-types')
85a3f8a7 4const TestUtils = require('../../test-utils')
325f50bc 5
a35560ba 6describe('Fixed cluster pool test suite', () => {
e1ffb94f
JB
7 const numberOfWorkers = 6
8 const pool = new FixedClusterPool(
9 numberOfWorkers,
10 './tests/worker-files/cluster/testWorker.js',
11 {
12 errorHandler: e => console.error(e)
13 }
14 )
594bfb84
JB
15 const queuePool = new FixedClusterPool(
16 numberOfWorkers,
17 './tests/worker-files/cluster/testWorker.js',
18 {
19 enableTasksQueue: true,
20 tasksQueueOptions: {
21 concurrency: 2
22 },
23 errorHandler: e => console.error(e)
24 }
25 )
e1ffb94f
JB
26 const emptyPool = new FixedClusterPool(
27 numberOfWorkers,
28 './tests/worker-files/cluster/emptyWorker.js',
29 { exitHandler: () => console.log('empty pool worker exited') }
30 )
31 const echoPool = new FixedClusterPool(
32 numberOfWorkers,
33 './tests/worker-files/cluster/echoWorker.js'
34 )
35 const errorPool = new FixedClusterPool(
36 numberOfWorkers,
37 './tests/worker-files/cluster/errorWorker.js',
38 {
39 errorHandler: e => console.error(e)
40 }
41 )
42 const asyncErrorPool = new FixedClusterPool(
43 numberOfWorkers,
44 './tests/worker-files/cluster/asyncErrorWorker.js',
45 {
46 errorHandler: e => console.error(e)
47 }
48 )
49 const asyncPool = new FixedClusterPool(
50 numberOfWorkers,
51 './tests/worker-files/cluster/asyncWorker.js'
52 )
53
8bc77620
APA
54 after('Destroy all pools', async () => {
55 // We need to clean up the resources after our test
56 await echoPool.destroy()
57 await asyncPool.destroy()
58 await errorPool.destroy()
59 await asyncErrorPool.destroy()
60 await emptyPool.destroy()
594bfb84 61 await queuePool.destroy()
8bc77620
APA
62 })
63
325f50bc 64 it('Verify that the function is executed in a worker cluster', async () => {
6db75ad9
JB
65 let result = await pool.execute({
66 function: WorkerFunctions.fibonacci
67 })
70a4f5ea 68 expect(result).toBe(121393)
6db75ad9
JB
69 result = await pool.execute({
70 function: WorkerFunctions.factorial
71 })
70a4f5ea 72 expect(result).toBe(9.33262154439441e157)
325f50bc
S
73 })
74
318d4156 75 it('Verify that is possible to invoke the execute() method without input', async () => {
325f50bc 76 const result = await pool.execute()
6db75ad9 77 expect(result).toBe(false)
325f50bc
S
78 })
79
aee46736 80 it("Verify that 'busy' event is emitted", async () => {
7c0ba920 81 let poolBusy = 0
aee46736 82 pool.emitter.on(PoolEvents.busy, () => ++poolBusy)
7c0ba920 83 for (let i = 0; i < numberOfWorkers * 2; i++) {
8cbb82eb 84 pool.execute()
7c0ba920 85 }
14916bf9
JB
86 // The `busy` event is triggered when the number of submitted tasks at once reach the number of fixed pool workers.
87 // So in total numberOfWorkers + 1 times for a loop submitting up to numberOfWorkers * 2 tasks to the fixed pool.
88 expect(poolBusy).toBe(numberOfWorkers + 1)
7c0ba920
JB
89 })
90
594bfb84
JB
91 it('Verify that tasks queuing is working', async () => {
92 const maxMultiplier = 10
d3d4b67d 93 const promises = new Set()
594bfb84 94 for (let i = 0; i < numberOfWorkers * maxMultiplier; i++) {
d3d4b67d 95 promises.add(queuePool.execute())
594bfb84 96 }
d3d4b67d 97 expect(promises.size).toBe(numberOfWorkers * maxMultiplier)
594bfb84
JB
98 for (const workerNode of queuePool.workerNodes) {
99 expect(workerNode.tasksUsage.running).toBeLessThanOrEqual(
100 queuePool.opts.tasksQueueOptions.concurrency
101 )
102 expect(workerNode.tasksUsage.run).toBe(0)
4d8bf9e4 103 expect(workerNode.tasksQueue.size).toBeGreaterThan(0)
594bfb84 104 }
d3d4b67d
JB
105 expect(queuePool.numberOfRunningTasks).toBe(numberOfWorkers)
106 expect(queuePool.numberOfQueuedTasks).toBe(
107 numberOfWorkers * maxMultiplier - numberOfWorkers
108 )
594bfb84
JB
109 await Promise.all(promises)
110 for (const workerNode of queuePool.workerNodes) {
111 expect(workerNode.tasksUsage.running).toBe(0)
112 expect(workerNode.tasksUsage.run).toBeGreaterThan(0)
4d8bf9e4 113 expect(workerNode.tasksQueue.size).toBe(0)
594bfb84 114 }
d3d4b67d 115 promises.clear()
594bfb84
JB
116 })
117
325f50bc
S
118 it('Verify that is possible to have a worker that return undefined', async () => {
119 const result = await emptyPool.execute()
6db75ad9 120 expect(result).toBeUndefined()
325f50bc
S
121 })
122
123 it('Verify that data are sent to the worker correctly', async () => {
124 const data = { f: 10 }
125 const result = await echoPool.execute(data)
e1ffb94f 126 expect(result).toStrictEqual(data)
325f50bc
S
127 })
128
129 it('Verify that error handling is working properly:sync', async () => {
130 const data = { f: 10 }
131 let inError
132 try {
133 await errorPool.execute(data)
134 } catch (e) {
135 inError = e
136 }
137 expect(inError).toBeDefined()
8620fb25 138 expect(typeof inError === 'string').toBe(true)
325f50bc
S
139 expect(inError).toBe('Error Message from ClusterWorker')
140 })
141
142 it('Verify that error handling is working properly:async', async () => {
143 const data = { f: 10 }
144 let inError
145 try {
146 await asyncErrorPool.execute(data)
147 } catch (e) {
148 inError = e
149 }
150 expect(inError).toBeDefined()
8620fb25 151 expect(typeof inError === 'string').toBe(true)
325f50bc
S
152 expect(inError).toBe('Error Message from ClusterWorker:async')
153 })
154
155 it('Verify that async function is working properly', async () => {
156 const data = { f: 10 }
15e5141f 157 const startTime = performance.now()
325f50bc 158 const result = await asyncPool.execute(data)
15e5141f 159 const usedTime = performance.now() - startTime
e1ffb94f 160 expect(result).toStrictEqual(data)
325f50bc
S
161 expect(usedTime).toBeGreaterThanOrEqual(2000)
162 })
163
164 it('Shutdown test', async () => {
85a3f8a7 165 const exitPromise = TestUtils.waitExits(pool, numberOfWorkers)
45dbbb14 166 await pool.destroy()
bdacc2d2
JB
167 const numberOfExitEvents = await exitPromise
168 expect(numberOfExitEvents).toBe(numberOfWorkers)
325f50bc
S
169 })
170
1a76932b
JB
171 it('Verify that cluster pool options are checked', async () => {
172 const workerFilePath = './tests/worker-files/cluster/testWorker.js'
173 let pool1 = new FixedClusterPool(numberOfWorkers, workerFilePath)
174 expect(pool1.opts.env).toBeUndefined()
175 expect(pool1.opts.settings).toBeUndefined()
176 await pool1.destroy()
177 pool1 = new FixedClusterPool(numberOfWorkers, workerFilePath, {
178 env: { TEST: 'test' },
179 settings: { args: ['--use', 'http'], silent: true }
180 })
181 expect(pool1.opts.env).toStrictEqual({ TEST: 'test' })
182 expect(pool1.opts.settings).toStrictEqual({
183 args: ['--use', 'http'],
184 silent: true
185 })
186 expect({ ...pool1.opts.settings, exec: workerFilePath }).toStrictEqual({
187 args: ['--use', 'http'],
188 silent: true,
189 exec: workerFilePath
190 })
191 await pool1.destroy()
192 })
193
325f50bc
S
194 it('Should work even without opts in input', async () => {
195 const pool1 = new FixedClusterPool(
e1ffb94f 196 numberOfWorkers,
76b1e974 197 './tests/worker-files/cluster/testWorker.js'
325f50bc 198 )
6db75ad9
JB
199 const res = await pool1.execute()
200 expect(res).toBe(false)
8bc77620
APA
201 // We need to clean up the resources after our test
202 await pool1.destroy()
325f50bc 203 })
8d3782fa
JB
204
205 it('Verify that a pool with zero worker fails', async () => {
206 expect(
207 () =>
208 new FixedClusterPool(0, './tests/worker-files/cluster/testWorker.js')
d4aeae5a 209 ).toThrowError('Cannot instantiate a fixed pool with no worker')
8d3782fa 210 })
325f50bc 211})