| import li.cil.oc.api |
| import li.cil.oc.api.network.Environment |
| import li.cil.oc.api.network.Message |
| import li.cil.oc.api.network.Node |
| import li.cil.oc.api.network.Visibility |
| import li.cil.oc.server.network.Network |
| import li.cil.oc.server.network.{Node => MutableNode} |
| import org.scalatest._ |
| import org.scalatest.mock.MockitoSugar |
| |
| import scala.collection.convert.WrapAsScala._ |
| |
| class NetworkTest extends FlatSpec with MockitoSugar { |
| Network.isServer = () => true |
| api.API.network = Network |
| |
| val host = mock[Environment] |
| |
| "A Node" should "not belong to a network after creation" in { |
| val node = api.Network.newNode(host, Visibility.Network).create() |
| assert(node.network == null) |
| } |
| |
| it should "belong to a network after joining a new network" in { |
| val node = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node) |
| assert(node.network != null) |
| } |
| |
| it should "not belong to a network after being removed from its new network" in { |
| val node = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node) |
| node.remove() |
| assert(node.network == null) |
| } |
| |
| it should "have a neighbor after being connected to another node" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| assert(node1.neighbors.nonEmpty) |
| assert(node2.neighbors.nonEmpty) |
| assert(node1.isNeighborOf(node2)) |
| assert(node2.isNeighborOf(node1)) |
| } |
| |
| it should "be reachable by neighbors when visibility is set to Neighbors" in { |
| val node1 = api.Network.newNode(host, Visibility.Neighbors).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| assert(node1.canBeReachedFrom(node2)) |
| } |
| |
| it should "be in the same network as nodes it is connected to" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| |
| assert(node1.network == node2.network) |
| assert(node2.network == node3.network) |
| assert(node1.network == node3.network) |
| } |
| |
| it should "have a different address than nodes it is connected to" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| |
| assert(node1.address != node2.address) |
| assert(node2.address != node3.address) |
| assert(node1.address != node3.address) |
| } |
| |
| it should "not be reachable by non neighbors when visibility is set to Neighbors" in { |
| val node1 = api.Network.newNode(host, Visibility.Neighbors).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| assert(!node1.canBeReachedFrom(node3)) |
| } |
| |
| it should "be reachable by all nodes when visibility is set to Network" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| assert(node1.canBeReachedFrom(node2)) |
| assert(node1.canBeReachedFrom(node3)) |
| } |
| |
| it should "not be reachable by any node when visibility is set to None" in { |
| val node1 = api.Network.newNode(host, Visibility.None).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| assert(!node1.canBeReachedFrom(node2)) |
| assert(!node1.canBeReachedFrom(node3)) |
| } |
| |
| it should "be in a separate network after a netsplit" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| |
| node2.remove() |
| |
| assert(node1.network != null) |
| assert(node2.network == null) |
| assert(node3.network != null) |
| assert(node1.network != node3.network) |
| } |
| |
| it should "change its address when joining a network containing a node with its address" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node2.asInstanceOf[MutableNode].address = node1.address |
| node1.connect(node2) |
| assert(node1.address != node2.address) |
| } |
| |
| "A Network" should "keep its local layout after being merged with another network" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node2.connect(node3) |
| |
| val node4 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node4) |
| val node5 = api.Network.newNode(host, Visibility.Network).create() |
| node4.connect(node5) |
| val node6 = api.Network.newNode(host, Visibility.Network).create() |
| node5.connect(node6) |
| |
| node2.connect(node5) |
| |
| assert(node1.neighbors.size == 1 && node1.isNeighborOf(node2)) |
| assert(node3.neighbors.size == 1 && node3.isNeighborOf(node2)) |
| |
| assert(node4.neighbors.size == 1 && node4.isNeighborOf(node5)) |
| assert(node6.neighbors.size == 1 && node6.isNeighborOf(node5)) |
| |
| assert(node2.isNeighborOf(node5)) |
| } |
| |
| it should "keep its local layout after being merged with another network containing nodes with duplicate addresses at bridge points" in { |
| val node1 = api.Network.newNode(host, Visibility.Network).create() |
| api.Network.joinNewNetwork(node1) |
| val node2 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node2) |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node1.connect(node3) |
| val node4 = api.Network.newNode(host, Visibility.Network).create() |
| node3.connect(node4) |
| |
| val node5 = api.Network.newNode(host, Visibility.Network).create() |
| node5.asInstanceOf[MutableNode].address = node1.address |
| api.Network.joinNewNetwork(node5) |
| val node6 = api.Network.newNode(host, Visibility.Network).create() |
| node6.asInstanceOf[MutableNode].address = node2.address |
| node5.connect(node6) |
| val node7 = api.Network.newNode(host, Visibility.Network).create() |
| node7.asInstanceOf[MutableNode].address = node3.address |
| node5.connect(node7) |
| val node8 = api.Network.newNode(host, Visibility.Network).create() |
| node8.asInstanceOf[MutableNode].address = node4.address |
| node7.connect(node8) |
| |
| node3.connect(node7) |
| |
| assert(node1.neighbors.size == 2 && node1.isNeighborOf(node2) && node1.isNeighborOf(node3)) |
| assert(node2.neighbors.size == 1 && node2.isNeighborOf(node1)) |
| assert(node3.neighbors.size == 3 && node3.isNeighborOf(node1) && node3.isNeighborOf(node4) && node3.isNeighborOf(node7)) |
| assert(node4.neighbors.size == 1 && node4.isNeighborOf(node3)) |
| |
| assert(node5.neighbors.size == 2 && node5.isNeighborOf(node6) && node5.isNeighborOf(node7)) |
| assert(node6.neighbors.size == 1 && node6.isNeighborOf(node5)) |
| assert(node7.neighbors.size == 3 && node7.isNeighborOf(node5) && node7.isNeighborOf(node8) && node7.isNeighborOf(node3)) |
| assert(node8.neighbors.size == 1 && node8.isNeighborOf(node7)) |
| } |
| |
| it should "not error when nodes disconnect themselves in a remapping operation" in { |
| val host = new Environment { |
| val node1 = api.Network.newNode(this, Visibility.Network).create() |
| val node2 = api.Network.newNode(this, Visibility.Network).create() |
| |
| api.Network.joinNewNetwork(node1) |
| |
| override def node: Node = node1 |
| |
| override def onMessage(message: Message): Unit = {} |
| |
| override def onConnect(node: Node): Unit = { |
| if (node == node1) { |
| node.connect(node2) |
| } |
| } |
| |
| override def onDisconnect(node: Node): Unit = { |
| if (node == node1) { |
| node2.remove() |
| } |
| } |
| } |
| |
| val node3 = api.Network.newNode(host, Visibility.Network).create() |
| node3.asInstanceOf[MutableNode].address = host.node.address |
| api.Network.joinNewNetwork(node3) |
| |
| node3.connect(host.node) |
| |
| assert(host.node1.neighbors.size == 2 && host.node1.isNeighborOf(host.node2) && host.node1.isNeighborOf(node3)) |
| assert(host.node2.neighbors.size == 1 && host.node2.isNeighborOf(host.node1)) |
| assert(node3.neighbors.size == 1 && node3.isNeighborOf(host.node1)) |
| } |
| } |