Skip to content

Commit b7db87e

Browse files
author
Dmitry Voronov
authored
[ETCM-503] testing in CI takes a lot of time (#877)
* [ETCM-503]-tests-timeout-in-ci * [ETCM-504] PeerStatisticsSpec fix
1 parent e9feccb commit b7db87e

File tree

9 files changed

+70
-35
lines changed

9 files changed

+70
-35
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.iohk.ethereum.sync.util
22

33
import java.nio.file.Files
4+
import java.time.Clock
45
import java.util.concurrent.atomic.AtomicReference
56

67
import akka.actor.{ActorRef, ActorSystem}
@@ -55,6 +56,8 @@ abstract class CommonFakePeer(peerName: String, fakePeerCustomConfig: FakePeerCu
5556

5657
import scala.language.postfixOps
5758

59+
implicit val clock = Clock.systemUTC()
60+
5861
implicit val system = ActorSystem(peerName)
5962

6063
val peerDiscoveryManager = TestProbe().ref

src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.iohk.ethereum.txExecTest.util
22

3+
import java.time.Clock
34
import java.util.concurrent.atomic.AtomicReference
45

56
import akka.actor.ActorSystem
@@ -97,7 +98,7 @@ object DumpChainApp extends App with NodeKeyBuilder with SecureRandomBuilder wit
9798

9899
val peerMessageBus = actorSystem.actorOf(PeerEventBusActor.props)
99100

100-
val peerStatistics = actorSystem.actorOf(PeerStatisticsActor.props(peerMessageBus, 1.minute, 30))
101+
val peerStatistics = actorSystem.actorOf(PeerStatisticsActor.props(peerMessageBus, 1.minute, 30)(Clock.systemUTC()))
101102

102103
val peerManager = actorSystem.actorOf(
103104
PeerManagerActor.props(

src/main/scala/io/iohk/ethereum/network/PeerStatisticsActor.scala

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import akka.actor._
44
import io.iohk.ethereum.network.PeerEventBusActor._
55
import io.iohk.ethereum.network.p2p.messages.Codes
66
import java.time.Clock
7+
8+
import io.iohk.ethereum.network.p2p.Message
9+
710
import scala.concurrent.duration.FiniteDuration
811

912
class PeerStatisticsActor(
1013
peerEventBus: ActorRef,
1114
var maybeStats: Option[TimeSlotStats[PeerId, PeerStat]]
12-
) extends Actor {
15+
)(implicit clock: Clock)
16+
extends Actor {
1317
import PeerStatisticsActor._
1418

1519
override def preStart(): Unit = {
@@ -23,14 +27,7 @@ class PeerStatisticsActor(
2327

2428
private def handlePeerEvents: Receive = {
2529
case PeerEvent.MessageFromPeer(msg, peerId) =>
26-
val now = System.currentTimeMillis()
27-
val obs = PeerStat(
28-
responsesReceived = if (ResponseCodes(msg.code)) 1 else 0,
29-
requestsReceived = if (RequestCodes(msg.code)) 1 else 0,
30-
firstSeenTimeMillis = Some(now),
31-
lastSeenTimeMillis = Some(now)
32-
)
33-
maybeStats = maybeStats.map(_.add(peerId, obs))
30+
handleMessageFromPeer(msg, peerId)
3431

3532
case PeerEvent.PeerDisconnected(peerId) =>
3633
maybeStats = maybeStats.map(_.remove(peerId))
@@ -45,13 +42,24 @@ class PeerStatisticsActor(
4542
val stats = maybeStats.map(_.get(peerId, Some(window))).getOrElse(PeerStat.empty)
4643
sender ! StatsForPeer(peerId, stats)
4744
}
45+
46+
private def handleMessageFromPeer(msg: Message, peerId: PeerId): Unit = {
47+
val now = clock.millis
48+
val obs = PeerStat(
49+
responsesReceived = if (ResponseCodes(msg.code)) 1 else 0,
50+
requestsReceived = if (RequestCodes(msg.code)) 1 else 0,
51+
firstSeenTimeMillis = Some(now),
52+
lastSeenTimeMillis = Some(now)
53+
)
54+
maybeStats = maybeStats.map(_.add(peerId, obs))
55+
}
4856
}
4957

5058
object PeerStatisticsActor {
51-
def props(peerEventBus: ActorRef, slotDuration: FiniteDuration, slotCount: Int): Props =
59+
def props(peerEventBus: ActorRef, slotDuration: FiniteDuration, slotCount: Int)(implicit clock: Clock): Props =
5260
Props {
53-
implicit val clock = Clock.systemUTC()
54-
new PeerStatisticsActor(peerEventBus, TimeSlotStats[PeerId, PeerStat](slotDuration, slotCount))
61+
val stats = TimeSlotStats[PeerId, PeerStat](slotDuration, slotCount)
62+
new PeerStatisticsActor(peerEventBus, stats)
5563
}
5664

5765
case class GetStatsForAll(window: FiniteDuration)

src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.iohk.ethereum.nodebuilder
22

3+
import java.time.Clock
4+
35
import akka.actor.{ActorRef, ActorSystem}
46
import io.iohk.ethereum.blockchain.data.GenesisDataLoader
57
import io.iohk.ethereum.blockchain.sync.{BlockchainHostActor, SyncController}
@@ -32,8 +34,10 @@ import io.iohk.ethereum.transactions.{PendingTransactionsManager, TransactionHis
3234
import io.iohk.ethereum.utils.Config.SyncConfig
3335
import io.iohk.ethereum.utils._
3436
import java.util.concurrent.atomic.AtomicReference
37+
3538
import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator
3639
import org.bouncycastle.crypto.AsymmetricCipherKeyPair
40+
3741
import scala.concurrent.duration._
3842
import scala.util.{Failure, Success, Try}
3943
import akka.util.ByteString
@@ -188,6 +192,9 @@ trait PeerEventBusBuilder {
188192
trait PeerStatisticsBuilder {
189193
self: ActorSystemBuilder with PeerEventBusBuilder =>
190194

195+
// TODO: a candidate to move upwards in trait hierarchy?
196+
implicit val clock = Clock.systemUTC()
197+
191198
lazy val peerStatistics: ActorRef = system.actorOf(
192199
PeerStatisticsActor.props(
193200
peerEventBus,

src/test/scala/io/iohk/ethereum/blockchain/sync/FastSyncSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class FastSyncSpec
2222
with FreeSpecBase
2323
with SpecFixtures
2424
with WithActorSystemShutDown { self =>
25-
implicit val timeout: Timeout = Timeout(10.seconds)
25+
implicit val timeout: Timeout = Timeout(30.seconds)
2626

2727
class Fixture extends EphemBlockchainTestSetup with TestSyncConfig with TestSyncPeers {
2828
override implicit lazy val system = self.system

src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class FakeJsonRpcHttpServer(
469469
def run(): Unit = ()
470470
override def corsAllowedOrigins: HttpOriginMatcher = cors
471471

472-
var mockedTime:Long = 0L
472+
var mockedTime: Long = 0L
473473

474474
override protected val rateLimit: RateLimit = new RateLimit(config.rateLimit) {
475475
override protected def getCurrentTimeNanos: Long = FakeJsonRpcHttpServer.this.mockedTime

src/test/scala/io/iohk/ethereum/network/PeerStatisticsSpec.scala

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import akka.testkit.{TestKit, TestProbe}
55
import io.iohk.ethereum.network.PeerEventBusActor._
66
import io.iohk.ethereum.network.p2p.messages.PV61.NewBlockHashes
77
import io.iohk.ethereum.WithActorSystemShutDown
8+
import io.iohk.ethereum.utils.MockClock
89
import org.scalatest.flatspec.AnyFlatSpecLike
910
import org.scalatest.matchers.should.Matchers
11+
1012
import scala.concurrent.duration._
1113

1214
class PeerStatisticsSpec
@@ -17,6 +19,14 @@ class PeerStatisticsSpec
1719

1820
import PeerStatisticsActor._
1921

22+
val TICK: Long = 50
23+
val mockClock = new MockClock(0L) {
24+
override def millis(): Long = {
25+
windByMillis(TICK)
26+
super.millis()
27+
}
28+
}
29+
2030
behavior of "PeerStatisticsActor"
2131

2232
it should "subscribe to peer events" in new Fixture {
@@ -48,7 +58,11 @@ class PeerStatisticsSpec
4858

4959
val statA = stats.stats(alice)
5060
statA.responsesReceived shouldBe 2
51-
statA.lastSeenTimeMillis shouldBe >(statA.firstSeenTimeMillis)
61+
val difference = for {
62+
first <- statA.firstSeenTimeMillis
63+
last <- statA.lastSeenTimeMillis
64+
} yield last - first
65+
assert(difference.exists(_ >= TICK))
5266

5367
val statB = stats.stats(bob)
5468
statB.responsesReceived shouldBe 1
@@ -61,6 +75,6 @@ class PeerStatisticsSpec
6175

6276
val peerEventBus = TestProbe()
6377
val peerStatistics =
64-
system.actorOf(PeerStatisticsActor.props(peerEventBus.ref, slotDuration = 1.minute, slotCount = 30))
78+
system.actorOf(PeerStatisticsActor.props(peerEventBus.ref, slotDuration = 1.minute, slotCount = 30)(mockClock))
6579
}
6680
}

src/test/scala/io/iohk/ethereum/network/TimeSlotStatsSpec.scala

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
1212
import org.scalacheck.{Arbitrary, Gen, Shrink}, Arbitrary.arbitrary
1313
import scala.concurrent.duration._
1414
import org.scalatest.compatible.Assertion
15-
import java.time.ZoneId
16-
import java.time.Instant
15+
import io.iohk.ethereum.utils.MockClock
1716

1817
class TimeSlotStatsSpec extends AnyFlatSpec with Matchers with ScalaCheckDrivenPropertyChecks {
1918
import TimeSlotStatsSpec._
@@ -154,7 +153,8 @@ class TimeSlotStatsSpec extends AnyFlatSpec with Matchers with ScalaCheckDrivenP
154153

155154
it should "handle 0 in configuration" in {
156155
// This might happen if we base the values on something which can be 0.
157-
implicit val clock = Clock.systemUTC()
156+
implicit val clock: Clock = Clock.systemUTC()
157+
158158
val zeros = List(
159159
TimeSlotStats[String, Int](slotDuration = 1.minutes, slotCount = 0),
160160
TimeSlotStats[String, Int](slotDuration = 0.minutes, slotCount = 1)
@@ -217,18 +217,7 @@ class TimeSlotStatsSpec extends AnyFlatSpec with Matchers with ScalaCheckDrivenP
217217

218218
object TimeSlotStatsSpec {
219219

220-
class MockClock(
221-
private var currentTimeMillis: Long = System.currentTimeMillis,
222-
zoneId: ZoneId = ZoneId.of("UTC")
223-
) extends Clock {
224-
def windByMillis(by: Long): Unit =
225-
currentTimeMillis = currentTimeMillis + by
226-
227-
override def instant(): Instant = Instant.ofEpochMilli(currentTimeMillis)
228-
// The following are implemented for completness' sake but not used:
229-
override def getZone(): ZoneId = zoneId
230-
override def withZone(x: ZoneId): Clock = new MockClock(currentTimeMillis, zoneId)
231-
}
220+
implicit val clock = new MockClock()
232221

233222
type TestState[K, V, A] = State[(TimeSlotStats[K, V], MockClock), A]
234223

@@ -256,7 +245,6 @@ object TimeSlotStatsSpec {
256245
}
257246

258247
def test[K, V: Monoid](s: TestState[K, V, Assertion]): Unit = {
259-
implicit val clock = new MockClock()
260248
val stats = TimeSlotStats[K, V](defaultSlotDuration, defaultSlotCount).get
261249
s.run(stats -> clock).value
262250
}
@@ -271,14 +259,12 @@ object TimeSlotStatsSpec {
271259
keyCount <- Gen.choose(1, 5)
272260
keys <- Gen.listOfN(keyCount, arbitrary[K])
273261
eventCount <- Gen.choose(0, 100)
274-
timestamp = System.currentTimeMillis
275262
event = for {
276263
d <- Gen.choose(0, 10 * 60).map(_.seconds)
277264
k <- Gen.oneOf(keys)
278265
v <- arbitrary[V]
279266
} yield (d, k, v)
280267
events <- Gen.listOfN(eventCount, event)
281-
clock = new MockClock()
282268
empty = TimeSlotStats[K, V](slotDuration, slotCount)(Monoid[V], clock).get
283269
stats = events.foldLeft(empty) { case (stats, (duration, key, stat)) =>
284270
clock.windByMillis(duration.toMillis)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.iohk.ethereum.utils
2+
3+
import java.time.{Clock, Instant, ZoneId}
4+
5+
class MockClock(
6+
private var currentTimeMillis: Long = System.currentTimeMillis,
7+
zoneId: ZoneId = ZoneId.of("UTC")
8+
) extends Clock {
9+
def windByMillis(by: Long): Unit =
10+
currentTimeMillis = currentTimeMillis + by
11+
12+
override def instant(): Instant = Instant.ofEpochMilli(currentTimeMillis)
13+
// The following are implemented for completness' sake but not used:
14+
override def getZone(): ZoneId = zoneId
15+
override def withZone(x: ZoneId): Clock = new MockClock(currentTimeMillis, zoneId)
16+
}

0 commit comments

Comments
 (0)