1 import { MessageChannel } from 'node:worker_threads'
2 import { expect } from 'expect'
3 import { WorkerNode } from '../../lib/pools/worker-node.js'
4 import { WorkerTypes } from '../../lib/index.js'
5 import { CircularArray } from '../../lib/circular-array.js'
6 import { Deque } from '../../lib/deque.js'
7 import { DEFAULT_TASK_NAME } from '../../lib/utils.js'
9 describe('Worker node test suite', () => {
10 const threadWorkerNode = new WorkerNode(
12 './tests/worker-files/thread/testWorker.mjs',
13 { tasksQueueBackPressureSize: 12 }
15 const clusterWorkerNode = new WorkerNode(
17 './tests/worker-files/cluster/testWorker.js',
18 { tasksQueueBackPressureSize: 12 }
21 it('Worker node instantiation', () => {
22 expect(() => new WorkerNode()).toThrow(
23 new TypeError('Cannot construct a worker node without a worker type')
29 './tests/worker-files/thread/testWorker.mjs',
30 { tasksQueueBackPressureSize: 12 }
34 "Cannot construct a worker node with an invalid worker type 'invalidWorkerType'"
41 './tests/worker-files/thread/testWorker.mjs'
45 'Cannot construct a worker node without worker node options'
52 './tests/worker-files/thread/testWorker.mjs',
57 'Cannot construct a worker node with invalid options: must be a plain object'
64 './tests/worker-files/thread/testWorker.mjs',
69 'Cannot construct a worker node without a tasks queue back pressure size option'
76 './tests/worker-files/thread/testWorker.mjs',
77 { tasksQueueBackPressureSize: 'invalidTasksQueueBackPressureSize' }
81 'Cannot construct a worker node with a tasks queue back pressure size option that is not an integer'
88 './tests/worker-files/thread/testWorker.mjs',
89 { tasksQueueBackPressureSize: 0.2 }
93 'Cannot construct a worker node with a tasks queue back pressure size option that is not an integer'
100 './tests/worker-files/thread/testWorker.mjs',
101 { tasksQueueBackPressureSize: 0 }
105 'Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer'
112 './tests/worker-files/thread/testWorker.mjs',
113 { tasksQueueBackPressureSize: -1 }
117 'Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer'
120 expect(threadWorkerNode).toBeInstanceOf(WorkerNode)
121 expect(threadWorkerNode.info).toStrictEqual({
122 id: threadWorkerNode.worker.threadId,
123 type: WorkerTypes.thread,
127 expect(threadWorkerNode.usage).toStrictEqual({
133 sequentiallyStolen: 0,
138 history: new CircularArray()
141 history: new CircularArray()
145 history: new CircularArray()
148 history: new CircularArray()
152 expect(threadWorkerNode.messageChannel).toBeInstanceOf(MessageChannel)
153 expect(threadWorkerNode.tasksQueueBackPressureSize).toBe(12)
154 expect(threadWorkerNode.tasksQueue).toBeInstanceOf(Deque)
155 expect(threadWorkerNode.tasksQueue.size).toBe(0)
156 expect(threadWorkerNode.tasksQueueSize()).toBe(
157 threadWorkerNode.tasksQueue.size
159 expect(threadWorkerNode.onBackPressureStarted).toBe(false)
160 expect(threadWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map)
162 expect(clusterWorkerNode).toBeInstanceOf(WorkerNode)
163 expect(clusterWorkerNode.info).toStrictEqual({
164 id: clusterWorkerNode.worker.id,
165 type: WorkerTypes.cluster,
169 expect(clusterWorkerNode.usage).toStrictEqual({
175 sequentiallyStolen: 0,
180 history: new CircularArray()
183 history: new CircularArray()
187 history: new CircularArray()
190 history: new CircularArray()
194 expect(clusterWorkerNode.messageChannel).toBeUndefined()
195 expect(clusterWorkerNode.tasksQueueBackPressureSize).toBe(12)
196 expect(clusterWorkerNode.tasksQueue).toBeInstanceOf(Deque)
197 expect(clusterWorkerNode.tasksQueue.size).toBe(0)
198 expect(clusterWorkerNode.tasksQueueSize()).toBe(
199 clusterWorkerNode.tasksQueue.size
201 expect(clusterWorkerNode.onBackPressureStarted).toBe(false)
202 expect(clusterWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map)
205 it('Worker node getTaskFunctionWorkerUsage()', () => {
207 threadWorkerNode.getTaskFunctionWorkerUsage('invalidTaskFunction')
210 "Cannot get task function worker usage for task function name 'invalidTaskFunction' when task function names list is not yet defined"
213 threadWorkerNode.info.taskFunctionNames = [DEFAULT_TASK_NAME, 'fn1']
215 threadWorkerNode.getTaskFunctionWorkerUsage('invalidTaskFunction')
218 "Cannot get task function worker usage for task function name 'invalidTaskFunction' when task function names list has less than 3 elements"
221 threadWorkerNode.info.taskFunctionNames = [DEFAULT_TASK_NAME, 'fn1', 'fn2']
223 threadWorkerNode.getTaskFunctionWorkerUsage(DEFAULT_TASK_NAME)
229 sequentiallyStolen: 0,
234 history: new CircularArray()
237 history: new CircularArray()
241 history: new CircularArray()
244 history: new CircularArray()
248 expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn1')).toStrictEqual({
253 sequentiallyStolen: 0,
258 history: new CircularArray()
261 history: new CircularArray()
265 history: new CircularArray()
268 history: new CircularArray()
272 expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn2')).toStrictEqual({
277 sequentiallyStolen: 0,
282 history: new CircularArray()
285 history: new CircularArray()
289 history: new CircularArray()
292 history: new CircularArray()
296 expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2)
299 it('Worker node deleteTaskFunctionWorkerUsage()', () => {
300 expect(threadWorkerNode.info.taskFunctionNames).toStrictEqual([
305 expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2)
307 threadWorkerNode.deleteTaskFunctionWorkerUsage('invalidTaskFunction')
309 expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2)
310 expect(threadWorkerNode.deleteTaskFunctionWorkerUsage('fn1')).toBe(true)
311 expect(threadWorkerNode.taskFunctionsUsage.size).toBe(1)