Skip to content

Commit

Permalink
start BlockchainMonitor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ross-weir committed Sep 13, 2023
1 parent a827abc commit 6b28eff
Showing 1 changed file with 188 additions and 0 deletions.
188 changes: 188 additions & 0 deletions src/blockchain/blockchain_monitor_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { assertEquals } from "std/testing/asserts.ts";
import { assertSpyCalls, spy } from "std/testing/mock.ts";
import { beforeEach, describe, it } from "std/testing/bdd.ts";
import { ErgomaticConfig } from "../config.ts";
import {
BlockchainMonitor,
BlockchainSnapshot,
MonitorState,
} from "./blockchain_monitor.ts";
import { BlockchainClient, DefaultBlockchainClient } from "./mod.ts";
import { testConfig } from "../_testing.ts";
import { Block, SignedTransaction } from "@fleet-sdk/common";

function mkSnapshot(
partial?: Partial<BlockchainSnapshot>,
): Readonly<BlockchainSnapshot> {
return {
height: 800000,
mempool: [],
...partial,
};
}

function mkBlock(txns: SignedTransaction[] = []): Block {
return {
header: {
id: "1",
},
blockTransactions: {
transactions: txns,
},
} as Block;
}

function defaultMonitorState(): MonitorState {
return {
currentHeight: 0,
mempoolTxState: {},
pastMempoolTxIds: [],
lastPeerMsgTimestamp: 0,
};
}

describe("BlockchainMonitor", () => {
let config: ErgomaticConfig;
let blockchainClient: BlockchainClient;
let blockchainMonitor: BlockchainMonitor;
const MAX_DROP_CHECKS = 5;

beforeEach(() => {
config = testConfig();
blockchainClient = new DefaultBlockchainClient(config);
blockchainMonitor = new BlockchainMonitor(
config,
blockchainClient,
500,
MAX_DROP_CHECKS,
);
});

describe("handleMempool()", () => {
it("should raise mempool tx events once for new mempool transactions", () => {
const tx = { id: "1337" } as SignedTransaction;
const state = defaultMonitorState();
const snapshot = mkSnapshot();
const dispatchSpy = spy(blockchainMonitor, "dispatchEvent");

try {
blockchainMonitor.handleMempool([tx], state, snapshot);
// ensure event is only raised once
blockchainMonitor.handleMempool([tx], state, snapshot);

assertSpyCalls(dispatchSpy, 1);
const [{ type, detail }] = dispatchSpy.calls[0].args as [CustomEvent];

assertEquals(type, "monitor:mempool-tx");
assertEquals(detail[0], tx);
assertEquals(detail[1], snapshot);
} finally {
dispatchSpy.restore();
}
});
});

describe("checkForMempoolDrops()", () => {
it("should raise mempool tx dropped event if drop check threshold exceeded", () => {
const droppedTx = { id: "1337" } as SignedTransaction;
const validTx = { id: "1338" } as SignedTransaction;
const state = defaultMonitorState();
const snapshot = mkSnapshot();
const dispatchSpy = spy(blockchainMonitor, "dispatchEvent");

state.mempoolTxState[droppedTx.id] = {
delivered: true,
dropChecks: MAX_DROP_CHECKS + 1,
tx: droppedTx,
};

state.mempoolTxState[validTx.id] = {
delivered: true,
dropChecks: 0,
tx: validTx,
};

try {
blockchainMonitor.checkMempoolDrops(state, snapshot);

// assert the event was raised once and only for tx exceeding check limit
assertSpyCalls(dispatchSpy, 1);
const [{ type, detail }] = dispatchSpy.calls[0].args as [CustomEvent];

assertEquals(type, "monitor:mempool-tx-drop");
assertEquals(detail[0], droppedTx);
assertEquals(detail[1], snapshot);

assertEquals(state.mempoolTxState[validTx.id].dropChecks, 1);
} finally {
dispatchSpy.restore();
}
});
});

describe("handleNewBlock()", () => {
it("should raise new block event", () => {
const block = mkBlock();
const state = defaultMonitorState();
const snapshot = mkSnapshot();
const dispatchSpy = spy(blockchainMonitor, "dispatchEvent");

try {
blockchainMonitor.handleNewBlock(block, state, snapshot);

assertSpyCalls(dispatchSpy, 1);
const [{ type, detail }] = dispatchSpy.calls[0].args as [CustomEvent];

assertEquals(type, "monitor:new-block");
assertEquals(detail[0], block);
assertEquals(detail[1], snapshot);
} finally {
dispatchSpy.restore();
}
});

it("should raise new tx event for all transactions in block", () => {
const tx = { id: "1337" } as SignedTransaction;
const tx2 = { id: "1338" } as SignedTransaction;
const block = mkBlock([tx, tx2]);
const state = defaultMonitorState();
const snapshot = mkSnapshot();
const dispatchSpy = spy(blockchainMonitor, "dispatchEvent");

state.mempoolTxState[tx.id] = {
delivered: true,
dropChecks: 0,
tx,
};

state.mempoolTxState[tx2.id] = {
delivered: true,
dropChecks: 0,
tx: tx2,
};

try {
blockchainMonitor.handleNewBlock(block, state, snapshot);

let { type, detail } = (dispatchSpy.calls[1].args as [CustomEvent])[0];

assertEquals(type, "monitor:included-tx");
assertEquals(detail[0], tx);
assertEquals(detail[1], snapshot);

type = (dispatchSpy.calls[2].args as [CustomEvent])[0].type;
detail = (dispatchSpy.calls[2].args as [CustomEvent])[0].detail;

assertEquals(type, "monitor:included-tx");
assertEquals(detail[0], tx2);
assertEquals(detail[1], snapshot);

// ensure its removed from mempool tx dropped tracking
assertEquals(state.mempoolTxState[tx.id], undefined);
assertEquals(state.mempoolTxState[tx2.id], undefined);
} finally {
dispatchSpy.restore();
}
});
});
});

0 comments on commit 6b28eff

Please sign in to comment.