aboutsummaryrefslogtreecommitdiffstats
path: root/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts')
-rw-r--r--packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts109
1 files changed, 109 insertions, 0 deletions
diff --git a/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts b/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts
new file mode 100644
index 000000000..06f1a5e86
--- /dev/null
+++ b/packages/pipeline/test/data_sources/contract-wrappers/utils_test.ts
@@ -0,0 +1,109 @@
+// tslint:disable:custom-no-magic-numbers
+import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import 'mocha';
+
+import { _getEventsWithRetriesAsync } from '../../../src/data_sources/contract-wrappers/utils';
+import { chaiSetup } from '../../utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const retryableMessage = 'network timeout: (simulated network timeout error)';
+const retryableError = new Error(retryableMessage);
+
+describe('data_sources/contract-wrappers/utils', () => {
+ describe('_getEventsWithRetriesAsync', () => {
+ it('sends a single request if it was successful', async () => {
+ // Pre-declare values for the fromBlock and toBlock arguments.
+ const expectedFromBlock = 100;
+ const expectedToBlock = 200;
+ const expectedLogs: Array<LogWithDecodedArgs<any>> = [
+ {
+ logIndex: 123,
+ transactionIndex: 456,
+ transactionHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657fe',
+ blockHash: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd33657ff',
+ blockNumber: 789,
+ address: '0x6dd106d002873746072fc5e496dd0fb2541b68c77bcf9184ae19a42fd3365800',
+ data: 'fake raw data',
+ topics: [],
+ event: 'TEST_EVENT',
+ args: [1, 2, 3],
+ },
+ ];
+
+ // mockGetEventsAsync checks its arguments, increments `callCount`
+ // and returns `expectedLogs`.
+ let callCount = 0;
+ const mockGetEventsAsync = async (
+ fromBlock: number,
+ toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ expect(fromBlock).equals(expectedFromBlock);
+ expect(toBlock).equals(expectedToBlock);
+ callCount += 1;
+ return expectedLogs;
+ };
+
+ // Make sure that we get what we expected and that the mock function
+ // was called exactly once.
+ const gotLogs = await _getEventsWithRetriesAsync(mockGetEventsAsync, 3, expectedFromBlock, expectedToBlock);
+ expect(gotLogs).deep.equals(expectedLogs);
+ expect(callCount).equals(
+ 1,
+ 'getEventsAsync function was called more than once even though it was successful',
+ );
+ });
+ it('retries and eventually succeeds', async () => {
+ const numRetries = 5;
+ let callCount = 0;
+ // mockGetEventsAsync throws unless callCount == numRetries + 1.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ callCount += 1;
+ if (callCount === numRetries + 1) {
+ return [];
+ }
+ throw retryableError;
+ };
+ await _getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300);
+ expect(callCount).equals(numRetries + 1, 'getEventsAsync function was called the wrong number of times');
+ });
+ it('throws for non-retryable errors', async () => {
+ const numRetries = 5;
+ const expectedMessage = 'Non-retryable error';
+ // mockGetEventsAsync always throws a non-retryable error.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ throw new Error(expectedMessage);
+ };
+ // Note(albrow): This does actually return a promise (or at least a
+ // "promise-like object" and is a false positive in TSLint.
+ // tslint:disable-next-line:await-promise
+ await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
+ expectedMessage,
+ );
+ });
+ it('throws after too many retries', async () => {
+ const numRetries = 5;
+ // mockGetEventsAsync always throws a retryable error.
+ const mockGetEventsAsync = async (
+ _fromBlock: number,
+ _toBlock: number,
+ ): Promise<Array<LogWithDecodedArgs<any>>> => {
+ throw retryableError;
+ };
+ // Note(albrow): This does actually return a promise (or at least a
+ // "promise-like object" and is a false positive in TSLint.
+ // tslint:disable-next-line:await-promise
+ await expect(_getEventsWithRetriesAsync(mockGetEventsAsync, numRetries, 100, 300)).to.be.rejectedWith(
+ retryableMessage,
+ );
+ });
+ });
+});