perf: avoid branching on pool type
[poolifier.git] / tests / utils.test.mjs
CommitLineData
a074ffee
JB
1import { Worker } from 'node:worker_threads'
2import cluster from 'node:cluster'
3import os from 'node:os'
4import { randomInt } from 'node:crypto'
5import { expect } from 'expect'
6import {
9274aa14
JB
7 DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
8 DEFAULT_TASK_NAME,
9274aa14 9 EMPTY_FUNCTION,
afe0d5bf 10 availableParallelism,
dc021bcc 11 average,
00e1bdeb 12 buildInternalWorkerChoiceStrategyOptions,
98446b39 13 exponentialDelay,
9fe8fd69 14 getWorkerId,
a074ffee 15 getWorkerType,
78ac1a90 16 isAsyncFunction,
59317253 17 isKillBehavior,
afe0d5bf 18 isPlainObject,
90d6701c 19 max,
afe0d5bf 20 median,
90d6701c 21 min,
55082af9 22 // once,
a91f7b35 23 round,
970b38d6 24 secureRandom,
bfc75cca 25 sleep
a074ffee
JB
26} from '../lib/utils.js'
27import { KillBehaviors, WorkerTypes } from '../lib/index.js'
aba955e1
JB
28
29describe('Utils test suite', () => {
9274aa14
JB
30 it('Verify DEFAULT_TASK_NAME value', () => {
31 expect(DEFAULT_TASK_NAME).toBe('default')
32 })
33
34 it('Verify EMPTY_FUNCTION value', () => {
35 expect(EMPTY_FUNCTION).toStrictEqual(expect.any(Function))
36 })
37
9274aa14
JB
38 it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => {
39 expect(DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS).toStrictEqual({
40 aggregate: false,
41 average: false,
42 median: false
43 })
44 })
45
afe0d5bf 46 it('Verify availableParallelism() behavior', () => {
9fe8fd69
JB
47 const parallelism = availableParallelism()
48 expect(typeof parallelism === 'number').toBe(true)
37e31fac 49 expect(Number.isSafeInteger(parallelism)).toBe(true)
562a4037
JB
50 let expectedParallelism = 1
51 try {
52 expectedParallelism = os.availableParallelism()
53 } catch {
54 expectedParallelism = os.cpus().length
55 }
56 expect(parallelism).toBe(expectedParallelism)
9fe8fd69
JB
57 })
58
59 it('Verify getWorkerType() behavior', () => {
60 expect(
b2fd3f4a 61 getWorkerType(new Worker('./tests/worker-files/thread/testWorker.mjs'))
9fe8fd69
JB
62 ).toBe(WorkerTypes.thread)
63 expect(getWorkerType(cluster.fork())).toBe(WorkerTypes.cluster)
64 })
65
66 it('Verify getWorkerId() behavior', () => {
b2fd3f4a
JB
67 const threadWorker = new Worker(
68 './tests/worker-files/thread/testWorker.mjs'
69 )
9fe8fd69
JB
70 const clusterWorker = cluster.fork()
71 expect(getWorkerId(threadWorker)).toBe(threadWorker.threadId)
72 expect(getWorkerId(clusterWorker)).toBe(clusterWorker.id)
afe0d5bf
JB
73 })
74
bb9423b7 75 it('Verify sleep() behavior', async () => {
65deb7f0 76 const start = performance.now()
b91134ce
JB
77 const sleepMs = 1000
78 await sleep(sleepMs)
6543999f 79 const elapsed = performance.now() - start
b91134ce 80 expect(elapsed).toBeGreaterThanOrEqual(sleepMs - 1)
98446b39
JB
81 })
82
83 it('Verify exponentialDelay() behavior', () => {
1f0766e7
JB
84 const delay = exponentialDelay(randomInt(1000))
85 expect(typeof delay === 'number').toBe(true)
86 expect(delay).toBeGreaterThanOrEqual(Number.MIN_VALUE)
87 expect(delay).toBeLessThanOrEqual(Number.MAX_VALUE)
98446b39
JB
88 })
89
dc021bcc
JB
90 it('Verify average() computation', () => {
91 expect(average([])).toBe(0)
92 expect(average([0.08])).toBe(0.08)
93 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(
94 3.1642857142857146
95 )
96 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(
97 2.8533333333333335
98 )
99 })
100
bb615bd0 101 it('Verify median() computation', () => {
4a45e8d2 102 expect(median([])).toBe(0)
76845835
JB
103 expect(median([0.08])).toBe(0.08)
104 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05)
105 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535)
aba955e1
JB
106 })
107
afe0d5bf
JB
108 it('Verify round() behavior', () => {
109 expect(round(0)).toBe(0)
110 expect(round(0.5, 0)).toBe(1)
111 expect(round(0.5)).toBe(0.5)
112 expect(round(-0.5, 0)).toBe(-1)
113 expect(round(-0.5)).toBe(-0.5)
114 expect(round(1.005)).toBe(1.01)
115 expect(round(2.175)).toBe(2.18)
116 expect(round(5.015)).toBe(5.02)
117 expect(round(-1.005)).toBe(-1.01)
118 expect(round(-2.175)).toBe(-2.18)
119 expect(round(-5.015)).toBe(-5.02)
120 })
121
aba955e1
JB
122 it('Verify isPlainObject() behavior', () => {
123 expect(isPlainObject(null)).toBe(false)
124 expect(isPlainObject(undefined)).toBe(false)
125 expect(isPlainObject(true)).toBe(false)
126 expect(isPlainObject(false)).toBe(false)
127 expect(isPlainObject(0)).toBe(false)
128 expect(isPlainObject('')).toBe(false)
129 expect(isPlainObject([])).toBe(false)
130 expect(isPlainObject(() => {})).toBe(false)
131 expect(isPlainObject(new Date())).toBe(false)
132 expect(isPlainObject(new RegExp())).toBe(false)
133 expect(isPlainObject(new Error())).toBe(false)
134 expect(isPlainObject(new Map())).toBe(false)
135 expect(isPlainObject(new Set())).toBe(false)
136 expect(isPlainObject(new WeakMap())).toBe(false)
137 expect(isPlainObject(new WeakSet())).toBe(false)
138 expect(isPlainObject(new Int8Array())).toBe(false)
139 expect(isPlainObject(new Uint8Array())).toBe(false)
140 expect(isPlainObject(new Uint8ClampedArray())).toBe(false)
141 expect(isPlainObject(new Int16Array())).toBe(false)
142 expect(isPlainObject(new Uint16Array())).toBe(false)
143 expect(isPlainObject(new Int32Array())).toBe(false)
144 expect(isPlainObject(new Uint32Array())).toBe(false)
145 expect(isPlainObject(new Float32Array())).toBe(false)
146 expect(isPlainObject(new Float64Array())).toBe(false)
147 expect(isPlainObject(new BigInt64Array())).toBe(false)
148 expect(isPlainObject(new BigUint64Array())).toBe(false)
149 expect(isPlainObject(new Promise(() => {}))).toBe(false)
150 expect(isPlainObject(new WeakRef({}))).toBe(false)
151 expect(isPlainObject(new FinalizationRegistry(() => {}))).toBe(false)
152 expect(isPlainObject(new ArrayBuffer())).toBe(false)
153 expect(isPlainObject(new SharedArrayBuffer())).toBe(false)
154 expect(isPlainObject(new DataView(new ArrayBuffer()))).toBe(false)
155 expect(isPlainObject({})).toBe(true)
156 expect(isPlainObject({ a: 1 })).toBe(true)
157 })
47aacbaa
JB
158
159 it('Verify isKillBehavior() behavior', () => {
160 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.SOFT)).toBe(true)
161 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.HARD)).toBe(false)
162 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.HARD)).toBe(true)
163 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.SOFT)).toBe(false)
164 expect(isKillBehavior(KillBehaviors.SOFT)).toBe(false)
165 expect(isKillBehavior(KillBehaviors.HARD)).toBe(false)
166 expect(isKillBehavior(KillBehaviors.HARD, null)).toBe(false)
78ac1a90 167 expect(isKillBehavior(KillBehaviors.HARD, undefined)).toBe(false)
47aacbaa
JB
168 expect(isKillBehavior(KillBehaviors.SOFT, 'unknown')).toBe(false)
169 })
78ac1a90
JB
170
171 it('Verify isAsyncFunction() behavior', () => {
172 expect(isAsyncFunction(null)).toBe(false)
173 expect(isAsyncFunction(undefined)).toBe(false)
174 expect(isAsyncFunction(true)).toBe(false)
175 expect(isAsyncFunction(false)).toBe(false)
176 expect(isAsyncFunction(0)).toBe(false)
177 expect(isAsyncFunction('')).toBe(false)
178 expect(isAsyncFunction([])).toBe(false)
179 expect(isAsyncFunction(new Date())).toBe(false)
180 expect(isAsyncFunction(new RegExp())).toBe(false)
181 expect(isAsyncFunction(new Error())).toBe(false)
182 expect(isAsyncFunction(new Map())).toBe(false)
183 expect(isAsyncFunction(new Set())).toBe(false)
184 expect(isAsyncFunction(new WeakMap())).toBe(false)
185 expect(isAsyncFunction(new WeakSet())).toBe(false)
186 expect(isAsyncFunction(new Int8Array())).toBe(false)
187 expect(isAsyncFunction(new Uint8Array())).toBe(false)
188 expect(isAsyncFunction(new Uint8ClampedArray())).toBe(false)
189 expect(isAsyncFunction(new Int16Array())).toBe(false)
190 expect(isAsyncFunction(new Uint16Array())).toBe(false)
191 expect(isAsyncFunction(new Int32Array())).toBe(false)
192 expect(isAsyncFunction(new Uint32Array())).toBe(false)
193 expect(isAsyncFunction(new Float32Array())).toBe(false)
194 expect(isAsyncFunction(new Float64Array())).toBe(false)
195 expect(isAsyncFunction(new BigInt64Array())).toBe(false)
196 expect(isAsyncFunction(new BigUint64Array())).toBe(false)
197 expect(isAsyncFunction(new Promise(() => {}))).toBe(false)
198 expect(isAsyncFunction(new WeakRef({}))).toBe(false)
199 expect(isAsyncFunction(new FinalizationRegistry(() => {}))).toBe(false)
200 expect(isAsyncFunction(new ArrayBuffer())).toBe(false)
201 expect(isAsyncFunction(new SharedArrayBuffer())).toBe(false)
202 expect(isAsyncFunction(new DataView(new ArrayBuffer()))).toBe(false)
203 expect(isAsyncFunction({})).toBe(false)
204 expect(isAsyncFunction({ a: 1 })).toBe(false)
205 expect(isAsyncFunction(() => {})).toBe(false)
206 expect(isAsyncFunction(function () {})).toBe(false)
207 expect(isAsyncFunction(function named () {})).toBe(false)
208 expect(isAsyncFunction(async () => {})).toBe(true)
209 expect(isAsyncFunction(async function () {})).toBe(true)
210 expect(isAsyncFunction(async function named () {})).toBe(true)
211 })
a91f7b35 212
970b38d6
JB
213 it('Verify secureRandom() behavior', () => {
214 const randomNumber = secureRandom()
215 expect(typeof randomNumber === 'number').toBe(true)
216 expect(randomNumber).toBeGreaterThanOrEqual(0)
217 expect(randomNumber).toBeLessThan(1)
218 })
90d6701c
JB
219
220 it('Verify min() behavior', () => {
625449e0 221 expect(min()).toBe(Infinity)
90d6701c
JB
222 expect(min(1, 2)).toBe(1)
223 expect(min(2, 1)).toBe(1)
224 expect(min(1, 1)).toBe(1)
225 })
226
227 it('Verify max() behavior', () => {
625449e0 228 expect(max()).toBe(-Infinity)
90d6701c
JB
229 expect(max(1, 2)).toBe(2)
230 expect(max(2, 1)).toBe(2)
231 expect(max(1, 1)).toBe(1)
232 })
d91689fd 233
00e1bdeb
JB
234 it('Verify buildInternalWorkerChoiceStrategyOptions() behavior', () => {
235 const poolMaxSize = 10
236 const internalWorkerChoiceStrategyOptions =
237 buildInternalWorkerChoiceStrategyOptions(poolMaxSize)
238 expect(internalWorkerChoiceStrategyOptions).toStrictEqual({
239 retries:
240 poolMaxSize +
241 Object.keys(internalWorkerChoiceStrategyOptions.weights).length,
242 runTime: { median: false },
243 waitTime: { median: false },
244 elu: { median: false },
245 weights: expect.objectContaining({
246 0: expect.any(Number),
247 [poolMaxSize - 1]: expect.any(Number)
248 })
249 })
250 })
251
55082af9
JB
252 // it('Verify once()', () => {
253 // let called = 0
254 // const fn = () => ++called
255 // const onceFn = once(fn, this)
256 // const result1 = onceFn()
257 // expect(called).toBe(1)
258 // expect(result1).toBe(1)
259 // const result2 = onceFn()
260 // expect(called).toBe(1)
261 // expect(result2).toBe(1)
262 // const result3 = onceFn()
263 // expect(called).toBe(1)
264 // expect(result3).toBe(1)
265 // })
aba955e1 266})