Merge branch 'master' into feature/task-functions
[poolifier.git] / tests / utils.test.js
CommitLineData
a449b585
JB
1const { randomInt } = require('node:crypto')
2const { Worker } = require('node:worker_threads')
3const cluster = require('node:cluster')
4const os = require('node:os')
aba955e1 5const { expect } = require('expect')
dc021bcc
JB
6const {
7 CircularArray,
8 DEFAULT_CIRCULAR_ARRAY_SIZE
9} = require('../lib/circular-array')
afe0d5bf 10const {
9274aa14
JB
11 DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
12 DEFAULT_TASK_NAME,
13 DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS,
14 EMPTY_FUNCTION,
afe0d5bf 15 availableParallelism,
dc021bcc 16 average,
98446b39 17 exponentialDelay,
9fe8fd69
JB
18 getWorkerType,
19 getWorkerId,
78ac1a90 20 isAsyncFunction,
59317253 21 isKillBehavior,
afe0d5bf 22 isPlainObject,
90d6701c 23 max,
afe0d5bf 24 median,
90d6701c 25 min,
a91f7b35 26 round,
970b38d6 27 secureRandom,
98446b39 28 sleep,
a91f7b35 29 updateMeasurementStatistics
afe0d5bf 30} = require('../lib/utils')
9fe8fd69 31const { KillBehaviors, WorkerTypes } = require('../lib')
aba955e1
JB
32
33describe('Utils test suite', () => {
9274aa14
JB
34 it('Verify DEFAULT_TASK_NAME value', () => {
35 expect(DEFAULT_TASK_NAME).toBe('default')
36 })
37
38 it('Verify EMPTY_FUNCTION value', () => {
39 expect(EMPTY_FUNCTION).toStrictEqual(expect.any(Function))
40 })
41
42 it('Verify DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS values', () => {
43 expect(DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS).toStrictEqual({
44 retries: 6,
45 runTime: { median: false },
46 waitTime: { median: false },
47 elu: { median: false }
48 })
49 })
50
51 it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => {
52 expect(DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS).toStrictEqual({
53 aggregate: false,
54 average: false,
55 median: false
56 })
57 })
58
afe0d5bf 59 it('Verify availableParallelism() behavior', () => {
9fe8fd69
JB
60 const parallelism = availableParallelism()
61 expect(typeof parallelism === 'number').toBe(true)
37e31fac 62 expect(Number.isSafeInteger(parallelism)).toBe(true)
562a4037
JB
63 let expectedParallelism = 1
64 try {
65 expectedParallelism = os.availableParallelism()
66 } catch {
67 expectedParallelism = os.cpus().length
68 }
69 expect(parallelism).toBe(expectedParallelism)
9fe8fd69
JB
70 })
71
72 it('Verify getWorkerType() behavior', () => {
73 expect(
74 getWorkerType(new Worker('./tests/worker-files/thread/testWorker.js'))
75 ).toBe(WorkerTypes.thread)
76 expect(getWorkerType(cluster.fork())).toBe(WorkerTypes.cluster)
77 })
78
79 it('Verify getWorkerId() behavior', () => {
80 const threadWorker = new Worker('./tests/worker-files/thread/testWorker.js')
81 const clusterWorker = cluster.fork()
82 expect(getWorkerId(threadWorker)).toBe(threadWorker.threadId)
83 expect(getWorkerId(clusterWorker)).toBe(clusterWorker.id)
afe0d5bf
JB
84 })
85
bb9423b7 86 it('Verify sleep() behavior', async () => {
65deb7f0 87 const start = performance.now()
98446b39 88 await sleep(1000)
6543999f 89 const elapsed = performance.now() - start
4be58f3c 90 expect(elapsed).toBeGreaterThanOrEqual(999)
98446b39
JB
91 })
92
93 it('Verify exponentialDelay() behavior', () => {
1f0766e7
JB
94 const delay = exponentialDelay(randomInt(1000))
95 expect(typeof delay === 'number').toBe(true)
96 expect(delay).toBeGreaterThanOrEqual(Number.MIN_VALUE)
97 expect(delay).toBeLessThanOrEqual(Number.MAX_VALUE)
98446b39
JB
98 })
99
dc021bcc
JB
100 it('Verify average() computation', () => {
101 expect(average([])).toBe(0)
102 expect(average([0.08])).toBe(0.08)
103 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(
104 3.1642857142857146
105 )
106 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(
107 2.8533333333333335
108 )
109 })
110
bb615bd0 111 it('Verify median() computation', () => {
4a45e8d2 112 expect(median([])).toBe(0)
76845835
JB
113 expect(median([0.08])).toBe(0.08)
114 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05)
115 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535)
aba955e1
JB
116 })
117
afe0d5bf
JB
118 it('Verify round() behavior', () => {
119 expect(round(0)).toBe(0)
120 expect(round(0.5, 0)).toBe(1)
121 expect(round(0.5)).toBe(0.5)
122 expect(round(-0.5, 0)).toBe(-1)
123 expect(round(-0.5)).toBe(-0.5)
124 expect(round(1.005)).toBe(1.01)
125 expect(round(2.175)).toBe(2.18)
126 expect(round(5.015)).toBe(5.02)
127 expect(round(-1.005)).toBe(-1.01)
128 expect(round(-2.175)).toBe(-2.18)
129 expect(round(-5.015)).toBe(-5.02)
130 })
131
aba955e1
JB
132 it('Verify isPlainObject() behavior', () => {
133 expect(isPlainObject(null)).toBe(false)
134 expect(isPlainObject(undefined)).toBe(false)
135 expect(isPlainObject(true)).toBe(false)
136 expect(isPlainObject(false)).toBe(false)
137 expect(isPlainObject(0)).toBe(false)
138 expect(isPlainObject('')).toBe(false)
139 expect(isPlainObject([])).toBe(false)
140 expect(isPlainObject(() => {})).toBe(false)
141 expect(isPlainObject(new Date())).toBe(false)
142 expect(isPlainObject(new RegExp())).toBe(false)
143 expect(isPlainObject(new Error())).toBe(false)
144 expect(isPlainObject(new Map())).toBe(false)
145 expect(isPlainObject(new Set())).toBe(false)
146 expect(isPlainObject(new WeakMap())).toBe(false)
147 expect(isPlainObject(new WeakSet())).toBe(false)
148 expect(isPlainObject(new Int8Array())).toBe(false)
149 expect(isPlainObject(new Uint8Array())).toBe(false)
150 expect(isPlainObject(new Uint8ClampedArray())).toBe(false)
151 expect(isPlainObject(new Int16Array())).toBe(false)
152 expect(isPlainObject(new Uint16Array())).toBe(false)
153 expect(isPlainObject(new Int32Array())).toBe(false)
154 expect(isPlainObject(new Uint32Array())).toBe(false)
155 expect(isPlainObject(new Float32Array())).toBe(false)
156 expect(isPlainObject(new Float64Array())).toBe(false)
157 expect(isPlainObject(new BigInt64Array())).toBe(false)
158 expect(isPlainObject(new BigUint64Array())).toBe(false)
159 expect(isPlainObject(new Promise(() => {}))).toBe(false)
160 expect(isPlainObject(new WeakRef({}))).toBe(false)
161 expect(isPlainObject(new FinalizationRegistry(() => {}))).toBe(false)
162 expect(isPlainObject(new ArrayBuffer())).toBe(false)
163 expect(isPlainObject(new SharedArrayBuffer())).toBe(false)
164 expect(isPlainObject(new DataView(new ArrayBuffer()))).toBe(false)
165 expect(isPlainObject({})).toBe(true)
166 expect(isPlainObject({ a: 1 })).toBe(true)
167 })
47aacbaa
JB
168
169 it('Verify isKillBehavior() behavior', () => {
170 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.SOFT)).toBe(true)
171 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.HARD)).toBe(false)
172 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.HARD)).toBe(true)
173 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.SOFT)).toBe(false)
174 expect(isKillBehavior(KillBehaviors.SOFT)).toBe(false)
175 expect(isKillBehavior(KillBehaviors.HARD)).toBe(false)
176 expect(isKillBehavior(KillBehaviors.HARD, null)).toBe(false)
78ac1a90 177 expect(isKillBehavior(KillBehaviors.HARD, undefined)).toBe(false)
47aacbaa
JB
178 expect(isKillBehavior(KillBehaviors.SOFT, 'unknown')).toBe(false)
179 })
78ac1a90
JB
180
181 it('Verify isAsyncFunction() behavior', () => {
182 expect(isAsyncFunction(null)).toBe(false)
183 expect(isAsyncFunction(undefined)).toBe(false)
184 expect(isAsyncFunction(true)).toBe(false)
185 expect(isAsyncFunction(false)).toBe(false)
186 expect(isAsyncFunction(0)).toBe(false)
187 expect(isAsyncFunction('')).toBe(false)
188 expect(isAsyncFunction([])).toBe(false)
189 expect(isAsyncFunction(new Date())).toBe(false)
190 expect(isAsyncFunction(new RegExp())).toBe(false)
191 expect(isAsyncFunction(new Error())).toBe(false)
192 expect(isAsyncFunction(new Map())).toBe(false)
193 expect(isAsyncFunction(new Set())).toBe(false)
194 expect(isAsyncFunction(new WeakMap())).toBe(false)
195 expect(isAsyncFunction(new WeakSet())).toBe(false)
196 expect(isAsyncFunction(new Int8Array())).toBe(false)
197 expect(isAsyncFunction(new Uint8Array())).toBe(false)
198 expect(isAsyncFunction(new Uint8ClampedArray())).toBe(false)
199 expect(isAsyncFunction(new Int16Array())).toBe(false)
200 expect(isAsyncFunction(new Uint16Array())).toBe(false)
201 expect(isAsyncFunction(new Int32Array())).toBe(false)
202 expect(isAsyncFunction(new Uint32Array())).toBe(false)
203 expect(isAsyncFunction(new Float32Array())).toBe(false)
204 expect(isAsyncFunction(new Float64Array())).toBe(false)
205 expect(isAsyncFunction(new BigInt64Array())).toBe(false)
206 expect(isAsyncFunction(new BigUint64Array())).toBe(false)
207 expect(isAsyncFunction(new Promise(() => {}))).toBe(false)
208 expect(isAsyncFunction(new WeakRef({}))).toBe(false)
209 expect(isAsyncFunction(new FinalizationRegistry(() => {}))).toBe(false)
210 expect(isAsyncFunction(new ArrayBuffer())).toBe(false)
211 expect(isAsyncFunction(new SharedArrayBuffer())).toBe(false)
212 expect(isAsyncFunction(new DataView(new ArrayBuffer()))).toBe(false)
213 expect(isAsyncFunction({})).toBe(false)
214 expect(isAsyncFunction({ a: 1 })).toBe(false)
215 expect(isAsyncFunction(() => {})).toBe(false)
216 expect(isAsyncFunction(function () {})).toBe(false)
217 expect(isAsyncFunction(function named () {})).toBe(false)
218 expect(isAsyncFunction(async () => {})).toBe(true)
219 expect(isAsyncFunction(async function () {})).toBe(true)
220 expect(isAsyncFunction(async function named () {})).toBe(true)
221 })
a91f7b35
JB
222
223 it('Verify updateMeasurementStatistics() behavior', () => {
997bbcba
JB
224 const measurementStatistics = {
225 history: new CircularArray()
226 }
a91f7b35
JB
227 updateMeasurementStatistics(
228 measurementStatistics,
229 { aggregate: true, average: false, median: false },
dc021bcc 230 0.01
a91f7b35 231 )
997bbcba 232 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
233 aggregate: 0.01,
234 maximum: 0.01,
997bbcba 235 minimum: 0.01,
dc021bcc 236 history: new CircularArray()
a91f7b35
JB
237 })
238 updateMeasurementStatistics(
239 measurementStatistics,
240 { aggregate: true, average: false, median: false },
dc021bcc 241 0.02
a91f7b35 242 )
997bbcba 243 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
244 aggregate: 0.03,
245 maximum: 0.02,
997bbcba 246 minimum: 0.01,
dc021bcc 247 history: new CircularArray()
a91f7b35
JB
248 })
249 updateMeasurementStatistics(
250 measurementStatistics,
251 { aggregate: true, average: true, median: false },
dc021bcc 252 0.001
a91f7b35 253 )
997bbcba 254 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
255 aggregate: 0.031,
256 maximum: 0.02,
257 minimum: 0.001,
dc021bcc
JB
258 average: 0.001,
259 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
260 })
261 updateMeasurementStatistics(
262 measurementStatistics,
263 { aggregate: true, average: true, median: false },
264 0.003
265 )
266 expect(measurementStatistics).toStrictEqual({
267 aggregate: 0.034,
268 maximum: 0.02,
269 minimum: 0.001,
270 average: 0.002,
271 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
a91f7b35 272 })
bdb9d712
JB
273 updateMeasurementStatistics(
274 measurementStatistics,
275 { aggregate: true, average: false, median: true },
276 0.006
277 )
278 expect(measurementStatistics).toStrictEqual({
279 aggregate: 0.04,
280 maximum: 0.02,
281 minimum: 0.001,
282 median: 0.003,
283 history: new CircularArray(
284 DEFAULT_CIRCULAR_ARRAY_SIZE,
285 0.001,
286 0.003,
287 0.006
288 )
289 })
290 updateMeasurementStatistics(
291 measurementStatistics,
292 { aggregate: true, average: true, median: false },
293 0.01
294 )
295 expect(measurementStatistics).toStrictEqual({
296 aggregate: 0.05,
297 maximum: 0.02,
298 minimum: 0.001,
299 average: 0.005,
300 history: new CircularArray(
301 DEFAULT_CIRCULAR_ARRAY_SIZE,
302 0.001,
303 0.003,
304 0.006,
305 0.01
306 )
307 })
a91f7b35 308 })
970b38d6
JB
309
310 it('Verify secureRandom() behavior', () => {
311 const randomNumber = secureRandom()
312 expect(typeof randomNumber === 'number').toBe(true)
313 expect(randomNumber).toBeGreaterThanOrEqual(0)
314 expect(randomNumber).toBeLessThan(1)
315 })
90d6701c
JB
316
317 it('Verify min() behavior', () => {
625449e0 318 expect(min()).toBe(Infinity)
90d6701c
JB
319 expect(min(1, 2)).toBe(1)
320 expect(min(2, 1)).toBe(1)
321 expect(min(1, 1)).toBe(1)
322 })
323
324 it('Verify max() behavior', () => {
625449e0 325 expect(max()).toBe(-Infinity)
90d6701c
JB
326 expect(max(1, 2)).toBe(2)
327 expect(max(2, 1)).toBe(2)
328 expect(max(1, 1)).toBe(1)
329 })
aba955e1 330})