Use only the hard exit LeaderElectionSpec, see #2113

This commit is contained in:
Patrik Nordwall 2012-05-28 13:55:22 +02:00
parent e3eec7e344
commit 59dd754819
2 changed files with 32 additions and 134 deletions

View file

@ -1,108 +0,0 @@
/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.cluster
import com.typesafe.config.ConfigFactory
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
object HardExitLeaderElectionMultiJvmSpec extends MultiNodeConfig {
val controller = role("controller")
val first = role("first")
val second = role("second")
val third = role("third")
val fourth = role("fourth")
commonConfig(debugConfig(on = false).
withFallback(ConfigFactory.parseString("""
akka.cluster.auto-down = off
""")).
withFallback(MultiNodeClusterSpec.clusterConfig))
}
class HardExitLeaderElectionMultiJvmNode1 extends HardExitLeaderElectionSpec
class HardExitLeaderElectionMultiJvmNode2 extends HardExitLeaderElectionSpec
class HardExitLeaderElectionMultiJvmNode3 extends HardExitLeaderElectionSpec
class HardExitLeaderElectionMultiJvmNode4 extends HardExitLeaderElectionSpec
class HardExitLeaderElectionMultiJvmNode5 extends HardExitLeaderElectionSpec
abstract class HardExitLeaderElectionSpec extends MultiNodeSpec(HardExitLeaderElectionMultiJvmSpec) with MultiNodeClusterSpec {
import HardExitLeaderElectionMultiJvmSpec._
override def initialParticipants = 5
lazy val firstAddress = node(first).address
// sorted in the order used by the cluster
lazy val roles = Seq(first, second, third, fourth).sorted
"A cluster of four nodes" must {
"be able to 'elect' a single leader" taggedAs LongRunningTest in {
// make sure that the node-to-join is started before other join
runOn(first) {
cluster
}
testConductor.enter("first-started")
if (mySelf != controller) {
cluster.join(firstAddress)
awaitUpConvergence(numberOfMembers = roles.size)
cluster.isLeader must be(mySelf == roles.head)
}
testConductor.enter("after")
}
def shutdownLeaderAndVerifyNewLeader(alreadyShutdown: Int): Unit = {
val currentRoles = roles.drop(alreadyShutdown)
currentRoles.size must be >= (2)
val leader = currentRoles.head
val aUser = currentRoles.last
mySelf match {
case `controller`
testConductor.enter("before-shutdown")
testConductor.shutdown(leader, 0)
testConductor.removeNode(leader)
testConductor.enter("after-shutdown", "after-down", "completed")
case `leader`
testConductor.enter("before-shutdown")
// this node will be shutdown by the controller and doesn't participate in more barriers
case `aUser`
val leaderAddress = node(leader).address
testConductor.enter("before-shutdown", "after-shutdown")
// user marks the shutdown leader as DOWN
cluster.down(leaderAddress)
testConductor.enter("after-down", "completed")
case _ if currentRoles.tail.contains(mySelf)
// remaining cluster nodes, not shutdown
testConductor.enter("before-shutdown", "after-shutdown", "after-down")
awaitUpConvergence(currentRoles.size - 1)
val nextExpectedLeader = currentRoles.tail.head
cluster.isLeader must be(mySelf == nextExpectedLeader)
testConductor.enter("completed")
}
}
"be able to 're-elect' a single leader after leader has left" taggedAs LongRunningTest in {
shutdownLeaderAndVerifyNewLeader(alreadyShutdown = 0)
}
"be able to 're-elect' a single leader after leader has left (again)" taggedAs LongRunningTest in {
shutdownLeaderAndVerifyNewLeader(alreadyShutdown = 1)
}
}
}

View file

@ -10,6 +10,7 @@ import akka.remote.testkit.MultiNodeSpec
import akka.testkit._ import akka.testkit._
object LeaderElectionMultiJvmSpec extends MultiNodeConfig { object LeaderElectionMultiJvmSpec extends MultiNodeConfig {
val controller = role("controller")
val first = role("first") val first = role("first")
val second = role("second") val second = role("second")
val third = role("third") val third = role("third")
@ -27,11 +28,12 @@ class LeaderElectionMultiJvmNode1 extends LeaderElectionSpec
class LeaderElectionMultiJvmNode2 extends LeaderElectionSpec class LeaderElectionMultiJvmNode2 extends LeaderElectionSpec
class LeaderElectionMultiJvmNode3 extends LeaderElectionSpec class LeaderElectionMultiJvmNode3 extends LeaderElectionSpec
class LeaderElectionMultiJvmNode4 extends LeaderElectionSpec class LeaderElectionMultiJvmNode4 extends LeaderElectionSpec
class LeaderElectionMultiJvmNode5 extends LeaderElectionSpec
abstract class LeaderElectionSpec extends MultiNodeSpec(LeaderElectionMultiJvmSpec) with MultiNodeClusterSpec { abstract class LeaderElectionSpec extends MultiNodeSpec(LeaderElectionMultiJvmSpec) with MultiNodeClusterSpec {
import LeaderElectionMultiJvmSpec._ import LeaderElectionMultiJvmSpec._
override def initialParticipants = 4 override def initialParticipants = 5
lazy val firstAddress = node(first).address lazy val firstAddress = node(first).address
@ -47,47 +49,51 @@ abstract class LeaderElectionSpec extends MultiNodeSpec(LeaderElectionMultiJvmSp
} }
testConductor.enter("first-started") testConductor.enter("first-started")
cluster.join(firstAddress) if (mySelf != controller) {
awaitUpConvergence(numberOfMembers = roles.size) cluster.join(firstAddress)
cluster.isLeader must be(mySelf == roles.head) awaitUpConvergence(numberOfMembers = roles.size)
cluster.isLeader must be(mySelf == roles.head)
}
testConductor.enter("after") testConductor.enter("after")
} }
def shutdownLeaderAndVerifyNewLeader(alreadyShutdown: Int): Unit = { def shutdownLeaderAndVerifyNewLeader(alreadyShutdown: Int): Unit = {
val currentRoles = roles.drop(alreadyShutdown) val currentRoles = roles.drop(alreadyShutdown)
currentRoles.size must be >= (2) currentRoles.size must be >= (2)
val leader = currentRoles.head
val aUser = currentRoles.last
runOn(currentRoles.head) { mySelf match {
cluster.shutdown()
testConductor.enter("after-shutdown")
testConductor.enter("after-down")
}
// runOn previously shutdown cluster nodes case `controller`
if ((roles diff currentRoles).contains(mySelf)) { testConductor.enter("before-shutdown")
testConductor.enter("after-shutdown") testConductor.shutdown(leader, 0)
testConductor.enter("after-down") testConductor.removeNode(leader)
} testConductor.enter("after-shutdown", "after-down", "completed")
// runOn remaining cluster nodes case `leader`
if (currentRoles.tail.contains(mySelf)) { testConductor.enter("before-shutdown")
// this node will be shutdown by the controller and doesn't participate in more barriers
testConductor.enter("after-shutdown") case `aUser`
val leaderAddress = node(leader).address
runOn(currentRoles.last) { testConductor.enter("before-shutdown", "after-shutdown")
// user marks the shutdown leader as DOWN // user marks the shutdown leader as DOWN
val leaderAddress = node(currentRoles.head).address
cluster.down(leaderAddress) cluster.down(leaderAddress)
} testConductor.enter("after-down", "completed")
testConductor.enter("after-down") case _ if currentRoles.tail.contains(mySelf)
// remaining cluster nodes, not shutdown
testConductor.enter("before-shutdown", "after-shutdown", "after-down")
awaitUpConvergence(currentRoles.size - 1)
val nextExpectedLeader = currentRoles.tail.head
cluster.isLeader must be(mySelf == nextExpectedLeader)
testConductor.enter("completed")
awaitUpConvergence(currentRoles.size - 1)
val nextExpectedLeader = currentRoles.tail.head
cluster.isLeader must be(mySelf == nextExpectedLeader)
} }
testConductor.enter("after")
} }
"be able to 're-elect' a single leader after leader has left" taggedAs LongRunningTest in { "be able to 're-elect' a single leader after leader has left" taggedAs LongRunningTest in {