Test + Bugfix for ImmutableTopologySnapshot.

Change-Id: I7760657eec763e08e8d7c946fc5f3aadeb160707
diff --git a/src/main/java/net/onrc/onos/core/topology/ImmutableTopologySnapshot.java b/src/main/java/net/onrc/onos/core/topology/ImmutableTopologySnapshot.java
index 6fd8d03..3166a6a 100644
--- a/src/main/java/net/onrc/onos/core/topology/ImmutableTopologySnapshot.java
+++ b/src/main/java/net/onrc/onos/core/topology/ImmutableTopologySnapshot.java
@@ -2,6 +2,7 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -252,6 +253,7 @@
             Map<String, LinkEvent> linksOnPort = linkMap.get(port);
             if (linksOnPort == null) {
                 linksOnPort = new HashMap<String, LinkEvent>();
+                linkMap.put(port, linksOnPort);
             }
             linksOnPort.put(link.getType(), link);
         }
@@ -364,6 +366,7 @@
                 // SortedSet, customized so that MASTER MastershipEvent appear
                 // earlier during iteration.
                 candidates = new TreeSet<>(new MastershipEvent.MasterFirstComparator());
+                current.mastership.put(master.getDpid(), candidates);
             }
 
             // always replace
@@ -592,7 +595,11 @@
         if (links == null) {
             return null;
         }
-        return links.get(type);
+        LinkEvent link = links.get(type);
+        if (link.getDst().equals(linkId.getDst())) {
+            return link;
+        }
+        return null;
     }
 
     @Override
@@ -622,8 +629,15 @@
             return Collections.emptyList();
         }
 
+        List<LinkEvent> linkEvents = new ArrayList<>();
+        for (LinkEvent e : links.values()) {
+            if (e.getDst().equals(linkId.getDst())) {
+                linkEvents.add(e);
+            }
+        }
+
         // unless invariant is broken, this should contain at most 1 element.
-        return Collections.unmodifiableCollection(links.values());
+        return linkEvents;
     }
 
     @Override
@@ -656,6 +670,7 @@
      * @param dpid switch dpid
      * @return master instance ID or null if there is no master
      */
+    @Override
     public OnosInstanceId getSwitchMaster(Dpid dpid) {
         final SortedSet<MastershipEvent> candidates = mastership.get(dpid);
         if (candidates == null) {
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
index 1dc14c6..cc1cc9f 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
@@ -445,7 +445,11 @@
         if (links == null) {
             return null;
         }
-        return links.get(type);
+        LinkEvent link = links.get(type);
+        if (link.getDst().equals(linkId.getDst())) {
+            return link;
+        }
+        return null;
     }
 
     @Override
@@ -473,8 +477,15 @@
             return Collections.emptyList();
         }
 
+        List<LinkEvent> linkEvents = new ArrayList<>();
+        for (LinkEvent e : links.values()) {
+            if (e.getDst().equals(linkId.getDst())) {
+                linkEvents.add(e);
+            }
+        }
+
         // unless invariant is broken, this should contain at most 1 element.
-        return Collections.unmodifiableCollection(links.values());
+        return linkEvents;
     }
 
     @Override
diff --git a/src/test/java/net/onrc/onos/core/topology/ImmutableTopologySnapshotTest.java b/src/test/java/net/onrc/onos/core/topology/ImmutableTopologySnapshotTest.java
new file mode 100644
index 0000000..5b5990a
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/topology/ImmutableTopologySnapshotTest.java
@@ -0,0 +1,635 @@
+package net.onrc.onos.core.topology;
+
+import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.*;
+
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.topology.ImmutableTopologySnapshot.Builder;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.LinkTuple;
+import net.onrc.onos.core.util.OnosInstanceId;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+import org.apache.commons.math3.random.RandomDataGenerator;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.collect.Iterators;
+
+/**
+ * Tests for {@link ImmutableTopologySnapshot}.
+ */
+public class ImmutableTopologySnapshotTest {
+
+    // randomly generated topology
+    private static ImmutableTopologySnapshot ss;
+
+    // randomly generated topology size
+    private static final int NUM_HOSTS = 12;
+    private static final int NUM_LINKS = 11;
+    private static final int NUM_PORTS = 48;
+    private static final int NUM_SWITCH = 10;
+
+    // a link that is assured to be in topology
+    private static final LinkTuple LINK_IN_TOPOLOGY = new LinkTuple(
+            new Dpid(1), PortNumber.uint32(1),
+            new Dpid(2), PortNumber.uint32(1));
+
+    // invalid port number, etc. which should not appear in topology
+    private static final int PORT_NUM_NA = NUM_PORTS + 2;
+    private static final long MAC_NA = NUM_HOSTS + 1L;
+
+    // master instance of all the switches in ramdomly generated topology
+    private static final OnosInstanceId INSTANCE_ID
+                            = new OnosInstanceId("TheInstance");
+
+    /**
+     * Generate topology to test.
+     */
+    @BeforeClass
+    public static void setUpBeforeClass() {
+        ss = createTopology(NUM_SWITCH, NUM_PORTS, NUM_LINKS, NUM_HOSTS);
+    }
+
+    /**
+     * InitialBuilder should contains empty topology.
+     */
+    @Test
+    public void testInitialBuilder() {
+        final Builder builder = ImmutableTopologySnapshot.initialBuilder();
+        assertTrue("Topology should be empty",
+                builder.getCurrentInternal().getAllSwitchEvents().isEmpty());
+        assertTrue("Topology should be empty",
+                builder.build().getAllSwitchEvents().isEmpty());
+    }
+
+    /**
+     * Builder should create a copy of the parent topology.
+     */
+    @Test
+    public void testBuilder() {
+        final Builder builder = ss.builder();
+        assertEquals("Number of switch", NUM_SWITCH,
+                builder.getCurrentInternal().getAllSwitchEvents().size());
+        assertEquals("Number of ports", NUM_PORTS * NUM_SWITCH,
+                builder.getCurrentInternal().getAllPortEvents().size());
+        assertEquals("Number of links", NUM_LINKS,
+                builder.getCurrentInternal().getAllLinkEvents().size());
+        assertEquals("Number of hosts", NUM_HOSTS,
+                builder.getCurrentInternal().getAllHostEvents().size());
+
+        final ImmutableTopologySnapshot clone = builder.build();
+        assertEquals("Number of switch", NUM_SWITCH,
+                clone.getAllSwitchEvents().size());
+        assertEquals("Number of ports", NUM_PORTS * NUM_SWITCH,
+                clone.getAllPortEvents().size());
+        assertEquals("Number of links", NUM_LINKS,
+                clone.getAllLinkEvents().size());
+        assertEquals("Number of hosts", NUM_HOSTS,
+                clone.getAllHostEvents().size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getSwitchEvent(Dpid)}.
+     */
+    @Test
+    public void testGetSwitchEvent() {
+        final Dpid dpid1 = new Dpid(1);
+        assertNotNull("Switch 1 should exist",
+                ss.getSwitchEvent(dpid1));
+
+        final Dpid dpidNa = new Dpid(NUM_SWITCH + 1);
+        assertNull("Switch NUM_SWITCH + 1 should not exist",
+                ss.getSwitchEvent(dpidNa));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getAllSwitchEvents()}.
+     */
+    @Test
+    public void testGetAllSwitchEvents() {
+        assertEquals("Number of switch", NUM_SWITCH,
+                ss.getAllSwitchEvents().size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPortEvent(SwitchPort)}.
+     */
+    @Test
+    public void testGetPortEventSwitchPort() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Switch 1 Port 1 should exist",
+                ss.getPortEvent(new SwitchPort(dpid1, port1)));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Switch 1 Port PORT_NUM_NA should not exist",
+                ss.getPortEvent(new SwitchPort(dpid1, portNa)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPortEvent(Dpid, PortNumber)}.
+     */
+    @Test
+    public void testGetPortEventDpidPortNumber() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Switch 1 Port 1 should exist",
+                ss.getPortEvent(dpid1, port1));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Switch 1 Port PORT_NUM_NA should not exist",
+                ss.getPortEvent(dpid1, portNa));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPortEvents(Dpid)}.
+     */
+    @Test
+    public void testGetPortEvents() {
+        final Dpid dpid1 = new Dpid(1);
+        assertEquals("Number of ports", NUM_PORTS,
+                ss.getPortEvents(dpid1).size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getAllPortEvents()}.
+     */
+    @Test
+    public void testGetAllPortEvents() {
+        assertEquals("Number of ports", NUM_PORTS * NUM_SWITCH,
+                ss.getAllPortEvents().size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinkEvent(LinkTuple)}.
+     */
+    @Test
+    public void testGetLinkEventLinkTuple() {
+        assertNotNull("Link (1:1 -> 2:1) should exist",
+                ss.getLinkEvent(LINK_IN_TOPOLOGY));
+
+        final Dpid dpid1 = new Dpid(1);
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Link (1:1 -> 2:PORT_NUM_NA) should not exist",
+                ss.getLinkEvent(new LinkTuple(dpid1, port1, dpid2, portNa)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinkEvent(LinkTuple, String)}.
+     */
+    @Test
+    public void testGetLinkEventLinkTupleString() {
+        assertNotNull("Link (1:1 -> 2:1) should exist",
+                ss.getLinkEvent(LINK_IN_TOPOLOGY,
+                        TopologyElement.TYPE_PACKET_LAYER));
+
+        final Dpid dpid1 = new Dpid(1);
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Link (1:1 -> 2:PORT_NUM_NA) should not exist",
+                ss.getLinkEvent(new LinkTuple(dpid1, port1, dpid2, portNa),
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinkEventsFrom(SwitchPort)}.
+     */
+    @Test
+    public void testGetLinkEventsFrom() {
+        assertThat("Port 1:1 should at least have 1 outgoing link",
+                ss.getLinkEventsFrom(LINK_IN_TOPOLOGY.getSrc()).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinkEventsTo(SwitchPort)}.
+     */
+    @Test
+    public void testGetLinkEventsTo() {
+        assertThat("Port 2:1 should at least have 1 incoming link",
+                ss.getLinkEventsTo(LINK_IN_TOPOLOGY.getDst()).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinkEvents(LinkTuple)}.
+     */
+    @Test
+    public void testGetLinkEvents() {
+        assertFalse("Link (1:1 -> 2:1) should exist",
+                ss.getLinkEvents(LINK_IN_TOPOLOGY).isEmpty());
+
+        final Dpid dpid1 = new Dpid(1);
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertTrue("Link (1:1 -> 2:PORT_NUM_NA) should not exist",
+                ss.getLinkEvents(new LinkTuple(dpid1, port1, dpid2, portNa)).isEmpty());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getAllLinkEvents()}.
+     */
+    @Test
+    public void testGetAllLinkEvents() {
+        assertEquals("Number of links", NUM_LINKS,
+                ss.getAllLinkEvents().size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getHostEvent(MACAddress)}.
+     */
+    @Test
+    public void testGetHostEvent() {
+        assertNotNull("Host 0:..:0 should exist",
+                ss.getHostEvent(MACAddress.valueOf(0L)));
+
+        assertNull("Host MAC_NA should exist",
+                ss.getHostEvent(MACAddress.valueOf(MAC_NA)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getHostEvents(SwitchPort)}.
+     */
+    @Test
+    public void testGetHostEvents() {
+        final HostEvent host = ss.getHostEvent(MACAddress.valueOf(0L));
+        final SwitchPort attachment = host.getAttachmentPoints().get(0);
+
+        assertThat("should at least have 1 host attached",
+                ss.getHostEvents(attachment).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getAllHostEvents()}.
+     */
+    @Test
+    public void testGetAllHostEvents() {
+        assertEquals("Number of hosts", NUM_HOSTS,
+                ss.getAllHostEvents().size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getSwitchMaster(Dpid)}.
+     */
+    @Test
+    public void testGetSwitchMaster() {
+        assertEquals("Master is stored", INSTANCE_ID, ss.getSwitchMaster(new Dpid(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getSwitch(Dpid)}.
+     */
+    @Test
+    public void testGetSwitch() {
+        final Dpid dpid1 = new Dpid(1);
+        assertNotNull("Switch 1 should exist",
+                ss.getSwitch(dpid1));
+
+        final Dpid dpidNa = new Dpid(NUM_SWITCH + 1);
+        assertNull("Switch NUM_SWITCH + 1 should not exist",
+                ss.getSwitch(dpidNa));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getSwitches()}.
+     */
+    @Test
+    public void testGetSwitches() {
+        assertEquals("Number of switch", NUM_SWITCH,
+                Iterators.size(ss.getSwitches().iterator()));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPort(Dpid, PortNumber)}.
+     */
+    @Test
+    public void testGetPortDpidPortNumber() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Switch 1 Port 1 should exist",
+                ss.getPort(dpid1, port1));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Switch 1 Port PORT_NUM_NA should not exist",
+                ss.getPort(dpid1, portNa));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPort(SwitchPort)}.
+     */
+    @Test
+    public void testGetPortSwitchPort() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Switch 1 Port 1 should exist",
+                ss.getPort(new SwitchPort(dpid1, port1)));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Switch 1 Port PORT_NUM_NA should not exist",
+                ss.getPort(new SwitchPort(dpid1, portNa)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getPorts(Dpid)}.
+     */
+    @Test
+    public void testGetPorts() {
+        final Dpid dpid1 = new Dpid(1);
+        assertEquals("Number of ports", NUM_PORTS,
+                ss.getPorts(dpid1).size());
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getOutgoingLink(Dpid, PortNumber)}.
+     */
+    @Test
+    public void testGetOutgoingLinkDpidPortNumber() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 1:1 should at least have 1 outgoing link",
+                ss.getOutgoingLink(dpid1, port1));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getOutgoingLink(SwitchPort)}.
+     */
+    @Test
+    public void testGetOutgoingLinkSwitchPort() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 1:1 should at least have 1 outgoing link",
+                ss.getOutgoingLink(new SwitchPort(dpid1, port1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getOutgoingLink(Dpid, PortNumber, String)}.
+     */
+    @Test
+    public void testGetOutgoingLinkDpidPortNumberString() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 1:1 should at least have 1 outgoing link",
+                ss.getOutgoingLink(dpid1, port1,
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getOutgoingLink(SwitchPort, String)}.
+     */
+    @Test
+    public void testGetOutgoingLinkSwitchPortString() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 1:1 should at least have 1 outgoing link",
+                ss.getOutgoingLink(new SwitchPort(dpid1, port1),
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getOutgoingLinks(SwitchPort)}.
+     */
+    @Test
+    public void testGetOutgoingLinks() {
+        final Dpid dpid1 = new Dpid(1);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertThat("Port 1:1 should at least have 1 outgoing link",
+                ss.getOutgoingLinks(new SwitchPort(dpid1, port1)).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getIncomingLink(Dpid, PortNumber)}.
+     */
+    @Test
+    public void testGetIncomingLinkDpidPortNumber() {
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 2:1 should at least have 1 outgoing link",
+                ss.getIncomingLink(dpid2, port1));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getIncomingLink(SwitchPort)}.
+     */
+    @Test
+    public void testGetIncomingLinkSwitchPort() {
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 2:1 should at least have 1 outgoing link",
+                ss.getIncomingLink(new SwitchPort(dpid2, port1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getIncomingLink(Dpid, PortNumber, String)}.
+     */
+    @Test
+    public void testGetIncomingLinkDpidPortNumberString() {
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 2:1 should at least have 1 outgoing link",
+                ss.getIncomingLink(dpid2, port1,
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getIncomingLink(SwitchPort, String)}.
+     */
+    @Test
+    public void testGetIncomingLinkSwitchPortString() {
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertNotNull("Port 2:1 should at least have 1 outgoing link",
+                ss.getIncomingLink(new SwitchPort(dpid2, port1),
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getIncomingLinks(SwitchPort)}.
+     */
+    @Test
+    public void testGetIncomingLinks() {
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+
+        assertThat("Port 2:1 should at least have 1 outgoing link",
+                ss.getIncomingLinks(new SwitchPort(dpid2, port1)).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLink(Dpid, PortNumber, Dpid, PortNumber)}.
+     */
+    @Test
+    public void testGetLinkDpidPortNumberDpidPortNumber() {
+        final Dpid dpid1 = new Dpid(1);
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Link (1:1 -> 2:1) should exist",
+                ss.getLink(dpid1, port1, dpid2, port1));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Link (1:1 -> 2:PORT_NUM_NA) should not exist",
+                ss.getLink(dpid1, port1, dpid2, portNa));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLink(Dpid, PortNumber, Dpid, PortNumber, String)}.
+     */
+    @Test
+    public void testGetLinkDpidPortNumberDpidPortNumberString() {
+        final Dpid dpid1 = new Dpid(1);
+        final Dpid dpid2 = new Dpid(2);
+        final PortNumber port1 = PortNumber.uint32(1);
+        assertNotNull("Link (1:1 -> 2:1) should exist",
+                ss.getLink(dpid1, port1, dpid2, port1,
+                        TopologyElement.TYPE_PACKET_LAYER));
+
+        final PortNumber portNa = PortNumber.uint32(PORT_NUM_NA);
+        assertNull("Link (1:1 -> 2:PORT_NUM_NA) should not exist",
+                ss.getLink(dpid1, port1, dpid2, portNa,
+                        TopologyElement.TYPE_PACKET_LAYER));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getLinks()}.
+     */
+    @Test
+    public void testGetLinks() {
+        assertEquals("Number of links", NUM_LINKS,
+                Iterators.size(ss.getLinks().iterator()));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getHostByMac(MACAddress)}.
+     */
+    @Test
+    public void testGetHostByMac() {
+        assertNotNull("Host 0:..:0 should exist",
+                ss.getHostByMac(MACAddress.valueOf(0L)));
+
+        assertNull("Host MAC_NA should exist",
+                ss.getHostByMac(MACAddress.valueOf(MAC_NA)));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getHosts()}.
+     */
+    @Test
+    public void testGetHosts() {
+        assertEquals("Number of host", NUM_HOSTS,
+                Iterators.size(ss.getHosts().iterator()));
+    }
+
+    /**
+     * Test for {@link ImmutableTopologySnapshot#getHosts(SwitchPort)}.
+     */
+    @Test
+    public void testGetHostsSwitchPort() {
+        final HostEvent host = ss.getHostEvent(MACAddress.valueOf(0L));
+        final SwitchPort attachment = host.getAttachmentPoints().get(0);
+
+        assertThat("should at least have 1 host attached",
+                ss.getHosts(attachment).size(),
+                is(greaterThanOrEqualTo(1)));
+    }
+
+    /**
+     * Create random topology with specified number of elements.
+     *
+     * @param switches number of switches
+     * @param ports number of ports
+     * @param links number of links
+     * @param hosts number of hosts
+     * @return created topology
+     */
+    private static ImmutableTopologySnapshot createTopology(
+                                                    final int switches,
+                                                    final int ports,
+                                                    final int links,
+                                                    final int hosts) {
+
+        Builder builder = ImmutableTopologySnapshot.initialBuilder();
+        for (int i = 0; i < switches; ++i) {
+            final Dpid dpid = new Dpid(i + 1);
+            builder.putSwitchMastershipEvent(new MastershipEvent(dpid,
+                                INSTANCE_ID,
+                                Role.MASTER));
+            builder.putSwitch(new SwitchEvent(dpid));
+            for (int j = 0; j < ports; ++j) {
+                builder.putPort(new PortEvent(dpid, PortNumber.uint32(j + 1)));
+            }
+        }
+
+
+        final RandomDataGenerator rand = new RandomDataGenerator();
+        int l = 0;
+        // Always add Link (1:1 -> 2:1)
+        builder.putLink(new LinkEvent(LINK_IN_TOPOLOGY));
+        ++l;
+
+        while (l < links) {
+            int sw1 = rand.nextInt(1, switches);
+            int port1 = rand.nextInt(1, ports);
+            int sw2 = rand.nextInt(1, switches);
+            int port2 = rand.nextInt(1, ports);
+            if (sw1 == sw2 && port1 == port2) {
+                continue;
+            }
+            LinkTuple linkId = new LinkTuple(
+                    new Dpid(sw1), PortNumber.uint32(port1),
+                    new Dpid(sw2), PortNumber.uint32(port2));
+
+            final BaseInternalTopology current = builder.getCurrentInternal();
+            if (!current.getLinkEventsFrom(linkId.getSrc()).isEmpty() ||
+                !current.getLinkEventsTo(linkId.getSrc()).isEmpty()) {
+                // src port already has a link
+                continue;
+            }
+            if (!current.getLinkEventsFrom(linkId.getDst()).isEmpty() ||
+                !current.getLinkEventsTo(linkId.getDst()).isEmpty()) {
+                // dst port already has a link
+                continue;
+            }
+
+            // add only if both port doesn't have any link
+            builder.putLink(new LinkEvent(linkId));
+            ++l;
+        }
+
+        // Add host with mac 0 -> hosts
+        int h = 0;
+        while (h < hosts) {
+            HostEvent host = new HostEvent(MACAddress.valueOf(h));
+            SwitchPort swp = new SwitchPort(
+                                new Dpid(rand.nextInt(1, switches)),
+                                PortNumber.uint32(rand.nextInt(1, ports)));
+
+            if (builder.getCurrent().getIncomingLinks(swp).isEmpty() &&
+                builder.getCurrent().getOutgoingLinks(swp).isEmpty()) {
+                // add only if link doesn't exist
+                host.addAttachmentPoint(swp);
+                builder.putHost(host);
+                ++h;
+            }
+        }
+
+        return builder.build();
+    }
+}