X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=tests%2Fpools%2Fabstract-pool.test.mjs;h=7054c46a3c02acc4a8fbc0efd1e601fcf6103bf8;hb=5d5885ee530724024f84e31acca92775a01da082;hp=0ea921f88cfcc9cb77fccfa0c0e77334fe776ecd;hpb=c426b04af6b85ef3ec6859929eb906bcea4fcaf7;p=poolifier.git diff --git a/tests/pools/abstract-pool.test.mjs b/tests/pools/abstract-pool.test.mjs index 0ea921f8..7054c46a 100644 --- a/tests/pools/abstract-pool.test.mjs +++ b/tests/pools/abstract-pool.test.mjs @@ -1,10 +1,15 @@ +// eslint-disable-next-line n/no-unsupported-features/node-builtins +import { createHook, executionAsyncId } from 'node:async_hooks' import { EventEmitterAsyncResource } from 'node:events' -import { dirname, join } from 'node:path' import { readFileSync } from 'node:fs' +import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' -import { createHook, executionAsyncId } from 'node:async_hooks' + import { expect } from 'expect' import { restore, stub } from 'sinon' + +import { CircularArray } from '../../lib/circular-array.cjs' +import { Deque } from '../../lib/deque.cjs' import { DynamicClusterPool, DynamicThreadPool, @@ -14,12 +19,10 @@ import { PoolTypes, WorkerChoiceStrategies, WorkerTypes -} from '../../lib/index.js' -import { CircularArray } from '../../lib/circular-array.js' -import { Deque } from '../../lib/deque.js' -import { DEFAULT_TASK_NAME } from '../../lib/utils.js' -import { waitPoolEvents } from '../test-utils.js' -import { WorkerNode } from '../../lib/pools/worker-node.js' +} from '../../lib/index.cjs' +import { WorkerNode } from '../../lib/pools/worker-node.cjs' +import { DEFAULT_TASK_NAME } from '../../lib/utils.cjs' +import { waitPoolEvents } from '../test-utils.cjs' describe('Abstract pool test suite', () => { const version = JSON.parse( @@ -105,7 +108,7 @@ describe('Abstract pool test suite', () => { it('Verify that a negative number of workers is checked', () => { expect( () => - new FixedClusterPool(-1, './tests/worker-files/cluster/testWorker.js') + new FixedClusterPool(-1, './tests/worker-files/cluster/testWorker.cjs') ).toThrow( new RangeError( 'Cannot instantiate a pool with a negative number of workers' @@ -146,7 +149,7 @@ describe('Abstract pool test suite', () => { new DynamicClusterPool( 1, undefined, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) ).toThrow( new TypeError( @@ -170,7 +173,7 @@ describe('Abstract pool test suite', () => { new DynamicClusterPool( 0, 0.5, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) ).toThrow( new TypeError( @@ -206,7 +209,7 @@ describe('Abstract pool test suite', () => { new DynamicClusterPool( 1, 1, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) ).toThrow( new RangeError( @@ -221,6 +224,7 @@ describe('Abstract pool test suite', () => { './tests/worker-files/thread/testWorker.mjs' ) expect(pool.emitter).toBeInstanceOf(EventEmitterAsyncResource) + expect(pool.emitter.eventNames()).toStrictEqual([]) expect(pool.opts).toStrictEqual({ startWorkers: true, enableEvents: true, @@ -228,30 +232,17 @@ describe('Abstract pool test suite', () => { enableTasksQueue: false, workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { - expect(workerChoiceStrategy.opts).toStrictEqual( - expect.objectContaining({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false } + expect(workerChoiceStrategy.opts).toStrictEqual({ + runTime: { median: false }, + waitTime: { median: false }, + elu: { median: false }, + weights: expect.objectContaining({ + 0: expect.any(Number), + [pool.info.maxSize - 1]: expect.any(Number) }) - ) + }) } await pool.destroy() const testHandler = () => console.info('test handler executed') @@ -297,21 +288,9 @@ describe('Abstract pool test suite', () => { errorHandler: testHandler, exitHandler: testHandler }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.opts.workerChoiceStrategyOptions.weights).length, - runTime: { median: true }, - waitTime: { median: false }, - elu: { median: false }, - weights: { 0: 300, 1: 200 } - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.opts.workerChoiceStrategyOptions.weights).length, runTime: { median: true }, waitTime: { median: false }, elu: { median: false }, @@ -468,30 +447,17 @@ describe('Abstract pool test suite', () => { { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } ) expect(pool.opts.workerChoiceStrategyOptions).toBeUndefined() - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { - expect(workerChoiceStrategy.opts).toStrictEqual( - expect.objectContaining({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false } + expect(workerChoiceStrategy.opts).toStrictEqual({ + runTime: { median: false }, + waitTime: { median: false }, + elu: { median: false }, + weights: expect.objectContaining({ + 0: expect.any(Number), + [pool.info.maxSize - 1]: expect.any(Number) }) - ) + }) } expect( pool.workerChoiceStrategyContext.getTaskStatisticsRequirements() @@ -520,30 +486,17 @@ describe('Abstract pool test suite', () => { runTime: { median: true }, elu: { median: true } }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: true }, - waitTime: { median: false }, - elu: { median: true }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { - expect(workerChoiceStrategy.opts).toStrictEqual( - expect.objectContaining({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, - runTime: { median: true }, - waitTime: { median: false }, - elu: { median: true } + expect(workerChoiceStrategy.opts).toStrictEqual({ + runTime: { median: true }, + waitTime: { median: false }, + elu: { median: true }, + weights: expect.objectContaining({ + 0: expect.any(Number), + [pool.info.maxSize - 1]: expect.any(Number) }) - ) + }) } expect( pool.workerChoiceStrategyContext.getTaskStatisticsRequirements() @@ -572,30 +525,17 @@ describe('Abstract pool test suite', () => { runTime: { median: false }, elu: { median: false } }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { - expect(workerChoiceStrategy.opts).toStrictEqual( - expect.objectContaining({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false } + expect(workerChoiceStrategy.opts).toStrictEqual({ + runTime: { median: false }, + waitTime: { median: false }, + elu: { median: false }, + weights: expect.objectContaining({ + 0: expect.any(Number), + [pool.info.maxSize - 1]: expect.any(Number) }) - ) + }) } expect( pool.workerChoiceStrategyContext.getTaskStatisticsRequirements() @@ -767,6 +707,7 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: 0, minSize: numberOfWorkers, maxSize: numberOfWorkers, workerNodes: numberOfWorkers, @@ -780,7 +721,7 @@ describe('Abstract pool test suite', () => { pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) expect(pool.info).toStrictEqual({ version, @@ -789,6 +730,7 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: 0, minSize: Math.floor(numberOfWorkers / 2), maxSize: numberOfWorkers, workerNodes: Math.floor(numberOfWorkers / 2), @@ -804,7 +746,7 @@ describe('Abstract pool test suite', () => { it('Verify that pool worker tasks usage are initialized', async () => { const pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) for (const workerNode of pool.workerNodes) { expect(workerNode).toBeInstanceOf(WorkerNode) @@ -840,7 +782,7 @@ describe('Abstract pool test suite', () => { it('Verify that pool worker tasks queue are initialized', async () => { let pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) for (const workerNode of pool.workerNodes) { expect(workerNode).toBeInstanceOf(WorkerNode) @@ -866,7 +808,7 @@ describe('Abstract pool test suite', () => { it('Verify that pool worker info are initialized', async () => { let pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) for (const workerNode of pool.workerNodes) { expect(workerNode).toBeInstanceOf(WorkerNode) @@ -874,7 +816,8 @@ describe('Abstract pool test suite', () => { id: expect.any(Number), type: WorkerTypes.cluster, dynamic: false, - ready: true + ready: true, + stealing: false }) } await pool.destroy() @@ -889,7 +832,8 @@ describe('Abstract pool test suite', () => { id: expect.any(Number), type: WorkerTypes.thread, dynamic: false, - ready: true + ready: true, + stealing: false }) } await pool.destroy() @@ -916,15 +860,15 @@ describe('Abstract pool test suite', () => { it('Verify that pool can be started after initialization', async () => { const pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js', + './tests/worker-files/cluster/testWorker.cjs', { startWorkers: false } ) expect(pool.info.started).toBe(false) expect(pool.info.ready).toBe(false) - expect(pool.readyEventEmitted).toBe(false) expect(pool.workerNodes).toStrictEqual([]) + expect(pool.readyEventEmitted).toBe(false) await expect(pool.execute()).rejects.toThrow( new Error('Cannot execute a task on not started pool') ) @@ -943,7 +887,7 @@ describe('Abstract pool test suite', () => { it('Verify that pool execute() arguments are checked', async () => { const pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) await expect(pool.execute(undefined, 0)).rejects.toThrow( new TypeError('name argument must be a string') @@ -966,7 +910,7 @@ describe('Abstract pool test suite', () => { it('Verify that pool worker tasks usage are computed', async () => { const pool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) const promises = new Set() const maxMultiplier = 2 @@ -1117,7 +1061,7 @@ describe('Abstract pool test suite', () => { const pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) expect(pool.emitter.eventNames()).toStrictEqual([]) let poolInfo @@ -1136,6 +1080,7 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: expect.any(Number), minSize: expect.any(Number), maxSize: expect.any(Number), workerNodes: expect.any(Number), @@ -1176,6 +1121,7 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: expect.any(Number), minSize: expect.any(Number), maxSize: expect.any(Number), workerNodes: expect.any(Number), @@ -1215,6 +1161,7 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: expect.any(Number), minSize: expect.any(Number), maxSize: expect.any(Number), workerNodes: expect.any(Number), @@ -1257,10 +1204,12 @@ describe('Abstract pool test suite', () => { started: true, ready: true, strategy: WorkerChoiceStrategies.ROUND_ROBIN, + strategyRetries: expect.any(Number), minSize: expect.any(Number), maxSize: expect.any(Number), workerNodes: expect.any(Number), idleWorkerNodes: expect.any(Number), + stealingWorkerNodes: expect.any(Number), busyWorkerNodes: expect.any(Number), executedTasks: expect.any(Number), executingTasks: expect.any(Number), @@ -1270,7 +1219,7 @@ describe('Abstract pool test suite', () => { stolenTasks: expect.any(Number), failedTasks: expect.any(Number) }) - expect(pool.hasBackPressure.callCount).toBe(5) + expect(pool.hasBackPressure.callCount).toBeGreaterThanOrEqual(7) await pool.destroy() }) @@ -1298,9 +1247,9 @@ describe('Abstract pool test suite', () => { const startTime = performance.now() await pool.destroy() const elapsedTime = performance.now() - startTime - expect(tasksFinished).toBe(numberOfWorkers * maxMultiplier) + expect(tasksFinished).toBeLessThanOrEqual(numberOfWorkers * maxMultiplier) expect(elapsedTime).toBeGreaterThanOrEqual(2000) - expect(elapsedTime).toBeLessThanOrEqual(tasksFinishedTimeout + 100) + expect(elapsedTime).toBeLessThanOrEqual(tasksFinishedTimeout + 800) }) it('Verify that destroy() waits until the tasks finished timeout is reached', async () => { @@ -1385,7 +1334,7 @@ describe('Abstract pool test suite', () => { await dynamicThreadPool.destroy() const fixedClusterPool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.js' + './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs' ) await waitPoolEvents(fixedClusterPool, PoolEvents.ready, 1) expect(fixedClusterPool.hasTaskFunction(DEFAULT_TASK_NAME)).toBe(true) @@ -1525,7 +1474,7 @@ describe('Abstract pool test suite', () => { await dynamicThreadPool.destroy() const fixedClusterPool = new FixedClusterPool( numberOfWorkers, - './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.js' + './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs' ) await waitPoolEvents(fixedClusterPool, PoolEvents.ready, 1) expect(fixedClusterPool.listTaskFunctionNames()).toStrictEqual([ @@ -1595,7 +1544,7 @@ describe('Abstract pool test suite', () => { const pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.js' + './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.cjs' ) const data = { n: 10 } const result0 = await pool.execute(data) @@ -1660,17 +1609,12 @@ describe('Abstract pool test suite', () => { const pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) const workerNodeKey = 0 await expect( pool.sendKillMessageToWorker(workerNodeKey) ).resolves.toBeUndefined() - await expect( - pool.sendKillMessageToWorker(numberOfWorkers) - ).rejects.toStrictEqual( - new Error(`Invalid worker node key '${numberOfWorkers}'`) - ) await pool.destroy() }) @@ -1678,7 +1622,7 @@ describe('Abstract pool test suite', () => { const pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) const workerNodeKey = 0 await expect( @@ -1698,7 +1642,7 @@ describe('Abstract pool test suite', () => { const pool = new DynamicClusterPool( Math.floor(numberOfWorkers / 2), numberOfWorkers, - './tests/worker-files/cluster/testWorker.js' + './tests/worker-files/cluster/testWorker.cjs' ) await expect( pool.sendTaskFunctionOperationToWorkers({