Implement basic unit tests for RouteHandler

In addition,
    - Refactor Segment Routing unit test mocking

Change-Id: I94cb75a8b12944264faa76301d58ee19f246d584
diff --git a/BUCK b/BUCK
index 073f5fe..b67b34b 100644
--- a/BUCK
+++ b/BUCK
@@ -20,6 +20,7 @@
 TEST_DEPS = [
     '//lib:TEST_ADAPTERS',
     '//incubator/api:onos-incubator-api-tests',
+    '//apps/route-service/api:onos-apps-route-service-api-tests',
 ]
 
 osgi_jar_with_tests (
diff --git a/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java b/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
index 314fef6..3ad2d52 100644
--- a/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
+++ b/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
@@ -18,7 +18,6 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -28,10 +27,8 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
-import org.onosproject.core.DefaultApplicationId;
-import org.onosproject.mastership.MastershipServiceAdapter;
+import org.onosproject.net.config.ConfigApplyDelegate;
 import org.onosproject.net.intf.Interface;
-import org.onosproject.net.intf.InterfaceServiceAdapter;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultHost;
 import org.onosproject.net.DeviceId;
@@ -39,47 +36,32 @@
 import org.onosproject.net.HostId;
 import org.onosproject.net.HostLocation;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.config.ConfigApplyDelegate;
 import org.onosproject.net.config.NetworkConfigRegistryAdapter;
-import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.EthCriterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction;
-import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostServiceAdapter;
 import org.onosproject.net.host.InterfaceIpAddress;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
 import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig;
 
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.junit.Assert.*;
 
-/**
+/**r
  * Unit test for {@link HostHandler}.
  */
 public class HostHandlerTest {
-    private SegmentRoutingManager srManager;
     private HostHandler hostHandler;
 
     // Mocked routing and bridging tables
-    private Map<BridingTableKey, BridingTableValue> bridgingTable = Maps.newConcurrentMap();
-    private Map<RoutingTableKey, RoutingTableValue> routingTable = Maps.newConcurrentMap();
+    private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
+            Maps.newConcurrentMap();
+    private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
+            Maps.newConcurrentMap();
     // Mocked Next Id
-    private Map<Integer, TrafficTreatment> nextTable = Maps.newConcurrentMap();
-    private AtomicInteger atomicNextId = new AtomicInteger();
+    private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
 
     // Host Mac, VLAN
     private static final ProviderId PROVIDER_ID = ProviderId.NONE;
@@ -142,44 +124,99 @@
             new InterfaceIpAddress(INTF_PREFIX1.address(), INTF_PREFIX1);
     private static final InterfaceIpAddress INTF_IP2 =
             new InterfaceIpAddress(INTF_PREFIX2.address(), INTF_PREFIX2);
+    // Interfaces
+    private static final Interface INTF11 =
+            new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF12 =
+            new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF13 =
+            new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
+                    null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
+    private static final Interface INTF21 =
+            new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF22 =
+            new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF31 =
+            new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF39 =
+            new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    null, INTF_VLAN_PAIR, null);
+    private static final Interface INTF41 =
+            new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    INTF_VLAN_UNTAGGED, null, null);
+    private static final Interface INTF49 =
+            new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
+                    null, INTF_VLAN_PAIR, null);
     // Host
     private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
             HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
             false);
 
+    // A set of hosts
+    private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
+    // A set of devices of which we have mastership
+    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
+    // A set of interfaces
+    private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
+            INTF22, INTF31, INTF39, INTF41, INTF49);
+
     @Before
     public void setUp() throws Exception {
-        srManager = new MockSegmentRoutingManager();
+        // Initialize pairDevice and pairLocalPort config
+        ObjectMapper mapper = new ObjectMapper();
+        ConfigApplyDelegate delegate = config -> { };
+
+        SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
+        JsonNode dev3Tree = mapper.createObjectNode();
+        dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
+        dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
+
+        SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
+        JsonNode dev4Tree = mapper.createObjectNode();
+        dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
+        dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
+
+        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
+        mockNetworkConfigRegistry.applyConfig(dev3Config);
+        mockNetworkConfigRegistry.applyConfig(dev4Config);
+
+        // Initialize Segment Routing Manager
+        SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
         srManager.cfgService = new NetworkConfigRegistryAdapter();
         srManager.deviceConfiguration = new DeviceConfiguration(srManager);
-        srManager.flowObjectiveService = new MockFlowObjectiveService();
-        srManager.routingRulePopulator = new MockRoutingRulePopulator();
-        srManager.interfaceService = new MockInterfaceService();
-        srManager.mastershipService = new MockMastershipService();
-        srManager.hostService = new MockHostService();
-        srManager.cfgService = new MockNetworkConfigRegistry();
+        srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
+        srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
+        srManager.interfaceService = new MockInterfaceService(INTERFACES);
+        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
+        srManager.hostService = new MockHostService(HOSTS);
+        srManager.cfgService = mockNetworkConfigRegistry;
 
         hostHandler = new HostHandler(srManager);
 
-        routingTable.clear();
-        bridgingTable.clear();
+        ROUTING_TABLE.clear();
+        BRIDGING_TABLE.clear();
     }
 
     @Test
     public void init() throws Exception {
         hostHandler.init(DEV1);
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         hostHandler.init(DEV2);
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -191,10 +228,10 @@
     @Test()
     public void testHostAddedAtCorrectLocation() throws Exception {
         hostHandler.processHostAddedAtLocation(HOST1, HOST_LOC11);
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -206,40 +243,40 @@
         subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
                 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Untagged host discovered on tagged/native port
         // Expect: add one routing rule and one bridging rule
         subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
                 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
 
         // Tagged host discovered on untagged port
         // Expect: ignore the host. No rule is added.
         subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
                 Sets.newHashSet(HOST_LOC11), Sets.newHashSet(HOST_IP11), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, routingTable.size());
-        assertEquals(2, bridgingTable.size());
+        assertEquals(2, ROUTING_TABLE.size());
+        assertEquals(2, BRIDGING_TABLE.size());
 
         // Tagged host discovered on tagged port with the same IP
         // Expect: update existing route, add one bridging rule
         subject = new DefaultHost(PROVIDER_ID, HOST_ID_TAGGED, HOST_MAC, HOST_VLAN_TAGGED,
                 Sets.newHashSet(HOST_LOC13), Sets.newHashSet(HOST_IP21), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(HOST_VLAN_TAGGED, routingTable.get(new RoutingTableKey(HOST_LOC13.deviceId(),
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertEquals(HOST_VLAN_TAGGED, ROUTING_TABLE.get(new MockRoutingTableKey(HOST_LOC13.deviceId(),
                 HOST_IP21.toIpPrefix())).vlanId);
-        assertEquals(3, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
+        assertEquals(3, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, HOST_VLAN_TAGGED)));
     }
 
     @Test
@@ -249,12 +286,12 @@
         Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
                 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -265,16 +302,16 @@
         // Add a host
         // Expect: add one routing rule and one bridging rule
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Remove the host
         // Expect: add the routing rule and the bridging rule
         hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
-        assertEquals(0, routingTable.size());
-        assertEquals(0, bridgingTable.size());
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
     }
 
     @Test
@@ -284,18 +321,18 @@
         Host subject = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC, HOST_VLAN_UNTAGGED,
                 Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11), false);
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, subject));
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Remove a dual-homed host that has 2 locations
         // Expect: all routing and bridging rules are removed
         hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, subject));
-        assertEquals(0, routingTable.size());
-        assertEquals(0, bridgingTable.size());
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
     }
 
     @Test
@@ -310,32 +347,32 @@
         // Add a host
         // Expect: add one new routing rule, one new bridging rule
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Move the host to CP13, which has different subnet setting
         // Expect: remove routing rule. Change vlan in bridging rule.
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host1));
-        assertEquals(0, routingTable.size());
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
-        assertNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_NATIVE)));
+        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Move the host to CP21, which has same subnet setting
         // Expect: add a new routing rule. Change vlan in bridging rule.
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
-        assertEquals(1, routingTable.size());
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -352,50 +389,50 @@
         // Add a host with IP11, IP12 and LOC11, LOC21
         // Expect: 4 routing rules and 2 bridging rules
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move the host to LOC12, LOC22 and keep the IP
         // Expect: 4 routing rules and 2 bridging rules all at the new location
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move the host to LOC11, LOC21 and change the IP to IP13, IP14 at the same time
         // Expect: 4 routing rules and 2 bridging rules all at the new location
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move the host to LOC11, LOC22 and change the IP to IP12, IP13 at the same time
         // Expect: 4 routing rules and 2 bridging rules all at the new location
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host4, host3));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P2, routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P2, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())).portNumber);
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P2, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P2, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
     }
 
     @Test
@@ -408,28 +445,28 @@
         // Add a host
         // Expect: add one new routing rule, one new bridging rule
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Move the host to an invalid location
         // Expect: Old flow is removed. New flow is not created
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(0, routingTable.size());
-        assertEquals(0, bridgingTable.size());
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
 
         // Move the host to a valid location
         // Expect: add one new routing rule, one new bridging rule
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -444,44 +481,44 @@
         // Add a host
         // Expect: add two new routing rules, two new bridging rules
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(2, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(2, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move first host location to an invalid location
         // Expect: One routing and one bridging flow
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(1, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(1, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(1, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move second host location to an invalid location
         // Expect: No routing or bridging rule
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host3, host2));
-        assertEquals(0, routingTable.size());
-        assertEquals(0, bridgingTable.size());
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
 
         // Move second host location back to a valid location
         // Expect: One routing and one bridging flow
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host3));
-        assertEquals(1, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(1, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(1, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Move first host location back to a valid location
         // Expect: Two routing and two bridging flow
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(2, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(2, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
     }
 
     @Test
@@ -494,38 +531,38 @@
         // Add a host
         // Expect: add four new routing rules, two new bridging rules
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Host becomes single-homed
         // Expect: redirect flows from host location to pair link
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Host becomes dual-homed again
         // Expect: Redirect flows from pair link back to host location
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host1, host2));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
     }
 
     @Test
@@ -538,32 +575,32 @@
         // Add a host
         // Expect: add four new routing rules, two new bridging rules
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Host becomes single-homed
         // Expect: redirect flows from host location to pair link
         hostHandler.processHostMovedEvent(new HostEvent(HostEvent.Type.HOST_MOVED, host2, host1));
-        assertEquals(4, routingTable.size());
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P1, routingTable.get(new RoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
-        assertEquals(P9, routingTable.get(new RoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
-        assertEquals(2, bridgingTable.size());
-        assertEquals(P1, bridgingTable.get(new BridingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
-        assertEquals(P9, bridgingTable.get(new BridingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(4, ROUTING_TABLE.size());
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P1, ROUTING_TABLE.get(new MockRoutingTableKey(DEV3, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP11.toIpPrefix())).portNumber);
+        assertEquals(P9, ROUTING_TABLE.get(new MockRoutingTableKey(DEV4, HOST_IP12.toIpPrefix())).portNumber);
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertEquals(P1, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV3, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
+        assertEquals(P9, BRIDGING_TABLE.get(new MockBridgingTableKey(DEV4, HOST_MAC, INTF_VLAN_UNTAGGED)).portNumber);
 
         // Host loses both locations
         // Expect: Remove last location and all previous redirection flows
         hostHandler.processHostRemovedEvent(new HostEvent(HostEvent.Type.HOST_REMOVED, host2));
-        assertEquals(0, routingTable.size());
-        assertEquals(0, bridgingTable.size());
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
     }
 
     @Test
@@ -578,29 +615,30 @@
         // Add a host
         // Expect: add one new routing rule. Add one new bridging rule.
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(1, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(HOST_LOC11.deviceId(), HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(HOST_LOC11.deviceId(), HOST_MAC,
+                INTF_VLAN_UNTAGGED)));
 
         // Update the host IP to same subnet
         // Expect: update routing rule with new IP. No change to bridging rule.
         hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
-        assertEquals(1, routingTable.size());
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Update the host IP to different subnet
         // Expect: Remove routing rule. No change to bridging rule.
         hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
-        assertEquals(0, routingTable.size());
-        assertEquals(1, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(1, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -615,44 +653,44 @@
         // Add a dual-homed host with two locations and two IPs
         // Expect: add four new routing rules. Add two new bridging rules
         hostHandler.processHostAddedEvent(new HostEvent(HostEvent.Type.HOST_ADDED, host1));
-        assertEquals(4, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(4, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Update both host IPs
         // Expect: update routing rules with new IP. No change to bridging rule.
         hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host3, host1));
-        assertEquals(4, routingTable.size());
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(4, ROUTING_TABLE.size());
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP13.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP14.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP13.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP14.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
 
         // Update one of the host IP to different subnet
         // Expect: update routing rule with new IP. No change to bridging rule.
         hostHandler.processHostUpdatedEvent(new HostEvent(HostEvent.Type.HOST_UPDATED, host2, host3));
-        assertEquals(2, routingTable.size());
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
-        assertNotNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
-        assertNull(routingTable.get(new RoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
-        assertEquals(2, bridgingTable.size());
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
-        assertNotNull(bridgingTable.get(new BridingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertEquals(2, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP21.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV1, HOST_IP12.toIpPrefix())));
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP11.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP21.toIpPrefix())));
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(DEV2, HOST_IP12.toIpPrefix())));
+        assertEquals(2, BRIDGING_TABLE.size());
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV1, HOST_MAC, INTF_VLAN_UNTAGGED)));
+        assertNotNull(BRIDGING_TABLE.get(new MockBridgingTableKey(DEV2, HOST_MAC, INTF_VLAN_UNTAGGED)));
     }
 
     @Test
@@ -660,275 +698,4 @@
         assertNotNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P1, false));
         assertNull(hostHandler.bridgingFwdObjBuilder(DEV2, HOST_MAC, HOST_VLAN_UNTAGGED, P3, false));
     }
-
-    class MockSegmentRoutingManager extends SegmentRoutingManager {
-        MockSegmentRoutingManager() {
-            appId = new DefaultApplicationId(1, SegmentRoutingManager.APP_NAME);
-        }
-
-        @Override
-        public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
-                                          TrafficTreatment treatment,
-                                          TrafficSelector meta,
-                                          boolean createIfMissing) {
-            int nextId = atomicNextId.incrementAndGet();
-            nextTable.put(nextId, treatment);
-            return nextId;
-        }
-    }
-
-    class MockInterfaceService extends InterfaceServiceAdapter {
-        @Override
-        public Set<Interface> getInterfacesByPort(ConnectPoint cp) {
-            Interface intf = null;
-
-            if (CP11.equals(cp)) {
-                intf = new Interface(null, CP11, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP12.equals(cp)) {
-                intf = new Interface(null, CP12, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP13.equals(cp)) {
-                intf = new Interface(null, CP13, Lists.newArrayList(INTF_IP2), MacAddress.NONE, null,
-                        null, INTF_VLAN_TAGGED, INTF_VLAN_NATIVE);
-            } else if (CP21.equals(cp)) {
-                intf = new Interface(null, CP21, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP22.equals(cp)) {
-                intf = new Interface(null, CP22, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP31.equals(cp)) {
-                intf = new Interface(null, CP31, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP39.equals(cp)) {
-                intf = new Interface(null, CP39, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        null, INTF_VLAN_PAIR, null);
-            } else if (CP41.equals(cp)) {
-                intf = new Interface(null, CP41, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        INTF_VLAN_UNTAGGED, null, null);
-            } else if (CP49.equals(cp)) {
-                intf = new Interface(null, CP49, Lists.newArrayList(INTF_IP1), MacAddress.NONE, null,
-                        null, INTF_VLAN_PAIR, null);
-            }
-            return Objects.nonNull(intf) ? Sets.newHashSet(intf) : Sets.newHashSet();
-        }
-    }
-
-    class MockMastershipService extends MastershipServiceAdapter {
-        @Override
-        public boolean isLocalMaster(DeviceId deviceId) {
-            Set<DeviceId> localDevices = ImmutableSet.of(DEV1, DEV2, DEV3, DEV4);
-            return localDevices.contains(deviceId);
-        }
-    }
-
-    class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
-        @Override
-        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
-            if (subject instanceof DeviceId) {
-                DeviceId deviceId = (DeviceId) subject;
-                ObjectMapper mapper = new ObjectMapper();
-                ConfigApplyDelegate delegate = new MockCfgDelegate();
-                JsonNode emptyTree = new ObjectMapper().createObjectNode();
-
-                SegmentRoutingDeviceConfig config = new SegmentRoutingDeviceConfig();
-                config.init(deviceId, "host-handler-test", emptyTree, mapper, delegate);
-                config.setPairDeviceId(subject.equals(DEV3) ? DEV4 : DEV3)
-                        .setPairLocalPort(P9);
-
-                return (C) config;
-            } else {
-                return null;
-            }
-        }
-    }
-
-    class MockCfgDelegate implements ConfigApplyDelegate {
-        @Override
-        public void onApply(@SuppressWarnings("rawtypes") Config config) {
-            config.apply();
-        }
-    }
-
-    class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
-        @Override
-        public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
-            TrafficSelector selector = forwardingObjective.selector();
-            TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
-            MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
-            VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
-
-            boolean popVlan = treatment.allInstructions().stream()
-                    .filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION))
-                    .anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype()
-                            .equals(L2ModificationInstruction.L2SubType.VLAN_POP));
-            PortNumber portNumber = treatment.allInstructions().stream()
-                    .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
-                    .map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
-            if (portNumber == null) {
-                throw new IllegalArgumentException();
-            }
-
-            Objective.Operation op = forwardingObjective.op();
-
-            BridingTableKey btKey = new BridingTableKey(deviceId, macAddress, vlanId);
-            BridingTableValue btValue = new BridingTableValue(popVlan, portNumber);
-
-            if (op.equals(Objective.Operation.ADD)) {
-                bridgingTable.put(btKey, btValue);
-            } else if (op.equals(Objective.Operation.REMOVE)) {
-                bridgingTable.remove(btKey, btValue);
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-    }
-
-    class MockHostService extends HostServiceAdapter {
-        @Override
-        public Set<Host> getHosts() {
-            return Sets.newHashSet(HOST1);
-        }
-    }
-
-    class MockRoutingRulePopulator extends RoutingRulePopulator {
-        MockRoutingRulePopulator() {
-            super(srManager);
-        }
-
-        @Override
-        public void populateRoute(DeviceId deviceId, IpPrefix prefix,
-                                  MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
-            RoutingTableKey rtKey = new RoutingTableKey(deviceId, prefix);
-            RoutingTableValue rtValue = new RoutingTableValue(outPort, hostMac, hostVlanId);
-            routingTable.put(rtKey, rtValue);
-        }
-
-        @Override
-        public void revokeRoute(DeviceId deviceId, IpPrefix prefix,
-                                MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
-            RoutingTableKey rtKey = new RoutingTableKey(deviceId, prefix);
-            RoutingTableValue rtValue = new RoutingTableValue(outPort, hostMac, hostVlanId);
-            routingTable.remove(rtKey, rtValue);
-        }
-    }
-
-    class BridingTableKey {
-        DeviceId deviceId;
-        MacAddress macAddress;
-        VlanId vlanId;
-
-        BridingTableKey(DeviceId deviceId, MacAddress macAddress, VlanId vlanId) {
-            this.deviceId = deviceId;
-            this.macAddress = macAddress;
-            this.vlanId = vlanId;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof BridingTableKey)) {
-                return false;
-            }
-            final BridingTableKey other = (BridingTableKey) obj;
-            return Objects.equals(this.macAddress, other.macAddress) &&
-                    Objects.equals(this.deviceId, other.deviceId) &&
-                    Objects.equals(this.vlanId, other.vlanId);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(macAddress, vlanId);
-        }
-    }
-
-    class BridingTableValue {
-        boolean popVlan;
-        PortNumber portNumber;
-
-        BridingTableValue(boolean popVlan, PortNumber portNumber) {
-            this.popVlan = popVlan;
-            this.portNumber = portNumber;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof BridingTableValue)) {
-                return false;
-            }
-            final BridingTableValue other = (BridingTableValue) obj;
-            return Objects.equals(this.popVlan, other.popVlan) &&
-                    Objects.equals(this.portNumber, other.portNumber);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(popVlan, portNumber);
-        }
-    }
-
-    class RoutingTableKey {
-        DeviceId deviceId;
-        IpPrefix ipPrefix;
-
-        RoutingTableKey(DeviceId deviceId, IpPrefix ipPrefix) {
-            this.deviceId = deviceId;
-            this.ipPrefix = ipPrefix;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof RoutingTableKey)) {
-                return false;
-            }
-            final RoutingTableKey other = (RoutingTableKey) obj;
-            return Objects.equals(this.deviceId, other.deviceId) &&
-                    Objects.equals(this.ipPrefix, other.ipPrefix);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(deviceId, ipPrefix);
-        }
-    }
-
-    class RoutingTableValue {
-        PortNumber portNumber;
-        MacAddress macAddress;
-        VlanId vlanId;
-
-        RoutingTableValue(PortNumber portNumber, MacAddress macAddress, VlanId vlanId) {
-            this.portNumber = portNumber;
-            this.macAddress = macAddress;
-            this.vlanId = vlanId;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof RoutingTableValue)) {
-                return false;
-            }
-            final RoutingTableValue other = (RoutingTableValue) obj;
-            return Objects.equals(this.portNumber, other.portNumber) &&
-                    Objects.equals(this.macAddress, other.macAddress) &&
-                    Objects.equals(this.vlanId, other.vlanId);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(portNumber, macAddress, vlanId);
-        }
-    }
-
 }
diff --git a/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java b/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
new file mode 100644
index 0000000..a90b1cf
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockBridgingTableKey.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Mock Bridging Table Key.
+ */
+class MockBridgingTableKey {
+    DeviceId deviceId;
+    MacAddress macAddress;
+    VlanId vlanId;
+
+    MockBridgingTableKey(DeviceId deviceId, MacAddress macAddress, VlanId vlanId) {
+        this.deviceId = deviceId;
+        this.macAddress = macAddress;
+        this.vlanId = vlanId;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof MockBridgingTableKey)) {
+            return false;
+        }
+        final MockBridgingTableKey other = (MockBridgingTableKey) obj;
+        return Objects.equals(this.macAddress, other.macAddress) &&
+                Objects.equals(this.deviceId, other.deviceId) &&
+                Objects.equals(this.vlanId, other.vlanId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(macAddress, vlanId);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java b/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
new file mode 100644
index 0000000..68b0db8
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockBridgingTableValue.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onosproject.net.PortNumber;
+
+import java.util.Objects;
+
+/**
+ * Mock Bridging Table Value.
+ */
+class MockBridgingTableValue {
+    boolean popVlan;
+    PortNumber portNumber;
+
+    MockBridgingTableValue(boolean popVlan, PortNumber portNumber) {
+        this.popVlan = popVlan;
+        this.portNumber = portNumber;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof MockBridgingTableValue)) {
+            return false;
+        }
+        final MockBridgingTableValue other = (MockBridgingTableValue) obj;
+        return Objects.equals(this.popVlan, other.popVlan) &&
+                Objects.equals(this.portNumber, other.portNumber);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(popVlan, portNumber);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java b/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
new file mode 100644
index 0000000..a69d5e7
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Mock Default Routing Handler.
+ */
+public class MockDefaultRoutingHandler extends DefaultRoutingHandler {
+    private Map<ConnectPoint, Set<IpPrefix>> subnetTable;
+
+    MockDefaultRoutingHandler(SegmentRoutingManager srManager,
+                              Map<ConnectPoint, Set<IpPrefix>> subnetTable) {
+        super(srManager);
+        this.subnetTable = subnetTable;
+    }
+
+    @Override
+    protected void populateSubnet(Set<ConnectPoint> cpts, Set<IpPrefix> subnets) {
+        cpts.forEach(cpt -> subnetTable.put(cpt, subnets));
+    }
+
+    @Override
+    protected boolean revokeSubnet(Set<IpPrefix> subnets) {
+        for (Map.Entry<ConnectPoint, Set<IpPrefix>> entry : subnetTable.entrySet()) {
+            entry.getValue().removeAll(subnets);
+            if (entry.getValue().isEmpty()) {
+                subnetTable.remove(entry.getKey());
+            }
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java b/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
new file mode 100644
index 0000000..138b98a
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockFlowObjectiveService.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
+
+import java.util.Map;
+
+/**
+ * Mock Flow Objective Service.
+ */
+public class MockFlowObjectiveService extends FlowObjectiveServiceAdapter {
+    private Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable;
+    private Map<Integer, TrafficTreatment> nextTable;
+
+    MockFlowObjectiveService(Map<MockBridgingTableKey, MockBridgingTableValue> bridgingTable,
+                             Map<Integer, TrafficTreatment> nextTable) {
+        this.bridgingTable = bridgingTable;
+        this.nextTable = nextTable;
+    }
+
+    @Override
+    public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
+        TrafficSelector selector = forwardingObjective.selector();
+        TrafficTreatment treatment = nextTable.get(forwardingObjective.nextId());
+        MacAddress macAddress = ((EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST)).mac();
+        VlanId vlanId = ((VlanIdCriterion) selector.getCriterion(Criterion.Type.VLAN_VID)).vlanId();
+
+        boolean popVlan = treatment.allInstructions().stream()
+                .filter(instruction -> instruction.type().equals(Instruction.Type.L2MODIFICATION))
+                .anyMatch(instruction -> ((L2ModificationInstruction) instruction).subtype()
+                        .equals(L2ModificationInstruction.L2SubType.VLAN_POP));
+        PortNumber portNumber = treatment.allInstructions().stream()
+                .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
+                .map(instruction -> ((Instructions.OutputInstruction) instruction).port()).findFirst().orElse(null);
+        if (portNumber == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Objective.Operation op = forwardingObjective.op();
+
+        MockBridgingTableKey btKey = new MockBridgingTableKey(deviceId, macAddress, vlanId);
+        MockBridgingTableValue btValue = new MockBridgingTableValue(popVlan, portNumber);
+
+        if (op.equals(Objective.Operation.ADD)) {
+            bridgingTable.put(btKey, btValue);
+        } else if (op.equals(Objective.Operation.REMOVE)) {
+            bridgingTable.remove(btKey, btValue);
+        } else {
+            throw new IllegalArgumentException();
+        }
+    }
+}
diff --git a/src/test/java/org/onosproject/segmentrouting/MockHostService.java b/src/test/java/org/onosproject/segmentrouting/MockHostService.java
new file mode 100644
index 0000000..1bd593c
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockHostService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostServiceAdapter;
+
+import java.util.Set;
+
+/**
+ * Mock Host Service.
+ */
+public class MockHostService extends HostServiceAdapter {
+    private Set<Host> hosts;
+
+    MockHostService(Set<Host> hosts) {
+        this.hosts = ImmutableSet.copyOf(hosts);
+    }
+
+    @Override
+    public Set<Host> getHosts() {
+        return hosts;
+    }
+}
diff --git a/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java b/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
new file mode 100644
index 0000000..2367b57
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockInterfaceService.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.net.intf.InterfaceServiceAdapter;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Mock Interface Service.
+ */
+public class MockInterfaceService extends InterfaceServiceAdapter {
+    private Set<Interface> interfaces;
+
+    MockInterfaceService(Set<Interface> interfaces) {
+        this.interfaces = ImmutableSet.copyOf(interfaces);
+    }
+
+    @Override
+    public Set<Interface> getInterfacesByPort(ConnectPoint cp) {
+        return interfaces.stream().filter(intf -> cp.equals(intf.connectPoint()))
+                .collect(Collectors.toSet());
+    }
+}
diff --git a/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java b/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
new file mode 100644
index 0000000..5494e27
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockMastershipService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.mastership.MastershipServiceAdapter;
+import org.onosproject.net.DeviceId;
+
+import java.util.Set;
+
+/**
+ * Mock Mastership Service.
+ */
+public class MockMastershipService extends MastershipServiceAdapter {
+    // A set of devices of which we have mastership.
+    private Set<DeviceId> localDevices;
+
+    MockMastershipService(Set<DeviceId> localDevices) {
+        this.localDevices = ImmutableSet.copyOf(localDevices);
+    }
+
+    @Override
+    public boolean isLocalMaster(DeviceId deviceId) {
+        return localDevices.contains(deviceId);
+    }
+}
diff --git a/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java b/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
new file mode 100644
index 0000000..09f8da2
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockNetworkConfigRegistry.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.Sets;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+
+import java.util.Set;
+
+/**
+ * Mock Network Config Registry.
+ */
+class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
+    private Set<Config> configs = Sets.newHashSet();
+
+    public void applyConfig(Config config) {
+        configs.add(config);
+    }
+
+    @Override
+    public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+        Config c = configs.stream()
+                .filter(config -> subject.equals(config.subject()))
+                .filter(config -> configClass.equals(config.getClass()))
+                .findFirst().orElse(null);
+        return (C) c;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockRouteService.java b/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
new file mode 100644
index 0000000..14e2166
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockRouteService.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.onosproject.routeservice.RouteInfo;
+import org.onosproject.routeservice.RouteServiceAdapter;
+import org.onosproject.routeservice.RouteTableId;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Mock Route Service.
+ * We assume there is only one routing table named "default".
+ */
+public class MockRouteService extends RouteServiceAdapter {
+    private Set<RouteInfo> routes;
+
+    MockRouteService(Set<RouteInfo> routes) {
+        this.routes = ImmutableSet.copyOf(routes);
+    }
+
+    @Override
+    public Collection<RouteInfo> getRoutes(RouteTableId id) {
+        return routes;
+    }
+
+    @Override
+    public Collection<RouteTableId> getRouteTables() {
+        return Sets.newHashSet(new RouteTableId("default"));
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java b/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
new file mode 100644
index 0000000..4eab7c0
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockRoutingRulePopulator.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import java.util.Map;
+
+/**
+ * Mock Routing Rule Populator.
+ */
+public class MockRoutingRulePopulator extends RoutingRulePopulator {
+    private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
+
+    MockRoutingRulePopulator(SegmentRoutingManager srManager,
+                             Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
+        super(srManager);
+        this.routingTable = routingTable;
+    }
+
+    @Override
+    public void populateRoute(DeviceId deviceId, IpPrefix prefix,
+                              MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
+        MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
+        MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
+        routingTable.put(rtKey, rtValue);
+    }
+
+    @Override
+    public void revokeRoute(DeviceId deviceId, IpPrefix prefix,
+                            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort) {
+        MockRoutingTableKey rtKey = new MockRoutingTableKey(deviceId, prefix);
+        MockRoutingTableValue rtValue = new MockRoutingTableValue(outPort, hostMac, hostVlanId);
+        routingTable.remove(rtKey, rtValue);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java b/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
new file mode 100644
index 0000000..4f09c2a
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockRoutingTableKey.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Mock Routing Table Key.
+ */
+class MockRoutingTableKey {
+    DeviceId deviceId;
+    IpPrefix ipPrefix;
+
+    MockRoutingTableKey(DeviceId deviceId, IpPrefix ipPrefix) {
+        this.deviceId = deviceId;
+        this.ipPrefix = ipPrefix;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof MockRoutingTableKey)) {
+            return false;
+        }
+        final MockRoutingTableKey other = (MockRoutingTableKey) obj;
+        return Objects.equals(this.deviceId, other.deviceId) &&
+                Objects.equals(this.ipPrefix, other.ipPrefix);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(deviceId, ipPrefix);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java b/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
new file mode 100644
index 0000000..5842d2d
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockRoutingTableValue.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.PortNumber;
+
+import java.util.Objects;
+
+/**
+ * Mock Routing Table Value.
+ */
+class MockRoutingTableValue {
+    PortNumber portNumber;
+    MacAddress macAddress;
+    VlanId vlanId;
+
+    MockRoutingTableValue(PortNumber portNumber, MacAddress macAddress, VlanId vlanId) {
+        this.portNumber = portNumber;
+        this.macAddress = macAddress;
+        this.vlanId = vlanId;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof MockRoutingTableValue)) {
+            return false;
+        }
+        final MockRoutingTableValue other = (MockRoutingTableValue) obj;
+        return Objects.equals(this.portNumber, other.portNumber) &&
+                Objects.equals(this.macAddress, other.macAddress) &&
+                Objects.equals(this.vlanId, other.vlanId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(portNumber, macAddress, vlanId);
+    }
+}
+
diff --git a/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java b/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
new file mode 100644
index 0000000..ad098b4
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/MockSegmentRoutingManager.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Mock Segment Routing Manager.
+ */
+public class MockSegmentRoutingManager extends SegmentRoutingManager {
+    private Map<Integer, TrafficTreatment> nextTable;
+    private AtomicInteger atomicNextId = new AtomicInteger();
+
+    MockSegmentRoutingManager(Map<Integer, TrafficTreatment> nextTable) {
+        appId = new DefaultApplicationId(1, SegmentRoutingManager.APP_NAME);
+        this.nextTable = nextTable;
+    }
+
+    @Override
+    public int getPortNextObjectiveId(DeviceId deviceId, PortNumber portNum,
+                                      TrafficTreatment treatment,
+                                      TrafficSelector meta,
+                                      boolean createIfMissing) {
+        int nextId = atomicNextId.incrementAndGet();
+        nextTable.put(nextId, treatment);
+        return nextId;
+    }
+}
diff --git a/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java b/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
new file mode 100644
index 0000000..fc8c294
--- /dev/null
+++ b/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.routeservice.ResolvedRoute;
+import org.onosproject.routeservice.Route;
+import org.onosproject.routeservice.RouteEvent;
+import org.onosproject.routeservice.RouteInfo;
+import org.onosproject.segmentrouting.config.DeviceConfiguration;
+
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+/**
+ * Unit test for {@link RouteHandler}.
+ */
+public class RouteHandlerTest {
+    private RouteHandler routeHandler;
+
+    // Mocked routing and bridging tables
+    private static final Map<MockBridgingTableKey, MockBridgingTableValue> BRIDGING_TABLE =
+            Maps.newConcurrentMap();
+    private static final Map<MockRoutingTableKey, MockRoutingTableValue> ROUTING_TABLE =
+            Maps.newConcurrentMap();
+    private static final Map<ConnectPoint, Set<IpPrefix>> SUBNET_TABLE = Maps.newConcurrentMap();
+    // Mocked Next Id
+    private static final Map<Integer, TrafficTreatment> NEXT_TABLE = Maps.newConcurrentMap();
+
+    private static final IpPrefix P1 = IpPrefix.valueOf("10.0.0.0/24");
+    private static final IpAddress N1 = IpAddress.valueOf("10.0.1.254");
+    private static final MacAddress M1 = MacAddress.valueOf("00:00:00:00:00:01");
+    private static final VlanId V1 = VlanId.vlanId((short) 1);
+    private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
+    private static final Route R1 = new Route(Route.Source.STATIC, P1, N1);
+    private static final ResolvedRoute RR1 = new ResolvedRoute(R1, M1, V1, CP1);
+
+    private static final IpAddress N2 = IpAddress.valueOf("10.0.2.254");
+    private static final MacAddress M2 = MacAddress.valueOf("00:00:00:00:00:02");
+    private static final VlanId V2 = VlanId.vlanId((short) 2);
+    private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
+    private static final Route R2 = new Route(Route.Source.STATIC, P1, N2);
+    private static final ResolvedRoute RR2 = new ResolvedRoute(R2, M2, V2, CP2);
+
+    private static final RouteInfo RI1 = new RouteInfo(P1, RR1, Sets.newHashSet(RR1));
+
+    // A set of hosts
+    private static final Set<Host> HOSTS = Sets.newHashSet();
+    // A set of devices of which we have mastership
+    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet();
+    // A set of interfaces
+    private static final Set<Interface> INTERFACES = Sets.newHashSet();
+    // A set of routes
+    private static final Set<RouteInfo> ROUTE_INFOS = Sets.newHashSet(RI1);
+
+    @Before
+    public void setUp() throws Exception {
+// TODO Initialize pairDevice and pairLocalPort config
+//        ObjectMapper mapper = new ObjectMapper();
+//        ConfigApplyDelegate delegate = config -> {};
+//
+//        SegmentRoutingDeviceConfig dev3Config = new SegmentRoutingDeviceConfig();
+//        JsonNode dev3Tree = mapper.createObjectNode();
+//        dev3Config.init(DEV3, "host-handler-test", dev3Tree, mapper, delegate);
+//        dev3Config.setPairDeviceId(DEV4).setPairLocalPort(P9);
+//
+//        SegmentRoutingDeviceConfig dev4Config = new SegmentRoutingDeviceConfig();
+//        JsonNode dev4Tree = mapper.createObjectNode();
+//        dev4Config.init(DEV4, "host-handler-test", dev4Tree, mapper, delegate);
+//        dev4Config.setPairDeviceId(DEV3).setPairLocalPort(P9);
+
+        MockNetworkConfigRegistry mockNetworkConfigRegistry = new MockNetworkConfigRegistry();
+//        mockNetworkConfigRegistry.applyConfig(dev3Config);
+//        mockNetworkConfigRegistry.applyConfig(dev4Config);
+
+        // Initialize Segment Routing Manager
+        SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE);
+        srManager.cfgService = new NetworkConfigRegistryAdapter();
+        srManager.deviceConfiguration = new DeviceConfiguration(srManager);
+        srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
+        srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
+        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE);
+        srManager.interfaceService = new MockInterfaceService(INTERFACES);
+        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
+        srManager.hostService = new MockHostService(HOSTS);
+        srManager.cfgService = mockNetworkConfigRegistry;
+        srManager.routeService = new MockRouteService(ROUTE_INFOS);
+
+        routeHandler = new RouteHandler(srManager);
+
+        ROUTING_TABLE.clear();
+        BRIDGING_TABLE.clear();
+        SUBNET_TABLE.clear();
+    }
+
+    @Test
+    public void init() throws Exception {
+        routeHandler.init(CP1.deviceId());
+
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1)));
+        assertEquals(1, SUBNET_TABLE.size());
+        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
+    }
+
+    @Test
+    public void processRouteAdded() throws Exception {
+        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_ADDED, RR1);
+        routeHandler.processRouteAdded(re);
+
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP1.deviceId(), P1)));
+        assertEquals(1, SUBNET_TABLE.size());
+        assertTrue(SUBNET_TABLE.get(CP1).contains(P1));
+    }
+
+    @Test
+    public void processRouteUpdated() throws Exception {
+        processRouteAdded();
+
+        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, RR2, RR1);
+        routeHandler.processRouteUpdated(re);
+
+        assertEquals(1, ROUTING_TABLE.size());
+        assertNotNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1)));
+        assertEquals(1, SUBNET_TABLE.size());
+        assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
+    }
+
+    @Test
+    public void processRouteRemoved() throws Exception {
+        processRouteAdded();
+
+        RouteEvent re = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, RR1);
+        routeHandler.processRouteRemoved(re);
+
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, SUBNET_TABLE.size());
+    }
+
+}
\ No newline at end of file