6869bda681315aab9b088bad60677df4e8bcc510
[poolifier.git] / tests / pools / utils.test.mjs
1 import { Worker as ThreadWorker } from 'node:worker_threads'
2 import cluster, { Worker as ClusterWorker } from 'node:cluster'
3 import { expect } from 'expect'
4 import {
5 CircularArray,
6 DEFAULT_CIRCULAR_ARRAY_SIZE
7 } from '../../lib/circular-array.cjs'
8 import {
9 DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
10 buildWorkerChoiceStrategyOptions,
11 createWorker,
12 getDefaultTasksQueueOptions,
13 getWorkerChoiceStrategyRetries,
14 getWorkerId,
15 getWorkerType,
16 updateMeasurementStatistics
17 } from '../../lib/pools/utils.cjs'
18 import {
19 FixedClusterPool,
20 FixedThreadPool,
21 WorkerTypes
22 } from '../../lib/index.cjs'
23
24 describe('Pool utils test suite', () => {
25 it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => {
26 expect(DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS).toStrictEqual({
27 aggregate: false,
28 average: false,
29 median: false
30 })
31 })
32
33 it('Verify getDefaultTasksQueueOptions() behavior', () => {
34 const poolMaxSize = 4
35 expect(getDefaultTasksQueueOptions(poolMaxSize)).toStrictEqual({
36 concurrency: 1,
37 size: Math.pow(poolMaxSize, 2),
38 taskStealing: true,
39 tasksStealingOnBackPressure: true,
40 tasksFinishedTimeout: 2000
41 })
42 })
43
44 it('Verify getWorkerChoiceStrategyRetries() behavior', async () => {
45 const numberOfThreads = 4
46 const pool = new FixedThreadPool(
47 numberOfThreads,
48 './tests/worker-files/thread/testWorker.mjs'
49 )
50 expect(getWorkerChoiceStrategyRetries(pool)).toBe(pool.info.maxSize * 2)
51 const workerChoiceStrategyOptions = {
52 runTime: { median: true },
53 waitTime: { median: true },
54 elu: { median: true },
55 weights: {
56 0: 100,
57 1: 100
58 }
59 }
60 expect(
61 getWorkerChoiceStrategyRetries(pool, workerChoiceStrategyOptions)
62 ).toBe(
63 pool.info.maxSize +
64 Object.keys(workerChoiceStrategyOptions.weights).length
65 )
66 await pool.destroy()
67 })
68
69 it('Verify buildWorkerChoiceStrategyOptions() behavior', async () => {
70 const numberOfWorkers = 4
71 const pool = new FixedClusterPool(
72 numberOfWorkers,
73 './tests/worker-files/cluster/testWorker.cjs'
74 )
75 expect(buildWorkerChoiceStrategyOptions(pool)).toStrictEqual({
76 runTime: { median: false },
77 waitTime: { median: false },
78 elu: { median: false },
79 weights: expect.objectContaining({
80 0: expect.any(Number),
81 [pool.info.maxSize - 1]: expect.any(Number)
82 })
83 })
84 const workerChoiceStrategyOptions = {
85 runTime: { median: true },
86 waitTime: { median: true },
87 elu: { median: true },
88 weights: {
89 0: 100,
90 1: 100
91 }
92 }
93 expect(
94 buildWorkerChoiceStrategyOptions(pool, workerChoiceStrategyOptions)
95 ).toStrictEqual(workerChoiceStrategyOptions)
96 await pool.destroy()
97 })
98
99 it('Verify updateMeasurementStatistics() behavior', () => {
100 const measurementStatistics = {
101 history: new CircularArray()
102 }
103 updateMeasurementStatistics(
104 measurementStatistics,
105 { aggregate: true, average: false, median: false },
106 0.01
107 )
108 expect(measurementStatistics).toStrictEqual({
109 aggregate: 0.01,
110 maximum: 0.01,
111 minimum: 0.01,
112 history: new CircularArray()
113 })
114 updateMeasurementStatistics(
115 measurementStatistics,
116 { aggregate: true, average: false, median: false },
117 0.02
118 )
119 expect(measurementStatistics).toStrictEqual({
120 aggregate: 0.03,
121 maximum: 0.02,
122 minimum: 0.01,
123 history: new CircularArray()
124 })
125 updateMeasurementStatistics(
126 measurementStatistics,
127 { aggregate: true, average: true, median: false },
128 0.001
129 )
130 expect(measurementStatistics).toStrictEqual({
131 aggregate: 0.031,
132 maximum: 0.02,
133 minimum: 0.001,
134 average: 0.001,
135 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
136 })
137 updateMeasurementStatistics(
138 measurementStatistics,
139 { aggregate: true, average: true, median: false },
140 0.003
141 )
142 expect(measurementStatistics).toStrictEqual({
143 aggregate: 0.034,
144 maximum: 0.02,
145 minimum: 0.001,
146 average: 0.002,
147 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
148 })
149 updateMeasurementStatistics(
150 measurementStatistics,
151 { aggregate: true, average: false, median: true },
152 0.006
153 )
154 expect(measurementStatistics).toStrictEqual({
155 aggregate: 0.04,
156 maximum: 0.02,
157 minimum: 0.001,
158 median: 0.003,
159 history: new CircularArray(
160 DEFAULT_CIRCULAR_ARRAY_SIZE,
161 0.001,
162 0.003,
163 0.006
164 )
165 })
166 updateMeasurementStatistics(
167 measurementStatistics,
168 { aggregate: true, average: true, median: false },
169 0.01
170 )
171 expect(measurementStatistics).toStrictEqual({
172 aggregate: 0.05,
173 maximum: 0.02,
174 minimum: 0.001,
175 average: 0.005,
176 history: new CircularArray(
177 DEFAULT_CIRCULAR_ARRAY_SIZE,
178 0.001,
179 0.003,
180 0.006,
181 0.01
182 )
183 })
184 })
185
186 it('Verify createWorker() behavior', () => {
187 expect(
188 createWorker(
189 WorkerTypes.thread,
190 './tests/worker-files/thread/testWorker.mjs',
191 {}
192 )
193 ).toBeInstanceOf(ThreadWorker)
194 expect(
195 createWorker(
196 WorkerTypes.cluster,
197 './tests/worker-files/cluster/testWorker.mjs',
198 {}
199 )
200 ).toBeInstanceOf(ClusterWorker)
201 })
202
203 it('Verify getWorkerType() behavior', () => {
204 expect(
205 getWorkerType(
206 new ThreadWorker('./tests/worker-files/thread/testWorker.mjs')
207 )
208 ).toBe(WorkerTypes.thread)
209 expect(getWorkerType(cluster.fork())).toBe(WorkerTypes.cluster)
210 })
211
212 it('Verify getWorkerId() behavior', () => {
213 const threadWorker = new ThreadWorker(
214 './tests/worker-files/thread/testWorker.mjs'
215 )
216 const clusterWorker = cluster.fork()
217 expect(getWorkerId(threadWorker)).toBe(threadWorker.threadId)
218 expect(getWorkerId(clusterWorker)).toBe(clusterWorker.id)
219 })
220 })