Skip to content

Commit

Permalink
fix RecordRate rate controller (#1292)
Browse files Browse the repository at this point in the history
Addresses the record rate controller as it doesn't work and causes a
node stack overflow

closes #1131

Signed-off-by: D <d_kelsey@uk.ibm.com>
  • Loading branch information
davidkel committed Apr 6, 2022
1 parent a372f18 commit 5f9aa29
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 3 deletions.
9 changes: 6 additions & 3 deletions packages/caliper-core/lib/worker/rate-control/recordRate.js
Expand Up @@ -78,7 +78,10 @@ class RecordRateController extends RateInterface {
this.pathTemplate = this.pathTemplate.replace(/<C>/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);
}

/**
Expand Down Expand Up @@ -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();
}

Expand All @@ -137,7 +140,7 @@ class RecordRateController extends RateInterface {
* @async
*/
async end() {
await this.rateController.end();
await this.recordedRateController.end();

try {
switch (this.outputFormat) {
Expand Down
34 changes: 34 additions & 0 deletions 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;
104 changes: 104 additions & 0 deletions 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<C>_round<R>.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<C>_round<R>.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/);
});
});

0 comments on commit 5f9aa29

Please sign in to comment.