From 2471e6f871c9cd10c219b5f0aef4ddfef111f4e6 Mon Sep 17 00:00:00 2001 From: Dmitry Tyshchenko Date: Tue, 25 Feb 2020 02:40:43 +0200 Subject: [PATCH] Processor test --- .../core-transaction-pool/processor.test.ts | 113 +++++++++++++++--- 1 file changed, 99 insertions(+), 14 deletions(-) diff --git a/__tests__/unit/core-transaction-pool/processor.test.ts b/__tests__/unit/core-transaction-pool/processor.test.ts index b4e53474ed..a389d46fc7 100644 --- a/__tests__/unit/core-transaction-pool/processor.test.ts +++ b/__tests__/unit/core-transaction-pool/processor.test.ts @@ -1,4 +1,4 @@ -import { Container } from "@arkecosystem/core-kernel"; +import { Container, Contracts } from "@arkecosystem/core-kernel"; import { Interfaces, Transactions } from "@arkecosystem/crypto"; import { Processor } from "../../../packages/core-transaction-pool/src/processor"; @@ -9,7 +9,7 @@ describe("Processor", () => { const container = new Container.Container(); describe("process", () => { - const logger = { warning: jest.fn() }; + const logger = { warning: jest.fn(), error: jest.fn() }; const pool = { addTransaction: jest.fn() }; const dynamicFeeMatcher = { canEnterPool: jest.fn(), canBroadcast: jest.fn() }; const transactionBroadcaster = { broadcastTransactions: jest.fn() }; @@ -23,30 +23,115 @@ describe("Processor", () => { }); beforeEach(() => { - (Transactions.TransactionFactory.fromData as jest.Mock).mockReset(); + (Transactions.TransactionFactory.fromData as jest.Mock).mockClear(); - logger.warning.mockReset(); - pool.addTransaction.mockReset(); - dynamicFeeMatcher.canEnterPool.mockReset(); - dynamicFeeMatcher.canBroadcast.mockReset(); - transactionBroadcaster.broadcastTransactions.mockReset(); + logger.warning.mockClear(); + pool.addTransaction.mockClear(); + dynamicFeeMatcher.canEnterPool.mockClear(); + dynamicFeeMatcher.canBroadcast.mockClear(); + transactionBroadcaster.broadcastTransactions.mockClear(); }); it("should add eligible transactions to pool", async () => { - (Transactions.TransactionFactory.fromData as jest.Mock).mockImplementation(d => ({ id: d.id })); + const data: any[] = [{ id: "id1" }, { id: "id2" }]; + (Transactions.TransactionFactory.fromData as jest.Mock).mockImplementation(d => ({ id: d.id })); dynamicFeeMatcher.canEnterPool.mockReturnValueOnce(true).mockReturnValueOnce(false); - const data: any[] = [{ id: "id_eligible" }, { id: "id_non_eligible" }]; const processor = container.resolve(Processor); await processor.process(data as Interfaces.ITransactionData[]); - expect(processor.accept).toEqual(["id_eligible"]); - expect(processor.invalid).toEqual(["id_non_eligible"]); + expect(dynamicFeeMatcher.canEnterPool).toBeCalledTimes(2); + expect(pool.addTransaction).toBeCalledTimes(1); + expect(dynamicFeeMatcher.canBroadcast).toBeCalledTimes(1); + expect(transactionBroadcaster.broadcastTransactions).not.toBeCalled(); + + expect(processor.accept).toEqual(["id1"]); + expect(processor.broadcast).toEqual([]); + expect(processor.invalid).toEqual(["id2"]); + expect(processor.excess).toEqual([]); expect(processor.errors).toEqual({ - id_non_eligible: { + id2: { type: "ERR_LOW_FEE", - message: "Transaction id_non_eligible fee is to low to include in pool", + message: "Transaction id2 fee is to low to include in pool", + }, + }); + }); + + it("should add broadcast eligible transaction", async () => { + const data: any[] = [{ id: "id1" }, { id: "id2" }]; + + (Transactions.TransactionFactory.fromData as jest.Mock).mockImplementation(d => ({ id: d.id })); + dynamicFeeMatcher.canEnterPool.mockReturnValueOnce(true).mockReturnValueOnce(true); + dynamicFeeMatcher.canBroadcast.mockReturnValueOnce(true).mockReturnValueOnce(false); + + const processor = container.resolve(Processor); + await processor.process(data as Interfaces.ITransactionData[]); + + expect(dynamicFeeMatcher.canEnterPool).toBeCalledTimes(2); + expect(pool.addTransaction).toBeCalledTimes(2); + expect(dynamicFeeMatcher.canBroadcast).toBeCalledTimes(2); + expect(transactionBroadcaster.broadcastTransactions).toBeCalled(); + + expect(processor.accept).toEqual(["id1", "id2"]); + expect(processor.broadcast).toEqual(["id1"]); + expect(processor.invalid).toEqual([]); + expect(processor.excess).toEqual([]); + expect(processor.errors).toEqual(undefined); + }); + + it("should rethrow unexpected error", async () => { + const data: any[] = [{ id: "id1" }]; + + (Transactions.TransactionFactory.fromData as jest.Mock).mockImplementation(d => ({ id: d.id })); + dynamicFeeMatcher.canEnterPool.mockReturnValueOnce(true); + pool.addTransaction.mockRejectedValueOnce(new Error("Unexpected error")); + + const processor = container.resolve(Processor); + const promise = processor.process(data as Interfaces.ITransactionData[]); + + await expect(promise).rejects.toThrow(); + + expect(dynamicFeeMatcher.canEnterPool).toBeCalledTimes(1); + expect(pool.addTransaction).toBeCalledTimes(1); + expect(dynamicFeeMatcher.canBroadcast).toBeCalledTimes(0); + expect(transactionBroadcaster.broadcastTransactions).not.toBeCalled(); + + expect(processor.accept).toEqual([]); + expect(processor.broadcast).toEqual([]); + expect(processor.invalid).toEqual(["id1"]); + expect(processor.excess).toEqual([]); + expect(processor.errors).toEqual(undefined); + }); + + it("should track excess transactions", async () => { + const data: any[] = [{ id: "id1" }]; + const exceedsError = new Contracts.TransactionPool.PoolError( + "Exceeds", + "ERR_EXCEEDS_MAX_COUNT", + data[0] as Interfaces.ITransaction, + ); + + (Transactions.TransactionFactory.fromData as jest.Mock).mockImplementation(d => ({ id: d.id })); + dynamicFeeMatcher.canEnterPool.mockReturnValueOnce(true); + pool.addTransaction.mockRejectedValueOnce(exceedsError); + + const processor = container.resolve(Processor); + await processor.process(data as Interfaces.ITransactionData[]); + + expect(dynamicFeeMatcher.canEnterPool).toBeCalledTimes(1); + expect(pool.addTransaction).toBeCalledTimes(1); + expect(dynamicFeeMatcher.canBroadcast).toBeCalledTimes(0); + expect(transactionBroadcaster.broadcastTransactions).not.toBeCalled(); + + expect(processor.accept).toEqual([]); + expect(processor.broadcast).toEqual([]); + expect(processor.invalid).toEqual(["id1"]); + expect(processor.excess).toEqual(["id1"]); + expect(processor.errors).toEqual({ + id1: { + type: "ERR_EXCEEDS_MAX_COUNT", + message: "Exceeds", }, }); });