Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/fix-block-wait' into fix-block-wait
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov committed Feb 16, 2021
2 parents b22c897 + 6113024 commit 68d082b
Showing 1 changed file with 57 additions and 117 deletions.
174 changes: 57 additions & 117 deletions test/integration/externalApis/tenderdash/BlockchainListener.spec.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
const EventEmitter = require('events');
const crypto = require('crypto');
const BlockchainListener = require('../../../../lib/externalApis/tenderdash/blockchainListener/BlockchainListener');
const TransactionWaitPeriodExceededError = require('../../../../lib/errors/TransactionWaitPeriodExceededError');

describe('BlockchainListener', () => {
let sinon;
let wsClientMock;
let blockchainListener;
let txDataMock;
const base64tx = 'aaaa';
let txHash;
let blockWithTxMock;
let emptyBlockMock;
let txQueryMessageMock;
let blockMessageMock;
let transactionHash;
let txBase64Mock;
let txBufferMock;

beforeEach(function beforeEach() {
({ sinon } = this);
Expand All @@ -20,27 +19,48 @@ describe('BlockchainListener', () => {
blockchainListener = new BlockchainListener(wsClientMock);
blockchainListener.start();

txHash = crypto.createHash('sha256')
.update(Buffer.from(base64tx, 'base64'))
sinon.spy(blockchainListener, 'on');
sinon.spy(blockchainListener, 'off');
sinon.spy(blockchainListener, 'emit');

txBase64Mock = 'aaaa';
txBufferMock = Buffer.from(txBase64Mock, 'base64');
transactionHash = crypto.createHash('sha256')
.update(Buffer.from(txBase64Mock, 'base64'))
.digest()
.toString('hex');

txDataMock = {
txQueryMessageMock = {
events: {
'tx.hash': [txHash],
'tx.hash': [transactionHash],
},
};

blockWithTxMock = {
data: { value: { block: { data: { txs: [base64tx] } } } },
};
emptyBlockMock = {
data: { value: { block: { data: { txs: [] } } } },
blockMessageMock = {
data: {
value: {
block: {
data: {
txs: [txBase64Mock],
},
},
},
},
};
});

sinon.spy(blockchainListener, 'on');
sinon.spy(blockchainListener, 'off');
sinon.spy(blockchainListener, 'emit');
describe('.getTransactionEventName', () => {
it('should work', () => {
const topic = BlockchainListener.getTransactionEventName(transactionHash);
expect(topic).to.be.equal(`transaction:${transactionHash}`);
});
});

describe('.getTransactionAddedToTheBlockEventName', () => {
it('should work', () => {
const topic = BlockchainListener.getTransactionAddedToTheBlockEventName(transactionHash);
expect(topic).to.be.equal(`blockTransactionAdded:${transactionHash}`);
});
});

describe('#start', () => {
Expand All @@ -53,115 +73,35 @@ describe('BlockchainListener', () => {
BlockchainListener.NEW_BLOCK_QUERY,
);
});
});

describe('.getTransactionEventName', () => {
it('should return transaction event name', () => {
const eventName = BlockchainListener.getTransactionEventName(txHash);
expect(eventName).to.be.equal(`transaction:${txHash}`);
});
});

describe('#waitForTransaction', () => {
it('should remove listener after transaction resolves', async () => {
const txPromise = blockchainListener.waitForTransactionToBeProvable(txHash, 2000);

// check that we attached events correctly
const events = blockchainListener.eventNames();
// transaction result, transaction in block an block events
expect(events.length).to.be.equal(3);
events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(1);
it('should emit transaction hash when transaction is added to the block', (done) => {
const topic = BlockchainListener.getTransactionEventName(transactionHash);
blockchainListener.on(topic, (message) => {
expect(message).to.be.deep.equal(txQueryMessageMock);
done();
});

setTimeout(() => {
wsClientMock.emit(BlockchainListener.TX_QUERY, Object.assign({}, txDataMock));
wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, Object.assign({}, blockWithTxMock));
wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, Object.assign({}, emptyBlockMock));
}, 10);

const txData = await txPromise;
wsClientMock.emit(BlockchainListener.TX_QUERY, txQueryMessageMock);
});

// Check that event listener was properly attached
expect(blockchainListener.on).to.be.calledThrice();
// Check that the event listener was properly removed
expect(blockchainListener.off).to.be.calledTwice();
events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(0);
it('should emit transaction buffer when received a block with this tx from WS connection', (done) => {
const topic = BlockchainListener.getTransactionAddedToTheBlockEventName(transactionHash);
blockchainListener.on(topic, (transactionBuffer) => {
expect(transactionBuffer).to.be.deep.equal(txBufferMock);
done();
});

expect(txData).to.be.deep.equal(txDataMock);
wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, blockMessageMock);
});

it('should not emit transaction event if event data has no transaction', async () => {
let events;
let error;
try {
const txPromise = blockchainListener.waitForTransactionToBeProvable(txHash, 1000);

// check that we attached events correctly
events = blockchainListener.eventNames();
// transaction result, transaction in block an block events
expect(events.length).to.be.equal(3);
events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(1);
});

setTimeout(() => {
wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, Object.assign({}, blockWithTxMock));
}, 10);

await txPromise;
} catch (e) {
error = e;
}

// Check that the error is correct
expect(error).to.be.instanceOf(TransactionWaitPeriodExceededError);
expect(error.message).to.be.equal(`Transaction waiting period for ${txHash} exceeded`);
expect(error.getTransactionHash()).to.be.equal(txHash);

// Check that event listener was properly attached
expect(blockchainListener.on).to.be.calledThrice();
events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(0);
it('should not emit any transaction hashes if block contents are empty', (done) => {
const topic = BlockchainListener.getTransactionAddedToTheBlockEventName(transactionHash);
blockchainListener.on(topic, (message) => {
expect(message).to.be.deep.equal(txBufferMock);
done();
});
// Check that no transaction data was emitted
expect(blockchainListener.emit).to.be.calledTwice();
});

it('should remove listener after timeout has been exceeded', async () => {
let events;
let error;
try {
const txPromise = blockchainListener.waitForTransactionToBeProvable(txHash, 100);

events = blockchainListener.eventNames();
expect(events.length).to.be.equal(3);
events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(1);
});

await txPromise;
} catch (e) {
error = e;
}

// Check that the error is correct
expect(error).to.be.instanceOf(TransactionWaitPeriodExceededError);
expect(error.message).to.be.equal(`Transaction waiting period for ${txHash} exceeded`);
expect(error.getTransactionHash()).to.be.equal(txHash);

// Check that event listener was properly attached
expect(blockchainListener.on).to.be.calledThrice();
// Check that event listener was properly removed
expect(blockchainListener.off).to.be.calledThrice();

events.forEach((eventName) => {
expect(blockchainListener.listenerCount(eventName)).to.be.equal(0);
});
// Check that no transaction data was emitted
expect(blockchainListener.emit).to.not.be.called();
wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, blockMessageMock);
});
});
});

0 comments on commit 68d082b

Please sign in to comment.