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