Skip to content

Instantly share code, notes, and snippets.

@bvenners
Created December 18, 2013 20:06
Show Gist options
  • Select an option

  • Save bvenners/8029009 to your computer and use it in GitHub Desktop.

Select an option

Save bvenners/8029009 to your computer and use it in GitHub Desktop.
Adding a few &&'s to get a pure variant of an asynchronous test
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.cluster
import scala.collection.immutable.SortedSet
import com.typesafe.config.ConfigFactory
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import scala.concurrent.duration._
object NodeLeavingAndExitingAndBeingRemovedMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
val second = role("second")
val third = role("third")
commonConfig(debugConfig(on = false).withFallback(ConfigFactory.parseString(
"akka.cluster.auto-down-unreachable-after = 0s")).
withFallback(MultiNodeClusterSpec.clusterConfigWithFailureDetectorPuppet))
}
class NodeLeavingAndExitingAndBeingRemovedMultiJvmNode1 extends NodeLeavingAndExitingAndBeingRemovedSpec
class NodeLeavingAndExitingAndBeingRemovedMultiJvmNode2 extends NodeLeavingAndExitingAndBeingRemovedSpec
class NodeLeavingAndExitingAndBeingRemovedMultiJvmNode3 extends NodeLeavingAndExitingAndBeingRemovedSpec
abstract class NodeLeavingAndExitingAndBeingRemovedSpec
extends MultiNodeSpec(NodeLeavingAndExitingAndBeingRemovedMultiJvmSpec)
with MultiNodeClusterSpec {
import NodeLeavingAndExitingAndBeingRemovedMultiJvmSpec._
"A node that is LEAVING a non-singleton cluster" must {
"eventually set to REMOVED and removed from membership ring and seen table" taggedAs LongRunningTest in {
awaitClusterUp(first, second, third)
within(30.seconds) {
runOn(first) {
cluster.leave(second)
}
enterBarrier("second-left")
runOn(first, third) {
enterBarrier("second-shutdown")
markNodeAsUnavailable(second)
// verify that the 'second' node is no longer part of the 'members'/'unreachable' set
awaitAssert {
clusterView.members.map(_.address) must not contain (address(second))
} &&
awaitAssert {
clusterView.unreachableMembers.map(_.address) must not contain (address(second))
}
} &&
runOn(second) {
// verify that the second node is shut down
awaitCond(cluster.isTerminated) &&
enterBarrier("second-shutdown")
}
} &&
enterBarrier("finished")
}
}
}
@rkuhn
Copy link

rkuhn commented Dec 18, 2013

The problem here is that awaitClusterUp, enterBarrier and address can also fail (i.e. throw). In the last case making it “pure” would break it because it needs to return either a value or a failure and that basically forces the whole test suite to be formulated as a for-comprehension within some monad (or be butt-ugly; consider that this is an extremely simple example with nearly as little structure as possible).

That is what I meant: there will always be throwing assertions (because rewriting in monad style is not going to fly; there simply is no gain justifying the enormous cost), which means that purity is unachievable and therefore not a sensible goal.

I’m not saying that you should evolve ScalaTest based on Akka’s usage of it—we are using at most 1% of its features in any case. I’m merely motivating why we (specifically) are not going to profit from pure assertions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment