Files
protocol/apps-node/rfq-api/test/background_job_test.ts
2023-03-09 11:19:11 -07:00

292 lines
13 KiB
TypeScript

import { ChainId } from '@0x/contract-addresses';
import { Job, Queue } from 'bullmq';
import Redis from 'ioredis';
import { anything, instance, mock, spy, when } from 'ts-mockito';
import backgroundJobMBCEvict from '../src/background-jobs/maker_balance_cache_evict';
import backgroundJobMBCUpdate from '../src/background-jobs/maker_balance_cache_update';
import { CHAIN_CONFIGURATIONS } from '../src/config';
import { RfqMakerBalanceCacheService } from '../src/services/rfq_maker_balance_cache_service';
import * as serviceBuilder from '../src/utils/rfqm_service_builder';
describe('Background Jobs Unit Tests', () => {
describe('maker-balance-cache-evict', () => {
it('should fail to create background job when bad chain id is passed', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(undefined);
const { createAsync, processAsync } = backgroundJobMBCEvict;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCEvict.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const badChainId = 11111111;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId: badChainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCEvict.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
expect(processAsync(job)).rejects.toThrow('chain configuration');
});
it('processes maker balance cache eviction without error', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(anything());
const rfqMakerBalanceCacheServiceMock = mock(RfqMakerBalanceCacheService);
when(rfqMakerBalanceCacheServiceMock.evictZeroBalancesAsync(anything())).thenResolve(1);
const spiedServiceBuilderAsync = spy(serviceBuilder);
when(spiedServiceBuilderAsync.buildRfqMakerBalanceCacheServiceAsync(anything())).thenResolve(
instance(rfqMakerBalanceCacheServiceMock),
);
const { createAsync, processAsync } = backgroundJobMBCEvict;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCEvict.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const chainId = ChainId.Ganache;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCEvict.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
const result = await processAsync(job);
expect(result.chainId).toEqual(chainId);
expect(result.numEvicted).toEqual(1);
});
it('should fail to process job when malformed cache service is passed', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(anything());
const spiedServiceBuilderAsync = spy(serviceBuilder);
when(spiedServiceBuilderAsync.buildRfqMakerBalanceCacheServiceAsync(anything())).thenResolve();
const { createAsync, processAsync } = backgroundJobMBCEvict;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCEvict.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const chainId = ChainId.Ganache;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCEvict.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
expect(processAsync(job)).rejects.toThrow('initialize dependencies');
});
it('should fail to process job when the cache service fails to evict entries', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(anything());
const rfqMakerBalanceCacheServiceMock = mock(RfqMakerBalanceCacheService);
when(rfqMakerBalanceCacheServiceMock.evictZeroBalancesAsync(anything())).thenReject(
new Error('cache failed'),
);
const spiedServiceBuilderAsync = spy(serviceBuilder);
when(spiedServiceBuilderAsync.buildRfqMakerBalanceCacheServiceAsync(anything())).thenResolve(
instance(rfqMakerBalanceCacheServiceMock),
);
const { createAsync, processAsync } = backgroundJobMBCEvict;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCEvict.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const chainId = ChainId.Ganache;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCEvict.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
expect(processAsync(job)).rejects.toThrow('evict maker balance cache');
});
});
describe('maker-balance-cache-update', () => {
it('should fail to create background job when bad chain id is passed', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(undefined);
const { createAsync, processAsync } = backgroundJobMBCUpdate;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCUpdate.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const badChainId = 11111111;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId: badChainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCUpdate.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
expect(processAsync(job)).rejects.toThrow('chain configuration');
});
it('processes maker balance cache update without error', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(anything());
const rfqMakerBalanceCacheServiceMock = mock(RfqMakerBalanceCacheService);
when(rfqMakerBalanceCacheServiceMock.updateERC20OwnerBalancesAsync(anything())).thenResolve();
const spiedServiceBuilderAsync = spy(serviceBuilder);
when(spiedServiceBuilderAsync.buildRfqMakerBalanceCacheServiceAsync(anything())).thenResolve(
instance(rfqMakerBalanceCacheServiceMock),
);
const { createAsync, processAsync } = backgroundJobMBCUpdate;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCUpdate.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const chainId = ChainId.Ganache;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCUpdate.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
const result = await processAsync(job);
expect(result.chainId).toEqual(chainId);
});
it('should fail to process job when the cache service fails to update entries', async () => {
const spiedChainConfigurations = spy(CHAIN_CONFIGURATIONS);
when(spiedChainConfigurations.find(anything())).thenReturn(anything());
const rfqMakerBalanceCacheServiceMock = mock(RfqMakerBalanceCacheService);
when(rfqMakerBalanceCacheServiceMock.updateERC20OwnerBalancesAsync(anything())).thenReject(
new Error('cache failed'),
);
const spiedServiceBuilderAsync = spy(serviceBuilder);
when(spiedServiceBuilderAsync.buildRfqMakerBalanceCacheServiceAsync(anything())).thenResolve(
instance(rfqMakerBalanceCacheServiceMock),
);
const { createAsync, processAsync } = backgroundJobMBCUpdate;
const connectionMock = mock(Redis);
const queue = new Queue(backgroundJobMBCUpdate.queueName, { connection: instance(connectionMock) });
const spiedQueue = spy(queue);
when(spiedQueue.emit(anything())).thenReturn(true);
const spiedJob = spy(Job);
when(spiedJob.create(anything(), anything(), anything(), anything())).thenCall(
// $eslint-fix-me https://github.com/rhinodavid/eslint-fix-me
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(q: Queue, name: any, data: any) => new Job(q, name, data),
);
const chainId = ChainId.Ganache;
const timestamp = Date.now();
const job = await createAsync(queue, {
chainId,
timestamp,
});
expect(job.queueName).toEqual(backgroundJobMBCUpdate.queueName);
const spiedJobInstance = spy(job);
when(spiedJobInstance.updateProgress(anything())).thenResolve();
expect(processAsync(job)).rejects.toThrow('update maker balance cache');
});
});
});