Skip to content

Commit 0a4b94a

Browse files
committed
[ETCM-283] Fix and Refactor tests
1 parent 397d0bd commit 0a4b94a

File tree

4 files changed

+55
-36
lines changed

4 files changed

+55
-36
lines changed

src/it/scala/io/iohk/ethereum/sync/util/RegularSyncItSpecUtils.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package io.iohk.ethereum.sync.util
33
import akka.actor.ActorRef
44
import akka.util.ByteString
55
import cats.effect.Resource
6-
import io.iohk.ethereum.Mocks.MockValidatorsAlwaysSucceed
76
import io.iohk.ethereum.blockchain.sync.{PeersClient, SyncProtocol}
87
import io.iohk.ethereum.blockchain.sync.regular.BlockBroadcasterActor.BroadcastBlock
98
import io.iohk.ethereum.blockchain.sync.regular.RegularSync
@@ -63,7 +62,7 @@ object RegularSyncItSpecUtils {
6362
"pending-transactions-manager"
6463
)
6564

66-
lazy val validators = new MockValidatorsAlwaysSucceed
65+
lazy val validators = buildEthashConsensus.validators
6766

6867
lazy val regularSync = system.actorOf(
6968
RegularSync.props(

src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherState.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ case class BlockFetcherState(
148148
else
149149
bodiesAreOrderedSubsetOfRequested(remainingHeaders, respondedBodies, matchedBlocks)
150150
}
151-
151+
152152
/**
153153
* If blocks is empty collection - headers in queue are removed as the cause is:
154154
* - the headers are from rejected fork and therefore it won't be possible to resolve blocks for them
@@ -161,7 +161,6 @@ case class BlockFetcherState(
161161
waitingHeaders = Queue.empty
162162
)
163163
else
164-
// We could optimize this by stopping as soon as a block is not enqueued.
165164
blocks.foldLeft(this) { case (state, block) =>
166165
state.enqueueRequestedBlock(block, fromPeer)
167166
}
@@ -174,7 +173,7 @@ case class BlockFetcherState(
174173
waitingHeaders.dequeueOption
175174
.map { case (waitingHeader, waitingHeadersTail) =>
176175
if (waitingHeader.hash == block.hash)
177-
withPeerForBlocks(fromPeer, Seq(block.header.number))
176+
withPeerForBlocks(fromPeer, Seq(block.number))
178177
.withPossibleNewTopAt(block.number)
179178
.withLastBlock(block.number)
180179
.copy(

src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import java.net.InetSocketAddress
44
import akka.actor.ActorSystem
55
import akka.testkit.{TestKit, TestProbe}
66
import com.miguno.akka.testing.VirtualTime
7-
import io.iohk.ethereum.Mocks.{
8-
MockValidatorsAlwaysSucceed,
9-
MockValidatorsFailingOnBlockBodies,
10-
MockValidatorsFailOnSpecificBlockNumber
11-
}
7+
import io.iohk.ethereum.Mocks.{MockValidatorsAlwaysSucceed, MockValidatorsFailingOnBlockBodies}
128
import io.iohk.ethereum.BlockHelpers
139
import io.iohk.ethereum.Fixtures.{Blocks => FixtureBlocks}
1410
import io.iohk.ethereum.blockchain.sync.PeersClient.BlacklistPeer
@@ -129,7 +125,7 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
129125
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == firstGetBlockHeadersRequest => () }
130126
}
131127

132-
"should not append new blocks if the received data does not match" in new TestSetup {
128+
"should not enqueue requested blocks if the received bodies does not match" in new TestSetup {
133129

134130
// Important: Here we are forcing the mismatch between request headers and received bodies
135131
override lazy val validators = new MockValidatorsFailingOnBlockBodies
@@ -151,8 +147,14 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
151147
val getBlockBodiesResponse = BlockBodies(chain.map(_.body))
152148
peersClient.reply(PeersClient.Response(fakePeer, getBlockBodiesResponse))
153149

150+
// Fetcher should blacklist the peer and retry asking for the same bodies
154151
peersClient.expectMsgClass(classOf[BlacklistPeer])
155152
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockBodiesRequest => () }
153+
154+
// Fetcher should not enqueue any new block
155+
importer.send(blockFetcher, PickBlocks(syncConfig.blocksBatchSize))
156+
importer.ignoreMsg({ case BlockImporter.NotOnTop => true })
157+
importer.expectNoMessage()
156158
}
157159

158160
"should be able to handle block bodies received in several parts" in new TestSetup {
@@ -172,13 +174,13 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
172174
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockBodiesRequest1 => () }
173175

174176
// It will receive all the requested bodies, but splitted in 2 parts.
175-
val (subChain1, subChain2) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2)
177+
val (subChain1, subChain2) = chain.splitAt(syncConfig.blockBodiesPerRequest / 2)
176178

177179
val getBlockBodiesResponse1 = BlockBodies(subChain1.map(_.body))
178180
peersClient.reply(PeersClient.Response(fakePeer, getBlockBodiesResponse1))
179181

180182
val getBlockHeadersRequest2 =
181-
GetBlockHeaders(Left(subChain1.last.number + 1), syncConfig.blockHeadersPerRequest, skip = 0, reverse = false)
183+
GetBlockHeaders(Left(chain.last.number + 1), syncConfig.blockHeadersPerRequest, skip = 0, reverse = false)
182184
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockHeadersRequest2 => () }
183185

184186
val getBlockBodiesRequest2 = GetBlockBodies(subChain2.map(_.hash))
@@ -188,13 +190,16 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
188190
peersClient.reply(PeersClient.Response(fakePeer, getBlockBodiesResponse2))
189191

190192
peersClient.expectNoMessage()
191-
}
192193

193-
"should ignore response, without blacklist the peer, in case a sub ordered block bodies chain is received" in new TestSetup {
194+
// Fetcher should enqueue all the received blocks
195+
importer.send(blockFetcher, PickBlocks(chain.size))
196+
importer.ignoreMsg({ case BlockImporter.NotOnTop => true })
197+
importer.expectMsgPF() { case BlockFetcher.PickedBlocks(blocks) =>
198+
blocks.map(_.hash).toList shouldEqual chain.map(_.hash)
199+
}
200+
}
194201

195-
// Important: Here (in a hacky way) we are enforcing received bodies
196-
// to be a sub ordered chain that fetcher can't append given their current state
197-
override lazy val validators = new MockValidatorsFailOnSpecificBlockNumber(1)
202+
"should stop requesting, without blacklist the peer, in case empty bodies are received" in new TestSetup {
198203

199204
startFetcher()
200205

@@ -210,12 +215,31 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
210215
val getBlockBodiesRequest1 = GetBlockBodies(chain.map(_.hash))
211216
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockBodiesRequest1 => () }
212217

213-
val (subChain1, _) = chain.splitAt(syncConfig.blockHeadersPerRequest / 2)
218+
// It will receive part of the requested bodies.
219+
val (subChain1, subChain2) = chain.splitAt(syncConfig.blockBodiesPerRequest / 2)
214220

215221
val getBlockBodiesResponse1 = BlockBodies(subChain1.map(_.body))
216222
peersClient.reply(PeersClient.Response(fakePeer, getBlockBodiesResponse1))
217223

218-
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockBodiesRequest1 => () }
224+
val getBlockHeadersRequest2 =
225+
GetBlockHeaders(Left(chain.last.number + 1), syncConfig.blockHeadersPerRequest, skip = 0, reverse = false)
226+
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockHeadersRequest2 => () }
227+
228+
val getBlockBodiesRequest2 = GetBlockBodies(subChain2.map(_.hash))
229+
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == getBlockBodiesRequest2 => () }
230+
231+
// We receive empty bodies instead of the second part
232+
val getBlockBodiesResponse2 = BlockBodies(List())
233+
peersClient.reply(PeersClient.Response(fakePeer, getBlockBodiesResponse2))
234+
235+
peersClient.expectNoMessage()
236+
237+
// If we try to pick the whole chain we should only receive the first part
238+
importer.send(blockFetcher, PickBlocks(chain.size))
239+
importer.ignoreMsg({ case BlockImporter.NotOnTop => true })
240+
importer.expectMsgPF() { case BlockFetcher.PickedBlocks(blocks) =>
241+
blocks.map(_.hash).toList shouldEqual subChain1.map(_.hash)
242+
}
219243
}
220244

221245
"should ensure blocks passed to importer are always forming chain" in new TestSetup {

src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherStateSpec.scala

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ package io.iohk.ethereum.blockchain.sync.regular
33
import akka.actor.ActorSystem
44
import akka.testkit.{TestKit, TestProbe}
55
import io.iohk.ethereum.Mocks.MockValidatorsAlwaysSucceed
6-
import io.iohk.ethereum.domain.Block
76
import io.iohk.ethereum.BlockHelpers
8-
import io.iohk.ethereum.Fixtures.Blocks.ValidBlock
9-
import io.iohk.ethereum.domain.Block
107
import io.iohk.ethereum.network.PeerId
118
import org.scalatest.matchers.should.Matchers
129
import org.scalatest.wordspec.AnyWordSpecLike
@@ -30,35 +27,35 @@ class BlockFetcherStateSpec extends TestKit(ActorSystem()) with AnyWordSpecLike
3027

3128
"handling requested blocks" should {
3229
"clear headers queue if got empty list of blocks" in {
30+
val importer = TestProbe().ref
3331
val headers = BlockHelpers.generateChain(5, BlockHelpers.genesis).map(_.header)
3432
val peer = PeerId("foo")
3533

3634
val result = BlockFetcherState
37-
.initial(TestProbe().ref, 0)
35+
.initial(importer, validators.blockValidator, 0)
3836
.appendHeaders(headers)
39-
.map(_.handleRequestedBlocks(peer, List()))
40-
.map(_.waitingHeaders)
37+
.map(_.handleRequestedBlocks(List(), peer))
4138

42-
assert(result === Right(Queue.empty))
43-
result.lastBlock shouldEqual 0
39+
assert(result.map(_.waitingHeaders) === Right(Queue.empty))
40+
assert(result.map(_.lastBlock) === Right(headers.last.number))
4441
}
4542

4643
"enqueue requested blocks" in {
47-
44+
val importer = TestProbe().ref
4845
val blocks = BlockHelpers.generateChain(5, BlockHelpers.genesis)
4946
val peer = PeerId("foo")
5047

5148
val result = BlockFetcherState
52-
.initial(TestProbe().ref, 0)
49+
.initial(importer, validators.blockValidator, 0)
5350
.appendHeaders(blocks.map(_.header))
54-
.map(_.handleRequestedBlocks(peer, blocks.map(_.body)))
51+
.map(_.handleRequestedBlocks(blocks, peer))
5552

56-
assert(result.waitingHeaders === Right(Queue.empty))
57-
result.lastBlock shouldEqual blocks.lastBlock.number
58-
blocks.forEach { block =>
59-
result.blockProviders(block.number) shouldEqual fakePeerId
53+
assert(result.map(_.waitingHeaders) === Right(Queue.empty))
54+
assert(result.map(_.lastBlock) === Right(blocks.last.number))
55+
blocks.foreach { block =>
56+
assert(result.map(_.blockProviders(block.number)) === Right(peer))
6057
}
61-
result.knownTop shouldEqual blocks.lastBlock.number
58+
assert(result.map(_.knownTop) === Right(blocks.last.number))
6259
}
6360
}
6461
}

0 commit comments

Comments
 (0)