@ -16,27 +16,27 @@ package org.hyperledger.besu.ethereum.eth.sync.tasks;
import static java.util.Arrays.asList ;
import static org.assertj.core.api.Assertions.assertThat ;
import static org.mockito.ArgumentMatchers.any ;
import static org.mockito.Mockito.times ;
import static org.mockito.Mockito.verify ;
import static org.assertj.core.api.Assertions.assertThatThrownBy ;
import org.hyperledger.besu.ethereum.core.Block ;
import org.hyperledger.besu.ethereum.core.BlockBody ;
import org.hyperledger.besu.ethereum.core.BlockHeader ;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture ;
import org.hyperledger.besu.ethereum.eth.manager.PeerRequest ;
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil ;
import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer ;
import org.hyperledger.besu.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest ;
import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException ;
import org.hyperledger.besu.ethereum.eth.manager.task.EthTask ;
import org.hyperledger.besu.ethereum.eth.messages.GetBlockBodiesMessage ;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData ;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem ;
import java.util.ArrayList ;
import java.util.List ;
import java.util.Optional ;
import java.util.concurrent.CompletableFuture ;
import java.util.stream.Collectors ;
import org.junit.Test ;
import org.mockito.ArgumentCaptor ;
public class CompleteBlocksTaskTest extends RetryingMessageTaskTest < List < Block > > {
@ -47,7 +47,7 @@ public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>>
protected List < Block > generateDataToBeRequested ( final int nbBlock ) {
// Setup data to be requested and expected response
final List < Block > blocks = new ArrayList < > ( ) ;
final List < Block > blocks = new ArrayList < > ( nbBlock ) ;
for ( long i = 0 ; i < nbBlock ; i + + ) {
final BlockHeader header = blockchain . getBlockHeader ( 10 + i ) . get ( ) ;
final BlockBody body = blockchain . getBlockBody ( header . getHash ( ) ) . get ( ) ;
@ -57,7 +57,7 @@ public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>>
}
@Override
protected EthTask < List < Block > > createTask ( final List < Block > requestedData ) {
protected CompleteBlocksTask createTask ( final List < Block > requestedData ) {
final List < BlockHeader > headersToComplete =
requestedData . stream ( ) . map ( Block : : getHeader ) . collect ( Collectors . toList ( ) ) ;
return CompleteBlocksTask . forHeaders (
@ -82,29 +82,33 @@ public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>>
@SuppressWarnings ( "unchecked" )
@Test
public void shouldReduceTheBlockSegmentSizeAfterEachRetry ( ) {
final RespondingEthPeer respondingPeer =
EthProtocolManagerTestUtil . createPeer ( ethProtocolManager , 1000 ) ;
peerCountToTimeout . set ( 3 ) ;
final List < Block > requestedData = generateDataToBeRequested ( 10 ) ;
final EthTask < List < Block > > task = createTask ( requestedData ) ;
final CompleteBlocksTask task = createTask ( requestedData ) ;
final CompletableFuture < List < Block > > future = task . run ( ) ;
ArgumentCaptor < Long > blockNumbersCaptor = ArgumentCaptor . forClass ( Long . class ) ;
final List < MessageData > messageCollector = new ArrayList < > ( ) ;
verify ( ethPeers , times ( 4 ) )
. executePeerRequest (
any ( PeerRequest . class ) , blockNumbersCaptor . capture ( ) , any ( Optional . class ) ) ;
respondingPeer . respond (
RespondingEthPeer . wrapResponderWithCollector (
RespondingEthPeer . emptyResponder ( ) , messageCollector ) ) ;
assertThat ( future . isDone ( ) ) . isFalse ( ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 0 ) ) . isEqualTo ( 19 ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 1 ) ) . isEqualTo ( 1 4) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 2 ) ) . isEqualTo ( 13 ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 3 ) ) . isEqualTo ( 10 ) ;
assertThat ( batchSize ( messageCollector . get ( 0 ) ) ) . isEqualTo ( 10 ) ;
assertThat ( batchSize ( messageCollector . get ( 1 ) ) ) . isEqualTo ( 5 ) ;
assertThat ( batchSize ( messageCollector . get ( 2 ) ) ) . isEqualTo ( 4 ) ;
assertThat ( future . isCompletedExceptionally ( ) ) . isTrue ( ) ;
assertThatThrownBy ( future : : get ) . hasCauseInstanceOf ( MaxRetriesReachedException . class ) ;
}
@SuppressWarnings ( "unchecked" )
@Test
public void shouldNotReduceTheBlockSegmentSizeIfOnlyOneBlockNeeded ( ) {
final RespondingEthPeer respondingPeer =
EthProtocolManagerTestUtil . createPeer ( ethProtocolManager , 1000 ) ;
peerCountToTimeout . set ( 3 ) ;
final List < Block > requestedData = generateDataToBeRequested ( 1 ) ;
@ -112,16 +116,20 @@ public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>>
final EthTask < List < Block > > task = createTask ( requestedData ) ;
final CompletableFuture < List < Block > > future = task . run ( ) ;
ArgumentCaptor < Long > blockNumbersCaptor = ArgumentCaptor . forClass ( Long . class ) ;
final List < MessageData > messageCollector = new ArrayList < > ( ) ;
respondingPeer . respond (
RespondingEthPeer . wrapResponderWithCollector (
RespondingEthPeer . emptyResponder ( ) , messageCollector ) ) ;
verify ( ethPeers , times ( 4 ) )
. executePeerRequest (
any ( PeerRequest . class ) , blockNumbersCaptor . capture ( ) , any ( Optional . class ) ) ;
assertThat ( batchSize ( messageCollector . get ( 0 ) ) ) . isEqualTo ( 1 ) ;
assertThat ( batchSize ( messageCollector . get ( 1 ) ) ) . isEqualTo ( 1 ) ;
assertThat ( batchSize ( messageCollector . get ( 2 ) ) ) . isEqualTo ( 1 ) ;
assertThat ( future . isCompletedExceptionally ( ) ) . isTrue ( ) ;
assertThatThrownBy ( future : : get ) . hasCauseInstanceOf ( MaxRetriesReachedException . class ) ;
}
assertThat ( future . isDone ( ) ) . isFalse ( ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 0 ) ) . isEqualTo ( 10 ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 1 ) ) . isEqualTo ( 10 ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 2 ) ) . isEqualTo ( 10 ) ;
assertThat ( blockNumbersCaptor . getAllValues ( ) . get ( 3 ) ) . isEqualTo ( 10 ) ;
private long batchSize ( final MessageData msg ) {
return ( ( GetBlockBodiesMessage ) msg ) . hashes ( ) . spliterator ( ) . getExactSizeIfKnown ( ) ;
}
}