Merge pull request #1250 from poolifier/combined-prs-branch
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 20 Sep 2023 04:08:43 +0000 (06:08 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Sep 2023 04:08:43 +0000 (06:08 +0200)
Combined PRs

src/pools/abstract-pool.ts
src/pools/utils.ts
src/pools/worker-node.ts
src/utils.ts
src/worker/abstract-worker.ts
src/worker/utils.ts [new file with mode: 0644]
tests/pools/abstract-pool.test.js [moved from tests/pools/abstract/abstract-pool.test.js with 99% similarity]
tests/pools/utils.test.js [new file with mode: 0644]
tests/pools/worker-node.test.js [moved from tests/pools/abstract/worker-node.test.js with 96% similarity]
tests/utils.test.js

index ce59c992f81a08d52ba2e42c2f1b1443c9979b72..52f9c0e3fc25aeb6a2169cf49243cfacb03d2153 100644 (file)
@@ -16,8 +16,7 @@ import {
   max,
   median,
   min,
-  round,
-  updateMeasurementStatistics
+  round
 } from '../utils'
 import { KillBehaviors } from '../worker/worker-options'
 import type { TaskFunction } from '../worker/task-functions'
@@ -51,7 +50,8 @@ import { WorkerNode } from './worker-node'
 import {
   checkFilePath,
   checkValidTasksQueueOptions,
-  checkValidWorkerChoiceStrategy
+  checkValidWorkerChoiceStrategy,
+  updateMeasurementStatistics
 } from './utils'
 
 /**
index 4aac5cda47d361fd723198a53ad44f254235b56c..e08b31aa838537c1ceee37f284ff39ac53960308 100644 (file)
@@ -1,10 +1,12 @@
 import { existsSync } from 'node:fs'
-import { isPlainObject } from '../utils'
+import { average, isPlainObject, max, median, min } from '../utils'
 import {
+  type MeasurementStatisticsRequirements,
   WorkerChoiceStrategies,
   type WorkerChoiceStrategy
 } from './selection-strategies/selection-strategies-types'
 import type { TasksQueueOptions } from './pool'
+import type { IWorker, MeasurementStatistics } from './worker'
 
 export const checkFilePath = (filePath: string): void => {
   if (
@@ -90,3 +92,71 @@ export const checkValidTasksQueueOptions = (
     )
   }
 }
+
+export const checkWorkerNodeArguments = <Worker extends IWorker>(
+  worker: Worker,
+  tasksQueueBackPressureSize: number
+): void => {
+  if (worker == null) {
+    throw new TypeError('Cannot construct a worker node without a worker')
+  }
+  if (tasksQueueBackPressureSize == null) {
+    throw new TypeError(
+      'Cannot construct a worker node without a tasks queue back pressure size'
+    )
+  }
+  if (!Number.isSafeInteger(tasksQueueBackPressureSize)) {
+    throw new TypeError(
+      'Cannot construct a worker node with a tasks queue back pressure size that is not an integer'
+    )
+  }
+  if (tasksQueueBackPressureSize <= 0) {
+    throw new RangeError(
+      'Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer'
+    )
+  }
+}
+
+/**
+ * Updates the given measurement statistics.
+ *
+ * @param measurementStatistics - The measurement statistics to update.
+ * @param measurementRequirements - The measurement statistics requirements.
+ * @param measurementValue - The measurement value.
+ * @param numberOfMeasurements - The number of measurements.
+ * @internal
+ */
+export const updateMeasurementStatistics = (
+  measurementStatistics: MeasurementStatistics,
+  measurementRequirements: MeasurementStatisticsRequirements,
+  measurementValue: number
+): void => {
+  if (measurementRequirements.aggregate) {
+    measurementStatistics.aggregate =
+      (measurementStatistics.aggregate ?? 0) + measurementValue
+    measurementStatistics.minimum = min(
+      measurementValue,
+      measurementStatistics.minimum ?? Infinity
+    )
+    measurementStatistics.maximum = max(
+      measurementValue,
+      measurementStatistics.maximum ?? -Infinity
+    )
+    if (
+      (measurementRequirements.average || measurementRequirements.median) &&
+      measurementValue != null
+    ) {
+      measurementStatistics.history.push(measurementValue)
+      if (measurementRequirements.average) {
+        measurementStatistics.average = average(measurementStatistics.history)
+      } else if (measurementStatistics.average != null) {
+        delete measurementStatistics.average
+      }
+      if (measurementRequirements.median) {
+        measurementStatistics.median = median(measurementStatistics.history)
+      } else if (measurementStatistics.median != null) {
+        delete measurementStatistics.median
+      }
+    }
+  }
+}
index e9680261b591e26707c11c5ca868873f3ca5a6e4..5a25f8d9bf233c4afdd205bfd504a6e43be23aab 100644 (file)
@@ -20,6 +20,7 @@ import {
   WorkerTypes,
   type WorkerUsage
 } from './worker'
+import { checkWorkerNodeArguments } from './utils'
 
 /**
  * Worker node.
@@ -57,7 +58,7 @@ implements IWorkerNode<Worker, Data> {
    * @param tasksQueueBackPressureSize - The tasks queue back pressure size.
    */
   constructor (worker: Worker, tasksQueueBackPressureSize: number) {
-    this.checkWorkerNodeArguments(worker, tasksQueueBackPressureSize)
+    checkWorkerNodeArguments<Worker>(worker, tasksQueueBackPressureSize)
     this.worker = worker
     this.info = this.initWorkerInfo(worker)
     this.usage = this.initWorkerUsage()
@@ -288,28 +289,4 @@ implements IWorkerNode<Worker, Data> {
       }
     }
   }
-
-  private checkWorkerNodeArguments (
-    worker: Worker,
-    tasksQueueBackPressureSize: number
-  ): void {
-    if (worker == null) {
-      throw new TypeError('Cannot construct a worker node without a worker')
-    }
-    if (tasksQueueBackPressureSize == null) {
-      throw new TypeError(
-        'Cannot construct a worker node without a tasks queue back pressure size'
-      )
-    }
-    if (!Number.isSafeInteger(tasksQueueBackPressureSize)) {
-      throw new TypeError(
-        'Cannot construct a worker node with a tasks queue back pressure size that is not an integer'
-      )
-    }
-    if (tasksQueueBackPressureSize <= 0) {
-      throw new RangeError(
-        'Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer'
-      )
-    }
-  }
 }
index 400a92b14a7f42e8518878af1744623c8f6c2290..d7ce5a210f2dea09290fd90a5f4eb64fcb2162d5 100644 (file)
@@ -7,12 +7,7 @@ import type {
   WorkerChoiceStrategyOptions
 } from './pools/selection-strategies/selection-strategies-types'
 import type { KillBehavior } from './worker/worker-options'
-import {
-  type IWorker,
-  type MeasurementStatistics,
-  type WorkerType,
-  WorkerTypes
-} from './pools/worker'
+import { type IWorker, type WorkerType, WorkerTypes } from './pools/worker'
 
 /**
  * Default task name.
@@ -224,50 +219,6 @@ export const isAsyncFunction = (
   return typeof fn === 'function' && fn.constructor.name === 'AsyncFunction'
 }
 
-/**
- * Updates the given measurement statistics.
- *
- * @param measurementStatistics - The measurement statistics to update.
- * @param measurementRequirements - The measurement statistics requirements.
- * @param measurementValue - The measurement value.
- * @param numberOfMeasurements - The number of measurements.
- * @internal
- */
-export const updateMeasurementStatistics = (
-  measurementStatistics: MeasurementStatistics,
-  measurementRequirements: MeasurementStatisticsRequirements,
-  measurementValue: number
-): void => {
-  if (measurementRequirements.aggregate) {
-    measurementStatistics.aggregate =
-      (measurementStatistics.aggregate ?? 0) + measurementValue
-    measurementStatistics.minimum = min(
-      measurementValue,
-      measurementStatistics.minimum ?? Infinity
-    )
-    measurementStatistics.maximum = max(
-      measurementValue,
-      measurementStatistics.maximum ?? -Infinity
-    )
-    if (
-      (measurementRequirements.average || measurementRequirements.median) &&
-      measurementValue != null
-    ) {
-      measurementStatistics.history.push(measurementValue)
-      if (measurementRequirements.average) {
-        measurementStatistics.average = average(measurementStatistics.history)
-      } else if (measurementStatistics.average != null) {
-        delete measurementStatistics.average
-      }
-      if (measurementRequirements.median) {
-        measurementStatistics.median = median(measurementStatistics.history)
-      } else if (measurementStatistics.median != null) {
-        delete measurementStatistics.median
-      }
-    }
-  }
-}
-
 /**
  * Generates a cryptographically secure random number in the [0,1[ range
  *
index fde55a588e85413d1f6bad59d0abffee25d39c73..311a56ad60e00684835e89ef0507d60f0c9d4432 100644 (file)
@@ -22,6 +22,11 @@ import type {
   TaskFunctions,
   TaskSyncFunction
 } from './task-functions'
+import {
+  checkTaskFunctionName,
+  checkValidTaskFunctionEntry,
+  checkValidWorkerOptions
+} from './utils'
 
 const DEFAULT_MAX_INACTIVE_TIME = 60000
 const DEFAULT_WORKER_OPTIONS: WorkerOptions = {
@@ -100,58 +105,10 @@ export abstract class AbstractWorker<
   }
 
   private checkWorkerOptions (opts: WorkerOptions): void {
-    if (opts != null && !isPlainObject(opts)) {
-      throw new TypeError('opts worker options parameter is not a plain object')
-    }
-    if (
-      opts?.killBehavior != null &&
-      !Object.values(KillBehaviors).includes(opts.killBehavior)
-    ) {
-      throw new TypeError(
-        `killBehavior option '${opts.killBehavior}' is not valid`
-      )
-    }
-    if (
-      opts?.maxInactiveTime != null &&
-      !Number.isSafeInteger(opts.maxInactiveTime)
-    ) {
-      throw new TypeError('maxInactiveTime option is not an integer')
-    }
-    if (opts?.maxInactiveTime != null && opts.maxInactiveTime < 5) {
-      throw new TypeError(
-        'maxInactiveTime option is not a positive integer greater or equal than 5'
-      )
-    }
-    if (opts?.killHandler != null && typeof opts.killHandler !== 'function') {
-      throw new TypeError('killHandler option is not a function')
-    }
-    if (opts?.async != null) {
-      throw new Error('async option is deprecated')
-    }
+    checkValidWorkerOptions(opts)
     this.opts = { ...DEFAULT_WORKER_OPTIONS, ...opts }
   }
 
-  private checkValidTaskFunctionEntry (
-    name: string,
-    fn: TaskFunction<Data, Response>
-  ): void {
-    if (typeof name !== 'string') {
-      throw new TypeError(
-        'A taskFunctions parameter object key is not a string'
-      )
-    }
-    if (typeof name === 'string' && name.trim().length === 0) {
-      throw new TypeError(
-        'A taskFunctions parameter object key is an empty string'
-      )
-    }
-    if (typeof fn !== 'function') {
-      throw new TypeError(
-        'A taskFunctions parameter object value is not a function'
-      )
-    }
-  }
-
   /**
    * Checks if the `taskFunctions` parameter is passed to the constructor and valid.
    *
@@ -177,7 +134,7 @@ export abstract class AbstractWorker<
     } else if (isPlainObject(taskFunctions)) {
       let firstEntry = true
       for (const [name, fn] of Object.entries(taskFunctions)) {
-        this.checkValidTaskFunctionEntry(name, fn)
+        checkValidTaskFunctionEntry<Data, Response>(name, fn)
         const boundFn = fn.bind(this)
         if (firstEntry) {
           this.taskFunctions.set(DEFAULT_TASK_NAME, boundFn)
@@ -203,7 +160,7 @@ export abstract class AbstractWorker<
    */
   public hasTaskFunction (name: string): TaskFunctionOperationResult {
     try {
-      this.checkTaskFunctionName(name)
+      checkTaskFunctionName(name)
     } catch (error) {
       return { status: false, error: error as Error }
     }
@@ -223,7 +180,7 @@ export abstract class AbstractWorker<
     fn: TaskFunction<Data, Response>
   ): TaskFunctionOperationResult {
     try {
-      this.checkTaskFunctionName(name)
+      checkTaskFunctionName(name)
       if (name === DEFAULT_TASK_NAME) {
         throw new Error(
           'Cannot add a task function with the default reserved name'
@@ -255,7 +212,7 @@ export abstract class AbstractWorker<
    */
   public removeTaskFunction (name: string): TaskFunctionOperationResult {
     try {
-      this.checkTaskFunctionName(name)
+      checkTaskFunctionName(name)
       if (name === DEFAULT_TASK_NAME) {
         throw new Error(
           'Cannot remove the task function with the default reserved name'
@@ -311,7 +268,7 @@ export abstract class AbstractWorker<
    */
   public setDefaultTaskFunction (name: string): TaskFunctionOperationResult {
     try {
-      this.checkTaskFunctionName(name)
+      checkTaskFunctionName(name)
       if (name === DEFAULT_TASK_NAME) {
         throw new Error(
           'Cannot set the default task function reserved name as the default task function'
@@ -333,15 +290,6 @@ export abstract class AbstractWorker<
     }
   }
 
-  private checkTaskFunctionName (name: string): void {
-    if (typeof name !== 'string') {
-      throw new TypeError('name parameter is not a string')
-    }
-    if (typeof name === 'string' && name.trim().length === 0) {
-      throw new TypeError('name parameter is an empty string')
-    }
-  }
-
   /**
    * Handles the ready message sent by the main worker.
    *
@@ -541,7 +489,6 @@ export abstract class AbstractWorker<
    * Runs the given task.
    *
    * @param task - The task to execute.
-   * @throws {@link https://nodejs.org/api/errors.html#class-error} If the task function is not found.
    */
   protected run (task: Task<Data>): void {
     const { name, taskId, data } = task
diff --git a/src/worker/utils.ts b/src/worker/utils.ts
new file mode 100644 (file)
index 0000000..f88ead7
--- /dev/null
@@ -0,0 +1,62 @@
+import { isPlainObject } from '../utils'
+import type { TaskFunction } from './task-functions'
+import { KillBehaviors, type WorkerOptions } from './worker-options'
+
+export const checkValidWorkerOptions = (opts: WorkerOptions): void => {
+  if (opts != null && !isPlainObject(opts)) {
+    throw new TypeError('opts worker options parameter is not a plain object')
+  }
+  if (
+    opts?.killBehavior != null &&
+    !Object.values(KillBehaviors).includes(opts.killBehavior)
+  ) {
+    throw new TypeError(
+      `killBehavior option '${opts.killBehavior}' is not valid`
+    )
+  }
+  if (
+    opts?.maxInactiveTime != null &&
+    !Number.isSafeInteger(opts.maxInactiveTime)
+  ) {
+    throw new TypeError('maxInactiveTime option is not an integer')
+  }
+  if (opts?.maxInactiveTime != null && opts.maxInactiveTime < 5) {
+    throw new TypeError(
+      'maxInactiveTime option is not a positive integer greater or equal than 5'
+    )
+  }
+  if (opts?.killHandler != null && typeof opts.killHandler !== 'function') {
+    throw new TypeError('killHandler option is not a function')
+  }
+  if (opts?.async != null) {
+    throw new Error('async option is deprecated')
+  }
+}
+
+export const checkValidTaskFunctionEntry = <Data = unknown, Response = unknown>(
+  name: string,
+  fn: TaskFunction<Data, Response>
+): void => {
+  if (typeof name !== 'string') {
+    throw new TypeError('A taskFunctions parameter object key is not a string')
+  }
+  if (typeof name === 'string' && name.trim().length === 0) {
+    throw new TypeError(
+      'A taskFunctions parameter object key is an empty string'
+    )
+  }
+  if (typeof fn !== 'function') {
+    throw new TypeError(
+      'A taskFunctions parameter object value is not a function'
+    )
+  }
+}
+
+export const checkTaskFunctionName = (name: string): void => {
+  if (typeof name !== 'string') {
+    throw new TypeError('name parameter is not a string')
+  }
+  if (typeof name === 'string' && name.trim().length === 0) {
+    throw new TypeError('name parameter is an empty string')
+  }
+}
similarity index 99%
rename from tests/pools/abstract/abstract-pool.test.js
rename to tests/pools/abstract-pool.test.js
index f6a54d5b4473894f42778dbb6ea3abc8536a9f02..3860a0eb95fc4f50de2ea9ff28813860faafd9b6 100644 (file)
@@ -10,13 +10,13 @@ const {
   PoolTypes,
   WorkerChoiceStrategies,
   WorkerTypes
-} = require('../../../lib')
-const { CircularArray } = require('../../../lib/circular-array')
-const { Deque } = require('../../../lib/deque')
-const { DEFAULT_TASK_NAME } = require('../../../lib/utils')
-const { version } = require('../../../package.json')
-const { waitPoolEvents } = require('../../test-utils')
-const { WorkerNode } = require('../../../lib/pools/worker-node')
+} = require('../../lib')
+const { CircularArray } = require('../../lib/circular-array')
+const { Deque } = require('../../lib/deque')
+const { DEFAULT_TASK_NAME } = require('../../lib/utils')
+const { version } = require('../../package.json')
+const { waitPoolEvents } = require('../test-utils')
+const { WorkerNode } = require('../../lib/pools/worker-node')
 
 describe('Abstract pool test suite', () => {
   const numberOfWorkers = 2
diff --git a/tests/pools/utils.test.js b/tests/pools/utils.test.js
new file mode 100644 (file)
index 0000000..23ef2e2
--- /dev/null
@@ -0,0 +1,95 @@
+const { expect } = require('expect')
+const {
+  DEFAULT_CIRCULAR_ARRAY_SIZE,
+  CircularArray
+} = require('../../lib/circular-array')
+const { updateMeasurementStatistics } = require('../../lib/pools/utils')
+
+describe('Pool utils test suite', () => {
+  it('Verify updateMeasurementStatistics() behavior', () => {
+    const measurementStatistics = {
+      history: new CircularArray()
+    }
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: false, median: false },
+      0.01
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.01,
+      maximum: 0.01,
+      minimum: 0.01,
+      history: new CircularArray()
+    })
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: false, median: false },
+      0.02
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.03,
+      maximum: 0.02,
+      minimum: 0.01,
+      history: new CircularArray()
+    })
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: true, median: false },
+      0.001
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.031,
+      maximum: 0.02,
+      minimum: 0.001,
+      average: 0.001,
+      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
+    })
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: true, median: false },
+      0.003
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.034,
+      maximum: 0.02,
+      minimum: 0.001,
+      average: 0.002,
+      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
+    })
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: false, median: true },
+      0.006
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.04,
+      maximum: 0.02,
+      minimum: 0.001,
+      median: 0.003,
+      history: new CircularArray(
+        DEFAULT_CIRCULAR_ARRAY_SIZE,
+        0.001,
+        0.003,
+        0.006
+      )
+    })
+    updateMeasurementStatistics(
+      measurementStatistics,
+      { aggregate: true, average: true, median: false },
+      0.01
+    )
+    expect(measurementStatistics).toStrictEqual({
+      aggregate: 0.05,
+      maximum: 0.02,
+      minimum: 0.001,
+      average: 0.005,
+      history: new CircularArray(
+        DEFAULT_CIRCULAR_ARRAY_SIZE,
+        0.001,
+        0.003,
+        0.006,
+        0.01
+      )
+    })
+  })
+})
similarity index 96%
rename from tests/pools/abstract/worker-node.test.js
rename to tests/pools/worker-node.test.js
index ee469eda7b39692f4a5a26e9ba3782453c66c981..bfbd5d8d148667576472d1d02efddd7121374685 100644 (file)
@@ -1,11 +1,11 @@
 const { MessageChannel, Worker } = require('node:worker_threads')
 const cluster = require('node:cluster')
 const { expect } = require('expect')
-const { WorkerNode } = require('../../../lib/pools/worker-node')
-const { WorkerTypes } = require('../../../lib')
-const { CircularArray } = require('../../../lib/circular-array')
-const { Deque } = require('../../../lib/deque')
-const { DEFAULT_TASK_NAME } = require('../../../lib/utils')
+const { WorkerNode } = require('../../lib/pools/worker-node')
+const { WorkerTypes } = require('../../lib')
+const { CircularArray } = require('../../lib/circular-array')
+const { Deque } = require('../../lib/deque')
+const { DEFAULT_TASK_NAME } = require('../../lib/utils')
 
 describe('Worker node test suite', () => {
   const threadWorker = new Worker('./tests/worker-files/thread/testWorker.js')
index 5041f1028a49fcf598922aa307e481b94a8745a8..061c1648d4f2217583f6b0a9370802578fb222a6 100644 (file)
@@ -3,10 +3,6 @@ const { Worker } = require('node:worker_threads')
 const cluster = require('node:cluster')
 const os = require('node:os')
 const { expect } = require('expect')
-const {
-  CircularArray,
-  DEFAULT_CIRCULAR_ARRAY_SIZE
-} = require('../lib/circular-array')
 const {
   DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS,
   DEFAULT_TASK_NAME,
@@ -25,8 +21,7 @@ const {
   min,
   round,
   secureRandom,
-  sleep,
-  updateMeasurementStatistics
+  sleep
 } = require('../lib/utils')
 const { KillBehaviors, WorkerTypes } = require('../lib')
 
@@ -220,93 +215,6 @@ describe('Utils test suite', () => {
     expect(isAsyncFunction(async function named () {})).toBe(true)
   })
 
-  it('Verify updateMeasurementStatistics() behavior', () => {
-    const measurementStatistics = {
-      history: new CircularArray()
-    }
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: false, median: false },
-      0.01
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.01,
-      maximum: 0.01,
-      minimum: 0.01,
-      history: new CircularArray()
-    })
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: false, median: false },
-      0.02
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.03,
-      maximum: 0.02,
-      minimum: 0.01,
-      history: new CircularArray()
-    })
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: true, median: false },
-      0.001
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.031,
-      maximum: 0.02,
-      minimum: 0.001,
-      average: 0.001,
-      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001)
-    })
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: true, median: false },
-      0.003
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.034,
-      maximum: 0.02,
-      minimum: 0.001,
-      average: 0.002,
-      history: new CircularArray(DEFAULT_CIRCULAR_ARRAY_SIZE, 0.001, 0.003)
-    })
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: false, median: true },
-      0.006
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.04,
-      maximum: 0.02,
-      minimum: 0.001,
-      median: 0.003,
-      history: new CircularArray(
-        DEFAULT_CIRCULAR_ARRAY_SIZE,
-        0.001,
-        0.003,
-        0.006
-      )
-    })
-    updateMeasurementStatistics(
-      measurementStatistics,
-      { aggregate: true, average: true, median: false },
-      0.01
-    )
-    expect(measurementStatistics).toStrictEqual({
-      aggregate: 0.05,
-      maximum: 0.02,
-      minimum: 0.001,
-      average: 0.005,
-      history: new CircularArray(
-        DEFAULT_CIRCULAR_ARRAY_SIZE,
-        0.001,
-        0.003,
-        0.006,
-        0.01
-      )
-    })
-  })
-
   it('Verify secureRandom() behavior', () => {
     const randomNumber = secureRandom()
     expect(typeof randomNumber === 'number').toBe(true)