1 const { expect
} = require('expect')
2 const { FixedThreadPool
, PoolEvents
} = require('../../../lib')
3 const { WorkerFunctions
} = require('../../test-types')
4 const TestUtils
= require('../../test-utils')
6 describe('Fixed thread pool test suite', () => {
7 const numberOfThreads
= 6
8 const pool
= new FixedThreadPool(
10 './tests/worker-files/thread/testWorker.js',
12 errorHandler
: e
=> console
.error(e
)
15 const queuePool
= new FixedThreadPool(
17 './tests/worker-files/thread/testWorker.js',
19 enableTasksQueue
: true,
23 errorHandler
: e
=> console
.error(e
)
26 const emptyPool
= new FixedThreadPool(
28 './tests/worker-files/thread/emptyWorker.js',
29 { exitHandler
: () => console
.log('empty pool worker exited') }
31 const echoPool
= new FixedThreadPool(
33 './tests/worker-files/thread/echoWorker.js'
35 const errorPool
= new FixedThreadPool(
37 './tests/worker-files/thread/errorWorker.js',
39 errorHandler
: e
=> console
.error(e
)
42 const asyncErrorPool
= new FixedThreadPool(
44 './tests/worker-files/thread/asyncErrorWorker.js',
46 errorHandler
: e
=> console
.error(e
)
49 const asyncPool
= new FixedThreadPool(
51 './tests/worker-files/thread/asyncWorker.js'
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()
61 await queuePool
.destroy()
64 it('Verify that the function is executed in a worker thread', async () => {
65 let result
= await pool
.execute({
66 function: WorkerFunctions
.fibonacci
68 expect(result
).toBe(121393)
69 result
= await pool
.execute({
70 function: WorkerFunctions
.factorial
72 expect(result
).toBe(9.33262154439441e157
)
75 it('Verify that is possible to invoke the execute() method without input', async () => {
76 const result
= await pool
.execute()
77 expect(result
).toBe(false)
80 it("Verify that 'busy' event is emitted", async () => {
82 pool
.emitter
.on(PoolEvents
.busy
, () => ++poolBusy
)
83 for (let i
= 0; i
< numberOfThreads
* 2; i
++) {
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)
91 it('Verify that tasks queuing is working', async () => {
92 const promises
= new Set()
93 const maxMultiplier
= 2
94 for (let i
= 0; i
< numberOfThreads
* maxMultiplier
; i
++) {
95 promises
.add(queuePool
.execute())
97 expect(promises
.size
).toBe(numberOfThreads
* maxMultiplier
)
98 for (const workerNode
of queuePool
.workerNodes
) {
99 expect(workerNode
.tasksUsage
.running
).toBeLessThanOrEqual(
100 queuePool
.opts
.tasksQueueOptions
.concurrency
102 expect(workerNode
.tasksUsage
.run
).toBe(0)
103 expect(workerNode
.tasksQueue
.size
).toBeGreaterThan(0)
105 expect(queuePool
.numberOfRunningTasks
).toBe(numberOfThreads
)
106 expect(queuePool
.numberOfQueuedTasks
).toBe(
107 numberOfThreads
* maxMultiplier
- numberOfThreads
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)
113 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(maxMultiplier
)
114 expect(workerNode
.tasksQueue
.size
).toBe(0)
119 it('Verify that is possible to have a worker that return undefined', async () => {
120 const result
= await emptyPool
.execute()
121 expect(result
).toBeUndefined()
124 it('Verify that data are sent to the worker correctly', async () => {
125 const data
= { f
: 10 }
126 const result
= await echoPool
.execute(data
)
127 expect(result
).toStrictEqual(data
)
130 it('Verify that error handling is working properly:sync', async () => {
131 const data
= { f
: 10 }
134 await errorPool
.execute(data
)
138 expect(inError
).toBeDefined()
139 expect(inError
).toBeInstanceOf(Error
)
140 expect(inError
.message
).toBeDefined()
141 expect(typeof inError
.message
=== 'string').toBe(true)
142 expect(inError
.message
).toBe('Error Message from ThreadWorker')
144 errorPool
.workerNodes
.some(
145 workerNode
=> workerNode
.tasksUsage
.error
=== 1
150 it('Verify that error handling is working properly:async', async () => {
151 const data
= { f
: 10 }
154 await asyncErrorPool
.execute(data
)
158 expect(inError
).toBeDefined()
159 expect(inError
).toBeInstanceOf(Error
)
160 expect(inError
.message
).toBeDefined()
161 expect(typeof inError
.message
=== 'string').toBe(true)
162 expect(inError
.message
).toBe('Error Message from ThreadWorker:async')
164 asyncErrorPool
.workerNodes
.some(
165 workerNode
=> workerNode
.tasksUsage
.error
=== 1
170 it('Verify that async function is working properly', async () => {
171 const data
= { f
: 10 }
172 const startTime
= performance
.now()
173 const result
= await asyncPool
.execute(data
)
174 const usedTime
= performance
.now() - startTime
175 expect(result
).toStrictEqual(data
)
176 expect(usedTime
).toBeGreaterThanOrEqual(2000)
179 it('Shutdown test', async () => {
180 const exitPromise
= TestUtils
.waitExits(pool
, numberOfThreads
)
182 const numberOfExitEvents
= await exitPromise
183 expect(numberOfExitEvents
).toBe(numberOfThreads
)
186 it('Should work even without opts in input', async () => {
187 const pool1
= new FixedThreadPool(
189 './tests/worker-files/thread/testWorker.js'
191 const res
= await pool1
.execute()
192 expect(res
).toBe(false)
193 // We need to clean up the resources after our test
194 await pool1
.destroy()
197 it('Verify that a pool with zero worker fails', async () => {
199 () => new FixedThreadPool(0, './tests/worker-files/thread/testWorker.js')
200 ).toThrowError('Cannot instantiate a fixed pool with no worker')