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