Merge dependabot/npm_and_yarn/examples/typescript/http-server-pool/fastify-cluster...
[poolifier.git] / tests / pools / abstract / worker-node.test.js
1 const { MessageChannel, Worker } = require('node:worker_threads')
2 const cluster = require('node:cluster')
3 const { expect } = require('expect')
4 const { WorkerNode } = require('../../../lib/pools/worker-node')
5 const { WorkerTypes } = require('../../../lib')
6 const { CircularArray } = require('../../../lib/circular-array')
7 const { Deque } = require('../../../lib/deque')
8 const { DEFAULT_TASK_NAME } = require('../../../lib/utils')
9
10 describe('Worker node test suite', () => {
11 const threadWorker = new Worker('./tests/worker-files/thread/testWorker.js')
12 const clusterWorker = cluster.fork()
13 const threadWorkerNode = new WorkerNode(threadWorker, 12)
14 const clusterWorkerNode = new WorkerNode(clusterWorker, 12)
15
16 it('Worker node instantiation', () => {
17 expect(() => new WorkerNode()).toThrowError(
18 new TypeError('Cannot construct a worker node without a worker')
19 )
20 expect(() => new WorkerNode(threadWorker)).toThrowError(
21 new TypeError(
22 'Cannot construct a worker node without a tasks queue back pressure size'
23 )
24 )
25 expect(
26 () => new WorkerNode(threadWorker, 'invalidTasksQueueBackPressureSize')
27 ).toThrowError(
28 new TypeError(
29 'Cannot construct a worker node with a tasks queue back pressure size that is not an integer'
30 )
31 )
32 expect(() => new WorkerNode(threadWorker, 0.2)).toThrowError(
33 new TypeError(
34 'Cannot construct a worker node with a tasks queue back pressure size that is not an integer'
35 )
36 )
37 expect(() => new WorkerNode(threadWorker, 0)).toThrowError(
38 new RangeError(
39 'Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer'
40 )
41 )
42 expect(() => new WorkerNode(threadWorker, -1)).toThrowError(
43 new RangeError(
44 'Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer'
45 )
46 )
47 expect(threadWorkerNode).toBeInstanceOf(WorkerNode)
48 expect(threadWorkerNode.worker).toBe(threadWorker)
49 expect(threadWorkerNode.info).toStrictEqual({
50 id: threadWorker.threadId,
51 type: WorkerTypes.thread,
52 dynamic: false,
53 ready: false
54 })
55 expect(threadWorkerNode.usage).toStrictEqual({
56 tasks: {
57 executed: 0,
58 executing: 0,
59 queued: 0,
60 maxQueued: 0,
61 stolen: 0,
62 failed: 0
63 },
64 runTime: {
65 history: new CircularArray()
66 },
67 waitTime: {
68 history: new CircularArray()
69 },
70 elu: {
71 idle: {
72 history: new CircularArray()
73 },
74 active: {
75 history: new CircularArray()
76 }
77 }
78 })
79 expect(threadWorkerNode.messageChannel).toBeInstanceOf(MessageChannel)
80 expect(threadWorkerNode.tasksQueueBackPressureSize).toBe(12)
81 expect(threadWorkerNode.tasksQueue).toBeInstanceOf(Deque)
82 expect(threadWorkerNode.tasksQueue.size).toBe(0)
83 expect(threadWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map)
84
85 expect(clusterWorkerNode).toBeInstanceOf(WorkerNode)
86 expect(clusterWorkerNode.worker).toBe(clusterWorker)
87 expect(clusterWorkerNode.info).toStrictEqual({
88 id: clusterWorker.id,
89 type: WorkerTypes.cluster,
90 dynamic: false,
91 ready: false
92 })
93 expect(clusterWorkerNode.usage).toStrictEqual({
94 tasks: {
95 executed: 0,
96 executing: 0,
97 queued: 0,
98 maxQueued: 0,
99 stolen: 0,
100 failed: 0
101 },
102 runTime: {
103 history: new CircularArray()
104 },
105 waitTime: {
106 history: new CircularArray()
107 },
108 elu: {
109 idle: {
110 history: new CircularArray()
111 },
112 active: {
113 history: new CircularArray()
114 }
115 }
116 })
117 expect(clusterWorkerNode.messageChannel).toBeUndefined()
118 expect(clusterWorkerNode.tasksQueueBackPressureSize).toBe(12)
119 expect(clusterWorkerNode.tasksQueue).toBeInstanceOf(Deque)
120 expect(clusterWorkerNode.tasksQueue.size).toBe(0)
121 expect(clusterWorkerNode.taskFunctionsUsage).toBeInstanceOf(Map)
122 })
123
124 it('Worker node getTaskFunctionWorkerUsage()', () => {
125 expect(() =>
126 threadWorkerNode.getTaskFunctionWorkerUsage('invalidTaskFunction')
127 ).toThrowError(
128 new TypeError(
129 "Cannot get task function worker usage for task function name 'invalidTaskFunction' when task function names list is not yet defined"
130 )
131 )
132 threadWorkerNode.info.taskFunctions = [DEFAULT_TASK_NAME, 'fn1']
133 expect(() =>
134 threadWorkerNode.getTaskFunctionWorkerUsage('invalidTaskFunction')
135 ).toThrowError(
136 new TypeError(
137 "Cannot get task function worker usage for task function name 'invalidTaskFunction' when task function names list has less than 3 elements"
138 )
139 )
140 threadWorkerNode.info.taskFunctions = [DEFAULT_TASK_NAME, 'fn1', 'fn2']
141 expect(
142 threadWorkerNode.getTaskFunctionWorkerUsage(DEFAULT_TASK_NAME)
143 ).toStrictEqual({
144 tasks: {
145 executed: 0,
146 executing: 0,
147 queued: 0,
148 stolen: 0,
149 failed: 0
150 },
151 runTime: {
152 history: new CircularArray()
153 },
154 waitTime: {
155 history: new CircularArray()
156 },
157 elu: {
158 idle: {
159 history: new CircularArray()
160 },
161 active: {
162 history: new CircularArray()
163 }
164 }
165 })
166 expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn1')).toStrictEqual({
167 tasks: {
168 executed: 0,
169 executing: 0,
170 queued: 0,
171 stolen: 0,
172 failed: 0
173 },
174 runTime: {
175 history: new CircularArray()
176 },
177 waitTime: {
178 history: new CircularArray()
179 },
180 elu: {
181 idle: {
182 history: new CircularArray()
183 },
184 active: {
185 history: new CircularArray()
186 }
187 }
188 })
189 expect(threadWorkerNode.getTaskFunctionWorkerUsage('fn2')).toStrictEqual({
190 tasks: {
191 executed: 0,
192 executing: 0,
193 queued: 0,
194 stolen: 0,
195 failed: 0
196 },
197 runTime: {
198 history: new CircularArray()
199 },
200 waitTime: {
201 history: new CircularArray()
202 },
203 elu: {
204 idle: {
205 history: new CircularArray()
206 },
207 active: {
208 history: new CircularArray()
209 }
210 }
211 })
212 expect(threadWorkerNode.taskFunctionsUsage.size).toBe(2)
213 })
214 })