/*
 * Copyright (C) 2009-2018 Lightbend Inc. <https://www.lightbend.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 NodeDowningAndBeingRemovedMultiJvmSpec 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 = off").withFallback(MultiNodeClusterSpec.clusterConfig)))
}

class NodeDowningAndBeingRemovedMultiJvmNode1 extends NodeDowningAndBeingRemovedSpec
class NodeDowningAndBeingRemovedMultiJvmNode2 extends NodeDowningAndBeingRemovedSpec
class NodeDowningAndBeingRemovedMultiJvmNode3 extends NodeDowningAndBeingRemovedSpec

abstract class NodeDowningAndBeingRemovedSpec
  extends MultiNodeSpec(NodeDowningAndBeingRemovedMultiJvmSpec)
  with MultiNodeClusterSpec {

  import NodeDowningAndBeingRemovedMultiJvmSpec._

  "A node that is downed" must {

    "eventually be removed from membership" taggedAs LongRunningTest in {

      awaitClusterUp(first, second, third)

      within(30.seconds) {
        runOn(first) {
          cluster.down(second)
          cluster.down(third)
        }
        enterBarrier("second-and-third-down")

        runOn(second, third) {
          // verify that the node is shut down
          awaitCond(cluster.isTerminated)
        }
        enterBarrier("second-and-third-shutdown")

        runOn(first) {
          // verify that the nodes are no longer part of the 'members' set
          awaitAssert {
            clusterView.members.map(_.address) should not contain (address(second))
            clusterView.members.map(_.address) should not contain (address(third))
          }
        }
      }

      enterBarrier("finished")
    }
  }
}
