perf: fine tune continuous task stealing algorithm
[poolifier.git] / tests / utils.test.js
CommitLineData
98446b39 1const { randomInt } = require('crypto')
aba955e1 2const { expect } = require('expect')
dc021bcc
JB
3const {
4 CircularArray,
5 DEFAULT_CIRCULAR_ARRAY_SIZE
6} = require('../lib/circular-array')
afe0d5bf
JB
7const {
8 availableParallelism,
dc021bcc 9 average,
98446b39 10 exponentialDelay,
78ac1a90 11 isAsyncFunction,
59317253 12 isKillBehavior,
afe0d5bf
JB
13 isPlainObject,
14 median,
a91f7b35 15 round,
970b38d6 16 secureRandom,
98446b39 17 sleep,
a91f7b35 18 updateMeasurementStatistics
afe0d5bf 19} = require('../lib/utils')
59317253 20const { KillBehaviors } = require('../lib/worker/worker-options')
aba955e1
JB
21
22describe('Utils test suite', () => {
afe0d5bf
JB
23 it('Verify availableParallelism() behavior', () => {
24 expect(typeof availableParallelism() === 'number').toBe(true)
51c90525
JB
25 expect(availableParallelism()).toBeGreaterThan(0)
26 expect(Number.isSafeInteger(availableParallelism())).toBe(true)
afe0d5bf
JB
27 })
28
6543999f 29 it.skip('Verify sleep() behavior', async () => {
65deb7f0 30 const start = performance.now()
98446b39 31 await sleep(1000)
6543999f
JB
32 const elapsed = performance.now() - start
33 expect(elapsed).toBeGreaterThanOrEqual(1000)
98446b39
JB
34 })
35
36 it('Verify exponentialDelay() behavior', () => {
1f0766e7
JB
37 const delay = exponentialDelay(randomInt(1000))
38 expect(typeof delay === 'number').toBe(true)
39 expect(delay).toBeGreaterThanOrEqual(Number.MIN_VALUE)
40 expect(delay).toBeLessThanOrEqual(Number.MAX_VALUE)
98446b39
JB
41 })
42
dc021bcc
JB
43 it('Verify average() computation', () => {
44 expect(average([])).toBe(0)
45 expect(average([0.08])).toBe(0.08)
46 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(
47 3.1642857142857146
48 )
49 expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(
50 2.8533333333333335
51 )
52 })
53
bb615bd0 54 it('Verify median() computation', () => {
4a45e8d2 55 expect(median([])).toBe(0)
76845835
JB
56 expect(median([0.08])).toBe(0.08)
57 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05)
58 expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535)
aba955e1
JB
59 })
60
afe0d5bf
JB
61 it('Verify round() behavior', () => {
62 expect(round(0)).toBe(0)
63 expect(round(0.5, 0)).toBe(1)
64 expect(round(0.5)).toBe(0.5)
65 expect(round(-0.5, 0)).toBe(-1)
66 expect(round(-0.5)).toBe(-0.5)
67 expect(round(1.005)).toBe(1.01)
68 expect(round(2.175)).toBe(2.18)
69 expect(round(5.015)).toBe(5.02)
70 expect(round(-1.005)).toBe(-1.01)
71 expect(round(-2.175)).toBe(-2.18)
72 expect(round(-5.015)).toBe(-5.02)
73 })
74
aba955e1
JB
75 it('Verify isPlainObject() behavior', () => {
76 expect(isPlainObject(null)).toBe(false)
77 expect(isPlainObject(undefined)).toBe(false)
78 expect(isPlainObject(true)).toBe(false)
79 expect(isPlainObject(false)).toBe(false)
80 expect(isPlainObject(0)).toBe(false)
81 expect(isPlainObject('')).toBe(false)
82 expect(isPlainObject([])).toBe(false)
83 expect(isPlainObject(() => {})).toBe(false)
84 expect(isPlainObject(new Date())).toBe(false)
85 expect(isPlainObject(new RegExp())).toBe(false)
86 expect(isPlainObject(new Error())).toBe(false)
87 expect(isPlainObject(new Map())).toBe(false)
88 expect(isPlainObject(new Set())).toBe(false)
89 expect(isPlainObject(new WeakMap())).toBe(false)
90 expect(isPlainObject(new WeakSet())).toBe(false)
91 expect(isPlainObject(new Int8Array())).toBe(false)
92 expect(isPlainObject(new Uint8Array())).toBe(false)
93 expect(isPlainObject(new Uint8ClampedArray())).toBe(false)
94 expect(isPlainObject(new Int16Array())).toBe(false)
95 expect(isPlainObject(new Uint16Array())).toBe(false)
96 expect(isPlainObject(new Int32Array())).toBe(false)
97 expect(isPlainObject(new Uint32Array())).toBe(false)
98 expect(isPlainObject(new Float32Array())).toBe(false)
99 expect(isPlainObject(new Float64Array())).toBe(false)
100 expect(isPlainObject(new BigInt64Array())).toBe(false)
101 expect(isPlainObject(new BigUint64Array())).toBe(false)
102 expect(isPlainObject(new Promise(() => {}))).toBe(false)
103 expect(isPlainObject(new WeakRef({}))).toBe(false)
104 expect(isPlainObject(new FinalizationRegistry(() => {}))).toBe(false)
105 expect(isPlainObject(new ArrayBuffer())).toBe(false)
106 expect(isPlainObject(new SharedArrayBuffer())).toBe(false)
107 expect(isPlainObject(new DataView(new ArrayBuffer()))).toBe(false)
108 expect(isPlainObject({})).toBe(true)
109 expect(isPlainObject({ a: 1 })).toBe(true)
110 })
47aacbaa
JB
111
112 it('Verify isKillBehavior() behavior', () => {
113 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.SOFT)).toBe(true)
114 expect(isKillBehavior(KillBehaviors.SOFT, KillBehaviors.HARD)).toBe(false)
115 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.HARD)).toBe(true)
116 expect(isKillBehavior(KillBehaviors.HARD, KillBehaviors.SOFT)).toBe(false)
117 expect(isKillBehavior(KillBehaviors.SOFT)).toBe(false)
118 expect(isKillBehavior(KillBehaviors.HARD)).toBe(false)
119 expect(isKillBehavior(KillBehaviors.HARD, null)).toBe(false)
78ac1a90 120 expect(isKillBehavior(KillBehaviors.HARD, undefined)).toBe(false)
47aacbaa
JB
121 expect(isKillBehavior(KillBehaviors.SOFT, 'unknown')).toBe(false)
122 })
78ac1a90
JB
123
124 it('Verify isAsyncFunction() behavior', () => {
125 expect(isAsyncFunction(null)).toBe(false)
126 expect(isAsyncFunction(undefined)).toBe(false)
127 expect(isAsyncFunction(true)).toBe(false)
128 expect(isAsyncFunction(false)).toBe(false)
129 expect(isAsyncFunction(0)).toBe(false)
130 expect(isAsyncFunction('')).toBe(false)
131 expect(isAsyncFunction([])).toBe(false)
132 expect(isAsyncFunction(new Date())).toBe(false)
133 expect(isAsyncFunction(new RegExp())).toBe(false)
134 expect(isAsyncFunction(new Error())).toBe(false)
135 expect(isAsyncFunction(new Map())).toBe(false)
136 expect(isAsyncFunction(new Set())).toBe(false)
137 expect(isAsyncFunction(new WeakMap())).toBe(false)
138 expect(isAsyncFunction(new WeakSet())).toBe(false)
139 expect(isAsyncFunction(new Int8Array())).toBe(false)
140 expect(isAsyncFunction(new Uint8Array())).toBe(false)
141 expect(isAsyncFunction(new Uint8ClampedArray())).toBe(false)
142 expect(isAsyncFunction(new Int16Array())).toBe(false)
143 expect(isAsyncFunction(new Uint16Array())).toBe(false)
144 expect(isAsyncFunction(new Int32Array())).toBe(false)
145 expect(isAsyncFunction(new Uint32Array())).toBe(false)
146 expect(isAsyncFunction(new Float32Array())).toBe(false)
147 expect(isAsyncFunction(new Float64Array())).toBe(false)
148 expect(isAsyncFunction(new BigInt64Array())).toBe(false)
149 expect(isAsyncFunction(new BigUint64Array())).toBe(false)
150 expect(isAsyncFunction(new Promise(() => {}))).toBe(false)
151 expect(isAsyncFunction(new WeakRef({}))).toBe(false)
152 expect(isAsyncFunction(new FinalizationRegistry(() => {}))).toBe(false)
153 expect(isAsyncFunction(new ArrayBuffer())).toBe(false)
154 expect(isAsyncFunction(new SharedArrayBuffer())).toBe(false)
155 expect(isAsyncFunction(new DataView(new ArrayBuffer()))).toBe(false)
156 expect(isAsyncFunction({})).toBe(false)
157 expect(isAsyncFunction({ a: 1 })).toBe(false)
158 expect(isAsyncFunction(() => {})).toBe(false)
159 expect(isAsyncFunction(function () {})).toBe(false)
160 expect(isAsyncFunction(function named () {})).toBe(false)
161 expect(isAsyncFunction(async () => {})).toBe(true)
162 expect(isAsyncFunction(async function () {})).toBe(true)
163 expect(isAsyncFunction(async function named () {})).toBe(true)
164 })
a91f7b35
JB
165
166 it('Verify updateMeasurementStatistics() behavior', () => {
997bbcba
JB
167 const measurementStatistics = {
168 history: new CircularArray()
169 }
a91f7b35
JB
170 updateMeasurementStatistics(
171 measurementStatistics,
172 { aggregate: true, average: false, median: false },
dc021bcc 173 0.01
a91f7b35 174 )
997bbcba 175 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
176 aggregate: 0.01,
177 maximum: 0.01,
997bbcba 178 minimum: 0.01,
dc021bcc 179 history: new CircularArray()
a91f7b35
JB
180 })
181 updateMeasurementStatistics(
182 measurementStatistics,
183 { aggregate: true, average: false, median: false },
dc021bcc 184 0.02
a91f7b35 185 )
997bbcba 186 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
187 aggregate: 0.03,
188 maximum: 0.02,
997bbcba 189 minimum: 0.01,
dc021bcc 190 history: new CircularArray()
a91f7b35
JB
191 })
192 updateMeasurementStatistics(
193 measurementStatistics,
194 { aggregate: true, average: true, median: false },
dc021bcc 195 0.001
a91f7b35 196 )
997bbcba 197 expect(measurementStatistics).toStrictEqual({
a91f7b35
JB
198 aggregate: 0.031,
199 maximum: 0.02,
200 minimum: 0.001,
dc021bcc
JB
201 average: 0.001,
202 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
203 })
204 updateMeasurementStatistics(
205 measurementStatistics,
206 { aggregate: true, average: true, median: false },
207 0.003
208 )
209 expect(measurementStatistics).toStrictEqual({
210 aggregate: 0.034,
211 maximum: 0.02,
212 minimum: 0.001,
213 average: 0.002,
214 history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
a91f7b35
JB
215 })
216 })
970b38d6
JB
217
218 it('Verify secureRandom() behavior', () => {
219 const randomNumber = secureRandom()
220 expect(typeof randomNumber === 'number').toBe(true)
221 expect(randomNumber).toBeGreaterThanOrEqual(0)
222 expect(randomNumber).toBeLessThan(1)
223 })
aba955e1 224})