mirror of https://github.com/hyperledger/besu
Add tests for FastSyncChainDownloader as a whole. (#758)
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
87685b1983
commit
234a97d81c
@ -0,0 +1,171 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2019 ConsenSys AG. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||||
|
* the License. You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||||
|
* specific language governing permissions and limitations under the License. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.ethereum.eth.sync.fastsync; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason.TOO_MANY_PEERS; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.ProtocolContext; |
||||||
|
import tech.pegasys.pantheon.ethereum.chain.Blockchain; |
||||||
|
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.BlockchainSetupUtil; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; |
||||||
|
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState; |
||||||
|
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; |
||||||
|
import tech.pegasys.pantheon.metrics.LabelledMetric; |
||||||
|
import tech.pegasys.pantheon.metrics.OperationTimer; |
||||||
|
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; |
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class FastSyncChainDownloaderTest { |
||||||
|
|
||||||
|
protected ProtocolSchedule<Void> protocolSchedule; |
||||||
|
protected EthProtocolManager ethProtocolManager; |
||||||
|
protected EthContext ethContext; |
||||||
|
protected ProtocolContext<Void> protocolContext; |
||||||
|
private SyncState syncState; |
||||||
|
|
||||||
|
protected MutableBlockchain localBlockchain; |
||||||
|
private BlockchainSetupUtil<Void> otherBlockchainSetup; |
||||||
|
protected Blockchain otherBlockchain; |
||||||
|
private LabelledMetric<OperationTimer> ethTaskTimer; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setupTest() { |
||||||
|
final BlockchainSetupUtil<Void> localBlockchainSetup = BlockchainSetupUtil.forTesting(); |
||||||
|
localBlockchain = localBlockchainSetup.getBlockchain(); |
||||||
|
otherBlockchainSetup = BlockchainSetupUtil.forTesting(); |
||||||
|
otherBlockchain = otherBlockchainSetup.getBlockchain(); |
||||||
|
|
||||||
|
protocolSchedule = localBlockchainSetup.getProtocolSchedule(); |
||||||
|
protocolContext = localBlockchainSetup.getProtocolContext(); |
||||||
|
ethProtocolManager = |
||||||
|
EthProtocolManagerTestUtil.create(localBlockchain, localBlockchainSetup.getWorldArchive()); |
||||||
|
ethContext = ethProtocolManager.ethContext(); |
||||||
|
syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); |
||||||
|
|
||||||
|
ethTaskTimer = NoOpMetricsSystem.NO_OP_LABELLED_TIMER; |
||||||
|
} |
||||||
|
|
||||||
|
private FastSyncChainDownloader<?> downloader( |
||||||
|
final SynchronizerConfiguration syncConfig, final long pivotBlockNumber) { |
||||||
|
return new FastSyncChainDownloader<>( |
||||||
|
syncConfig, |
||||||
|
protocolSchedule, |
||||||
|
protocolContext, |
||||||
|
ethContext, |
||||||
|
syncState, |
||||||
|
ethTaskTimer, |
||||||
|
otherBlockchain.getBlockHeader(pivotBlockNumber).get()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldSyncToPivotBlockInMultipleSegments() { |
||||||
|
otherBlockchainSetup.importFirstBlocks(30); |
||||||
|
|
||||||
|
final RespondingEthPeer peer = |
||||||
|
EthProtocolManagerTestUtil.createPeer(ethProtocolManager, otherBlockchain); |
||||||
|
final Responder responder = RespondingEthPeer.blockchainResponder(otherBlockchain); |
||||||
|
|
||||||
|
final SynchronizerConfiguration syncConfig = |
||||||
|
SynchronizerConfiguration.builder() |
||||||
|
.downloaderChainSegmentSize(5) |
||||||
|
.downloaderHeadersRequestSize(3) |
||||||
|
.build() |
||||||
|
.validated(localBlockchain); |
||||||
|
final long pivotBlockNumber = 25; |
||||||
|
final FastSyncChainDownloader<?> downloader = downloader(syncConfig, pivotBlockNumber); |
||||||
|
final CompletableFuture<Void> result = downloader.start(); |
||||||
|
|
||||||
|
peer.respondWhile(responder, () -> !result.isDone()); |
||||||
|
|
||||||
|
assertThat(result).isCompleted(); |
||||||
|
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(pivotBlockNumber); |
||||||
|
assertThat(localBlockchain.getChainHeadHeader()) |
||||||
|
.isEqualTo(otherBlockchain.getBlockHeader(pivotBlockNumber).get()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldSyncToPivotBlockInSingleSegment() { |
||||||
|
otherBlockchainSetup.importFirstBlocks(30); |
||||||
|
|
||||||
|
final RespondingEthPeer peer = |
||||||
|
EthProtocolManagerTestUtil.createPeer(ethProtocolManager, otherBlockchain); |
||||||
|
final Responder responder = RespondingEthPeer.blockchainResponder(otherBlockchain); |
||||||
|
|
||||||
|
final long pivotBlockNumber = 5; |
||||||
|
final SynchronizerConfiguration syncConfig = |
||||||
|
SynchronizerConfiguration.builder().build().validated(localBlockchain); |
||||||
|
final FastSyncChainDownloader<?> downloader = downloader(syncConfig, pivotBlockNumber); |
||||||
|
final CompletableFuture<Void> result = downloader.start(); |
||||||
|
|
||||||
|
peer.respondWhile(responder, () -> !result.isDone()); |
||||||
|
|
||||||
|
assertThat(result).isCompleted(); |
||||||
|
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(pivotBlockNumber); |
||||||
|
assertThat(localBlockchain.getChainHeadHeader()) |
||||||
|
.isEqualTo(otherBlockchain.getBlockHeader(pivotBlockNumber).get()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void recoversFromSyncTargetDisconnect() { |
||||||
|
final BlockchainSetupUtil<Void> shorterChainUtil = BlockchainSetupUtil.forTesting(); |
||||||
|
final MutableBlockchain shorterChain = shorterChainUtil.getBlockchain(); |
||||||
|
|
||||||
|
otherBlockchainSetup.importFirstBlocks(30); |
||||||
|
shorterChainUtil.importFirstBlocks(28); |
||||||
|
|
||||||
|
final RespondingEthPeer bestPeer = |
||||||
|
EthProtocolManagerTestUtil.createPeer(ethProtocolManager, otherBlockchain); |
||||||
|
final Responder bestResponder = RespondingEthPeer.blockchainResponder(otherBlockchain); |
||||||
|
final RespondingEthPeer secondBestPeer = |
||||||
|
EthProtocolManagerTestUtil.createPeer(ethProtocolManager, shorterChain); |
||||||
|
final Responder shorterResponder = RespondingEthPeer.blockchainResponder(shorterChain); |
||||||
|
|
||||||
|
final SynchronizerConfiguration syncConfig = |
||||||
|
SynchronizerConfiguration.builder() |
||||||
|
.downloaderChainSegmentSize(5) |
||||||
|
.downloaderHeadersRequestSize(3) |
||||||
|
.build() |
||||||
|
.validated(localBlockchain); |
||||||
|
final long pivotBlockNumber = 25; |
||||||
|
final FastSyncChainDownloader<?> downloader = downloader(syncConfig, pivotBlockNumber); |
||||||
|
final CompletableFuture<Void> result = downloader.start(); |
||||||
|
|
||||||
|
while (localBlockchain.getChainHeadBlockNumber() < 15) { |
||||||
|
bestPeer.respond(bestResponder); |
||||||
|
secondBestPeer.respond(shorterResponder); |
||||||
|
} |
||||||
|
|
||||||
|
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(15); |
||||||
|
assertThat(result).isNotCompleted(); |
||||||
|
|
||||||
|
ethProtocolManager.handleDisconnect(bestPeer.getPeerConnection(), TOO_MANY_PEERS, true); |
||||||
|
|
||||||
|
secondBestPeer.respondWhile(shorterResponder, () -> !result.isDone()); |
||||||
|
|
||||||
|
assertThat(result).isCompleted(); |
||||||
|
assertThat(localBlockchain.getChainHeadBlockNumber()).isEqualTo(pivotBlockNumber); |
||||||
|
assertThat(localBlockchain.getChainHeadHeader()) |
||||||
|
.isEqualTo(otherBlockchain.getBlockHeader(pivotBlockNumber).get()); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue