From 5f9aa29294b87a2fdec7bc5338676c3f86810616 Mon Sep 17 00:00:00 2001 From: Dave Kelsey <25582377+davidkel@users.noreply.github.com> Date: Wed, 6 Apr 2022 09:21:03 +0100 Subject: [PATCH] fix RecordRate rate controller (#1292) Addresses the record rate controller as it doesn't work and causes a node stack overflow closes #1131 Signed-off-by: D --- .../lib/worker/rate-control/recordRate.js | 9 +- .../test/worker/rate-control/mockRate.js | 34 ++++++ .../test/worker/rate-control/recordRate.js | 104 ++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 packages/caliper-core/test/worker/rate-control/mockRate.js create mode 100644 packages/caliper-core/test/worker/rate-control/recordRate.js diff --git a/packages/caliper-core/lib/worker/rate-control/recordRate.js b/packages/caliper-core/lib/worker/rate-control/recordRate.js index 7282b248e..3e7e04cac 100644 --- a/packages/caliper-core/lib/worker/rate-control/recordRate.js +++ b/packages/caliper-core/lib/worker/rate-control/recordRate.js @@ -78,7 +78,10 @@ class RecordRateController extends RateInterface { this.pathTemplate = this.pathTemplate.replace(//gi, this.workerIndex.toString()); this.pathTemplate = util.resolvePath(this.pathTemplate); - this.rateController = new RateControl(testMessage, stats, workerIndex,); + let rateControllerTestMessage = this.testMessage.clone(); + rateControllerTestMessage.setRateControlSpec(this.options.rateController); + + this.recordedRateController = new RateControl(rateControllerTestMessage, stats, workerIndex); } /** @@ -128,7 +131,7 @@ class RecordRateController extends RateInterface { * @async */ async applyRateControl() { - await this.rateController.applyRateControl(); + await this.recordedRateController.applyRateControl(); this.records[this.stats.getTotalSubmittedTx()] = Date.now() - this.stats.getRoundStartTime(); } @@ -137,7 +140,7 @@ class RecordRateController extends RateInterface { * @async */ async end() { - await this.rateController.end(); + await this.recordedRateController.end(); try { switch (this.outputFormat) { diff --git a/packages/caliper-core/test/worker/rate-control/mockRate.js b/packages/caliper-core/test/worker/rate-control/mockRate.js new file mode 100644 index 000000000..802682900 --- /dev/null +++ b/packages/caliper-core/test/worker/rate-control/mockRate.js @@ -0,0 +1,34 @@ +/* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +class MockRate { + + reset() { + MockRate.applyRateControlCalled = false; + } + + isApplyRateControlCalled() { + return MockRate.applyRateControlCalled; + } + + async applyRateControl() { + MockRate.applyRateControlCalled = true; + } +} + +function createRateController(testMessage, stats, workerIndex) { + return new MockRate(); +} + +module.exports.createRateController = createRateController; \ No newline at end of file diff --git a/packages/caliper-core/test/worker/rate-control/recordRate.js b/packages/caliper-core/test/worker/rate-control/recordRate.js new file mode 100644 index 000000000..0509a48f6 --- /dev/null +++ b/packages/caliper-core/test/worker/rate-control/recordRate.js @@ -0,0 +1,104 @@ +/* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +const mockery = require('mockery'); +const path = require('path'); +const RecordRate = require('../../../lib/worker/rate-control/recordRate'); +const TestMessage = require('../../../lib/common/messages/testMessage'); +const MockRate = require('./mockRate'); +const TransactionStatisticsCollector = require('../../../lib/common/core/transaction-statistics-collector'); + +const chai = require('chai'); +chai.should(); +const sinon = require('sinon'); + +describe('RecordRate controller', () => { + before(() => { + mockery.enable({ + warnOnReplace: false, + warnOnUnregistered: false, + useCleanCache: true + }); + + mockery.registerMock(path.join(__dirname, '../../../lib/worker/rate-control/noRate.js'), MockRate); + }); + + after(() => { + mockery.deregisterAll(); + mockery.disable(); + }); + + it('should apply rate control to the recorded rate controller', async () => { + const msgContent = { + label: 'test', + rateControl: { + "type": "record-rate", + "opts": { + "rateController": { + "type": "zero-rate" + }, + "pathTemplate": "../tx_records_client_round.txt", + "outputFormat": "TEXT", + "logEnd": true + } + }, + workload: { + module: 'module.js' + }, + testRound: 0, + txDuration: 250, + totalWorkers: 2 + }; + + const testMessage = new TestMessage('test', [], msgContent); + const stubStatsCollector = sinon.createStubInstance(TransactionStatisticsCollector); + const rateController = RecordRate.createRateController(testMessage, stubStatsCollector, 0); + const mockRate = MockRate.createRateController(); + mockRate.reset(); + mockRate.isApplyRateControlCalled().should.equal(false); + await rateController.applyRateControl(); + mockRate.isApplyRateControlCalled().should.equal(true); + }); + + it('should throw an error if the rate controller to record is unknown', async () => { + const msgContent = { + label: 'test', + rateControl: { + "type": "record-rate", + "opts": { + "rateController": { + "type": "nonexistent-rate" + }, + "pathTemplate": "../tx_records_client_round.txt", + "outputFormat": "TEXT", + "logEnd": true + } + }, + workload: { + module: 'module.js' + }, + testRound: 0, + txDuration: 250, + totalWorkers: 2 + }; + const testMessage = new TestMessage('test', [], msgContent); + + const stubStatsCollector = sinon.createStubInstance(TransactionStatisticsCollector); + (() => { + RecordRate.createRateController(testMessage, stubStatsCollector, 0) + }).should.throw(/Module "nonexistent-rate" could not be loaded/); + }); +});