pekko/akka-cluster/src/multi-jvm/scala/akka/cluster/ClusterWatcherNoClusterWatcheeSpec.scala

199 lines
6.8 KiB
Scala

/*
* Copyright (C) 2019-2021 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.cluster
import scala.concurrent.duration._
import com.typesafe.config.ConfigFactory
import org.scalatest.concurrent.ScalaFutures
import akka.actor.Actor
import akka.actor.ActorIdentity
import akka.actor.ActorRef
import akka.actor.Identify
import akka.actor.Props
import akka.actor.Terminated
import akka.remote.RARP
import akka.remote.RemoteWatcher.Heartbeat
import akka.remote.RemoteWatcher.Stats
import akka.remote.testconductor.RoleName
import akka.remote.testkit.MultiNodeConfig
import akka.testkit.ImplicitSender
import akka.testkit.TestProbe
class ClusterWatcherNoClusterWatcheeConfig(val useUnsafe: Boolean, artery: Boolean) extends MultiNodeConfig {
val clustered = role("clustered")
val remoting = role("remoting")
commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(s"""
akka.remote.use-unsafe-remote-features-outside-cluster = $useUnsafe
akka.remote.log-remote-lifecycle-events = off
akka.remote.artery.enabled = $artery
akka.log-dead-letters = off
akka.loggers =["akka.testkit.TestEventListener"]
akka.actor.allow-java-serialization = on
""")))
nodeConfig(remoting)(ConfigFactory.parseString(s"""
akka.actor.provider = remote"""))
nodeConfig(clustered)(ConfigFactory.parseString("""
akka.actor.provider = cluster
akka.cluster.jmx.enabled = off"""))
}
class ClusterWatcherNoClusterWatcheeUnsafeArterySpecMultiJvmNode1
extends ClusterWatcherNoClusterWatcheeArterySpec(useUnsafe = true)
class ClusterWatcherNoClusterWatcheeUnsafeArterySpecMultiJvmNode2
extends ClusterWatcherNoClusterWatcheeArterySpec(useUnsafe = true)
class ClusterWatcherNoClusterWatcheeSafeArterySpecMultiJvmNode1
extends ClusterWatcherNoClusterWatcheeArterySpec(useUnsafe = false)
class ClusterWatcherNoClusterWatcheeSafeArterySpecMultiJvmNode2
extends ClusterWatcherNoClusterWatcheeArterySpec(useUnsafe = false)
class ClusterWatcherNoClusterWatcheeUnsafeClassicSpecMultiJvmNode1
extends ClusterWatcherNoClusterWatcheeClassicSpec(useUnsafe = true)
class ClusterWatcherNoClusterWatcheeUnsafeClassicSpecMultiJvmNode2
extends ClusterWatcherNoClusterWatcheeClassicSpec(useUnsafe = true)
class ClusterWatcherNoClusterWatcheeSafeClassicSpecMultiJvmNode1
extends ClusterWatcherNoClusterWatcheeClassicSpec(useUnsafe = false)
class ClusterWatcherNoClusterWatcheeSafeClassicSpecMultiJvmNode2
extends ClusterWatcherNoClusterWatcheeClassicSpec(useUnsafe = false)
abstract class ClusterWatcherNoClusterWatcheeArterySpec(useUnsafe: Boolean)
extends ClusterWatcherNoClusterWatcheeSpec(new ClusterWatcherNoClusterWatcheeConfig(useUnsafe, artery = true))
abstract class ClusterWatcherNoClusterWatcheeClassicSpec(useUnsafe: Boolean)
extends ClusterWatcherNoClusterWatcheeSpec(new ClusterWatcherNoClusterWatcheeConfig(useUnsafe, artery = true))
private object ClusterWatcherNoClusterWatcheeSpec {
final case class WatchIt(watchee: ActorRef)
case object Ack
final case class WrappedTerminated(t: Terminated)
class Listener(testActor: ActorRef) extends Actor {
def receive: Receive = {
case WatchIt(watchee) =>
context.watch(watchee)
sender() ! Ack
case t: Terminated =>
testActor.forward(WrappedTerminated(t))
}
}
}
abstract class ClusterWatcherNoClusterWatcheeSpec(multiNodeConfig: ClusterWatcherNoClusterWatcheeConfig)
extends MultiNodeClusterSpec(multiNodeConfig)
with ImplicitSender
with ScalaFutures {
import ClusterWatcherNoClusterWatcheeSpec._
import multiNodeConfig._
override def initialParticipants: Int = roles.size
muteDeadLetters(Heartbeat.getClass)()
protected val probe = TestProbe()
protected def identify(role: RoleName, actorName: String, within: FiniteDuration = 10.seconds): ActorRef =
identifyWithPath(role, "user", actorName, within)
protected def identifyWithPath(
role: RoleName,
path: String,
actorName: String,
within: FiniteDuration = 10.seconds): ActorRef = {
system.actorSelection(node(role) / path / actorName) ! Identify(actorName)
val id = expectMsgType[ActorIdentity](within)
assert(id.ref.isDefined, s"Unable to Identify actor [$actorName] on node [$role].")
id.ref.get
}
private val provider = RARP(system).provider
s"Remoting with UseUnsafeRemoteFeaturesWithoutCluster enabled=$useUnsafe, " +
"watcher system using `cluster`, but watchee system using `remote`" must {
val send = if (system.settings.HasCluster || (!system.settings.HasCluster && useUnsafe)) "send" else "not send"
s"$send `Watch`/`Unwatch`/`Terminate` when watching from cluster to non-cluster remoting watchee" in {
runOn(remoting) {
system.actorOf(Props(classOf[Listener], probe.ref), "watchee")
enterBarrier("watchee-created")
enterBarrier("watcher-created")
}
runOn(clustered) {
enterBarrier("watchee-created")
val watcher = system.actorOf(Props(classOf[Listener], probe.ref), "watcher")
enterBarrier("watcher-created")
val watchee = identify(remoting, "watchee")
probe.send(watcher, WatchIt(watchee))
probe.expectMsg(1.second, Ack)
provider.remoteWatcher.get ! Stats
awaitAssert(expectMsgType[Stats].watchingRefs == Set((watchee, watcher)), 2.seconds)
}
enterBarrier("cluster-watching-remote")
runOn(remoting) {
system.stop(identify(remoting, "watchee"))
enterBarrier("watchee-stopped")
}
runOn(clustered) {
enterBarrier("watchee-stopped")
if (useUnsafe)
probe.expectMsgType[WrappedTerminated](2.seconds)
else
probe.expectNoMessage(2.seconds)
}
}
s"$send `Watch`/`Unwatch`/`Terminate` when watching from non-cluster remoting to cluster watchee" in {
runOn(clustered) {
system.actorOf(Props(classOf[Listener], probe.ref), "watchee2")
enterBarrier("watchee2-created")
enterBarrier("watcher2-created")
}
runOn(remoting) {
enterBarrier("watchee2-created")
val watchee = identify(clustered, "watchee2")
val watcher = system.actorOf(Props(classOf[Listener], probe.ref), "watcher2")
enterBarrier("watcher2-created")
probe.send(watcher, WatchIt(watchee))
probe.expectMsg(1.second, Ack)
if (useUnsafe) {
provider.remoteWatcher.get ! Stats
awaitAssert(expectMsgType[Stats].watchingRefs == Set((watchee, watcher)), 2.seconds)
}
}
runOn(clustered) {
system.stop(identify(clustered, "watchee2"))
enterBarrier("watchee2-stopped")
}
runOn(remoting) {
enterBarrier("watchee2-stopped")
if (useUnsafe)
probe.expectMsgType[WrappedTerminated](2.seconds)
else
probe.expectNoMessage(2.seconds)
}
enterBarrier("done")
}
}
}