From b569869b61aa64cd4d0027131697d1a336c03a34 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 12:10:17 +0200 Subject: [PATCH 01/10] Use better sort order of members. See #2133 --- .../src/main/scala/akka/cluster/Cluster.scala | 12 +++++++- .../test/scala/akka/cluster/MemberSpec.scala | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala diff --git a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala index 76e3356143..55f9967596 100644 --- a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala +++ b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala @@ -100,7 +100,17 @@ class Member(val address: Address, val status: MemberStatus) extends ClusterMess object Member { import MemberStatus._ - implicit val ordering = Ordering.fromLessThan[Member](_.address.toString < _.address.toString) + implicit val addressOrdering: Ordering[Address] = Ordering.fromLessThan[Address] { (a, b) ⇒ + if (a.protocol < b.protocol) true + else if (a.system < b.system) true + else if (a.host.getOrElse("") < b.host.getOrElse("")) true + else if (a.port.getOrElse(0) < b.port.getOrElse(0)) true + else false + } + + implicit val ordering: Ordering[Member] = new Ordering[Member] { + def compare(x: Member, y: Member) = addressOrdering.compare(x.address, y.address) + } def apply(address: Address, status: MemberStatus): Member = new Member(address, status) diff --git a/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala new file mode 100644 index 0000000000..a75ead0149 --- /dev/null +++ b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ + +package akka.cluster + +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers +import akka.actor.Address +import scala.util.Random + +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) +class MemberSpec extends WordSpec with MustMatchers { + + "Member" must { + + "be sorted by address correctly" in { + import Member.ordering + val m1 = Member(Address("akka", "sys1", "host1", 9000), MemberStatus.Up) + val m2 = Member(Address("akka", "sys1", "host1", 10000), MemberStatus.Up) + val m3 = Member(Address("cluster", "sys1", "host1", 10000), MemberStatus.Up) + val m4 = Member(Address("cluster", "sys1", "host2", 10000), MemberStatus.Up) + val m5 = Member(Address("cluster", "sys2", "host2", 10000), MemberStatus.Up) + + val expected = IndexedSeq(m1, m2, m3, m4, m5) + val shuffled = Random.shuffle(expected) + shuffled.sorted must be(expected) + } + } +} From 829783f359ffb6b1a093d3b4dcb4a5bc07b9ea91 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 12:10:37 +0200 Subject: [PATCH 02/10] Remove port awareness in asserts of leader and members. See #2133 * Extracted common parts to MultiNodeClusterSpec --- .../akka/cluster/JoinTwoClustersSpec.scala | 27 +++----- .../MembershipChangeListenerSpec.scala | 13 +--- .../akka/cluster/MultiNodeClusterSpec.scala | 63 +++++++++++++++++++ .../akka/cluster/NodeMembershipSpec.scala | 26 ++------ .../scala/akka/cluster/NodeStartupSpec.scala | 12 +--- 5 files changed, 80 insertions(+), 61 deletions(-) create mode 100644 akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala index 9ed003944f..c15af5e651 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala @@ -18,13 +18,7 @@ object JoinTwoClustersMultiJvmSpec extends MultiNodeConfig { val c1 = role("c1") val c2 = role("c2") - commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(""" - akka.cluster { - gossip-frequency = 200 ms - leader-actions-frequency = 200 ms - periodic-tasks-initial-delay = 300 ms - } - """))) + commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) } @@ -35,13 +29,11 @@ class JoinTwoClustersMultiJvmNode4 extends JoinTwoClustersSpec class JoinTwoClustersMultiJvmNode5 extends JoinTwoClustersSpec class JoinTwoClustersMultiJvmNode6 extends JoinTwoClustersSpec -abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvmSpec) with ImplicitSender with BeforeAndAfter { +abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { import JoinTwoClustersMultiJvmSpec._ override def initialParticipants = 6 - def cluster: Cluster = Cluster(system) - after { testConductor.enter("after") } @@ -50,12 +42,6 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm val b1Address = node(b1).address val c1Address = node(c1).address - def awaitUpConvergence(numberOfMembers: Int): Unit = { - awaitCond(cluster.latestGossip.members.size == numberOfMembers) - awaitCond(cluster.latestGossip.members.forall(_.status == MemberStatus.Up)) - awaitCond(cluster.convergence.isDefined) - } - "Three different clusters (A, B and C)" must { "be able to 'elect' a single leader after joining (A -> B)" in { @@ -72,7 +58,9 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm awaitUpConvergence(numberOfMembers = 2) - cluster.isLeader must be(ifNode(a1, b1, c1)(true)(false)) + assertLeader(a1, a2) + assertLeader(b1, b2) + assertLeader(c1, c2) runOn(b2) { cluster.join(a1Address) @@ -82,7 +70,8 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm awaitUpConvergence(numberOfMembers = 4) } - cluster.isLeader must be(ifNode(a1, c1)(true)(false)) + assertLeader(a1, a2, b1, b2) + assertLeader(c1, c2) } @@ -94,7 +83,7 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm awaitUpConvergence(numberOfMembers = 6) - cluster.isLeader must be(ifNode(a1)(true)(false)) + assertLeader(a1, a2, b1, b2, c1, c2) } } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala index c5ae2f11e7..844d2803a1 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala @@ -16,13 +16,7 @@ object MembershipChangeListenerMultiJvmSpec extends MultiNodeConfig { val second = role("second") val third = role("third") - commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(""" - akka.cluster { - gossip-frequency = 200 ms - leader-actions-frequency = 200 ms - periodic-tasks-initial-delay = 300 ms - } - """))) + commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) } @@ -30,13 +24,12 @@ class MembershipChangeListenerMultiJvmNode1 extends MembershipChangeListenerSpec class MembershipChangeListenerMultiJvmNode2 extends MembershipChangeListenerSpec class MembershipChangeListenerMultiJvmNode3 extends MembershipChangeListenerSpec -abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChangeListenerMultiJvmSpec) with ImplicitSender with BeforeAndAfter { +abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChangeListenerMultiJvmSpec) + with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { import MembershipChangeListenerMultiJvmSpec._ override def initialParticipants = 3 - def cluster: Cluster = Cluster(system) - after { testConductor.enter("after") } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala new file mode 100644 index 0000000000..873d819dbb --- /dev/null +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/MultiNodeClusterSpec.scala @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ +package akka.cluster + +import com.typesafe.config.Config +import com.typesafe.config.ConfigFactory +import akka.actor.Address +import akka.remote.testconductor.RoleName +import akka.remote.testkit.MultiNodeSpec +import akka.util.duration._ + +object MultiNodeClusterSpec { + def clusterConfig: Config = ConfigFactory.parseString(""" + akka.cluster { + gossip-frequency = 200 ms + leader-actions-frequency = 200 ms + periodic-tasks-initial-delay = 300 ms + } + akka.test { + single-expect-default = 5 s + } + """) +} + +trait MultiNodeClusterSpec { self: MultiNodeSpec ⇒ + + def cluster: Cluster = Cluster(system) + + /** + * Assert that the member addresses match the expected addresses in the + * sort order used by the cluster. + */ + def assertMembers(gotMembers: Iterable[Member], expectedAddresses: Address*): Unit = { + import Member.addressOrdering + val members = gotMembers.toIndexedSeq + members.size must be(expectedAddresses.length) + expectedAddresses.sorted.zipWithIndex.foreach { case (a, i) ⇒ members(i).address must be(a) } + } + + /** + * Assert that the cluster has elected the correct leader + * out of all nodes in the cluster. First + * member in the cluster ring is expected leader. + */ + def assertLeader(nodesInCluster: RoleName*): Unit = if (nodesInCluster.contains(mySelf)) { + nodesInCluster.length must not be (0) + import Member.addressOrdering + val expectedLeader = nodesInCluster.map(role ⇒ (role, node(role).address)).sortBy(_._2).head._1 + cluster.isLeader must be(ifNode(expectedLeader)(true)(false)) + } + + /** + * Wait until the expected number of members has status Up + * and convergence has been reached. + */ + def awaitUpConvergence(numberOfMembers: Int): Unit = { + awaitCond(cluster.latestGossip.members.size == numberOfMembers) + awaitCond(cluster.latestGossip.members.forall(_.status == MemberStatus.Up)) + awaitCond(cluster.convergence.isDefined, 10 seconds) + } + +} \ No newline at end of file diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala index a8af644fe0..b5dc5d4d42 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala @@ -14,13 +14,7 @@ object NodeMembershipMultiJvmSpec extends MultiNodeConfig { val second = role("second") val third = role("third") - commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(""" - akka.cluster { - gossip-frequency = 200 ms - leader-actions-frequency = 200 ms - periodic-tasks-initial-delay = 300 ms - } - """))) + commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) } @@ -28,13 +22,11 @@ class NodeMembershipMultiJvmNode1 extends NodeMembershipSpec class NodeMembershipMultiJvmNode2 extends NodeMembershipSpec class NodeMembershipMultiJvmNode3 extends NodeMembershipSpec -abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSpec) with ImplicitSender with BeforeAndAfter { +abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { import NodeMembershipMultiJvmSpec._ override def initialParticipants = 3 - def cluster: Cluster = Cluster(system) - after { testConductor.enter("after") } @@ -50,11 +42,7 @@ abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSp runOn(first, second) { cluster.join(firstAddress) awaitCond(cluster.latestGossip.members.size == 2) - val members = cluster.latestGossip.members.toIndexedSeq - members.size must be(2) - val sortedAddresses = IndexedSeq(firstAddress, secondAddress).sortBy(_.toString) - members(0).address must be(sortedAddresses(0)) - members(1).address must be(sortedAddresses(1)) + assertMembers(cluster.latestGossip.members, firstAddress, secondAddress) awaitCond { cluster.latestGossip.members.forall(_.status == MemberStatus.Up) } @@ -69,14 +57,8 @@ abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSp cluster.join(firstAddress) } - // runOn all awaitCond(cluster.latestGossip.members.size == 3) - val members = cluster.latestGossip.members.toIndexedSeq - members.size must be(3) - val sortedAddresses = IndexedSeq(firstAddress, secondAddress, thirdAddress).sortBy(_.toString) - members(0).address must be(sortedAddresses(0)) - members(1).address must be(sortedAddresses(1)) - members(2).address must be(sortedAddresses(2)) + assertMembers(cluster.latestGossip.members, firstAddress, secondAddress, thirdAddress) awaitCond { cluster.latestGossip.members.forall(_.status == MemberStatus.Up) } diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala index f2206f8d89..55a0b15f63 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala @@ -13,26 +13,18 @@ object NodeStartupMultiJvmSpec extends MultiNodeConfig { val first = role("first") val second = role("second") - commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(""" - akka.cluster { - gossip-frequency = 200 ms - leader-actions-frequency = 200 ms - periodic-tasks-initial-delay = 300 ms - } - """))) + commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) } class NodeStartupMultiJvmNode1 extends NodeStartupSpec class NodeStartupMultiJvmNode2 extends NodeStartupSpec -abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) with ImplicitSender with BeforeAndAfter { +abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { import NodeStartupMultiJvmSpec._ override def initialParticipants = 2 - def cluster: Cluster = Cluster(system) - after { testConductor.enter("after") } From 34915063cda510ba06baba744af1c3ee2bfcaf22 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 12:51:37 +0200 Subject: [PATCH 03/10] Correct sort. See #2133 --- akka-cluster/src/main/scala/akka/cluster/Cluster.scala | 8 ++++---- akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala index 55f9967596..259f487358 100644 --- a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala +++ b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala @@ -101,10 +101,10 @@ object Member { import MemberStatus._ implicit val addressOrdering: Ordering[Address] = Ordering.fromLessThan[Address] { (a, b) ⇒ - if (a.protocol < b.protocol) true - else if (a.system < b.system) true - else if (a.host.getOrElse("") < b.host.getOrElse("")) true - else if (a.port.getOrElse(0) < b.port.getOrElse(0)) true + if (a.protocol != b.protocol) a.protocol.compareTo(b.protocol) < 0 + else if (a.system != b.system) a.system.compareTo(b.system) < 0 + else if (a.host.getOrElse("") != b.host.getOrElse("")) a.host.getOrElse("").compareTo(b.host.getOrElse("")) < 0 + else if (a.port.getOrElse(0) != b.port.getOrElse(0)) a.port.getOrElse(0) < b.port.getOrElse(0) else false } diff --git a/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala index a75ead0149..ba1037b8bc 100644 --- a/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala +++ b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala @@ -21,8 +21,9 @@ class MemberSpec extends WordSpec with MustMatchers { val m3 = Member(Address("cluster", "sys1", "host1", 10000), MemberStatus.Up) val m4 = Member(Address("cluster", "sys1", "host2", 10000), MemberStatus.Up) val m5 = Member(Address("cluster", "sys2", "host2", 10000), MemberStatus.Up) + val m6 = Member(Address("cluster", "sys2", "host3", 8000), MemberStatus.Up) - val expected = IndexedSeq(m1, m2, m3, m4, m5) + val expected = IndexedSeq(m1, m2, m3, m4, m5, m6) val shuffled = Random.shuffle(expected) shuffled.sorted must be(expected) } From dc17bba62fd08a4b3e100735f0b23e6a51be358f Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 25 May 2012 14:33:28 +0200 Subject: [PATCH 04/10] Removing warning from serialization.rst by adding whitespace, thanks reST. --- akka-docs/java/serialization.rst | 4 ++-- akka-docs/scala/serialization.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/akka-docs/java/serialization.rst b/akka-docs/java/serialization.rst index c352b6e1ae..d9aff609d8 100644 --- a/akka-docs/java/serialization.rst +++ b/akka-docs/java/serialization.rst @@ -181,7 +181,7 @@ which might contain actor references. External Akka Serializers ========================= -`Akka-protostuff by Roman Levenstein`_ +`Akka-protostuff by Roman Levenstein `_ -`Akka-quickser by Roman Levenstein`_ +`Akka-quickser by Roman Levenstein `_ diff --git a/akka-docs/scala/serialization.rst b/akka-docs/scala/serialization.rst index c1c2c16a8b..404847affc 100644 --- a/akka-docs/scala/serialization.rst +++ b/akka-docs/scala/serialization.rst @@ -188,7 +188,7 @@ which might contain actor references. External Akka Serializers ========================= -`Akka-protostuff by Roman Levenstein`_ +`Akka-protostuff by Roman Levenstein `_ -`Akka-quickser by Roman Levenstein`_ +`Akka-quickser by Roman Levenstein `_ From 24f6406634b39e350df4e2ee3efb080b9c91d7c3 Mon Sep 17 00:00:00 2001 From: Roland Date: Fri, 25 May 2012 14:42:22 +0200 Subject: [PATCH 05/10] fix specs2 samples so they system.shutdown --- akka-docs/java/typed-actors.rst | 2 +- .../code/docs/testkit/Specs2DemoAcceptance.scala | 8 +++++--- .../scala/code/docs/testkit/Specs2DemoSpec.scala | 11 ++++++----- akka-docs/scala/testing.rst | 14 +++++++++----- akka-docs/scala/typed-actors.rst | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/akka-docs/java/typed-actors.rst b/akka-docs/java/typed-actors.rst index 7712622dfe..90bdc5616c 100644 --- a/akka-docs/java/typed-actors.rst +++ b/akka-docs/java/typed-actors.rst @@ -163,7 +163,7 @@ Typed Actor Hierarchies Since you can obtain a contextual Typed Actor Extension by passing in an ``ActorContext`` you can create child Typed Actors by invoking ``typedActorOf(..)`` on that. -.. includecode:: code/akka/docs/actor/TypedActorDocTestBase.java +.. includecode:: code/docs/actor/TypedActorDocTestBase.java :include: typed-actor-hierarchy You can also create a child Typed Actor in regular Akka Actors by giving the ``UntypedActorContext`` diff --git a/akka-docs/scala/code/docs/testkit/Specs2DemoAcceptance.scala b/akka-docs/scala/code/docs/testkit/Specs2DemoAcceptance.scala index a3edb6a093..ab8bac9bf3 100644 --- a/akka-docs/scala/code/docs/testkit/Specs2DemoAcceptance.scala +++ b/akka-docs/scala/code/docs/testkit/Specs2DemoAcceptance.scala @@ -1,7 +1,7 @@ package docs.testkit -import org.specs2._ -import org.specs2.specification.Scope +import org.specs2.Specification +import org.specs2.specification.{ Step, Scope } import akka.actor.{ Props, ActorSystem, Actor } import akka.testkit.{ TestKit, ImplicitSender } @@ -13,10 +13,12 @@ class Specs2DemoAcceptance extends Specification { p ^ "A TestKit should" ^ "work properly with Specs2 acceptance tests" ! e1 ^ - "correctly convert durations" ! e2 + "correctly convert durations" ! e2 ^ + Step(system.shutdown()) ^ end // do not forget to shutdown! val system = ActorSystem() + // an alternative to mixing in NoTimeConversions implicit def d2d(d: org.specs2.time.Duration): akka.util.FiniteDuration = akka.util.Duration(d.inMilliseconds, "millis") diff --git a/akka-docs/scala/code/docs/testkit/Specs2DemoSpec.scala b/akka-docs/scala/code/docs/testkit/Specs2DemoSpec.scala index efe7b6088e..a620c5139b 100644 --- a/akka-docs/scala/code/docs/testkit/Specs2DemoSpec.scala +++ b/akka-docs/scala/code/docs/testkit/Specs2DemoSpec.scala @@ -2,20 +2,19 @@ package docs.testkit import org.specs2.mutable.Specification import org.specs2.specification.Scope +import org.specs2.time.NoTimeConversions import akka.actor.{ Props, ActorSystem, Actor } import akka.testkit.{ TestKit, ImplicitSender } +import akka.util.duration._ -class Specs2DemoUnitSpec extends Specification { +class Specs2DemoUnitSpec extends Specification with NoTimeConversions { val system = ActorSystem() - implicit def d2d(d: org.specs2.time.Duration): akka.util.FiniteDuration = - akka.util.Duration(d.inMilliseconds, "millis") - /* * this is needed if different test cases would clash when run concurrently, - * e.g. when creating specifically named top-level actors + * e.g. when creating specifically named top-level actors; leave out otherwise */ sequential @@ -31,4 +30,6 @@ class Specs2DemoUnitSpec extends Specification { } } } + + step(system.shutdown) // do not forget to shutdown! } diff --git a/akka-docs/scala/testing.rst b/akka-docs/scala/testing.rst index ac27655342..a98ee14917 100644 --- a/akka-docs/scala/testing.rst +++ b/akka-docs/scala/testing.rst @@ -684,11 +684,15 @@ Some `Specs2 `_ users have contributed examples of how to wor with :class:`org.specs2.specification.Scope`. * The Specification traits provide a :class:`Duration` DSL which uses partly the same method names as :class:`akka.util.Duration`, resulting in ambiguous - implicits if ``akka.util.duration._`` is imported. The work-around is to use - the Specification variants and supply an implicit conversion to the Akka - Duration. This conversion is not supplied with the Akka distribution because - that would mean that our JAR files would dependon Specs2, which is not - justified by this little feature. + implicits if ``akka.util.duration._`` is imported. There are two work-arounds: + + * either use the Specification variant of Duration and supply an implicit + conversion to the Akka Duration. This conversion is not supplied with the + Akka distribution because that would mean that our JAR files would dependon + Specs2, which is not justified by this little feature. + + * or mix :class:`org.specs2.time.NoTimeConversions` into the Specification. + * Specifications are by default executed concurrently, which requires some care when writing the tests or alternatively the ``sequential`` keyword. diff --git a/akka-docs/scala/typed-actors.rst b/akka-docs/scala/typed-actors.rst index 7c039a1db6..349b574888 100644 --- a/akka-docs/scala/typed-actors.rst +++ b/akka-docs/scala/typed-actors.rst @@ -163,7 +163,7 @@ Typed Actor Hierarchies Since you can obtain a contextual Typed Actor Extension by passing in an ``ActorContext`` you can create child Typed Actors by invoking ``typedActorOf(..)`` on that: -.. includecode:: code/akka/docs/actor/TypedActorDocSpec.scala +.. includecode:: code/docs/actor/TypedActorDocSpec.scala :include: typed-actor-hierarchy You can also create a child Typed Actor in regular Akka Actors by giving the ``ActorContext`` From a2cd84e0470cd6e1076d652238cd5a7bcc80a6e4 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 12:59:14 +0200 Subject: [PATCH 06/10] Sort on host and port only. See #2133 --- akka-cluster/src/main/scala/akka/cluster/Cluster.scala | 9 +++++---- .../src/test/scala/akka/cluster/MemberSpec.scala | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala index 259f487358..d55882205c 100644 --- a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala +++ b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala @@ -100,11 +100,12 @@ class Member(val address: Address, val status: MemberStatus) extends ClusterMess object Member { import MemberStatus._ + /** + * Sort Address by host and port + */ implicit val addressOrdering: Ordering[Address] = Ordering.fromLessThan[Address] { (a, b) ⇒ - if (a.protocol != b.protocol) a.protocol.compareTo(b.protocol) < 0 - else if (a.system != b.system) a.system.compareTo(b.system) < 0 - else if (a.host.getOrElse("") != b.host.getOrElse("")) a.host.getOrElse("").compareTo(b.host.getOrElse("")) < 0 - else if (a.port.getOrElse(0) != b.port.getOrElse(0)) a.port.getOrElse(0) < b.port.getOrElse(0) + if (a.host != b.host) a.host.getOrElse("").compareTo(b.host.getOrElse("")) < 0 + else if (a.port != b.port) a.port.getOrElse(0) < b.port.getOrElse(0) else false } diff --git a/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala index ba1037b8bc..050407577e 100644 --- a/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala +++ b/akka-cluster/src/test/scala/akka/cluster/MemberSpec.scala @@ -16,14 +16,14 @@ class MemberSpec extends WordSpec with MustMatchers { "be sorted by address correctly" in { import Member.ordering + // sorting should be done on host and port, only val m1 = Member(Address("akka", "sys1", "host1", 9000), MemberStatus.Up) val m2 = Member(Address("akka", "sys1", "host1", 10000), MemberStatus.Up) - val m3 = Member(Address("cluster", "sys1", "host1", 10000), MemberStatus.Up) - val m4 = Member(Address("cluster", "sys1", "host2", 10000), MemberStatus.Up) - val m5 = Member(Address("cluster", "sys2", "host2", 10000), MemberStatus.Up) - val m6 = Member(Address("cluster", "sys2", "host3", 8000), MemberStatus.Up) + val m3 = Member(Address("cluster", "sys2", "host2", 8000), MemberStatus.Up) + val m4 = Member(Address("cluster", "sys2", "host2", 9000), MemberStatus.Up) + val m5 = Member(Address("cluster", "sys1", "host2", 10000), MemberStatus.Up) - val expected = IndexedSeq(m1, m2, m3, m4, m5, m6) + val expected = IndexedSeq(m1, m2, m3, m4, m5) val shuffled = Random.shuffle(expected) shuffled.sorted must be(expected) } From bd6b46d665979af48822534e68c0525893decb17 Mon Sep 17 00:00:00 2001 From: Roland Date: Fri, 25 May 2012 15:11:00 +0200 Subject: [PATCH 07/10] improve logging of NoStackTrace exceptions --- .../src/main/scala/akka/event/Logging.scala | 6 ++++-- .../akka/remote/testconductor/Conductor.scala | 17 +++++++++++------ .../akka/remote/testconductor/BarrierSpec.scala | 6 +++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index 6e6f92ad0d..b91509ac9f 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -648,7 +648,7 @@ object Logging { import java.util.Date private val dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS") - private val errorFormat = "[ERROR] [%s] [%s] [%s] %s\n%s".intern + private val errorFormat = "[ERROR] [%s] [%s] [%s] %s%s".intern private val errorFormatWithoutCause = "[ERROR] [%s] [%s] [%s] %s".intern private val warningFormat = "[WARN] [%s] [%s] [%s] %s".intern private val infoFormat = "[INFO] [%s] [%s] [%s] %s".intern @@ -728,10 +728,12 @@ object Logging { * Returns the StackTrace for the given Throwable as a String */ def stackTraceFor(e: Throwable): String = e match { - case null | Error.NoCause | _: NoStackTrace ⇒ "" + case null | Error.NoCause ⇒ "" + case _: NoStackTrace ⇒ " (" + e.getClass.getName + ")" case other ⇒ val sw = new java.io.StringWriter val pw = new java.io.PrintWriter(sw) + pw.append('\n') other.printStackTrace(pw) sw.toString } diff --git a/akka-remote-tests/src/main/scala/akka/remote/testconductor/Conductor.scala b/akka-remote-tests/src/main/scala/akka/remote/testconductor/Conductor.scala index d46f682d58..8fa8eeff21 100644 --- a/akka-remote-tests/src/main/scala/akka/remote/testconductor/Conductor.scala +++ b/akka-remote-tests/src/main/scala/akka/remote/testconductor/Conductor.scala @@ -468,11 +468,16 @@ private[akka] object BarrierCoordinator { override def toString = productPrefix + productIterator.mkString("(", ", ", ")") } - case class BarrierTimeout(data: Data) extends RuntimeException(data.barrier) with NoStackTrace with Printer - case class DuplicateNode(data: Data, node: Controller.NodeInfo) extends RuntimeException with NoStackTrace with Printer - case class WrongBarrier(barrier: String, client: ActorRef, data: Data) extends RuntimeException(barrier) with NoStackTrace with Printer + case class BarrierTimeout(data: Data) + extends RuntimeException("timeout while waiting for barrier '" + data.barrier + "'") with NoStackTrace with Printer + case class DuplicateNode(data: Data, node: Controller.NodeInfo) + extends RuntimeException(node.toString) with NoStackTrace with Printer + case class WrongBarrier(barrier: String, client: ActorRef, data: Data) + extends RuntimeException(data.clients.find(_.fsm == client).map(_.name.toString).getOrElse(client.toString) + + " tried to enter '" + barrier + "' while we were waiting for '" + data.barrier + "'") with NoStackTrace with Printer case class BarrierEmpty(data: Data, msg: String) extends RuntimeException(msg) with NoStackTrace with Printer - case class ClientLost(data: Data, client: RoleName) extends RuntimeException with NoStackTrace with Printer + case class ClientLost(data: Data, client: RoleName) + extends RuntimeException("unannounced disconnect of " + client) with NoStackTrace with Printer } /** @@ -506,7 +511,7 @@ private[akka] class BarrierCoordinator extends Actor with LoggingFSM[BarrierCoor if (clients.find(_.name == n.name).isDefined) throw new DuplicateNode(d, n) stay using d.copy(clients = clients + n) case Event(ClientDisconnected(name), d @ Data(clients, _, arrived)) ⇒ - if (clients.isEmpty) throw BarrierEmpty(d, "no client to disconnect") + if (clients.isEmpty) throw BarrierEmpty(d, "cannot disconnect " + name + ": no client to disconnect") (clients find (_.name == name)) match { case None ⇒ stay case Some(c) ⇒ throw ClientLost(d.copy(clients = clients - c, arrived = arrived filterNot (_ == c.fsm)), name) @@ -524,7 +529,7 @@ private[akka] class BarrierCoordinator extends Actor with LoggingFSM[BarrierCoor else goto(Waiting) using d.copy(barrier = name, arrived = sender :: Nil) case Event(RemoveClient(name), d @ Data(clients, _, _)) ⇒ - if (clients.isEmpty) throw BarrierEmpty(d, "no client to remove") + if (clients.isEmpty) throw BarrierEmpty(d, "cannot remove " + name + ": no client to remove") stay using d.copy(clients = clients filterNot (_.name == name)) } diff --git a/akka-remote-tests/src/test/scala/akka/remote/testconductor/BarrierSpec.scala b/akka-remote-tests/src/test/scala/akka/remote/testconductor/BarrierSpec.scala index e0fd5dfb97..b8bce31708 100644 --- a/akka-remote-tests/src/test/scala/akka/remote/testconductor/BarrierSpec.scala +++ b/akka-remote-tests/src/test/scala/akka/remote/testconductor/BarrierSpec.scala @@ -54,7 +54,7 @@ class BarrierSpec extends AkkaSpec(BarrierSpec.config) with ImplicitSender with EventFilter[BarrierEmpty](occurrences = 1) intercept { b ! RemoveClient(A) } - expectMsg(Failed(b, BarrierEmpty(Data(Set(), "", Nil), "no client to remove"))) + expectMsg(Failed(b, BarrierEmpty(Data(Set(), "", Nil), "cannot remove RoleName(a): no client to remove"))) } "register clients and disconnect them" in { @@ -68,7 +68,7 @@ class BarrierSpec extends AkkaSpec(BarrierSpec.config) with ImplicitSender with EventFilter[BarrierEmpty](occurrences = 1) intercept { b ! ClientDisconnected(A) } - expectMsg(Failed(b, BarrierEmpty(Data(Set(), "", Nil), "no client to disconnect"))) + expectMsg(Failed(b, BarrierEmpty(Data(Set(), "", Nil), "cannot disconnect RoleName(a): no client to disconnect"))) } "fail entering barrier when nobody registered" in { @@ -187,7 +187,7 @@ class BarrierSpec extends AkkaSpec(BarrierSpec.config) with ImplicitSender with EventFilter[BarrierEmpty](occurrences = 1) intercept { barrier ! RemoveClient(A) } - expectMsg(Failed(barrier, BarrierEmpty(Data(Set(), "", Nil), "no client to remove"))) + expectMsg(Failed(barrier, BarrierEmpty(Data(Set(), "", Nil), "cannot remove RoleName(a): no client to remove"))) barrier ! NodeInfo(A, AddressFromURIString("akka://sys"), a.ref) a.send(barrier, EnterBarrier("right")) a.expectMsg(ToClient(BarrierResult("right", false))) From 17d54f1ae8c984066c06edcc733b940be0248d56 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 15:45:13 +0200 Subject: [PATCH 08/10] Tag as LongRunningTest --- .../multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala | 6 +++--- .../scala/akka/cluster/MembershipChangeListenerSpec.scala | 7 +++---- .../multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala | 4 ++-- .../src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala | 6 +++--- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala index c15af5e651..4bbe703405 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala @@ -8,7 +8,7 @@ import org.scalatest.BeforeAndAfter import com.typesafe.config.ConfigFactory import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec -import akka.testkit.ImplicitSender +import akka.testkit._ object JoinTwoClustersMultiJvmSpec extends MultiNodeConfig { val a1 = role("a1") @@ -44,7 +44,7 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm "Three different clusters (A, B and C)" must { - "be able to 'elect' a single leader after joining (A -> B)" in { + "be able to 'elect' a single leader after joining (A -> B)" taggedAs LongRunningTest in { runOn(a1, a2) { cluster.join(a1Address) @@ -75,7 +75,7 @@ abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvm } - "be able to 'elect' a single leader after joining (C -> A + B)" in { + "be able to 'elect' a single leader after joining (C -> A + B)" taggedAs LongRunningTest in { runOn(b2) { cluster.join(c1Address) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala index 844d2803a1..64019c102c 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala @@ -8,8 +8,7 @@ import org.scalatest.BeforeAndAfter import com.typesafe.config.ConfigFactory import akka.remote.testkit.MultiNodeConfig import akka.remote.testkit.MultiNodeSpec -import akka.testkit.ImplicitSender -import akka.testkit.TestLatch +import akka.testkit._ object MembershipChangeListenerMultiJvmSpec extends MultiNodeConfig { val first = role("first") @@ -39,7 +38,7 @@ abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChan val firstAddress = node(first).address val secondAddress = node(second).address - "(when two systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" in { + "(when two systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { runOn(first, second) { cluster.join(firstAddress) @@ -56,7 +55,7 @@ abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChan } - "(when three systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" in { + "(when three systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { runOn(third) { cluster.join(firstAddress) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala index b5dc5d4d42..f96265ac5a 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala @@ -37,7 +37,7 @@ abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSp "A set of connected cluster systems" must { - "(when two systems) start gossiping to each other so that both systems gets the same gossip info" in { + "(when two systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { runOn(first, second) { cluster.join(firstAddress) @@ -51,7 +51,7 @@ abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSp } - "(when three systems) start gossiping to each other so that both systems gets the same gossip info" in { + "(when three systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { runOn(third) { cluster.join(firstAddress) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala index 55a0b15f63..65cd7891a9 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala @@ -34,7 +34,7 @@ abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) wi "A first cluster node with a 'node-to-join' config set to empty string (singleton cluster)" must { - "be a singleton cluster when started up" in { + "be a singleton cluster when started up" taggedAs LongRunningTest in { runOn(first) { awaitCond(cluster.isSingletonCluster) // FIXME #2117 singletonCluster should reach convergence @@ -42,7 +42,7 @@ abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) wi } } - "be in 'Joining' phase when started up" in { + "be in 'Joining' phase when started up" taggedAs LongRunningTest in { runOn(first) { val members = cluster.latestGossip.members members.size must be(1) @@ -55,7 +55,7 @@ abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) wi } "A second cluster node" must { - "join the other node cluster when sending a Join command" in { + "join the other node cluster when sending a Join command" taggedAs LongRunningTest in { runOn(second) { cluster.join(firstAddress) From 2abe5308dabf452885eaad2c1b63c3ce34774dfe Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 25 May 2012 17:04:21 +0200 Subject: [PATCH 09/10] Commented out the cluster tests because it's not possible to exclude them right now --- .../akka/cluster/JoinTwoClustersSpec.scala | 180 +++++++++--------- .../MembershipChangeListenerSpec.scala | 154 +++++++-------- .../akka/cluster/NodeMembershipSpec.scala | 140 +++++++------- .../scala/akka/cluster/NodeStartupSpec.scala | 148 +++++++------- 4 files changed, 311 insertions(+), 311 deletions(-) diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala index 4bbe703405..87129a7a7c 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/JoinTwoClustersSpec.scala @@ -1,90 +1,90 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ - -package akka.cluster - -import org.scalatest.BeforeAndAfter -import com.typesafe.config.ConfigFactory -import akka.remote.testkit.MultiNodeConfig -import akka.remote.testkit.MultiNodeSpec -import akka.testkit._ - -object JoinTwoClustersMultiJvmSpec extends MultiNodeConfig { - val a1 = role("a1") - val a2 = role("a2") - val b1 = role("b1") - val b2 = role("b2") - val c1 = role("c1") - val c2 = role("c2") - - commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) - -} - -class JoinTwoClustersMultiJvmNode1 extends JoinTwoClustersSpec -class JoinTwoClustersMultiJvmNode2 extends JoinTwoClustersSpec -class JoinTwoClustersMultiJvmNode3 extends JoinTwoClustersSpec -class JoinTwoClustersMultiJvmNode4 extends JoinTwoClustersSpec -class JoinTwoClustersMultiJvmNode5 extends JoinTwoClustersSpec -class JoinTwoClustersMultiJvmNode6 extends JoinTwoClustersSpec - -abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { - import JoinTwoClustersMultiJvmSpec._ - - override def initialParticipants = 6 - - after { - testConductor.enter("after") - } - - val a1Address = node(a1).address - val b1Address = node(b1).address - val c1Address = node(c1).address - - "Three different clusters (A, B and C)" must { - - "be able to 'elect' a single leader after joining (A -> B)" taggedAs LongRunningTest in { - - runOn(a1, a2) { - cluster.join(a1Address) - } - runOn(b1, b2) { - cluster.join(b1Address) - } - runOn(c1, c2) { - cluster.join(c1Address) - } - - awaitUpConvergence(numberOfMembers = 2) - - assertLeader(a1, a2) - assertLeader(b1, b2) - assertLeader(c1, c2) - - runOn(b2) { - cluster.join(a1Address) - } - - runOn(a1, a2, b1, b2) { - awaitUpConvergence(numberOfMembers = 4) - } - - assertLeader(a1, a2, b1, b2) - assertLeader(c1, c2) - - } - - "be able to 'elect' a single leader after joining (C -> A + B)" taggedAs LongRunningTest in { - - runOn(b2) { - cluster.join(c1Address) - } - - awaitUpConvergence(numberOfMembers = 6) - - assertLeader(a1, a2, b1, b2, c1, c2) - } - } - -} +///** +// * Copyright (C) 2009-2012 Typesafe Inc. +// */ +// +//package akka.cluster +// +//import org.scalatest.BeforeAndAfter +//import com.typesafe.config.ConfigFactory +//import akka.remote.testkit.MultiNodeConfig +//import akka.remote.testkit.MultiNodeSpec +//import akka.testkit._ +// +//object JoinTwoClustersMultiJvmSpec extends MultiNodeConfig { +// val a1 = role("a1") +// val a2 = role("a2") +// val b1 = role("b1") +// val b2 = role("b2") +// val c1 = role("c1") +// val c2 = role("c2") +// +// commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) +// +//} +// +//class JoinTwoClustersMultiJvmNode1 extends JoinTwoClustersSpec +//class JoinTwoClustersMultiJvmNode2 extends JoinTwoClustersSpec +//class JoinTwoClustersMultiJvmNode3 extends JoinTwoClustersSpec +//class JoinTwoClustersMultiJvmNode4 extends JoinTwoClustersSpec +//class JoinTwoClustersMultiJvmNode5 extends JoinTwoClustersSpec +//class JoinTwoClustersMultiJvmNode6 extends JoinTwoClustersSpec +// +//abstract class JoinTwoClustersSpec extends MultiNodeSpec(JoinTwoClustersMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { +// import JoinTwoClustersMultiJvmSpec._ +// +// override def initialParticipants = 6 +// +// after { +// testConductor.enter("after") +// } +// +// val a1Address = node(a1).address +// val b1Address = node(b1).address +// val c1Address = node(c1).address +// +// "Three different clusters (A, B and C)" must { +// +// "be able to 'elect' a single leader after joining (A -> B)" taggedAs LongRunningTest in { +// +// runOn(a1, a2) { +// cluster.join(a1Address) +// } +// runOn(b1, b2) { +// cluster.join(b1Address) +// } +// runOn(c1, c2) { +// cluster.join(c1Address) +// } +// +// awaitUpConvergence(numberOfMembers = 2) +// +// assertLeader(a1, a2) +// assertLeader(b1, b2) +// assertLeader(c1, c2) +// +// runOn(b2) { +// cluster.join(a1Address) +// } +// +// runOn(a1, a2, b1, b2) { +// awaitUpConvergence(numberOfMembers = 4) +// } +// +// assertLeader(a1, a2, b1, b2) +// assertLeader(c1, c2) +// +// } +// +// "be able to 'elect' a single leader after joining (C -> A + B)" taggedAs LongRunningTest in { +// +// runOn(b2) { +// cluster.join(c1Address) +// } +// +// awaitUpConvergence(numberOfMembers = 6) +// +// assertLeader(a1, a2, b1, b2, c1, c2) +// } +// } +// +//} diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala index 64019c102c..6bb0f556d5 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/MembershipChangeListenerSpec.scala @@ -1,77 +1,77 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ -package akka.cluster - -import scala.collection.immutable.SortedSet -import org.scalatest.BeforeAndAfter -import com.typesafe.config.ConfigFactory -import akka.remote.testkit.MultiNodeConfig -import akka.remote.testkit.MultiNodeSpec -import akka.testkit._ - -object MembershipChangeListenerMultiJvmSpec extends MultiNodeConfig { - val first = role("first") - val second = role("second") - val third = role("third") - - commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) - -} - -class MembershipChangeListenerMultiJvmNode1 extends MembershipChangeListenerSpec -class MembershipChangeListenerMultiJvmNode2 extends MembershipChangeListenerSpec -class MembershipChangeListenerMultiJvmNode3 extends MembershipChangeListenerSpec - -abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChangeListenerMultiJvmSpec) - with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { - import MembershipChangeListenerMultiJvmSpec._ - - override def initialParticipants = 3 - - after { - testConductor.enter("after") - } - - "A set of connected cluster systems" must { - - val firstAddress = node(first).address - val secondAddress = node(second).address - - "(when two systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { - - runOn(first, second) { - cluster.join(firstAddress) - val latch = TestLatch() - cluster.registerListener(new MembershipChangeListener { - def notify(members: SortedSet[Member]) { - if (members.size == 2 && members.forall(_.status == MemberStatus.Up)) - latch.countDown() - } - }) - latch.await - cluster.convergence.isDefined must be(true) - } - - } - - "(when three systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { - - runOn(third) { - cluster.join(firstAddress) - } - - val latch = TestLatch() - cluster.registerListener(new MembershipChangeListener { - def notify(members: SortedSet[Member]) { - if (members.size == 3 && members.forall(_.status == MemberStatus.Up)) - latch.countDown() - } - }) - latch.await - cluster.convergence.isDefined must be(true) - - } - } - -} +///** +// * Copyright (C) 2009-2012 Typesafe Inc. +// */ +//package akka.cluster +// +//import scala.collection.immutable.SortedSet +//import org.scalatest.BeforeAndAfter +//import com.typesafe.config.ConfigFactory +//import akka.remote.testkit.MultiNodeConfig +//import akka.remote.testkit.MultiNodeSpec +//import akka.testkit._ +// +//object MembershipChangeListenerMultiJvmSpec extends MultiNodeConfig { +// val first = role("first") +// val second = role("second") +// val third = role("third") +// +// commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) +// +//} +// +//class MembershipChangeListenerMultiJvmNode1 extends MembershipChangeListenerSpec +//class MembershipChangeListenerMultiJvmNode2 extends MembershipChangeListenerSpec +//class MembershipChangeListenerMultiJvmNode3 extends MembershipChangeListenerSpec +// +//abstract class MembershipChangeListenerSpec extends MultiNodeSpec(MembershipChangeListenerMultiJvmSpec) +// with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { +// import MembershipChangeListenerMultiJvmSpec._ +// +// override def initialParticipants = 3 +// +// after { +// testConductor.enter("after") +// } +// +// "A set of connected cluster systems" must { +// +// val firstAddress = node(first).address +// val secondAddress = node(second).address +// +// "(when two systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { +// +// runOn(first, second) { +// cluster.join(firstAddress) +// val latch = TestLatch() +// cluster.registerListener(new MembershipChangeListener { +// def notify(members: SortedSet[Member]) { +// if (members.size == 2 && members.forall(_.status == MemberStatus.Up)) +// latch.countDown() +// } +// }) +// latch.await +// cluster.convergence.isDefined must be(true) +// } +// +// } +// +// "(when three systems) after cluster convergence updates the membership table then all MembershipChangeListeners should be triggered" taggedAs LongRunningTest in { +// +// runOn(third) { +// cluster.join(firstAddress) +// } +// +// val latch = TestLatch() +// cluster.registerListener(new MembershipChangeListener { +// def notify(members: SortedSet[Member]) { +// if (members.size == 3 && members.forall(_.status == MemberStatus.Up)) +// latch.countDown() +// } +// }) +// latch.await +// cluster.convergence.isDefined must be(true) +// +// } +// } +// +//} diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala index f96265ac5a..21defd1d97 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeMembershipSpec.scala @@ -1,70 +1,70 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ -package akka.cluster - -import com.typesafe.config.ConfigFactory -import org.scalatest.BeforeAndAfter -import akka.remote.testkit.MultiNodeConfig -import akka.remote.testkit.MultiNodeSpec -import akka.testkit._ - -object NodeMembershipMultiJvmSpec extends MultiNodeConfig { - val first = role("first") - val second = role("second") - val third = role("third") - - commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) - -} - -class NodeMembershipMultiJvmNode1 extends NodeMembershipSpec -class NodeMembershipMultiJvmNode2 extends NodeMembershipSpec -class NodeMembershipMultiJvmNode3 extends NodeMembershipSpec - -abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { - import NodeMembershipMultiJvmSpec._ - - override def initialParticipants = 3 - - after { - testConductor.enter("after") - } - - val firstAddress = node(first).address - val secondAddress = node(second).address - val thirdAddress = node(third).address - - "A set of connected cluster systems" must { - - "(when two systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { - - runOn(first, second) { - cluster.join(firstAddress) - awaitCond(cluster.latestGossip.members.size == 2) - assertMembers(cluster.latestGossip.members, firstAddress, secondAddress) - awaitCond { - cluster.latestGossip.members.forall(_.status == MemberStatus.Up) - } - awaitCond(cluster.convergence.isDefined) - } - - } - - "(when three systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { - - runOn(third) { - cluster.join(firstAddress) - } - - awaitCond(cluster.latestGossip.members.size == 3) - assertMembers(cluster.latestGossip.members, firstAddress, secondAddress, thirdAddress) - awaitCond { - cluster.latestGossip.members.forall(_.status == MemberStatus.Up) - } - awaitCond(cluster.convergence.isDefined) - - } - } - -} +///** +// * Copyright (C) 2009-2012 Typesafe Inc. +// */ +//package akka.cluster +// +//import com.typesafe.config.ConfigFactory +//import org.scalatest.BeforeAndAfter +//import akka.remote.testkit.MultiNodeConfig +//import akka.remote.testkit.MultiNodeSpec +//import akka.testkit._ +// +//object NodeMembershipMultiJvmSpec extends MultiNodeConfig { +// val first = role("first") +// val second = role("second") +// val third = role("third") +// +// commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) +// +//} +// +//class NodeMembershipMultiJvmNode1 extends NodeMembershipSpec +//class NodeMembershipMultiJvmNode2 extends NodeMembershipSpec +//class NodeMembershipMultiJvmNode3 extends NodeMembershipSpec +// +//abstract class NodeMembershipSpec extends MultiNodeSpec(NodeMembershipMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { +// import NodeMembershipMultiJvmSpec._ +// +// override def initialParticipants = 3 +// +// after { +// testConductor.enter("after") +// } +// +// val firstAddress = node(first).address +// val secondAddress = node(second).address +// val thirdAddress = node(third).address +// +// "A set of connected cluster systems" must { +// +// "(when two systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { +// +// runOn(first, second) { +// cluster.join(firstAddress) +// awaitCond(cluster.latestGossip.members.size == 2) +// assertMembers(cluster.latestGossip.members, firstAddress, secondAddress) +// awaitCond { +// cluster.latestGossip.members.forall(_.status == MemberStatus.Up) +// } +// awaitCond(cluster.convergence.isDefined) +// } +// +// } +// +// "(when three systems) start gossiping to each other so that both systems gets the same gossip info" taggedAs LongRunningTest in { +// +// runOn(third) { +// cluster.join(firstAddress) +// } +// +// awaitCond(cluster.latestGossip.members.size == 3) +// assertMembers(cluster.latestGossip.members, firstAddress, secondAddress, thirdAddress) +// awaitCond { +// cluster.latestGossip.members.forall(_.status == MemberStatus.Up) +// } +// awaitCond(cluster.convergence.isDefined) +// +// } +// } +// +//} diff --git a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala index 65cd7891a9..ff4c06215d 100644 --- a/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala +++ b/akka-cluster/src/multi-jvm/scala/akka/cluster/NodeStartupSpec.scala @@ -1,74 +1,74 @@ -/** - * Copyright (C) 2009-2012 Typesafe Inc. - */ -package akka.cluster - -import com.typesafe.config.ConfigFactory -import org.scalatest.BeforeAndAfter -import akka.remote.testkit.MultiNodeConfig -import akka.remote.testkit.MultiNodeSpec -import akka.testkit._ - -object NodeStartupMultiJvmSpec extends MultiNodeConfig { - val first = role("first") - val second = role("second") - - commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) - -} - -class NodeStartupMultiJvmNode1 extends NodeStartupSpec -class NodeStartupMultiJvmNode2 extends NodeStartupSpec - -abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { - import NodeStartupMultiJvmSpec._ - - override def initialParticipants = 2 - - after { - testConductor.enter("after") - } - - val firstAddress = node(first).address - val secondAddress = node(second).address - - "A first cluster node with a 'node-to-join' config set to empty string (singleton cluster)" must { - - "be a singleton cluster when started up" taggedAs LongRunningTest in { - runOn(first) { - awaitCond(cluster.isSingletonCluster) - // FIXME #2117 singletonCluster should reach convergence - //awaitCond(cluster.convergence.isDefined) - } - } - - "be in 'Joining' phase when started up" taggedAs LongRunningTest in { - runOn(first) { - val members = cluster.latestGossip.members - members.size must be(1) - - val joiningMember = members find (_.address == firstAddress) - joiningMember must not be (None) - joiningMember.get.status must be(MemberStatus.Joining) - } - } - } - - "A second cluster node" must { - "join the other node cluster when sending a Join command" taggedAs LongRunningTest in { - - runOn(second) { - cluster.join(firstAddress) - } - - awaitCond { - cluster.latestGossip.members.exists { member ⇒ - member.address == secondAddress && member.status == MemberStatus.Up - } - } - cluster.latestGossip.members.size must be(2) - awaitCond(cluster.convergence.isDefined) - } - } - -} +///** +// * Copyright (C) 2009-2012 Typesafe Inc. +// */ +//package akka.cluster +// +//import com.typesafe.config.ConfigFactory +//import org.scalatest.BeforeAndAfter +//import akka.remote.testkit.MultiNodeConfig +//import akka.remote.testkit.MultiNodeSpec +//import akka.testkit._ +// +//object NodeStartupMultiJvmSpec extends MultiNodeConfig { +// val first = role("first") +// val second = role("second") +// +// commonConfig(debugConfig(on = false).withFallback(MultiNodeClusterSpec.clusterConfig)) +// +//} +// +//class NodeStartupMultiJvmNode1 extends NodeStartupSpec +//class NodeStartupMultiJvmNode2 extends NodeStartupSpec +// +//abstract class NodeStartupSpec extends MultiNodeSpec(NodeStartupMultiJvmSpec) with MultiNodeClusterSpec with ImplicitSender with BeforeAndAfter { +// import NodeStartupMultiJvmSpec._ +// +// override def initialParticipants = 2 +// +// after { +// testConductor.enter("after") +// } +// +// val firstAddress = node(first).address +// val secondAddress = node(second).address +// +// "A first cluster node with a 'node-to-join' config set to empty string (singleton cluster)" must { +// +// "be a singleton cluster when started up" taggedAs LongRunningTest in { +// runOn(first) { +// awaitCond(cluster.isSingletonCluster) +// // FIXME #2117 singletonCluster should reach convergence +// //awaitCond(cluster.convergence.isDefined) +// } +// } +// +// "be in 'Joining' phase when started up" taggedAs LongRunningTest in { +// runOn(first) { +// val members = cluster.latestGossip.members +// members.size must be(1) +// +// val joiningMember = members find (_.address == firstAddress) +// joiningMember must not be (None) +// joiningMember.get.status must be(MemberStatus.Joining) +// } +// } +// } +// +// "A second cluster node" must { +// "join the other node cluster when sending a Join command" taggedAs LongRunningTest in { +// +// runOn(second) { +// cluster.join(firstAddress) +// } +// +// awaitCond { +// cluster.latestGossip.members.exists { member ⇒ +// member.address == secondAddress && member.status == MemberStatus.Up +// } +// } +// cluster.latestGossip.members.size must be(2) +// awaitCond(cluster.convergence.isDefined) +// } +// } +// +//} From 7cd1d38eb1d8acb07ea9a1dc2312925d57f82023 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 25 May 2012 17:15:35 +0200 Subject: [PATCH 10/10] #2130 - Fixing unforunate naming in DiningHakkers --- .../src/main/scala/DiningHakkersOnBecome.scala | 8 +++----- .../src/main/scala/DiningHakkersOnFsm.scala | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala b/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala index b82699ebe4..65d7d7c23c 100644 --- a/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala +++ b/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnBecome.scala @@ -131,17 +131,15 @@ class Hakker(name: String, left: ActorRef, right: ActorRef) extends Actor { object DiningHakkers { val system = ActorSystem() - def main(args: Array[String]): Unit = { - run - } + def main(args: Array[String]): Unit = run def run { //Create 5 chopsticks - val chopsticks = for (i ← 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick " + i) + val chopsticks = for (i ← 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick" + i) //Create 5 awesome hakkers and assign them their left and right chopstick val hakkers = for { - (name, i) ← List("Ghosh", "Bonér", "Klang", "Krasser", "Manie").zipWithIndex + (name, i) ← List("Ghosh", "Boner", "Klang", "Krasser", "Manie").zipWithIndex } yield system.actorOf(Props(new Hakker(name, chopsticks(i), chopsticks((i + 1) % 5)))) //Signal all hakkers that they should start thinking, and watch the show diff --git a/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnFsm.scala b/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnFsm.scala index 52ed49797a..7928a85334 100644 --- a/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnFsm.scala +++ b/akka-samples/akka-sample-fsm/src/main/scala/DiningHakkersOnFsm.scala @@ -169,16 +169,14 @@ object DiningHakkersOnFsm { val system = ActorSystem() - def main(args: Array[String]): Unit = { - run - } + def main(args: Array[String]): Unit = run def run = { // Create 5 chopsticks - val chopsticks = for (i ← 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick " + i) + val chopsticks = for (i ← 1 to 5) yield system.actorOf(Props[Chopstick], "Chopstick" + i) // Create 5 awesome fsm hakkers and assign them their left and right chopstick val hakkers = for { - (name, i) ← List("Ghosh", "Bonér", "Klang", "Krasser", "Manie").zipWithIndex + (name, i) ← List("Ghosh", "Boner", "Klang", "Krasser", "Manie").zipWithIndex } yield system.actorOf(Props(new FSMHakker(name, chopsticks(i), chopsticks((i + 1) % 5)))) hakkers.foreach(_ ! Think)