diff --git a/akka-remote-tests/src/main/scala/akka/remote/testkit/MultiNodeSpec.scala b/akka-remote-tests/src/main/scala/akka/remote/testkit/MultiNodeSpec.scala index 04cf9bf3c9..c3081f31c4 100644 --- a/akka-remote-tests/src/main/scala/akka/remote/testkit/MultiNodeSpec.scala +++ b/akka-remote-tests/src/main/scala/akka/remote/testkit/MultiNodeSpec.scala @@ -100,35 +100,84 @@ abstract class MultiNodeConfig { object MultiNodeSpec { /** - * Names (or IP addresses; must be resolvable using InetAddress.getByName) - * of all nodes taking part in this test, including symbolic name and host - * definition: + * Number of nodes node taking part in this test. * * {{{ - * -D"multinode.hosts=host1@workerA.example.com,host2@workerB.example.com" + * -D"multinode.max-nodes=4" * }}} */ - val nodeNames: Seq[String] = Vector.empty ++ ( - Option(System.getProperty("multinode.hosts")) getOrElse - (throw new IllegalStateException("need system property multinode.hosts to be set")) split ",") + val maxNodes: Int = Option(Integer.getInteger("multinode.max-nodes")) getOrElse + (throw new IllegalStateException("need system property multinode.max-nodes to be set")) - require(nodeNames != List(""), "multinode.hosts must not be empty") + require(maxNodes > 0, "multinode.max-nodes must be greater than 0") /** - * Index of this node in the nodeNames / nodeAddresses lists. The TestConductor + * Name (or IP address; must be resolvable using InetAddress.getByName) + * of the host this node is running on. + * + * {{{ + * -D"multinode.host=host.example.com" + * }}} + */ + val selfName: String = Option(System.getProperty("multinode.host")) getOrElse + (throw new IllegalStateException("need system property multinode.host to be set")) + + require(selfName != "", "multinode.host must not be empty") + + /** + * Port number of this node. Defaults to 0 which means a random port. + * + * {{{ + * -D"multinode.port=0" + * }}} + */ + val selfPort: Int = Integer.getInteger("multinode.port", 0) + + require(selfPort >= 0 && selfPort < 65535, "multinode.port is out of bounds: " + selfPort) + + /** + * Name (or IP address; must be resolvable using InetAddress.getByName) + * of the host that the server node is running on. + * + * {{{ + * -D"multinode.server-host=server.example.com" + * }}} + */ + val serverName: String = Option(System.getProperty("multinode.server-host")) getOrElse + (throw new IllegalStateException("need system property multinode.server-host to be set")) + + require(serverName != "", "multinode.server-host must not be empty") + + /** + * Port number of the node that's running the server system. Defaults to 4711. + * + * {{{ + * -D"multinode.server-port=4711" + * }}} + */ + val serverPort: Int = Integer.getInteger("multinode.server-port", 4711) + + require(serverPort > 0 && serverPort < 65535, "multinode.server-port is out of bounds: " + serverPort) + + /** + * Index of this node in the roles sequence. The TestConductor * is started in “controller” mode on selfIndex 0, i.e. there you can inject * failures and shutdown other nodes etc. + * + * {{{ + * -D"multinode.index=0" + * }}} */ val selfIndex = Option(Integer.getInteger("multinode.index")) getOrElse (throw new IllegalStateException("need system property multinode.index to be set")) - require(selfIndex >= 0 && selfIndex < nodeNames.size, "selfIndex out of bounds: " + selfIndex) + require(selfIndex >= 0 && selfIndex < maxNodes, "multinode.index is out of bounds: " + selfIndex) private[testkit] val nodeConfig = mapToConfig(Map( "akka.actor.provider" -> "akka.remote.RemoteActorRefProvider", "akka.remote.transport" -> "akka.remote.testconductor.TestConductorTransport", - "akka.remote.netty.hostname" -> nodeNames(selfIndex), - "akka.remote.netty.port" -> 0)) + "akka.remote.netty.hostname" -> selfName, + "akka.remote.netty.port" -> selfPort)) private[testkit] val baseConfig: Config = ConfigFactory.parseString(""" akka { @@ -235,7 +284,7 @@ abstract class MultiNodeSpec(val myself: RoleName, _system: ActorSystem, _roles: */ def initialParticipants: Int require(initialParticipants > 0, "initialParticipants must be a 'def' or early initializer, and it must be greater zero") - require(initialParticipants <= nodeNames.size, "not enough nodes to run this test") + require(initialParticipants <= maxNodes, "not enough nodes to run this test") /** * Access to the barriers, failure injection, etc. The extension will have @@ -289,7 +338,7 @@ abstract class MultiNodeSpec(val myself: RoleName, _system: ActorSystem, _roles: * Implementation (i.e. wait for start etc.) */ - private val controllerAddr = new InetSocketAddress(nodeNames(0), 4711) + private val controllerAddr = new InetSocketAddress(serverName, serverPort) if (selfIndex == 0) { Await.result(testConductor.startController(initialParticipants, myself, controllerAddr), testConductor.Settings.BarrierTimeout.duration) diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 2bbf27f3d2..8921b162a6 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -378,6 +378,7 @@ object AkkaBuild extends Build { lazy val defaultMultiJvmOptions: Seq[String] = { import scala.collection.JavaConverters._ val akkaProperties = System.getProperties.propertyNames.asScala.toList.collect { + case key: String if key.startsWith("multinode.") => "-D" + key + "=" + System.getProperty(key) case key: String if key.startsWith("akka.") => "-D" + key + "=" + System.getProperty(key) } akkaProperties ::: (if (getBoolean("sbt.log.noformat")) List("-Dakka.test.nocolor=true") else Nil) diff --git a/project/plugins.sbt b/project/plugins.sbt index d5d8cbcc0c..8762942bac 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,7 @@ resolvers += Classpaths.typesafeResolver -addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.3") addSbtPlugin("com.typesafe.sbtscalariform" % "sbtscalariform" % "0.4.0")