From 88156f22956a08eb40cc15e41ab80a4b673ea151 Mon Sep 17 00:00:00 2001 From: fmacleal Date: Wed, 20 Mar 2024 13:16:54 +0100 Subject: [PATCH 1/2] Adding some tests for SnapshotProcessor class --- .../co/rsk/net/SnapshotProcessorTest.java | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java diff --git a/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java b/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java new file mode 100644 index 00000000000..d9b7d80c071 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java @@ -0,0 +1,206 @@ +package co.rsk.net; + +import co.rsk.core.BlockDifficulty; +import co.rsk.net.messages.*; +import co.rsk.net.sync.PeersInformation; +import co.rsk.net.sync.SnapSyncState; +import co.rsk.test.builders.BlockChainBuilder; +import co.rsk.trie.TrieStore; +import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; +import org.ethereum.core.TransactionPool; +import org.ethereum.db.BlockStore; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +class SnapshotProcessorTest { + public static final int TEST_CHUNK_SIZE = 200; + private BlockChainBuilder blockChainBuilder; + private Blockchain blockchain; + private TransactionPool transactionPool; + private BlockStore blockStore; + private TrieStore trieStore; + private Peer peer; + private PeersInformation peersInformation = mock(PeersInformation.class); + private SnapSyncState snapSyncState = mock(SnapSyncState.class); + + private SnapshotProcessor underTest; + @BeforeEach + void setUp() throws UnknownHostException { + peer = mockedPeer(); + when(peersInformation.getBestPeerCandidates()).thenReturn(Arrays.asList(peer)); + } + + @Test + void givenStartSyncingIsCalled_thenSnapStatusStartToBeRequestedFromPeer() { + //given + initializeBlockchainWithAmountOfBlocks(10); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + TEST_CHUNK_SIZE, + false); + //when + underTest.startSyncing(peersInformation, snapSyncState); + //then + verify(peer).sendMessage(any(SnapStatusRequestMessage.class)); + } + + @Test + void givenSnapStatusResponseCalled_thenSnapChunkRequestsAreMade() { + //given + List blocks = new ArrayList<>(); + List difficulties = new ArrayList<>(); + initializeBlockchainWithAmountOfBlocks(10); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + TEST_CHUNK_SIZE, + false); + + for (int blockNumber = 0; blockNumber < blockchain.getSize(); blockNumber ++){ + Block currentBlock = blockchain.getBlockByNumber(blockNumber); + blocks.add(currentBlock); + difficulties.add(blockStore.getTotalDifficultyForHash(currentBlock.getHash().getBytes())); + } + + SnapStatusResponseMessage snapStatusResponseMessage = new SnapStatusResponseMessage(blocks, difficulties, 100000L); + underTest.startSyncing(peersInformation, snapSyncState); + + //when + underTest.processSnapStatusResponse(peer, snapStatusResponseMessage); + + //then + verify(peer, atLeast(3)).sendMessage(any()); // 1 for SnapStatusRequestMessage, 1 for SnapBlocksRequestMessage and 1 for SnapStateChunkRequestMessage + verify(peersInformation, times(2)).getBestPeerCandidates(); + } + + @Test + void givenSnapStatusRequestReceived_thenSnapStatusResponseIsSent() { + //given + initializeBlockchainWithAmountOfBlocks(5010); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + TEST_CHUNK_SIZE, + false); + //when + underTest.processSnapStatusRequest(peer); + + //then + verify(peer, atLeast(1)).sendMessage(any(SnapStatusResponseMessage.class)); + } + + @Test + void givenSnapBlockRequestReceived_thenSnapBlocksResponseMessageIsSent() { + //given + initializeBlockchainWithAmountOfBlocks(5010); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + TEST_CHUNK_SIZE, + false); + SnapBlocksRequestMessage snapBlocksRequestMessage = new SnapBlocksRequestMessage(460); + //when + underTest.processSnapBlocksRequest(peer, snapBlocksRequestMessage); + + //then + verify(peer, atLeast(1)).sendMessage(any(SnapBlocksResponseMessage.class)); + } + + @Test + void givenSnapBlocksResponseReceived_thenSnapBlocksRequestMessageIsSent() { + //given + List blocks = new ArrayList<>(); + List difficulties = new ArrayList<>(); + initializeBlockchainWithAmountOfBlocks(10); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + 200, + false); + + for (int blockNumber = 0; blockNumber < blockchain.getSize(); blockNumber ++){ + Block currentBlock = blockchain.getBlockByNumber(blockNumber); + blocks.add(currentBlock); + difficulties.add(blockStore.getTotalDifficultyForHash(currentBlock.getHash().getBytes())); + } + + SnapStatusResponseMessage snapStatusResponseMessage = new SnapStatusResponseMessage(blocks, difficulties, 100000L); + underTest.startSyncing(peersInformation, snapSyncState); + underTest.processSnapStatusResponse(peer, snapStatusResponseMessage); + + SnapBlocksResponseMessage snapBlocksResponseMessage = new SnapBlocksResponseMessage(blocks, difficulties); + //when + underTest.processSnapBlocksResponse(peer, snapBlocksResponseMessage); + + //then + verify(peer, atLeast(2)).sendMessage(any(SnapBlocksRequestMessage.class)); + } + + @Test + void givenSnapStateChunkRequest_thenSnapStateChunkResponseMessageIsSent() { + //given + initializeBlockchainWithAmountOfBlocks(1000); + underTest = new SnapshotProcessor( + blockchain, + trieStore, + peersInformation, + blockStore, + transactionPool, + TEST_CHUNK_SIZE, + false); + + SnapStateChunkRequestMessage snapStateChunkRequestMessage = new SnapStateChunkRequestMessage(1L, 1L,1, TEST_CHUNK_SIZE); + + //when + underTest.processStateChunkRequest(peer, snapStateChunkRequestMessage); + + //then + verify(peer, timeout(5000).atLeast(1)).sendMessage(any(SnapStateChunkResponseMessage.class)); // We have to wait because this method does the job insides thread + } + + private void initializeBlockchainWithAmountOfBlocks(int numberOfBlocks) { + blockChainBuilder = new BlockChainBuilder(); + blockchain = blockChainBuilder.ofSize(numberOfBlocks); + transactionPool = blockChainBuilder.getTransactionPool(); + blockStore = blockChainBuilder.getBlockStore(); + trieStore = blockChainBuilder.getTrieStore(); + } + + private Peer mockedPeer() throws UnknownHostException { + Peer mockedPeer = mock(Peer.class); + NodeID nodeID = mock(NodeID.class); + when(mockedPeer.getPeerNodeID()).thenReturn(nodeID); + when(mockedPeer.getAddress()).thenReturn(InetAddress.getByName("127.0.0.1")); + when(peersInformation.getBestPeerCandidates()).thenReturn(Arrays.asList(peer)); + return mockedPeer; + } + +} \ No newline at end of file From cecbfea2cf8df8d602d3e41de7090a1f136d14ab Mon Sep 17 00:00:00 2001 From: fmacleal Date: Wed, 20 Mar 2024 16:50:50 +0100 Subject: [PATCH 2/2] Adding copyright headers for missing classes --- .../co/rsk/net/SnapshotProcessorTest.java | 21 ++++++++++++++++--- .../rsk/trie/TrieDTOInOrderIteratorTest.java | 18 ++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java b/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java index d9b7d80c071..7c8e5c7e6fb 100644 --- a/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java +++ b/rskj-core/src/test/java/co/rsk/net/SnapshotProcessorTest.java @@ -1,3 +1,21 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * (derived from ethereumJ library, Copyright (c) 2016 ) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package co.rsk.net; import co.rsk.core.BlockDifficulty; @@ -12,16 +30,13 @@ import org.ethereum.db.BlockStore; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.CountDownLatch; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; class SnapshotProcessorTest { diff --git a/rskj-core/src/test/java/co/rsk/trie/TrieDTOInOrderIteratorTest.java b/rskj-core/src/test/java/co/rsk/trie/TrieDTOInOrderIteratorTest.java index 3563b137cea..d6429475c72 100644 --- a/rskj-core/src/test/java/co/rsk/trie/TrieDTOInOrderIteratorTest.java +++ b/rskj-core/src/test/java/co/rsk/trie/TrieDTOInOrderIteratorTest.java @@ -1,3 +1,21 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * (derived from ethereumJ library, Copyright (c) 2016 ) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package co.rsk.trie; import org.ethereum.datasource.HashMapDB;