test: revert wrong path change to hyperfine
[poolifier.git] / tests / pools / thread / fixed.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
aee46736 2const { FixedThreadPool, PoolEvents } = require('../../../lib/index')
2d2e32c2 3const { WorkerFunctions } = require('../../test-types')
85a3f8a7 4const TestUtils = require('../../test-utils')
506c2a14 5
a35560ba 6describe('Fixed thread pool test suite', () => {
e1ffb94f
JB
7 const numberOfThreads = 6
8 const pool = new FixedThreadPool(
9 numberOfThreads,
10 './tests/worker-files/thread/testWorker.js',
11 {
12 errorHandler: e => console.error(e)
13 }
14 )
594bfb84
JB
15 const queuePool = new FixedThreadPool(
16 numberOfThreads,
17 './tests/worker-files/thread/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 FixedThreadPool(
27 numberOfThreads,
28 './tests/worker-files/thread/emptyWorker.js',
29 { exitHandler: () => console.log('empty pool worker exited') }
30 )
31 const echoPool = new FixedThreadPool(
32 numberOfThreads,
33 './tests/worker-files/thread/echoWorker.js'
34 )
35 const errorPool = new FixedThreadPool(
36 numberOfThreads,
37 './tests/worker-files/thread/errorWorker.js',
38 {
39 errorHandler: e => console.error(e)
40 }
41 )
42 const asyncErrorPool = new FixedThreadPool(
43 numberOfThreads,
44 './tests/worker-files/thread/asyncErrorWorker.js',
45 {
46 errorHandler: e => console.error(e)
47 }
48 )
49 const asyncPool = new FixedThreadPool(
50 numberOfThreads,
51 './tests/worker-files/thread/asyncWorker.js'
52 )
53
0e2503fc
JB
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()
7c0ba920 59 await asyncErrorPool.destroy()
0e2503fc 60 await emptyPool.destroy()
594bfb84 61 await queuePool.destroy()
0e2503fc
JB
62 })
63
506c2a14 64 it('Verify that the function is executed in a worker thread', async () => {
6db75ad9
JB
65 let result = await pool.execute({
66 function: WorkerFunctions.fibonacci
67 })
68 expect(result).toBe(false)
69 result = await pool.execute({
70 function: WorkerFunctions.factorial
71 })
72 expect(result).toBe(false)
506c2a14 73 })
74
106744f7 75 it('Verify that is possible to invoke the execute method without input', async () => {
76 const result = await pool.execute()
6db75ad9 77 expect(result).toBe(false)
106744f7 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 < numberOfThreads * 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 numberOfThreads + 1 times for a loop submitting up to numberOfThreads * 2 tasks to the fixed pool.
88 expect(poolBusy).toBe(numberOfThreads + 1)
7c0ba920
JB
89 })
90
594bfb84
JB
91 it('Verify that tasks queuing is working', async () => {
92 const maxMultiplier = 10
93 for (let i = 0; i < numberOfThreads * maxMultiplier; i++) {
94 queuePool.execute()
95 }
96 for (const workerNode of queuePool.workerNodes) {
97 expect(workerNode.tasksUsage.running).toBeLessThanOrEqual(
98 queuePool.opts.tasksQueueOptions.concurrency
99 )
100 expect(workerNode.tasksUsage.run).toBe(0)
101 expect(workerNode.tasksQueue.length).toBeGreaterThan(0)
102 }
103 // FIXME: wait for ongoing tasks to be executed
104 const promises = []
105 for (let i = 0; i < numberOfThreads * maxMultiplier; i++) {
106 promises.push(queuePool.execute())
107 }
108 await Promise.all(promises)
109 for (const workerNode of queuePool.workerNodes) {
110 expect(workerNode.tasksUsage.running).toBe(0)
111 expect(workerNode.tasksUsage.run).toBeGreaterThan(0)
112 expect(workerNode.tasksQueue.length).toBe(0)
113 }
114 })
115
106744f7 116 it('Verify that is possible to have a worker that return undefined', async () => {
117 const result = await emptyPool.execute()
6db75ad9 118 expect(result).toBeUndefined()
106744f7 119 })
120
121 it('Verify that data are sent to the worker correctly', async () => {
122 const data = { f: 10 }
123 const result = await echoPool.execute(data)
e1ffb94f 124 expect(result).toStrictEqual(data)
106744f7 125 })
126
7c0ba920 127 it('Verify that error handling is working properly:sync', async () => {
106744f7 128 const data = { f: 10 }
129 let inError
130 try {
131 await errorPool.execute(data)
132 } catch (e) {
133 inError = e
134 }
7c0ba920
JB
135 expect(inError).toBeDefined()
136 expect(inError).toBeInstanceOf(Error)
137 expect(inError.message).toBeDefined()
8620fb25 138 expect(typeof inError.message === 'string').toBe(true)
0302f8ec 139 expect(inError.message).toBe('Error Message from ThreadWorker')
7c0ba920
JB
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()
151 expect(inError).toBeInstanceOf(Error)
152 expect(inError.message).toBeDefined()
8620fb25 153 expect(typeof inError.message === 'string').toBe(true)
0302f8ec 154 expect(inError.message).toBe('Error Message from ThreadWorker:async')
106744f7 155 })
156
7784f548 157 it('Verify that async function is working properly', async () => {
158 const data = { f: 10 }
15e5141f 159 const startTime = performance.now()
7784f548 160 const result = await asyncPool.execute(data)
15e5141f 161 const usedTime = performance.now() - startTime
e1ffb94f 162 expect(result).toStrictEqual(data)
32d490eb 163 expect(usedTime).toBeGreaterThanOrEqual(2000)
7784f548 164 })
165
506c2a14 166 it('Shutdown test', async () => {
85a3f8a7 167 const exitPromise = TestUtils.waitExits(pool, numberOfThreads)
1f9a5a44 168 await pool.destroy()
bdacc2d2
JB
169 const numberOfExitEvents = await exitPromise
170 expect(numberOfExitEvents).toBe(numberOfThreads)
506c2a14 171 })
172
173 it('Should work even without opts in input', async () => {
76b1e974 174 const pool1 = new FixedThreadPool(
e1ffb94f 175 numberOfThreads,
76b1e974
S
176 './tests/worker-files/thread/testWorker.js'
177 )
6db75ad9
JB
178 const res = await pool1.execute()
179 expect(res).toBe(false)
0e2503fc
JB
180 // We need to clean up the resources after our test
181 await pool1.destroy()
506c2a14 182 })
8d3782fa
JB
183
184 it('Verify that a pool with zero worker fails', async () => {
185 expect(
186 () => new FixedThreadPool(0, './tests/worker-files/thread/testWorker.js')
187 ).toThrowError(new Error('Cannot instantiate a fixed pool with no worker'))
188 })
506c2a14 189})