resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
- resolve@1.22.10:
- resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
- engines: {node: '>= 0.4'}
- hasBin: true
-
resolve@1.22.11:
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
engines: {node: '>= 0.4'}
brfs@2.0.2:
dependencies:
quote-stream: 1.0.2
- resolve: 1.22.10
+ resolve: 1.22.11
static-module: 3.0.4
through2: 2.0.5
browser-resolve@2.0.0:
dependencies:
- resolve: 1.22.10
+ resolve: 1.22.11
browserify-aes@1.2.0:
dependencies:
querystring-es3: 0.2.1
read-only-stream: 2.0.0
readable-stream: 2.3.8
- resolve: 1.22.10
+ resolve: 1.22.11
shasum-object: 1.0.1
shell-quote: 1.8.3
stream-browserify: 3.0.0
inherits: 2.0.4
parents: 1.0.1
readable-stream: 2.3.8
- resolve: 1.22.10
+ resolve: 1.22.11
stream-combiner2: 1.1.1
subarg: 1.0.0
through2: 2.0.5
postcss: 8.5.6
postcss-value-parser: 4.2.0
read-cache: 1.0.0
- resolve: 1.22.10
+ resolve: 1.22.11
postcss-selector-parser@6.1.2:
dependencies:
resolve-pkg-maps@1.0.0: {}
- resolve@1.22.10:
- dependencies:
- is-core-module: 2.16.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
resolve@1.22.11:
dependencies:
is-core-module: 2.16.1
type WorkerConfiguration,
} from '../types/index.js'
import {
+ checkWorkerProcessType,
DEFAULT_ELEMENT_ADD_DELAY,
DEFAULT_POOL_MAX_SIZE,
DEFAULT_POOL_MIN_SIZE,
import {
buildPerformanceUriFilePath,
checkWorkerElementsPerWorker,
- checkWorkerProcessType,
getDefaultPerformanceStorageUri,
handleFileException,
logPrefix,
import { fileURLToPath, pathToFileURL } from 'node:url'
import { type ElementsPerWorkerType, type FileType, StorageType } from '../types/index.js'
-import { WorkerProcessType } from '../worker/index.js'
import { Constants } from './Constants.js'
import { isNotEmptyString, logPrefix as utilsLogPrefix } from './Utils.js'
throw error
}
-export const checkWorkerProcessType = (workerProcessType: WorkerProcessType): void => {
- if (!Object.values(WorkerProcessType).includes(workerProcessType)) {
- throw new SyntaxError(
- `Invalid worker process type '${workerProcessType}' defined in configuration`
- )
- }
-}
-
export const checkWorkerElementsPerWorker = (
elementsPerWorker: ElementsPerWorkerType | undefined
): void => {
import chalk from 'chalk'
import { getRandomValues } from 'node:crypto'
+import { WorkerProcessType } from './WorkerTypes.js'
+
export const sleep = async (milliSeconds: number): Promise<NodeJS.Timeout> => {
return await new Promise<NodeJS.Timeout>(resolve => {
const timeout = setTimeout(() => {
return delay + sign * randomSum
}
+export const checkWorkerProcessType = (workerProcessType: WorkerProcessType): void => {
+ if (!Object.values(WorkerProcessType).includes(workerProcessType)) {
+ throw new SyntaxError(
+ `Invalid worker process type '${workerProcessType}' defined in configuration`
+ )
+ }
+}
+
/**
* Generates a cryptographically secure random number in the [0,1[ range
* @returns A number in the [0,1[ range
WorkerMessageEvents,
WorkerProcessType,
} from './WorkerTypes.js'
+export { checkWorkerProcessType } from './WorkerUtils.js'
-// /* eslint-disable @typescript-eslint/no-unsafe-member-access */
-// import { expect } from '@std/expect'
-// import { describe, it } from 'node:test'
-
-// import { FileType } from '../../src/types/index.js'
-// import { handleFileException, logPrefix } from '../../src/utils/ConfigurationUtils.js'
-
-// await describe('ConfigurationUtils test suite', async () => {
-// await it('Verify logPrefix()', () => {
-// expect(logPrefix()).toContain(' Simulator configuration |')
-// })
-
-// await it('Verify handleFileException()', t => {
-// t.mock.method(console, 'error')
-// const error = new Error()
-// error.code = 'ENOENT'
-// expect(() => {
-// handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |')
-// }).toThrow(error)
-// expect(console.error.mock.calls.length).toBe(1)
-// })
-// })
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import { FileType, StorageType } from '../../src/types/index.js'
+import {
+ buildPerformanceUriFilePath,
+ checkWorkerElementsPerWorker,
+ getDefaultPerformanceStorageUri,
+ handleFileException,
+ logPrefix,
+} from '../../src/utils/ConfigurationUtils.js'
+
+await describe('ConfigurationUtils test suite', async () => {
+ await it('Verify logPrefix()', () => {
+ expect(logPrefix()).toContain(' Simulator configuration |')
+ })
+
+ await it('Verify buildPerformanceUriFilePath()', () => {
+ const result = buildPerformanceUriFilePath('test.json')
+ expect(result).toContain('test.json')
+ expect(result).toMatch(/^file:\/\/.*test\.json$/)
+ })
+
+ await it('Verify getDefaultPerformanceStorageUri()', () => {
+ // Test JSON_FILE storage type
+ const jsonUri = getDefaultPerformanceStorageUri(StorageType.JSON_FILE)
+ expect(jsonUri).toMatch(/^file:\/\/.*\.json$/)
+ expect(jsonUri).toContain('performanceRecords.json')
+
+ // Test SQLITE storage type
+ const sqliteUri = getDefaultPerformanceStorageUri(StorageType.SQLITE)
+ expect(sqliteUri).toMatch(/^file:\/\/.*\.db$/)
+ expect(sqliteUri).toContain('charging-stations-simulator.db')
+
+ // Test unsupported storage type
+ expect(() => {
+ getDefaultPerformanceStorageUri('unsupported' as StorageType)
+ }).toThrow(Error)
+ })
+
+ await it('Verify handleFileException()', t => {
+ const mockConsoleError = t.mock.method(console, 'error')
+ const error = new Error() as NodeJS.ErrnoException
+ error.code = 'ENOENT'
+ expect(() => {
+ handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |')
+ }).toThrow(error)
+ expect(mockConsoleError.mock.calls.length).toBe(1)
+ })
+
+ await it('Verify checkWorkerElementsPerWorker()', () => {
+ // These calls should not throw exceptions
+ expect(() => {
+ checkWorkerElementsPerWorker(undefined)
+ }).not.toThrow()
+ expect(() => {
+ checkWorkerElementsPerWorker('auto')
+ }).not.toThrow()
+ expect(() => {
+ checkWorkerElementsPerWorker('all')
+ }).not.toThrow()
+ expect(() => {
+ checkWorkerElementsPerWorker(4)
+ }).not.toThrow()
+
+ // These calls should throw exceptions
+ expect(() => {
+ checkWorkerElementsPerWorker(0)
+ }).toThrow(RangeError)
+ expect(() => {
+ checkWorkerElementsPerWorker(-1)
+ }).toThrow(RangeError)
+ expect(() => {
+ checkWorkerElementsPerWorker(1.5)
+ }).toThrow(SyntaxError)
+ })
+})
--- /dev/null
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import { WorkerProcessType } from '../../src/worker/WorkerTypes.js'
+import {
+ checkWorkerProcessType,
+ defaultErrorHandler,
+ defaultExitHandler,
+ randomizeDelay,
+ sleep,
+} from '../../src/worker/WorkerUtils.js'
+
+await describe('WorkerUtils test suite', async () => {
+ await it('Verify checkWorkerProcessType()', () => {
+ // Valid worker process types should not throw
+ expect(() => {
+ checkWorkerProcessType(WorkerProcessType.dynamicPool)
+ }).not.toThrow()
+ expect(() => {
+ checkWorkerProcessType(WorkerProcessType.fixedPool)
+ }).not.toThrow()
+ expect(() => {
+ checkWorkerProcessType(WorkerProcessType.workerSet)
+ }).not.toThrow()
+
+ // Invalid worker process type should throw
+ expect(() => {
+ checkWorkerProcessType('invalidType' as WorkerProcessType)
+ }).toThrow(SyntaxError)
+ })
+
+ await it('Verify sleep()', async () => {
+ const startTime = Date.now()
+ const delay = 10 // 10ms for fast test execution
+
+ const timeout = await sleep(delay)
+ const endTime = Date.now()
+ const actualDelay = endTime - startTime
+
+ // Verify timeout object is returned
+ expect(timeout).toBeDefined()
+ expect(typeof timeout).toBe('object')
+
+ // Verify actual delay is approximately correct (within reasonable tolerance)
+ expect(actualDelay).toBeGreaterThanOrEqual(delay)
+ expect(actualDelay).toBeLessThan(delay + 50) // Allow 50ms tolerance for system variance
+
+ // Clean up timeout
+ clearTimeout(timeout)
+ })
+
+ await it('Verify defaultExitHandler()', t => {
+ const mockConsoleInfo = t.mock.method(console, 'info')
+ const mockConsoleError = t.mock.method(console, 'error')
+
+ // Test successful exit (code 0)
+ defaultExitHandler(0)
+ expect(mockConsoleInfo.mock.calls.length).toBe(1)
+ expect(mockConsoleError.mock.calls.length).toBe(0)
+
+ // Reset mocks
+ mockConsoleInfo.mock.resetCalls()
+ mockConsoleError.mock.resetCalls()
+
+ // Test terminated successfully (code 1)
+ defaultExitHandler(1)
+ expect(mockConsoleInfo.mock.calls.length).toBe(1)
+ expect(mockConsoleError.mock.calls.length).toBe(0)
+
+ // Reset mocks
+ mockConsoleInfo.mock.resetCalls()
+ mockConsoleError.mock.resetCalls()
+
+ // Test error exit (code > 1)
+ defaultExitHandler(2)
+ expect(mockConsoleInfo.mock.calls.length).toBe(0)
+ expect(mockConsoleError.mock.calls.length).toBe(1)
+
+ // Test another error code
+ mockConsoleError.mock.resetCalls()
+ defaultExitHandler(5)
+ expect(mockConsoleError.mock.calls.length).toBe(1)
+ })
+
+ await it('Verify defaultErrorHandler()', t => {
+ const mockConsoleError = t.mock.method(console, 'error')
+ const testError = new Error('Test error message')
+
+ defaultErrorHandler(testError)
+
+ expect(mockConsoleError.mock.calls.length).toBe(1)
+
+ // Test with different error types
+ const syntaxError = new SyntaxError('Syntax error')
+ defaultErrorHandler(syntaxError)
+ expect(mockConsoleError.mock.calls.length).toBe(2)
+ })
+
+ await it('Verify randomizeDelay()', () => {
+ const baseDelay = 1000
+ const tolerance = baseDelay * 0.2 // 20% tolerance as per implementation
+
+ // Test multiple random variations to verify range
+ const results: number[] = []
+ for (let i = 0; i < 100; i++) {
+ const randomized = randomizeDelay(baseDelay)
+ results.push(randomized)
+
+ // Each result should be within ±20% of base delay
+ expect(randomized).toBeGreaterThanOrEqual(baseDelay - tolerance)
+ expect(randomized).toBeLessThanOrEqual(baseDelay + tolerance)
+ }
+
+ // Verify we get some variation (not all values identical)
+ const uniqueValues = new Set(results)
+ expect(uniqueValues.size).toBeGreaterThan(1)
+
+ // Test with zero delay
+ const zeroResult = randomizeDelay(0)
+ expect(zeroResult).toBeGreaterThanOrEqual(-0)
+ expect(zeroResult).toBeLessThanOrEqual(0)
+
+ // Test with negative delay (edge case)
+ const negativeDelay = -100
+ const negativeResult = randomizeDelay(negativeDelay)
+ const negativeTolerance = Math.abs(negativeDelay) * 0.2
+ expect(negativeResult).toBeGreaterThanOrEqual(negativeDelay - negativeTolerance)
+ expect(negativeResult).toBeLessThanOrEqual(negativeDelay + negativeTolerance)
+ })
+})