From fcda9151b9eb6d13f06f7a5db45c89a77bda9eb8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 18 Mar 2024 15:19:53 +0100 Subject: [PATCH] refactor: use native node random integer generator MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../AutomaticTransactionGenerator.ts | 15 ++++---- src/charging-station/ChargingStation.ts | 5 ++- .../ocpp/1.6/OCPP16IncomingRequestService.ts | 13 ++++--- src/charging-station/ocpp/OCPPServiceUtils.ts | 4 +-- src/utils/Constants.ts | 2 +- src/utils/Utils.ts | 12 +------ src/utils/index.ts | 1 - tests/utils/Utils.test.ts | 34 ++----------------- 8 files changed, 22 insertions(+), 64 deletions(-) diff --git a/src/charging-station/AutomaticTransactionGenerator.ts b/src/charging-station/AutomaticTransactionGenerator.ts index 40b7c781..a6143a8c 100644 --- a/src/charging-station/AutomaticTransactionGenerator.ts +++ b/src/charging-station/AutomaticTransactionGenerator.ts @@ -1,5 +1,7 @@ // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. +import { randomInt } from 'node:crypto' + import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns' import { BaseError } from '../exception/index.js' @@ -18,7 +20,6 @@ import { Constants, convertToDate, formatDurationMilliSeconds, - getRandomInteger, isValidDate, logger, logPrefix, @@ -199,11 +200,11 @@ export class AutomaticTransactionGenerator { break } const wait = secondsToMilliseconds( - getRandomInteger( + randomInt( this.chargingStation.getAutomaticTransactionGeneratorConfiguration() - ?.maxDelayBetweenTwoTransactions, + ?.minDelayBetweenTwoTransactions, this.chargingStation.getAutomaticTransactionGeneratorConfiguration() - ?.minDelayBetweenTwoTransactions + ?.maxDelayBetweenTwoTransactions ) ) logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`) @@ -221,9 +222,9 @@ export class AutomaticTransactionGenerator { if (startResponse?.idTagInfo.status === AuthorizationStatus.ACCEPTED) { // Wait until end of transaction const waitTrxEnd = secondsToMilliseconds( - getRandomInteger( - this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.maxDuration, - this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.minDuration + randomInt( + this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.minDuration, + this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.maxDuration ) ) logger.info( diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 9bf299aa..0a1ed4ed 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -1,6 +1,6 @@ // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. -import { createHash } from 'node:crypto' +import { createHash, randomInt } from 'node:crypto' import { EventEmitter } from 'node:events' import { existsSync, type FSWatcher, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { dirname, join } from 'node:path' @@ -88,7 +88,6 @@ import { exponentialDelay, formatDurationMilliSeconds, formatDurationSeconds, - getRandomInteger, getWebSocketCloseEventStatusString, handleFileException, isNotEmptyArray, @@ -1554,7 +1553,7 @@ export class ChargingStation extends EventEmitter { } const templateConnectorId = connectorId > 0 && stationTemplate.randomConnectors === true - ? getRandomInteger(templateMaxAvailableConnectors, 1) + ? randomInt(1, templateMaxAvailableConnectors) : connectorId const connectorStatus = stationTemplate.Connectors[templateConnectorId] checkStationInfoConnectorStatus( diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 04182664..ea7a89e9 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -1,5 +1,6 @@ // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved. +import { randomInt } from 'node:crypto' import { createWriteStream, readdirSync } from 'node:fs' import { dirname, extname, join, resolve } from 'node:path' import { fileURLToPath, URL } from 'node:url' @@ -104,7 +105,6 @@ import { convertToDate, convertToInt, formatDurationMilliSeconds, - getRandomInteger, isAsyncFunction, isNotEmptyArray, isNotEmptyString, @@ -1346,7 +1346,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.DownloadFailed ) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1357,7 +1357,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo.firmwareUpgrade.failureStatus return } - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1413,8 +1413,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { transactionsStarted = false } } while (transactionsStarted) - !wasTransactionsStarted && - (await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay)))) + !wasTransactionsStarted && (await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))) if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) { return } @@ -1430,7 +1429,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo?.firmwareUpgrade?.failureStatus === OCPP16FirmwareStatus.InstallationFailed ) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse @@ -1442,7 +1441,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return } if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) { - await sleep(secondsToMilliseconds(getRandomInteger(maxDelay, minDelay))) + await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))) await chargingStation.reset(OCPP16StopTransactionReason.REBOOT) } } diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index 38f218ee..8a42bf67 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -1,3 +1,4 @@ +import { randomInt } from 'node:crypto' import { readFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -53,7 +54,6 @@ import { DCElectricUtils, getRandomFloatFluctuatedRounded, getRandomFloatRounded, - getRandomInteger, handleFileException, isNotEmptyArray, isNotEmptyString, @@ -284,7 +284,7 @@ export const buildMeterValue = ( parseInt(socSampledValueTemplate.value), socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT ) - : getRandomInteger(socMaximumValue, socMinimumValue) + : randomInt(socMinimumValue, socMaximumValue) meterValue.sampledValue.push( buildSampledValue(socSampledValueTemplate, socSampledValueTemplateValue) ) diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index ea0ff8fc..a5e46f60 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -85,7 +85,7 @@ export class Constants { | RequestCommand | IncomingRequestCommand - static readonly MAX_RANDOM_INTEGER = 281474976710654 + static readonly MAX_RANDOM_INTEGER = 281474976710655 static readonly STOP_CHARGING_STATIONS_TIMEOUT = 60000 // Ms diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index bc9a8f43..7ff24ac8 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,4 +1,4 @@ -import { getRandomValues, randomBytes, randomInt, randomUUID } from 'node:crypto' +import { getRandomValues, randomBytes, randomUUID } from 'node:crypto' import { env, nextTick } from 'node:process' import { @@ -19,7 +19,6 @@ import { type TimestampedData, WebSocketCloseEventStatusString } from '../types/index.js' -import { Constants } from './Constants.js' export const logPrefix = (prefixString = ''): string => { return `${new Date().toLocaleString()}${prefixString}` @@ -159,15 +158,6 @@ export const getRandomFloat = (max = Number.MAX_VALUE, min = 0): number => { return (randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min } -export const getRandomInteger = (max = Constants.MAX_RANDOM_INTEGER, min = 0): number => { - max = Math.floor(max) - if (min !== 0) { - min = Math.ceil(min) - return Math.floor(randomInt(min, max + 1)) - } - return Math.floor(randomInt(max + 1)) -} - /** * Rounds the given number to the given scale. * The rounding is done using the "round half away from zero" method. diff --git a/src/utils/index.ts b/src/utils/index.ts index 549b8347..a09ae0a5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -41,7 +41,6 @@ export { generateUUID, getRandomFloatFluctuatedRounded, getRandomFloatRounded, - getRandomInteger, getWebSocketCloseEventStatusString, isArraySorted, isAsyncFunction, diff --git a/tests/utils/Utils.test.ts b/tests/utils/Utils.test.ts index a8676529..5672b032 100644 --- a/tests/utils/Utils.test.ts +++ b/tests/utils/Utils.test.ts @@ -1,3 +1,4 @@ +import { randomInt } from 'node:crypto' import { version } from 'node:process' import { describe, it } from 'node:test' @@ -17,7 +18,6 @@ import { formatDurationSeconds, generateUUID, getRandomFloat, - getRandomInteger, hasOwnProp, isArraySorted, isAsyncFunction, @@ -95,7 +95,7 @@ await describe('Utils test suite', async () => { expect(convertToInt(undefined)).toBe(0) expect(convertToInt(null)).toBe(0) expect(convertToInt(0)).toBe(0) - const randomInteger = getRandomInteger() + const randomInteger = randomInt(Constants.MAX_RANDOM_INTEGER) expect(convertToInt(randomInteger)).toEqual(randomInteger) expect(convertToInt('-1')).toBe(-1) expect(convertToInt('1')).toBe(1) @@ -157,36 +157,6 @@ await describe('Utils test suite', async () => { expect(random).toBeLessThan(1) }) - await it('Verify getRandomInteger()', () => { - let randomInteger = getRandomInteger() - expect(Number.isSafeInteger(randomInteger)).toBe(true) - expect(randomInteger).toBeGreaterThanOrEqual(0) - expect(randomInteger).toBeLessThanOrEqual(Constants.MAX_RANDOM_INTEGER) - expect(randomInteger).not.toEqual(getRandomInteger()) - randomInteger = getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER) - expect(randomInteger).toBeGreaterThanOrEqual(-Constants.MAX_RANDOM_INTEGER) - expect(randomInteger).toBeLessThanOrEqual(0) - expect(() => getRandomInteger(0, 1)).toThrow( - 'The value of "max" is out of range. It must be greater than the value of "min" (1). Received 1' - ) - expect(() => getRandomInteger(-1)).toThrow( - 'The value of "max" is out of range. It must be greater than the value of "min" (0). Received 0' - ) - expect(() => getRandomInteger(Constants.MAX_RANDOM_INTEGER + 1)).toThrow( - `The value of "max" is out of range. It must be <= ${ - Constants.MAX_RANDOM_INTEGER + 1 - }. Received 281_474_976_710_656` - ) - randomInteger = getRandomInteger(2, 1) - expect(randomInteger).toBeGreaterThanOrEqual(1) - expect(randomInteger).toBeLessThanOrEqual(2) - const maximum = 2.2 - const minimum = 1.1 - randomInteger = getRandomInteger(maximum, minimum) - expect(randomInteger).toBeLessThanOrEqual(Math.floor(maximum)) - expect(randomInteger).toBeGreaterThanOrEqual(Math.ceil(minimum)) - }) - await it('Verify roundTo()', () => { expect(roundTo(0, 2)).toBe(0) expect(roundTo(0.5, 0)).toBe(1) -- 2.34.1