Merge pull request #1365 from akka/wip-3255-ClusterDeathWatchSpec-patriknw

Coordinate shutdown of ClusterDeathWatchSpec with messages, see #3255
This commit is contained in:
Patrik Nordwall 2013-04-23 05:50:20 -07:00
commit c1b08fb6dc
3 changed files with 64 additions and 6 deletions

View file

@ -24,6 +24,8 @@ import akka.actor.ActorIdentity
import akka.actor.Identify
import akka.actor.ActorRef
import akka.remote.RemoteWatcher
import akka.actor.ActorSystem
import akka.cluster.MultiNodeClusterSpec.EndActor
object ClusterDeathWatchMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
@ -39,6 +41,7 @@ object ClusterDeathWatchMultiJvmSpec extends MultiNodeConfig {
class Hello extends Actor {
def receive = Actor.emptyBehavior
}
}
class ClusterDeathWatchMultiJvmNode1 extends ClusterDeathWatchSpec
@ -206,6 +209,14 @@ abstract class ClusterDeathWatchSpec
}
"be able to shutdown system when using remote deployed actor on node that crash" taggedAs LongRunningTest in within(20 seconds) {
// fourth actor system will be shutdown, not part of testConductor any more
// so we can't use barriers to synchronize with it
val firstAddress = address(first)
runOn(first) {
system.actorOf(Props(classOf[EndActor], testActor, None), "end")
}
enterBarrier("end-actor-created")
runOn(fourth) {
val hello = system.actorOf(Props[Hello], "hello")
hello.isInstanceOf[RemoteActorRef] must be(true)
@ -231,14 +242,32 @@ abstract class ClusterDeathWatchSpec
fail("Failed to stop [%s] within [%s] \n%s".format(system.name, timeout,
system.asInstanceOf[ActorSystemImpl].printTree))
}
// signal to the first node that fourth is done
val endSystem = ActorSystem("EndSystem", system.settings.config)
try {
val endProbe = TestProbe()(endSystem)
val endActor = endSystem.actorOf(Props(classOf[EndActor], endProbe.ref, Some(firstAddress)), "end")
endActor ! EndActor.SendEnd
endProbe.expectMsg(EndActor.EndAck)
} finally {
endSystem.shutdown()
endSystem.awaitTermination(10 seconds)
}
// no barrier here, because it is not part of testConductor roles any more
}
runOn(first, second, third, fifth) {
enterBarrier("hello-deployed")
enterBarrier("first-unavailable")
// don't end the test until the fourth is done
runOn(first) {
// fourth system will be shutdown, remove to not participate in barriers any more
testConductor.removeNode(fourth)
expectMsg(EndActor.End)
}
enterBarrier("after-4")

View file

@ -18,6 +18,9 @@ import scala.concurrent.duration._
import scala.collection.immutable
import java.util.concurrent.ConcurrentHashMap
import akka.remote.DefaultFailureDetectorRegistry
import akka.actor.ActorRef
import akka.actor.Actor
import akka.actor.RootActorPath
object MultiNodeClusterSpec {
@ -48,6 +51,28 @@ object MultiNodeClusterSpec {
single-expect-default = 5 s
}
""")
// sometimes we need to coordinate test shutdown with messages instead of barriers
object EndActor {
case object SendEnd
case object End
case object EndAck
}
class EndActor(testActor: ActorRef, target: Option[Address]) extends Actor {
import EndActor._
def receive = {
case SendEnd
target foreach { t
context.actorSelection(RootActorPath(t) / self.path.elements) ! End
}
case End
testActor forward End
sender ! EndAck
case EndAck
testActor forward EndAck
}
}
}
trait MultiNodeClusterSpec extends Suite with STMultiNodeSpec with WatchedByCoroner { self: MultiNodeSpec

View file

@ -18,6 +18,7 @@ import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.Props
import akka.actor.RootActorPath
import akka.cluster.MultiNodeClusterSpec.EndActor
object UnreachableNodeJoinsAgainMultiNodeConfig extends MultiNodeConfig {
val first = role("first")
@ -37,9 +38,6 @@ object UnreachableNodeJoinsAgainMultiNodeConfig extends MultiNodeConfig {
testTransport(on = true)
class EndActor(testActor: ActorRef) extends Actor {
def receive = { case msg testActor forward msg }
}
}
class UnreachableNodeJoinsAgainMultiJvmNode1 extends UnreachableNodeJoinsAgainSpec
@ -147,7 +145,7 @@ abstract class UnreachableNodeJoinsAgainSpec
// so we can't use barriers to synchronize with it
val masterAddress = address(master)
runOn(master) {
system.actorOf(Props(classOf[EndActor], testActor), "end")
system.actorOf(Props(classOf[EndActor], testActor, None), "end")
}
enterBarrier("end-actor-created")
@ -186,7 +184,13 @@ abstract class UnreachableNodeJoinsAgainSpec
awaitAssert(Cluster(freshSystem).readView.members.size must be(expectedNumberOfMembers))
awaitAssert(clusterView.members.map(_.status) must be(Set(MemberStatus.Up)))
}
freshSystem.actorSelection(RootActorPath(master) / "user" / "end") ! "done"
// signal to master node that victim is done
val endProbe = TestProbe()(freshSystem)
val endActor = freshSystem.actorOf(Props(classOf[EndActor], endProbe.ref, Some(masterAddress)), "end")
endActor ! EndActor.SendEnd
endProbe.expectMsg(EndActor.EndAck)
} finally {
freshSystem.shutdown()
freshSystem.awaitTermination(10 seconds)
@ -198,7 +202,7 @@ abstract class UnreachableNodeJoinsAgainSpec
awaitMembersUp(expectedNumberOfMembers)
// don't end the test until the freshSystem is done
runOn(master) {
expectMsg("done")
expectMsg(EndActor.End)
}
endBarrier()
}