test: refine UTs
[poolifier.git] / tests / utils.test.js
CommitLineData
98446b39 1const { randomInt } = require('crypto')
9fe8fd69
JB
2const { Worker } = require('worker_threads')
3const cluster = require('cluster')
562a4037 4const os = require('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
JB
22 isPlainObject,
23 median,
a91f7b35 24 round,
970b38d6 25 secureRandom,
98446b39 26 sleep,
a91f7b35 27 updateMeasurementStatistics
afe0d5bf 28} = require('../lib/utils')
9fe8fd69 29const { KillBehaviors, WorkerTypes } = require('../lib')
aba955e1
JB
30
31describe('Utils test suite', () => {
9274aa14
JB
32 it('Verify DEFAULT_TASK_NAME value', () => {
33 expect(DEFAULT_TASK_NAME).toBe('default')
34 })
35
36 it('Verify EMPTY_FUNCTION value', () => {
37 expect(EMPTY_FUNCTION).toStrictEqual(expect.any(Function))
38 })
39
40 it('Verify DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS values', () => {
41 expect(DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS).toStrictEqual({
42 retries: 6,
43 runTime: { median: false },
44 waitTime: { median: false },
45 elu: { median: false }
46 })
47 })
48
49 it('Verify DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS values', () => {
50 expect(DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS).toStrictEqual({
51 aggregate: false,
52 average: false,
53 median: false
54 })
55 })
56
afe0d5bf 57 it('Verify availableParallelism() behavior', () => {
9fe8fd69
JB
58 const parallelism = availableParallelism()
59 expect(typeof parallelism === 'number').toBe(true)
562a4037
JB
60 let expectedParallelism = 1
61 try {
62 expectedParallelism = os.availableParallelism()
63 } catch {
64 expectedParallelism = os.cpus().length
65 }
66 expect(parallelism).toBe(expectedParallelism)
9fe8fd69
JB
67 expect(Number.isSafeInteger(parallelism)).toBe(true)
68 })
69
70 it('Verify getWorkerType() behavior', () => {
71 expect(
72 getWorkerType(new Worker('./tests/worker-files/thread/testWorker.js'))
73 ).toBe(WorkerTypes.thread)
74 expect(getWorkerType(cluster.fork())).toBe(WorkerTypes.cluster)
75 })
76
77 it('Verify getWorkerId() behavior', () => {
78 const threadWorker = new Worker('./tests/worker-files/thread/testWorker.js')
79 const clusterWorker = cluster.fork()
80 expect(getWorkerId(threadWorker)).toBe(threadWorker.threadId)
81 expect(getWorkerId(clusterWorker)).toBe(clusterWorker.id)
afe0d5bf
JB
82 })
83
bb9423b7 84 it('Verify sleep() behavior', async () => {
65deb7f0 85 const start = performance.now()
98446b39 86 await sleep(1000)
6543999f 87 const elapsed = performance.now() - start
4be58f3c 88 expect(elapsed).toBeGreaterThanOrEqual(999)
98446b39
JB
89 })
90
91 it('Verify exponentialDelay() behavior', () => {
1f0766e7
JB
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)
98446b39
JB
96 })
97
dc021bcc
JB
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
bb615bd0 109 it('Verify median() computation', () => {
4a45e8d2 110 expect(median([])).toBe(0)
76845835
JB
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)
aba955e1
JB
114 })
115
afe0d5bf
JB
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
aba955e1
JB
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 })
47aacbaa
JB
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)
78ac1a90 175 expect(isKillBehavior(KillBehaviors.HARD, undefined)).toBe(false)
47aacbaa
JB
176 expect(isKillBehavior(KillBehaviors.SOFT, 'unknown')).toBe(false)
177 })
78ac1a90
JB
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 })
a91f7b35
JB
220
221 it('Verify updateMeasurementStatistics() behavior', () => {
997bbcba
JB
222 const measurementStatistics = {
223 history: new CircularArray()
224 }
a91f7b35
JB
225 updateMeasurementStatistics(
226 measurementStatistics,
227 { aggregate: true, average: false, median: false },
dc021bcc 228 0.01
a91f7b35 229 )
997bbcba 230 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
231 aggregate: 0.01,
232 maximum: 0.01,
997bbcba 233 minimum: 0.01,
dc021bcc 234 history: new CircularArray()
a91f7b35
JB
235 })
236 updateMeasurementStatistics(
237 measurementStatistics,
238 { aggregate: true, average: false, median: false },
dc021bcc 239 0.02
a91f7b35 240 )
997bbcba 241 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
242 aggregate: 0.03,
243 maximum: 0.02,
997bbcba 244 minimum: 0.01,
dc021bcc 245 history: new CircularArray()
a91f7b35
JB
246 })
247 updateMeasurementStatistics(
248 measurementStatistics,
249 { aggregate: true, average: true, median: false },
dc021bcc 250 0.001
a91f7b35 251 )
997bbcba 252 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
253 aggregate: 0.031,
254 maximum: 0.02,
255 minimum: 0.001,
dc021bcc
JB
256 average: 0.001,
257 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
258 })
259 updateMeasurementStatistics(
260 measurementStatistics,
261 { aggregate: true, average: true, median: false },
262 0.003
263 )
264 expect(measurementStatistics).toStrictEqual({
265 aggregate: 0.034,
266 maximum: 0.02,
267 minimum: 0.001,
268 average: 0.002,
269 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
a91f7b35 270 })
bdb9d712
JB
271 updateMeasurementStatistics(
272 measurementStatistics,
273 { aggregate: true, average: false, median: true },
274 0.006
275 )
276 expect(measurementStatistics).toStrictEqual({
277 aggregate: 0.04,
278 maximum: 0.02,
279 minimum: 0.001,
280 median: 0.003,
281 history: new CircularArray(
282 DEFAULT_CIRCULAR_ARRAY_SIZE,
283 0.001,
284 0.003,
285 0.006
286 )
287 })
288 updateMeasurementStatistics(
289 measurementStatistics,
290 { aggregate: true, average: true, median: false },
291 0.01
292 )
293 expect(measurementStatistics).toStrictEqual({
294 aggregate: 0.05,
295 maximum: 0.02,
296 minimum: 0.001,
297 average: 0.005,
298 history: new CircularArray(
299 DEFAULT_CIRCULAR_ARRAY_SIZE,
300 0.001,
301 0.003,
302 0.006,
303 0.01
304 )
305 })
a91f7b35 306 })
970b38d6
JB
307
308 it('Verify secureRandom() behavior', () => {
309 const randomNumber = secureRandom()
310 expect(typeof randomNumber === 'number').toBe(true)
311 expect(randomNumber).toBeGreaterThanOrEqual(0)
312 expect(randomNumber).toBeLessThan(1)
313 })
aba955e1 314})