pekko/akka-remote/src/test/scala/akka/remote/artery/compress/HandshakeShouldDropCompressionTableSpec.scala
Konrad Malawski d1015c1dc6 Compression tables properly *used* for Outgoing Compression (#20874)
* =art now correctly compresses and 2 table mode working
* =art AGRESSIVELY optimising hashing, not convienved about correctness yet
* fix HandshakeShouldDropCompressionTableSpec
2016-07-04 16:48:11 +02:00

155 lines
5.7 KiB
Scala

/*
* Copyright (C) 2016 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.remote.artery.compress
import akka.actor.{ ActorIdentity, ActorRef, ActorSystem, Identify }
import akka.remote.artery.compress.CompressionProtocol.Events
import akka.testkit._
import akka.util.Timeout
import akka.pattern.ask
import akka.remote.RARP
import akka.remote.artery.ArteryTransport
import akka.remote.artery.compress.CompressionProtocol.Events.{ Event, ReceivedCompressionTable }
import com.typesafe.config.ConfigFactory
import org.scalatest.BeforeAndAfter
import scala.concurrent.Await
import scala.concurrent.duration._
object HandshakeShouldDropCompressionTableSpec {
// need the port before systemB is started
val portB = SocketUtil.temporaryServerAddress("localhost", udp = true).getPort
val commonConfig = ConfigFactory.parseString(s"""
akka {
loglevel = INFO
actor.provider = "akka.remote.RemoteActorRefProvider"
remote.artery.enabled = on
remote.artery.hostname = localhost
remote.artery.port = 0
remote.handshake-timeout = 10s
remote.artery.advanced.compression {
enabled = on
actor-refs {
enabled = on
# we'll trigger advertisement manually
advertisement-interval = 10 hours
}
}
}
""")
val configB = ConfigFactory.parseString(s"akka.remote.artery.port = $portB")
.withFallback(commonConfig)
}
class HandshakeShouldDropCompressionTableSpec extends AkkaSpec(HandshakeShouldDropCompressionTableSpec.commonConfig)
with ImplicitSender with BeforeAndAfter
with CompressionTestKit {
import HandshakeShouldDropCompressionTableSpec._
implicit val t = Timeout(3.seconds)
var systemB: ActorSystem = null
before {
systemB = ActorSystem("systemB", configB)
}
"Outgoing compression table" must {
// FIXME this is failing, we must rethink how tables are identified and updated
"be dropped on system restart" in {
val messagesToExchange = 10
val systemATransport = RARP(system).provider.transport.asInstanceOf[ArteryTransport]
def systemBTransport = RARP(systemB).provider.transport.asInstanceOf[ArteryTransport]
// listen for compression table events
val aProbe = TestProbe()
val a1Probe = TestProbe()
val b1Probe = TestProbe()(systemB)
system.eventStream.subscribe(aProbe.ref, classOf[Event])
systemB.eventStream.subscribe(b1Probe.ref, classOf[Event])
def echoSel = system.actorSelection(s"artery://systemB@localhost:$portB/user/echo")
systemB.actorOf(TestActors.echoActorProps, "echo")
// cause testActor-1 to become a heavy hitter
(1 to messagesToExchange).foreach { i echoSel ! s"hello-$i" } // does not reply, but a hot receiver should be advertised
waitForEcho(this, s"hello-$messagesToExchange")
systemBTransport.triggerCompressionAdvertisements(actorRef = true, manifest = false)
val a0 = aProbe.expectMsgType[ReceivedCompressionTable[ActorRef]](10.seconds)
info("System [A] received: " + a0)
a0.table.map.keySet should contain(testActor)
// cause a1Probe to become a heavy hitter (we want to not have it in the 2nd compression table later)
(1 to messagesToExchange).foreach { i echoSel.tell(s"hello-$i", a1Probe.ref) }
waitForEcho(a1Probe, s"hello-$messagesToExchange")
systemBTransport.triggerCompressionAdvertisements(actorRef = true, manifest = false)
val a1 = aProbe.expectMsgType[ReceivedCompressionTable[ActorRef]](10.seconds)
info("System [A] received: " + a1)
a1.table.map.keySet should contain(a1Probe.ref)
log.warning("SHUTTING DOWN system {}...", systemB)
shutdown(systemB)
systemB = ActorSystem("systemB", configB)
Thread.sleep(1000)
log.warning("SYSTEM READY {}...", systemB)
val aNewProbe = TestProbe()
system.eventStream.subscribe(aNewProbe.ref, classOf[Event])
systemB.actorOf(TestActors.echoActorProps, "echo") // start it again
(1 to 5) foreach { _
// since some messages may end up being lost
(1 to messagesToExchange).foreach { i echoSel ! s"hello-$i" } // does not reply, but a hot receiver should be advertised
Thread.sleep(100)
}
waitForEcho(this, s"hello-$messagesToExchange", max = 10.seconds)
systemBTransport.triggerCompressionAdvertisements(actorRef = true, manifest = false)
val a2 = aNewProbe.expectMsgType[ReceivedCompressionTable[ActorRef]](10.seconds)
info("System [A] received: " + a2)
a2.table.map.keySet should contain(testActor)
val aNew2Probe = TestProbe()
(1 to messagesToExchange).foreach { i echoSel.tell(s"hello-$i", aNew2Probe.ref) } // does not reply, but a hot receiver should be advertised
waitForEcho(aNew2Probe, s"hello-$messagesToExchange")
systemBTransport.triggerCompressionAdvertisements(actorRef = true, manifest = false)
val a3 = aNewProbe.expectMsgType[ReceivedCompressionTable[ActorRef]](10.seconds)
info("Received second compression: " + a3)
a3.table.map.keySet should contain(aNew2Probe.ref)
}
}
def waitForEcho(probe: TestKit, m: String, max: Duration = 3.seconds): Any =
probe.fishForMessage(max = max, hint = s"waiting for '$m'") {
case `m` true
case x false
}
def identify(_system: String, port: Int, name: String) = {
val selection =
system.actorSelection(s"artery://${_system}@localhost:$port/user/$name")
val ActorIdentity(1, ref) = Await.result(selection ? Identify(1), 3.seconds)
ref.get
}
after {
shutdownAllActorSystems()
}
override def afterTermination(): Unit =
shutdownAllActorSystems()
private def shutdownAllActorSystems(): Unit = {
if (systemB != null) shutdown(systemB)
}
}