diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
index e4808f7..d13aa2a 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
@@ -16,9 +16,8 @@
 package org.onosproject.sdnip;
 
 import com.google.common.collect.Sets;
-import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
-import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
-import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
+import org.easymock.EasyMock;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.junit.TestUtils;
@@ -32,18 +31,12 @@
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
 import org.onosproject.net.host.InterfaceIpAddress;
 import org.onosproject.net.intent.AbstractIntentTest;
 import org.onosproject.net.intent.Intent;
@@ -51,10 +44,18 @@
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.IntentState;
 import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.net.provider.ProviderId;
+import org.onosproject.routingapi.FibEntry;
+import org.onosproject.routingapi.FibUpdate;
+import org.onosproject.routingapi.RouteEntry;
+import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
+import org.onosproject.sdnip.config.BgpPeer;
 import org.onosproject.sdnip.config.Interface;
+import org.onosproject.sdnip.config.SdnIpConfigurationService;
 
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -71,9 +72,9 @@
  */
 public class IntentSyncTest extends AbstractIntentTest {
 
+    private SdnIpConfigurationService sdnIpConfigService;
     private InterfaceService interfaceService;
     private IntentService intentService;
-    private HostService hostService;
 
     private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
             DeviceId.deviceId("of:0000000000000001"),
@@ -87,8 +88,11 @@
             DeviceId.deviceId("of:0000000000000003"),
             PortNumber.portNumber(1));
 
+    private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
+            DeviceId.deviceId("of:0000000000000004"),
+            PortNumber.portNumber(1));
+
     private IntentSynchronizer intentSynchronizer;
-    private Router router;
 
     private static final ApplicationId APPID = new ApplicationId() {
         @Override
@@ -106,12 +110,42 @@
     public void setUp() throws Exception {
         super.setUp();
         setUpInterfaceService();
-        setUpHostService();
+
+        setUpBgpPeers();
         intentService = createMock(IntentService.class);
 
         intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    null, interfaceService);
-        router = new Router(intentSynchronizer, hostService);
+                                                    sdnIpConfigService, interfaceService);
+    }
+
+    /**
+     * Sets up BGP peers in external networks.
+     */
+    private void setUpBgpPeers() {
+
+        Map<IpAddress, BgpPeer> peers = new HashMap<>();
+
+        String peerSw1Eth1 = "192.168.10.1";
+        peers.put(IpAddress.valueOf(peerSw1Eth1),
+                  new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
+
+        // Two BGP peers are connected to switch 2 port 1.
+        String peer1Sw2Eth1 = "192.168.20.1";
+        peers.put(IpAddress.valueOf(peer1Sw2Eth1),
+                  new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
+
+        String peer2Sw2Eth1 = "192.168.20.2";
+        peers.put(IpAddress.valueOf(peer2Sw2Eth1),
+                  new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
+
+        String peer1Sw4Eth1 = "192.168.40.1";
+        peers.put(IpAddress.valueOf(peer1Sw4Eth1),
+                  new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
+
+        sdnIpConfigService = createMock(SdnIpConfigurationService.class);
+        expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
+        EasyMock.replay(sdnIpConfigService);
+
     }
 
     /**
@@ -133,80 +167,279 @@
         interfaces.add(sw1Eth1);
 
         Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
-        interfaceIpAddresses2.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.20.101"),
-                IpPrefix.valueOf("192.168.20.0/24")));
+        interfaceIpAddresses2.add(
+                new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
+                                       IpPrefix.valueOf("192.168.20.0/24")));
         Interface sw2Eth1 = new Interface(SW2_ETH1,
                 interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
                 VlanId.NONE);
         interfaces.add(sw2Eth1);
 
         Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
-        interfaceIpAddresses3.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.30.101"),
-                IpPrefix.valueOf("192.168.30.0/24")));
+        interfaceIpAddresses3.add(
+                new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
+                                       IpPrefix.valueOf("192.168.30.0/24")));
         Interface sw3Eth1 = new Interface(SW3_ETH1,
                 interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
                 VlanId.NONE);
         interfaces.add(sw3Eth1);
 
+        InterfaceIpAddress interfaceIpAddress4 =
+                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
+                                       IpPrefix.valueOf("192.168.40.0/24"));
+        Interface sw4Eth1 = new Interface(SW4_ETH1,
+                                          Sets.newHashSet(interfaceIpAddress4),
+                                          MacAddress.valueOf("00:00:00:00:00:04"),
+                                          VlanId.vlanId((short) 1));
+
+        expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
+        interfaces.add(sw4Eth1);
+
         expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
                 sw1Eth1).anyTimes();
         expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
                 sw2Eth1).anyTimes();
         expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
                 sw3Eth1).anyTimes();
-        expect(interfaceService.getInterfaces()).andReturn(
-                interfaces).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
         replay(interfaceService);
     }
 
     /**
-     * Sets up the host service with details of hosts.
+     * Tests adding a FIB entry to the IntentSynchronizer.
+     *
+     * We verify that the synchronizer records the correct state and that the
+     * correct intent is submitted to the IntentService.
+     *
+     * @throws TestUtilsException
      */
-    private void setUpHostService() {
-        hostService = createMock(HostService.class);
+    @Test
+    public void testFibAdd() throws TestUtilsException {
+        FibEntry fibEntry = new FibEntry(
+                Ip4Prefix.valueOf("1.1.1.0/24"),
+                Ip4Address.valueOf("192.168.10.1"),
+                MacAddress.valueOf("00:00:00:00:00:01"));
 
-        hostService.addListener(anyObject(HostListener.class));
-        expectLastCall().anyTimes();
+        // Construct a MultiPointToSinglePointIntent intent
+        TrafficSelector.Builder selectorBuilder =
+                DefaultTrafficSelector.builder();
+        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
+                fibEntry.prefix());
 
-        IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
-        Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
-                new HostLocation(SW1_ETH1, 1),
-                        Sets.newHashSet(host1Address));
+        TrafficTreatment.Builder treatmentBuilder =
+                DefaultTrafficTreatment.builder();
+        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
 
-        expect(hostService.getHostsByIp(host1Address))
-                .andReturn(Sets.newHashSet(host1)).anyTimes();
-        hostService.startMonitoringIp(host1Address);
-        expectLastCall().anyTimes();
+        Set<ConnectPoint> ingressPoints = new HashSet<>();
+        ingressPoints.add(SW2_ETH1);
+        ingressPoints.add(SW3_ETH1);
+        ingressPoints.add(SW4_ETH1);
+
+        MultiPointToSinglePointIntent intent =
+                new MultiPointToSinglePointIntent(APPID,
+                                                  selectorBuilder.build(), treatmentBuilder.build(),
+                                                  ingressPoints, SW1_ETH1);
+
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intent);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                builder.build()));
+        replay(intentService);
+
+        intentSynchronizer.leaderChanged(true);
+        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+
+        FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
+                                            fibEntry);
+        intentSynchronizer.update(Collections.singleton(fibUpdate),
+                                  Collections.emptyList());
+
+        Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+        Intent firstIntent =
+                intentSynchronizer.getRouteIntents().iterator().next();
+        IntentKey firstIntentKey = new IntentKey(firstIntent);
+        IntentKey intentKey = new IntentKey(intent);
+        assertTrue(firstIntentKey.equals(intentKey));
+        verify(intentService);
+    }
+
+    /**
+     * Tests adding a FIB entry with to a next hop in a VLAN.
+     *
+     * We verify that the synchronizer records the correct state and that the
+     * correct intent is submitted to the IntentService.
+     *
+     * @throws TestUtilsException
+     */
+    @Test
+    public void testFibAddWithVlan() throws TestUtilsException {
+        FibEntry fibEntry = new FibEntry(
+                Ip4Prefix.valueOf("3.3.3.0/24"),
+                Ip4Address.valueOf("192.168.40.1"),
+                MacAddress.valueOf("00:00:00:00:00:04"));
+
+        // Construct a MultiPointToSinglePointIntent intent
+        TrafficSelector.Builder selectorBuilder =
+                DefaultTrafficSelector.builder();
+        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
+                       .matchIPDst(fibEntry.prefix())
+                       .matchVlanId(VlanId.ANY);
+
+        TrafficTreatment.Builder treatmentBuilder =
+                DefaultTrafficTreatment.builder();
+        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:04"))
+                        .setVlanId(VlanId.vlanId((short) 1));
+
+        Set<ConnectPoint> ingressPoints = new HashSet<>();
+        ingressPoints.add(SW1_ETH1);
+        ingressPoints.add(SW2_ETH1);
+        ingressPoints.add(SW3_ETH1);
+
+        MultiPointToSinglePointIntent intent =
+                new MultiPointToSinglePointIntent(APPID,
+                        selectorBuilder.build(), treatmentBuilder.build(),
+                        ingressPoints, SW4_ETH1);
+
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intent);
+        intentService.execute(
+                TestIntentServiceHelper.eqExceptId(builder.build()));
+        replay(intentService);
+
+        // Run the test
+        intentSynchronizer.leaderChanged(true);
+        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+        FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
+
+        intentSynchronizer.update(Collections.singleton(fibUpdate),
+                                  Collections.emptyList());
+
+        // Verify
+        Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+        Intent firstIntent =
+            intentSynchronizer.getRouteIntents().iterator().next();
+        IntentKey firstIntentKey = new IntentKey(firstIntent);
+        IntentKey intentKey = new IntentKey(intent);
+        assertTrue(firstIntentKey.equals(intentKey));
+        verify(intentService);
+    }
+
+    /**
+     * Tests updating a FIB entry.
+     *
+     * We verify that the synchronizer records the correct state and that the
+     * correct intent is submitted to the IntentService.
+     *
+     * @throws TestUtilsException
+     */
+    @Test
+    public void testFibUpdate() throws TestUtilsException {
+        // Firstly add a route
+        testFibAdd();
+
+        Intent addedIntent =
+                intentSynchronizer.getRouteIntents().iterator().next();
+
+        // Start to construct a new route entry and new intent
+        FibEntry fibEntryUpdate = new FibEntry(
+                Ip4Prefix.valueOf("1.1.1.0/24"),
+                Ip4Address.valueOf("192.168.20.1"),
+                MacAddress.valueOf("00:00:00:00:00:02"));
+
+        // Construct a new MultiPointToSinglePointIntent intent
+        TrafficSelector.Builder selectorBuilderNew =
+                DefaultTrafficSelector.builder();
+        selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
+                fibEntryUpdate.prefix());
+
+        TrafficTreatment.Builder treatmentBuilderNew =
+                DefaultTrafficTreatment.builder();
+        treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
 
 
-        IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
-        Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
-                new HostLocation(SW2_ETH1, 1),
-                        Sets.newHashSet(host2Address));
+        Set<ConnectPoint> ingressPointsNew = new HashSet<>();
+        ingressPointsNew.add(SW1_ETH1);
+        ingressPointsNew.add(SW3_ETH1);
+        ingressPointsNew.add(SW4_ETH1);
 
-        expect(hostService.getHostsByIp(host2Address))
-                .andReturn(Sets.newHashSet(host2)).anyTimes();
-        hostService.startMonitoringIp(host2Address);
-        expectLastCall().anyTimes();
+        MultiPointToSinglePointIntent intentNew =
+                new MultiPointToSinglePointIntent(APPID,
+                                                  selectorBuilderNew.build(),
+                                                  treatmentBuilderNew.build(),
+                                                  ingressPointsNew, SW2_ETH1);
 
+        // Set up test expectation
+        reset(intentService);
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(addedIntent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                builder.build()));
+        builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intentNew);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                builder.build()));
+        replay(intentService);
 
-        IpAddress host3Address = IpAddress.valueOf("192.168.30.1");
-        Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE,
-                new HostLocation(SW3_ETH1, 1),
-                        Sets.newHashSet(host3Address));
+        // Call the update() method in IntentSynchronizer class
+        intentSynchronizer.leaderChanged(true);
+        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+        FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
+                                                  fibEntryUpdate);
+        intentSynchronizer.update(Collections.singletonList(fibUpdate),
+                                  Collections.emptyList());
 
-        expect(hostService.getHostsByIp(host3Address))
-                .andReturn(Sets.newHashSet(host3)).anyTimes();
-        hostService.startMonitoringIp(host3Address);
-        expectLastCall().anyTimes();
+        // Verify
+        Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
+        Intent firstIntent =
+                intentSynchronizer.getRouteIntents().iterator().next();
+        IntentKey firstIntentKey = new IntentKey(firstIntent);
+        IntentKey intentNewKey = new IntentKey(intentNew);
+        assertTrue(firstIntentKey.equals(intentNewKey));
+        verify(intentService);
+    }
 
+    /**
+     * Tests deleting a FIB entry.
+     *
+     * We verify that the synchronizer records the correct state and that the
+     * correct intent is withdrawn from the IntentService.
+     *
+     * @throws TestUtilsException
+     */
+    @Test
+    public void testFibDelete() throws TestUtilsException {
+        // Firstly add a route
+        testFibAdd();
 
-        replay(hostService);
+        Intent addedIntent =
+                intentSynchronizer.getRouteIntents().iterator().next();
+
+        // Construct the existing route entry
+        FibEntry fibEntry = new FibEntry(
+                Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
+
+        // Set up expectation
+        reset(intentService);
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(addedIntent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                builder.build()));
+        replay(intentService);
+
+        // Call the update() method in IntentSynchronizer class
+        intentSynchronizer.leaderChanged(true);
+        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
+        FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
+        intentSynchronizer.update(Collections.emptyList(),
+                                  Collections.singletonList(fibUpdate));
+
+        // Verify
+        Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
+        verify(intentService);
     }
 
     /**
@@ -287,25 +520,7 @@
         MultiPointToSinglePointIntent intent6 = intentBuilder(
                 routeEntry6.prefix(), "00:00:00:00:00:01",  SW1_ETH1);
 
-        // Set up the ribTable field in Router class and routeIntents fields
-        // in IntentSynchronizer class
-        InvertedRadixTree<RouteEntry> ribTable =
-                new ConcurrentInvertedRadixTree<>(
-                new DefaultByteArrayNodeFactory());
-        ribTable.put(RouteEntry.createBinaryString(routeEntry1.prefix()),
-                     routeEntry1);
-        ribTable.put(RouteEntry.createBinaryString(routeEntry3.prefix()),
-                     routeEntry3);
-        ribTable.put(RouteEntry.createBinaryString(routeEntry4Update.prefix()),
-                     routeEntry4Update);
-        ribTable.put(RouteEntry.createBinaryString(routeEntry5.prefix()),
-                     routeEntry5);
-        ribTable.put(RouteEntry.createBinaryString(routeEntry6.prefix()),
-                     routeEntry6);
-        ribTable.put(RouteEntry.createBinaryString(routeEntry7.prefix()),
-                     routeEntry7);
-        TestUtils.setField(router, "ribTable4", ribTable);
-
+        // Set up the routeIntents field in IntentSynchronizer class
         ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
             routeIntents =  new ConcurrentHashMap<>();
         routeIntents.put(routeEntry1.prefix(), intent1);
@@ -353,20 +568,9 @@
 
         // Start the test
         intentSynchronizer.leaderChanged(true);
-        /*
-        TestUtils.callMethod(intentSynchronizer, "synchronizeIntents",
-                             new Class<?>[] {});
-        */
         intentSynchronizer.synchronizeIntents();
 
         // Verify
-        assertEquals(router.getRoutes4().size(), 6);
-        assertTrue(router.getRoutes4().contains(routeEntry1));
-        assertTrue(router.getRoutes4().contains(routeEntry3));
-        assertTrue(router.getRoutes4().contains(routeEntry4Update));
-        assertTrue(router.getRoutes4().contains(routeEntry5));
-        assertTrue(router.getRoutes4().contains(routeEntry6));
-
         assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
         assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
         assertTrue(intentSynchronizer.getRouteIntents().contains(intent3));
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
index 5311a72..298972d 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
@@ -41,7 +41,6 @@
 import org.onosproject.net.intent.IntentOperations;
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.sdnip.bgp.BgpConstants;
 import org.onosproject.sdnip.config.BgpPeer;
 import org.onosproject.sdnip.config.BgpSpeaker;
 import org.onosproject.sdnip.config.Interface;
@@ -302,7 +301,7 @@
      */
     private void setUpBgpIntents() {
 
-        Short bgpPort = Short.valueOf((short) BgpConstants.BGP_PORT);
+        Short bgpPort = 179;
 
         // Start to build intents between BGP speaker1 and BGP peer1
         bgpPathintentConstructor(
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouteEntryTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/RouteEntryTest.java
deleted file mode 100644
index b977917..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouteEntryTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-
-import org.junit.Test;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-
-/**
- * Unit tests for the RouteEntry class.
- */
-public class RouteEntryTest {
-    /**
-     * Tests valid class constructor.
-     */
-    @Test
-    public void testConstructor() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-
-        RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
-        assertThat(routeEntry.toString(),
-                   is("RouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8}"));
-    }
-
-    /**
-     * Tests invalid class constructor for null IPv4 prefix.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullPrefix() {
-        Ip4Prefix prefix = null;
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-
-        new RouteEntry(prefix, nextHop);
-    }
-
-    /**
-     * Tests invalid class constructor for null IPv4 next-hop.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullNextHop() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = null;
-
-        new RouteEntry(prefix, nextHop);
-    }
-
-    /**
-     * Tests getting the fields of a route entry.
-     */
-    @Test
-    public void testGetFields() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-
-        RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
-        assertThat(routeEntry.prefix(), is(prefix));
-        assertThat(routeEntry.nextHop(), is(nextHop));
-    }
-
-    /**
-     * Tests creating a binary string from IPv4 prefix.
-     */
-    @Test
-    public void testCreateBinaryString() {
-        Ip4Prefix prefix;
-
-        prefix = Ip4Prefix.valueOf("0.0.0.0/0");
-        assertThat(RouteEntry.createBinaryString(prefix), is(""));
-
-        prefix = Ip4Prefix.valueOf("192.168.166.0/22");
-        assertThat(RouteEntry.createBinaryString(prefix),
-                   is("1100000010101000101001"));
-
-        prefix = Ip4Prefix.valueOf("192.168.166.0/23");
-        assertThat(RouteEntry.createBinaryString(prefix),
-                   is("11000000101010001010011"));
-
-        prefix = Ip4Prefix.valueOf("192.168.166.0/24");
-        assertThat(RouteEntry.createBinaryString(prefix),
-                   is("110000001010100010100110"));
-
-        prefix = Ip4Prefix.valueOf("130.162.10.1/25");
-        assertThat(RouteEntry.createBinaryString(prefix),
-                   is("1000001010100010000010100"));
-
-        prefix = Ip4Prefix.valueOf("255.255.255.255/32");
-        assertThat(RouteEntry.createBinaryString(prefix),
-                   is("11111111111111111111111111111111"));
-    }
-
-    /**
-     * Tests equality of {@link RouteEntry}.
-     */
-    @Test
-    public void testEquality() {
-        Ip4Prefix prefix1 = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop1 = Ip4Address.valueOf("5.6.7.8");
-        RouteEntry routeEntry1 = new RouteEntry(prefix1, nextHop1);
-
-        Ip4Prefix prefix2 = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop2 = Ip4Address.valueOf("5.6.7.8");
-        RouteEntry routeEntry2 = new RouteEntry(prefix2, nextHop2);
-
-        assertThat(routeEntry1, is(routeEntry2));
-    }
-
-    /**
-     * Tests non-equality of {@link RouteEntry}.
-     */
-    @Test
-    public void testNonEquality() {
-        Ip4Prefix prefix1 = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop1 = Ip4Address.valueOf("5.6.7.8");
-        RouteEntry routeEntry1 = new RouteEntry(prefix1, nextHop1);
-
-        Ip4Prefix prefix2 = Ip4Prefix.valueOf("1.2.3.0/25");      // Different
-        Ip4Address nextHop2 = Ip4Address.valueOf("5.6.7.8");
-        RouteEntry routeEntry2 = new RouteEntry(prefix2, nextHop2);
-
-        Ip4Prefix prefix3 = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop3 = Ip4Address.valueOf("5.6.7.9");      // Different
-        RouteEntry routeEntry3 = new RouteEntry(prefix3, nextHop3);
-
-        assertThat(routeEntry1, is(not(routeEntry2)));
-        assertThat(routeEntry1, is(not(routeEntry3)));
-    }
-
-    /**
-     * Tests object string representation.
-     */
-    @Test
-    public void testToString() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
-
-        assertThat(routeEntry.toString(),
-                   is("RouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8}"));
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterAsyncArpTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterAsyncArpTest.java
deleted file mode 100644
index 4d14228..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterAsyncArpTest.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip;
-
-import com.google.common.collect.Sets;
-import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
-import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
-import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.junit.TestUtils;
-import org.onlab.junit.TestUtils.TestUtilsException;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intent.AbstractIntentTest;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentOperations;
-import org.onosproject.net.intent.IntentService;
-import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
-import org.onosproject.sdnip.Router.InternalHostListener;
-import org.onosproject.sdnip.config.BgpPeer;
-import org.onosproject.sdnip.config.Interface;
-import org.onosproject.sdnip.config.SdnIpConfigurationService;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * This class tests adding a route, updating a route, deleting a route, and
- * the ARP module answers the MAC address asynchronously.
- */
-public class RouterAsyncArpTest extends AbstractIntentTest {
-
-    private SdnIpConfigurationService sdnIpConfigService;
-    private InterfaceService interfaceService;
-    private IntentService intentService;
-    private HostService hostService;
-
-    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000001"),
-            PortNumber.portNumber(1));
-
-    private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000002"),
-            PortNumber.portNumber(1));
-
-    private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000003"),
-            PortNumber.portNumber(1));
-
-    private IntentSynchronizer intentSynchronizer;
-    private Router router;
-    private InternalHostListener internalHostListener;
-
-    private static final ApplicationId APPID = new ApplicationId() {
-        @Override
-        public short id() {
-            return 1;
-        }
-
-        @Override
-        public String name() {
-            return "SDNIP";
-        }
-    };
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        setUpSdnIpConfigService();
-        setUpInterfaceService();
-        hostService = createMock(HostService.class);
-        intentService = createMock(IntentService.class);
-
-        intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    sdnIpConfigService,
-                                                    interfaceService);
-        router = new Router(intentSynchronizer, hostService);
-        internalHostListener = router.new InternalHostListener();
-    }
-
-    /**
-     * Sets up SdnIpConfigService.
-     */
-    private void setUpSdnIpConfigService() {
-
-        sdnIpConfigService = createMock(SdnIpConfigurationService.class);
-
-        Map<IpAddress, BgpPeer> peers = new HashMap<>();
-
-        String peerSw1Eth1 = "192.168.10.1";
-        peers.put(IpAddress.valueOf(peerSw1Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
-
-        // Two BGP peers are connected to switch 2 port 1.
-        String peer1Sw2Eth1 = "192.168.20.1";
-        peers.put(IpAddress.valueOf(peer1Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
-
-        String peer2Sw2Eth1 = "192.168.20.2";
-        peers.put(IpAddress.valueOf(peer2Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
-
-        expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
-        replay(sdnIpConfigService);
-    }
-
-    /**
-     * Sets up InterfaceService.
-     */
-    private void setUpInterfaceService() {
-
-        interfaceService = createMock(InterfaceService.class);
-
-        Set<Interface> interfaces = Sets.newHashSet();
-
-        Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
-        interfaceIpAddresses1.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.10.101"),
-                IpPrefix.valueOf("192.168.10.0/24")));
-        Interface sw1Eth1 = new Interface(SW1_ETH1,
-                interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
-                VlanId.NONE);
-        interfaces.add(sw1Eth1);
-
-        Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
-        interfaceIpAddresses2.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.20.101"),
-                IpPrefix.valueOf("192.168.20.0/24")));
-        Interface sw2Eth1 = new Interface(SW2_ETH1,
-                interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
-                VlanId.NONE);
-        interfaces.add(sw2Eth1);
-
-        Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
-        interfaceIpAddresses3.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.30.101"),
-                IpPrefix.valueOf("192.168.30.0/24")));
-        Interface sw3Eth1 = new Interface(SW3_ETH1,
-                interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
-                VlanId.NONE);
-        interfaces.add(sw3Eth1);
-
-        expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
-        expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
-        expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
-        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-        replay(interfaceService);
-    }
-
-    /**
-     * This method tests adding a route entry.
-     */
-    @Test
-    public void testRouteAdd() throws TestUtilsException {
-
-        // Construct a route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.10.1"));
-
-        // Construct a route intent
-        MultiPointToSinglePointIntent intent = staticIntentBuilder();
-
-        // Set up test expectation
-        reset(hostService);
-        expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
-                new HashSet<Host>()).anyTimes();
-        hostService.startMonitoringIp(IpAddress.valueOf("192.168.10.1"));
-        replay(hostService);
-
-        reset(intentService);
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addSubmitOperation(intent);
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
-                new HostLocation(
-                        SW1_ETH1.deviceId(),
-                        SW1_ETH1.port(), 1),
-                        Sets.newHashSet(IpAddress.valueOf("192.168.10.1")));
-        internalHostListener.event(
-                new HostEvent(HostEvent.Type.HOST_ADDED, host));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntry));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
-        Intent firstIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-        IntentKey firstIntentKey = new IntentKey(firstIntent);
-        IntentKey intentKey = new IntentKey(intent);
-        assertTrue(firstIntentKey.equals(intentKey));
-        verify(intentService);
-        verify(hostService);
-
-    }
-
-    /**
-     * This method tests updating a route entry.
-     *
-     * @throws TestUtilsException
-     */
-    @Test
-    public void testRouteUpdate() throws TestUtilsException {
-
-        // Construct the existing route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.10.1"));
-
-        // Construct the existing MultiPointToSinglePointIntent intent
-        MultiPointToSinglePointIntent intent = staticIntentBuilder();
-
-        // Set up the ribTable field of Router class with existing route, and
-        // routeIntents field with the corresponding existing intent
-        setRibTableField(routeEntry);
-        setRouteIntentsField(routeEntry, intent);
-
-        // Start to construct a new route entry and new intent
-        RouteEntry routeEntryUpdate = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.20.1"));
-
-        // Construct a new MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilderNew =
-                DefaultTrafficSelector.builder();
-        selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                routeEntryUpdate.prefix());
-
-        TrafficTreatment.Builder treatmentBuilderNew =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
-
-        Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
-        ingressPointsNew.add(SW1_ETH1);
-        ingressPointsNew.add(SW3_ETH1);
-
-        MultiPointToSinglePointIntent intentNew =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilderNew.build(),
-                        treatmentBuilderNew.build(),
-                        ingressPointsNew, SW2_ETH1);
-
-        // Set up test expectation
-        reset(hostService);
-        expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
-                new HashSet<Host>()).anyTimes();
-        hostService.startMonitoringIp(IpAddress.valueOf("192.168.20.1"));
-        replay(hostService);
-
-        reset(intentService);
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addWithdrawOperation(intent.id());
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        builder = IntentOperations.builder(APPID);
-        builder.addSubmitOperation(intentNew);
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntryUpdate);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
-                new HostLocation(
-                        SW2_ETH1.deviceId(),
-                        SW2_ETH1.port(), 1),
-                        Sets.newHashSet(IpAddress.valueOf("192.168.20.1")));
-        internalHostListener.event(
-                new HostEvent(HostEvent.Type.HOST_ADDED, host));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntryUpdate));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
-        Intent firstIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-        IntentKey firstIntentKey = new IntentKey(firstIntent);
-        IntentKey intentNewKey = new IntentKey(intentNew);
-        assertTrue(firstIntentKey.equals(intentNewKey));
-        verify(intentService);
-        verify(hostService);
-    }
-
-    /**
-     * This method tests deleting a route entry.
-     */
-    @Test
-    public void testRouteDelete() throws TestUtilsException {
-
-        // Construct the existing route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.10.1"));
-
-        // Construct the existing MultiPointToSinglePointIntent intent
-        MultiPointToSinglePointIntent intent = staticIntentBuilder();
-
-        // Set up the ribTable field of Router class with existing route, and
-        // routeIntents field with the corresponding existing intent
-        setRibTableField(routeEntry);
-        setRouteIntentsField(routeEntry, intent);
-
-        // Set up expectation
-        reset(intentService);
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addWithdrawOperation(intent.id());
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 0);
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
-        verify(intentService);
-    }
-
-    /**
-     * Constructs a static MultiPointToSinglePointIntent.
-     */
-    private MultiPointToSinglePointIntent staticIntentBuilder() {
-
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                IpPrefix.valueOf("1.1.1.0/24"));
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        ingressPoints.add(SW2_ETH1);
-        ingressPoints.add(SW3_ETH1);
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilder.build(), treatmentBuilder.build(),
-                        ingressPoints, SW1_ETH1);
-
-        return intent;
-    }
-
-    /**
-     * Sets ribTable Field in Router class.
-     *
-     * @throws TestUtilsException
-     */
-    private void setRibTableField(RouteEntry routeEntry)
-            throws TestUtilsException {
-
-        InvertedRadixTree<RouteEntry> ribTable =
-                new ConcurrentInvertedRadixTree<>(
-                new DefaultByteArrayNodeFactory());
-        ribTable.put(RouteEntry.createBinaryString(routeEntry.prefix()),
-                     routeEntry);
-        TestUtils.setField(router, "ribTable4", ribTable);
-    }
-
-    /**
-     * Sets routeIntentsField in IntentSynchronizer class.
-     *
-     * @throws TestUtilsException
-     */
-    private void setRouteIntentsField(RouteEntry routeEntry,
-            MultiPointToSinglePointIntent intent)
-            throws TestUtilsException {
-
-        ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
-            routeIntents =  new ConcurrentHashMap<>();
-        routeIntents.put(routeEntry.prefix(), intent);
-        TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterTest.java
deleted file mode 100644
index a7b4cce..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/RouterTest.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip;
-
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.junit.TestUtils;
-import org.onlab.junit.TestUtils.TestUtilsException;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intent.AbstractIntentTest;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentOperations;
-import org.onosproject.net.intent.IntentService;
-import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
-import org.onosproject.sdnip.config.BgpPeer;
-import org.onosproject.sdnip.config.Interface;
-import org.onosproject.sdnip.config.SdnIpConfigurationService;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * This class tests adding a route, updating a route, deleting a route,
- * and adding a route whose next hop is the local BGP speaker.
- * <p/>
- * ARP module answers the MAC address synchronously.
- */
-public class RouterTest extends AbstractIntentTest {
-
-    private SdnIpConfigurationService sdnIpConfigService;
-    private InterfaceService interfaceService;
-    private IntentService intentService;
-    private HostService hostService;
-
-    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000001"),
-            PortNumber.portNumber(1));
-
-    private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000002"),
-            PortNumber.portNumber(1));
-
-    private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000003"),
-            PortNumber.portNumber(1));
-
-    private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000004"),
-            PortNumber.portNumber(1));
-
-    private static final ApplicationId APPID = new ApplicationId() {
-        @Override
-        public short id() {
-            return 1;
-        }
-
-        @Override
-        public String name() {
-            return "SDNIP";
-        }
-    };
-
-    private IntentSynchronizer intentSynchronizer;
-    private Router router;
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        setUpBgpPeers();
-
-        setUpInterfaceService();
-        setUpHostService();
-
-        intentService = createMock(IntentService.class);
-
-        intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    sdnIpConfigService,
-                                                    interfaceService);
-        router = new Router(intentSynchronizer, hostService);
-    }
-
-    /**
-     * Sets up BGP peers in external networks.
-     */
-    private void setUpBgpPeers() {
-
-        Map<IpAddress, BgpPeer> peers = new HashMap<>();
-
-        String peerSw1Eth1 = "192.168.10.1";
-        peers.put(IpAddress.valueOf(peerSw1Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
-
-        // Two BGP peers are connected to switch 2 port 1.
-        String peer1Sw2Eth1 = "192.168.20.1";
-        peers.put(IpAddress.valueOf(peer1Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
-
-        String peer2Sw2Eth1 = "192.168.20.2";
-        peers.put(IpAddress.valueOf(peer2Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
-
-        String peer1Sw4Eth1 = "192.168.40.1";
-        peers.put(IpAddress.valueOf(peer1Sw4Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
-
-        sdnIpConfigService = createMock(SdnIpConfigurationService.class);
-        expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
-        replay(sdnIpConfigService);
-
-    }
-
-    /**
-     * Sets up logical interfaces, which emulate the configured interfaces
-     * in SDN-IP application.
-     */
-    private void setUpInterfaceService() {
-        interfaceService = createMock(InterfaceService.class);
-
-        Set<Interface> interfaces = Sets.newHashSet();
-
-        InterfaceIpAddress ia1 =
-            new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
-                                   IpPrefix.valueOf("192.168.10.0/24"));
-        Interface sw1Eth1 = new Interface(SW1_ETH1,
-                Sets.newHashSet(ia1),
-                MacAddress.valueOf("00:00:00:00:00:01"),
-                VlanId.NONE);
-
-        expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
-        interfaces.add(sw1Eth1);
-
-        InterfaceIpAddress ia2 =
-            new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
-                                   IpPrefix.valueOf("192.168.20.0/24"));
-        Interface sw2Eth1 = new Interface(SW2_ETH1,
-                Sets.newHashSet(ia2),
-                MacAddress.valueOf("00:00:00:00:00:02"),
-                VlanId.NONE);
-
-        expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
-        interfaces.add(sw2Eth1);
-
-        InterfaceIpAddress ia3 =
-            new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
-                                   IpPrefix.valueOf("192.168.30.0/24"));
-        Interface sw3Eth1 = new Interface(SW3_ETH1,
-                Sets.newHashSet(ia3),
-                MacAddress.valueOf("00:00:00:00:00:03"),
-                VlanId.NONE);
-
-        expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
-        interfaces.add(sw3Eth1);
-
-        InterfaceIpAddress ia4 =
-                new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
-                                       IpPrefix.valueOf("192.168.40.0/24"));
-            Interface sw4Eth1 = new Interface(SW4_ETH1,
-                    Sets.newHashSet(ia4),
-                    MacAddress.valueOf("00:00:00:00:00:04"),
-                    VlanId.vlanId((short) 1));
-
-            expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
-            interfaces.add(sw4Eth1);
-
-        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-
-        replay(interfaceService);
-    }
-
-    /**
-     * Sets up the host service with details of some hosts.
-     */
-    private void setUpHostService() {
-        hostService = createMock(HostService.class);
-
-        hostService.addListener(anyObject(HostListener.class));
-        expectLastCall().anyTimes();
-
-        IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
-        Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
-                new HostLocation(SW1_ETH1, 1),
-                Sets.newHashSet(host1Address));
-
-        expect(hostService.getHostsByIp(host1Address))
-                .andReturn(Sets.newHashSet(host1)).anyTimes();
-        hostService.startMonitoringIp(host1Address);
-        expectLastCall().anyTimes();
-
-
-        IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
-        Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
-                new HostLocation(SW2_ETH1, 1),
-                Sets.newHashSet(host2Address));
-
-        expect(hostService.getHostsByIp(host2Address))
-                .andReturn(Sets.newHashSet(host2)).anyTimes();
-        hostService.startMonitoringIp(host2Address);
-        expectLastCall().anyTimes();
-
-        // Next hop on a VLAN
-        IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
-        Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
-                new HostLocation(SW4_ETH1, 1),
-                Sets.newHashSet(host3Address));
-
-        expect(hostService.getHostsByIp(host3Address))
-                .andReturn(Sets.newHashSet(host3)).anyTimes();
-        hostService.startMonitoringIp(host3Address);
-        expectLastCall().anyTimes();
-
-
-        replay(hostService);
-    }
-
-    /**
-     * This method tests adding a route entry.
-     */
-    @Test
-    public void testRouteAdd() throws TestUtilsException {
-        // Construct a route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.10.1"));
-
-        // Construct a MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                routeEntry.prefix());
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        ingressPoints.add(SW2_ETH1);
-        ingressPoints.add(SW3_ETH1);
-        ingressPoints.add(SW4_ETH1);
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilder.build(), treatmentBuilder.build(),
-                        ingressPoints, SW1_ETH1);
-
-        // Set up test expectation
-        reset(intentService);
-        // Setup the expected intents
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addSubmitOperation(intent);
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntry));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
-        Intent firstIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-        IntentKey firstIntentKey = new IntentKey(firstIntent);
-        IntentKey intentKey = new IntentKey(intent);
-        assertTrue(firstIntentKey.equals(intentKey));
-        verify(intentService);
-    }
-
-    /**
-     * This method tests adding a route entry.
-     */
-    @Test
-    public void testRouteAddWithVlan() throws TestUtilsException {
-        // Construct a route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("3.3.3.0/24"),
-                Ip4Address.valueOf("192.168.40.1"));
-
-        // Construct a MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                       .matchIPDst(routeEntry.prefix())
-                       .matchVlanId(VlanId.ANY);
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
-                        .setVlanId(VlanId.vlanId((short) 1));
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        ingressPoints.add(SW1_ETH1);
-        ingressPoints.add(SW2_ETH1);
-        ingressPoints.add(SW3_ETH1);
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilder.build(), treatmentBuilder.build(),
-                        ingressPoints, SW4_ETH1);
-
-        // Set up test expectation
-        reset(intentService);
-        // Setup the expected intents
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addSubmitOperation(intent);
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntry));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
-        Intent firstIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-        IntentKey firstIntentKey = new IntentKey(firstIntent);
-        IntentKey intentKey = new IntentKey(intent);
-        assertTrue(firstIntentKey.equals(intentKey));
-        verify(intentService);
-    }
-
-    /**
-     * This method tests updating a route entry.
-     *
-     * @throws TestUtilsException
-     */
-    @Test
-    public void testRouteUpdate() throws TestUtilsException {
-        // Firstly add a route
-        testRouteAdd();
-
-        Intent addedIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-
-        // Start to construct a new route entry and new intent
-        RouteEntry routeEntryUpdate = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.20.1"));
-
-        // Construct a new MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilderNew =
-                DefaultTrafficSelector.builder();
-        selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                routeEntryUpdate.prefix());
-
-        TrafficTreatment.Builder treatmentBuilderNew =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
-
-
-        Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
-        ingressPointsNew.add(SW1_ETH1);
-        ingressPointsNew.add(SW3_ETH1);
-        ingressPointsNew.add(SW4_ETH1);
-
-        MultiPointToSinglePointIntent intentNew =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilderNew.build(),
-                        treatmentBuilderNew.build(),
-                        ingressPointsNew, SW2_ETH1);
-
-        // Set up test expectation
-        reset(intentService);
-        // Setup the expected intents
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addWithdrawOperation(addedIntent.id());
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        builder = IntentOperations.builder(APPID);
-        builder.addSubmitOperation(intentNew);
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntryUpdate);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntryUpdate));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
-        Intent firstIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-        IntentKey firstIntentKey = new IntentKey(firstIntent);
-        IntentKey intentNewKey = new IntentKey(intentNew);
-        assertTrue(firstIntentKey.equals(intentNewKey));
-        verify(intentService);
-    }
-
-    /**
-     * This method tests deleting a route entry.
-     */
-    @Test
-    public void testRouteDelete() throws TestUtilsException {
-        // Firstly add a route
-        testRouteAdd();
-
-        Intent addedIntent =
-            intentSynchronizer.getRouteIntents().iterator().next();
-
-        // Construct the existing route entry
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("192.168.10.1"));
-
-        // Set up expectation
-        reset(intentService);
-        // Setup the expected intents
-        IntentOperations.Builder builder = IntentOperations.builder(APPID);
-        builder.addWithdrawOperation(addedIntent.id());
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                                builder.build()));
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 0);
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
-        verify(intentService);
-    }
-
-    /**
-     * This method tests when the next hop of a route is the local BGP speaker.
-     *
-     * @throws TestUtilsException
-     */
-    @Test
-    public void testLocalRouteAdd() throws TestUtilsException {
-        // Construct a route entry, the next hop is the local BGP speaker
-        RouteEntry routeEntry = new RouteEntry(
-                Ip4Prefix.valueOf("1.1.1.0/24"),
-                Ip4Address.valueOf("0.0.0.0"));
-
-        // Reset intentService to check whether the submit method is called
-        reset(intentService);
-        replay(intentService);
-
-        // Call the processRouteUpdates() method in Router class
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
-                                                  routeEntry);
-        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
-
-        // Verify
-        assertEquals(router.getRoutes4().size(), 1);
-        assertTrue(router.getRoutes4().contains(routeEntry));
-        assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
-        verify(intentService);
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpTest.java
deleted file mode 100644
index 157c73f..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpTest.java
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip;
-
-import com.google.common.collect.Sets;
-import org.easymock.IAnswer;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.onlab.junit.IntegrationTest;
-import org.onlab.junit.TestUtils;
-import org.onlab.junit.TestUtils.TestUtilsException;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.intent.AbstractIntentTest;
-import org.onosproject.net.intent.IntentService;
-import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.sdnip.config.BgpPeer;
-import org.onosproject.sdnip.config.Interface;
-import org.onosproject.sdnip.config.SdnIpConfigurationService;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Integration tests for the SDN-IP application.
- * <p/>
- * The tests are very coarse-grained. They feed route updates in to
- * {@link Router} (simulating routes learnt from iBGP module inside SDN-IP
- * application), then they check that the correct intents are created and
- * submitted to the intent service. The entire route processing logic of
- * Router class is tested.
- */
-@Category(IntegrationTest.class)
-public class SdnIpTest extends AbstractIntentTest {
-    private static final int MAC_ADDRESS_LENGTH = 6;
-    private static final int MIN_PREFIX_LENGTH = 1;
-    private static final int MAX_PREFIX_LENGTH = 32;
-
-    private IntentSynchronizer intentSynchronizer;
-    static Router router;
-
-    private SdnIpConfigurationService sdnIpConfigService;
-    private InterfaceService interfaceService;
-    private HostService hostService;
-    private IntentService intentService;
-
-    private Map<IpAddress, BgpPeer> bgpPeers;
-
-    private Random random;
-
-    static final ConnectPoint SW1_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000001"),
-            PortNumber.portNumber(1));
-
-    static final ConnectPoint SW2_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000002"),
-            PortNumber.portNumber(1));
-
-    static final ConnectPoint SW3_ETH1 = new ConnectPoint(
-            DeviceId.deviceId("of:0000000000000003"),
-            PortNumber.portNumber(1));
-
-    private static final ApplicationId APPID = new ApplicationId() {
-        @Override
-        public short id() {
-            return 1;
-        }
-
-        @Override
-        public String name() {
-            return "SDNIP";
-        }
-    };
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        setUpInterfaceService();
-        setUpSdnIpConfigService();
-
-        hostService = new TestHostService();
-        intentService = createMock(IntentService.class);
-        random = new Random();
-
-        intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    sdnIpConfigService,
-                                                    interfaceService);
-        router = new Router(intentSynchronizer, hostService);
-    }
-
-    /**
-     * Sets up InterfaceService and virtual {@link Interface}s.
-     */
-    private void setUpInterfaceService() {
-
-        interfaceService = createMock(InterfaceService.class);
-
-        Set<Interface> interfaces = Sets.newHashSet();
-
-        Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
-        interfaceIpAddresses1.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.10.101"),
-                IpPrefix.valueOf("192.168.10.0/24")));
-        Interface sw1Eth1 = new Interface(SW1_ETH1,
-                interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
-                VlanId.NONE);
-        interfaces.add(sw1Eth1);
-
-        Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
-        interfaceIpAddresses2.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.20.101"),
-                IpPrefix.valueOf("192.168.20.0/24")));
-        Interface sw2Eth1 = new Interface(SW2_ETH1,
-                interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
-                VlanId.NONE);
-        interfaces.add(sw2Eth1);
-
-        Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
-        interfaceIpAddresses3.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.30.101"),
-                IpPrefix.valueOf("192.168.30.0/24")));
-        Interface sw3Eth1 = new Interface(SW3_ETH1,
-                interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
-                VlanId.NONE);
-        interfaces.add(sw3Eth1);
-
-        expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
-                sw1Eth1).anyTimes();
-        expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
-                sw2Eth1).anyTimes();
-        expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
-                sw3Eth1).anyTimes();
-
-        expect(interfaceService.getInterfaces()).andReturn(
-                interfaces).anyTimes();
-        replay(interfaceService);
-    }
-
-    /**
-     * Sets up SdnIpConfigService and BGP peers in external networks.
-     */
-    private void setUpSdnIpConfigService() {
-
-        sdnIpConfigService = createMock(SdnIpConfigurationService.class);
-
-        bgpPeers = new HashMap<>();
-
-        String peerSw1Eth1 = "192.168.10.1";
-        bgpPeers.put(IpAddress.valueOf(peerSw1Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
-
-        String peer1Sw2Eth1 = "192.168.20.1";
-        bgpPeers.put(IpAddress.valueOf(peer1Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
-
-        String peer2Sw2Eth1 = "192.168.30.1";
-        bgpPeers.put(IpAddress.valueOf(peer2Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:03", 1, peer2Sw2Eth1));
-
-        expect(sdnIpConfigService.getBgpPeers()).andReturn(bgpPeers).anyTimes();
-        replay(sdnIpConfigService);
-    }
-
-    /**
-     * Tests adding a set of routes into {@link Router}.
-     * <p/>
-     * Random routes are generated and fed in to the route processing
-     * logic (via processRouteAdd in Router class). We check that the correct
-     * intents are generated and submitted to our mock intent service.
-     *
-     * @throws InterruptedException if interrupted while waiting on a latch
-     * @throws TestUtilsException if exceptions when using TestUtils
-     */
-    @Test
-    public void testAddRoutes() throws InterruptedException, TestUtilsException {
-        int numRoutes = 100;
-
-        final CountDownLatch latch = new CountDownLatch(numRoutes);
-
-        List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);
-
-        // Set up expectation
-        reset(intentService);
-
-        for (RouteUpdate update : routeUpdates) {
-            IpAddress nextHopAddress = update.routeEntry().nextHop();
-
-            // Find out the egress ConnectPoint
-            ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
-
-            MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
-                    generateMacAddress(nextHopAddress),
-                    egressConnectPoint);
-            intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
-
-            expectLastCall().andAnswer(new IAnswer<Object>() {
-                @Override
-                public Object answer() throws Throwable {
-                    latch.countDown();
-                    return null;
-                }
-            }).once();
-        }
-
-        replay(intentService);
-
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-
-        // Add route updates
-        router.processRouteUpdates(routeUpdates);
-
-        latch.await(5000, TimeUnit.MILLISECONDS);
-
-        assertEquals(router.getRoutes4().size(), numRoutes);
-        assertEquals(intentSynchronizer.getRouteIntents().size(),
-                     numRoutes);
-
-        verify(intentService);
-    }
-
-    /**
-     * Tests adding then deleting a set of routes from {@link Router}.
-     * <p/>
-     * Random routes are generated and fed in to the route processing
-     * logic (via processRouteAdd in Router class), and we check that the
-     * correct intents are generated. We then delete the entire set of routes
-     * (by feeding updates to processRouteDelete), and check that the correct
-     * intents are withdrawn from the intent service.
-     *
-     * @throws InterruptedException if interrupted while waiting on a latch
-     * @throws TestUtilsException exceptions when using TestUtils
-     */
-    @Test
-    public void testDeleteRoutes() throws InterruptedException, TestUtilsException {
-        int numRoutes = 100;
-        List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);
-
-        final CountDownLatch installCount = new CountDownLatch(numRoutes);
-        final CountDownLatch deleteCount = new CountDownLatch(numRoutes);
-
-        // Set up expectation
-        reset(intentService);
-
-        for (RouteUpdate update : routeUpdates) {
-            IpAddress nextHopAddress = update.routeEntry().nextHop();
-
-            // Find out the egress ConnectPoint
-            ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
-            MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
-                    generateMacAddress(nextHopAddress),
-                    egressConnectPoint);
-            intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
-            expectLastCall().andAnswer(new IAnswer<Object>() {
-                @Override
-                public Object answer() throws Throwable {
-                    installCount.countDown();
-                    return null;
-                }
-            }).once();
-            intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
-            expectLastCall().andAnswer(new IAnswer<Object>() {
-                @Override
-                public Object answer() throws Throwable {
-                    deleteCount.countDown();
-                    return null;
-                }
-            }).once();
-        }
-
-        replay(intentService);
-
-        intentSynchronizer.leaderChanged(true);
-        TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-
-        // Send the add updates first
-        router.processRouteUpdates(routeUpdates);
-
-        // Give some time to let the intents be submitted
-        installCount.await(5000, TimeUnit.MILLISECONDS);
-
-        // Send the DELETE updates
-        List<RouteUpdate> deleteRouteUpdates = new ArrayList<>();
-        for (RouteUpdate update : routeUpdates) {
-            RouteUpdate deleteUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
-                                                       update.routeEntry());
-            deleteRouteUpdates.add(deleteUpdate);
-        }
-        router.processRouteUpdates(deleteRouteUpdates);
-
-        deleteCount.await(5000, TimeUnit.MILLISECONDS);
-
-        assertEquals(0, router.getRoutes4().size());
-        assertEquals(0, intentSynchronizer.getRouteIntents().size());
-        verify(intentService);
-    }
-
-    /**
-     * This methods generates random route updates.
-     *
-     * @param numRoutes the number of route updates to generate
-     * @return a list of route update
-     */
-    private List<RouteUpdate> generateRouteUpdates(int numRoutes) {
-        List<RouteUpdate> routeUpdates = new ArrayList<>(numRoutes);
-
-        Set<Ip4Prefix> prefixes = new HashSet<>();
-
-        for (int i = 0; i < numRoutes; i++) {
-            Ip4Prefix prefix;
-            do {
-                // Generate a random prefix length between MIN_PREFIX_LENGTH
-                // and MAX_PREFIX_LENGTH
-                int prefixLength = random.nextInt(
-                        (MAX_PREFIX_LENGTH - MIN_PREFIX_LENGTH) + 1)
-                        + MIN_PREFIX_LENGTH;
-                prefix =
-                    Ip4Prefix.valueOf(Ip4Address.valueOf(random.nextInt()),
-                                      prefixLength);
-                // We have to ensure we don't generate the same prefix twice
-                // (this is quite easy to happen with small prefix lengths).
-            } while (prefixes.contains(prefix));
-
-            prefixes.add(prefix);
-
-            // Randomly select a peer to use as the next hop
-            BgpPeer nextHop = null;
-            int peerNumber = random.nextInt(sdnIpConfigService.getBgpPeers()
-                    .size());
-            int j = 0;
-            for (BgpPeer peer : sdnIpConfigService.getBgpPeers().values()) {
-                if (j++ == peerNumber) {
-                    nextHop = peer;
-                    break;
-                }
-            }
-
-            assertNotNull(nextHop);
-
-            RouteUpdate update =
-                new RouteUpdate(RouteUpdate.Type.UPDATE,
-                        new RouteEntry(prefix,
-                                       nextHop.ipAddress().getIp4Address()));
-
-            routeUpdates.add(update);
-        }
-
-        return routeUpdates;
-    }
-
-    /**
-     * Generates the MultiPointToSinglePointIntent that should be
-     * submitted/withdrawn for a particular RouteUpdate.
-     *
-     * @param update the RouteUpdate to generate an intent for
-     * @param nextHopMac a MAC address to use as the dst-mac for the intent
-     * @param egressConnectPoint the outgoing ConnectPoint for the intent
-     * @return the generated intent
-     */
-    private MultiPointToSinglePointIntent getIntentForUpdate(RouteUpdate update,
-            MacAddress nextHopMac, ConnectPoint egressConnectPoint) {
-        IpPrefix ip4Prefix = update.routeEntry().prefix();
-
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ip4Prefix);
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(nextHopMac);
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        for (Interface intf : interfaceService.getInterfaces()) {
-            if (!intf.connectPoint().equals(egressConnectPoint)) {
-                ConnectPoint srcPort = intf.connectPoint();
-                ingressPoints.add(srcPort);
-            }
-        }
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                selectorBuilder.build(), treatmentBuilder.build(),
-                ingressPoints, egressConnectPoint);
-
-        return intent;
-    }
-
-    /**
-     * Generates a MAC address based on an IP address.
-     * For the test we need MAC addresses but the actual values don't have any
-     * meaning, so we'll just generate them based on the IP address. This means
-     * we have a deterministic mapping from IP address to MAC address.
-     *
-     * @param ipAddress IP address used to generate a MAC address
-     * @return generated MAC address
-     */
-    static MacAddress generateMacAddress(IpAddress ipAddress) {
-        byte[] macAddress = new byte[MAC_ADDRESS_LENGTH];
-        ByteBuffer bb = ByteBuffer.wrap(macAddress);
-
-        // Put the IP address bytes into the lower four bytes of the MAC
-        // address. Leave the first two bytes set to 0.
-        bb.position(2);
-        bb.put(ipAddress.toOctets());
-
-        return MacAddress.valueOf(bb.array());
-    }
-
-    /**
-     * Finds out the ConnectPoint for a BGP peer address.
-     *
-     * @param bgpPeerAddress the BGP peer address.
-     */
-    private ConnectPoint getConnectPoint(IpAddress bgpPeerAddress) {
-        ConnectPoint connectPoint = null;
-
-        for (BgpPeer bgpPeer: bgpPeers.values()) {
-            if (bgpPeer.ipAddress().equals(bgpPeerAddress)) {
-                connectPoint = bgpPeer.connectPoint();
-                break;
-            }
-        }
-        return connectPoint;
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/TestHostService.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/TestHostService.java
deleted file mode 100644
index 7e84f8e..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/TestHostService.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip;
-
-import java.util.HashSet;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.PortAddresses;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.sdnip.Router.InternalHostListener;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-
-import com.google.common.collect.Sets;
-
-/**
- * Test version of the HostService which is used to simulate delays in
- * receiving ARP replies, as you would see in a real system due to the time
- * it takes to proxy ARP packets to/from the host. Requests are asynchronous,
- * and replies may come back to the requestor in a different order than the
- * requests were sent, which again you would expect to see in a real system.
- */
-public class TestHostService implements HostService {
-
-    /**
-     * The maximum possible delay before an ARP reply is received.
-     */
-    private static final int MAX_ARP_REPLY_DELAY = 30; // milliseconds
-
-    /**
-     * The probability that we already have the MAC address cached when the
-     * caller calls {@link #getHostsByIp(IpAddress ipAddress)}.
-     */
-    private static final float MAC_ALREADY_KNOWN_PROBABILITY = 0.3f;
-
-    private final ScheduledExecutorService replyTaskExecutor;
-    private final Random random;
-
-    /**
-     * Class constructor.
-     */
-    public TestHostService() {
-        replyTaskExecutor = Executors.newSingleThreadScheduledExecutor();
-        random = new Random();
-    }
-
-    /**
-     * Task used to reply to ARP requests from a different thread. Replies
-     * usually come on a different thread in the real system, so we need to
-     * ensure we test this behavior.
-     */
-    private class ReplyTask implements Runnable {
-        private HostListener listener;
-        private IpAddress ipAddress;
-
-        /**
-         * Class constructor.
-         *
-         * @param listener the client who requests and waits the MAC address
-         * @param ipAddress the target IP address of the request
-         */
-        public ReplyTask(InternalHostListener listener,
-                IpAddress ipAddress) {
-            this.listener = listener;
-            this.ipAddress = ipAddress;
-        }
-
-        @Override
-        public void run() {
-            Host host = getHostsByIp(ipAddress).iterator().next();
-            HostEvent hostevent =
-                    new HostEvent(HostEvent.Type.HOST_ADDED, host);
-            listener.event(hostevent);
-        }
-    }
-
-    @Override
-    public Set<Host> getHostsByIp(IpAddress ipAddress) {
-        float replyChance = random.nextFloat();
-
-        // We don't care what the attachment point is in the test,
-        // so for all the hosts, we use a same ConnectPoint.
-        Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
-                SdnIpTest.generateMacAddress(ipAddress), VlanId.NONE,
-                new HostLocation(SdnIpTest.SW1_ETH1, 1),
-                Sets.newHashSet(ipAddress));
-
-        if (replyChance < MAC_ALREADY_KNOWN_PROBABILITY) {
-            // Some percentage of the time we already know the MAC address, so
-            // we reply directly when the requestor asks for the MAC address
-            return Sets.newHashSet(host);
-        }
-        return new HashSet<Host>();
-    }
-
-    @Override
-    public void startMonitoringIp(IpAddress ipAddress) {
-
-        // Randomly select an amount of time to delay the reply coming back to
-        int delay = random.nextInt(MAX_ARP_REPLY_DELAY);
-        ReplyTask replyTask = new ReplyTask(
-                (SdnIpTest.router.new InternalHostListener()), ipAddress);
-        replyTaskExecutor.schedule(replyTask, delay, TimeUnit.MILLISECONDS);
-    }
-
-    @Override
-    public int getHostCount() {
-        return 0;
-    }
-
-    @Override
-    public Iterable<Host> getHosts() {
-        return null;
-    }
-
-    @Override
-    public Host getHost(HostId hostId) {
-        return null;
-    }
-
-    @Override
-    public Set<Host> getHostsByVlan(VlanId vlanId) {
-        return null;
-    }
-
-    @Override
-    public Set<Host> getHostsByMac(MacAddress mac) {
-        return null;
-    }
-
-    @Override
-    public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
-        return null;
-    }
-
-    @Override
-    public Set<Host> getConnectedHosts(DeviceId deviceId) {
-        return null;
-    }
-
-    @Override
-    public void stopMonitoringIp(IpAddress ip) {
-
-    }
-
-    @Override
-    public void requestMac(IpAddress ip) {
-
-    }
-
-    @Override
-    public Set<PortAddresses> getAddressBindings() {
-        return null;
-    }
-
-    @Override
-    public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) {
-        return null;
-    }
-
-    @Override
-    public void addListener(HostListener listener) {
-
-    }
-
-    @Override
-    public void removeListener(HostListener listener) {
-
-    }
-
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/AsPathTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/AsPathTest.java
deleted file mode 100644
index 481ca43..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/AsPathTest.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-
-import java.util.ArrayList;
-
-import org.junit.Test;
-
-/**
- * Unit tests for the BgpRouteEntry.AsPath class.
- */
-public class AsPathTest {
-    /**
-     * Generates Path Segments.
-     *
-     * @return the generated Path Segments
-     */
-    private ArrayList<BgpRouteEntry.PathSegment> generatePathSegments() {
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType;
-        ArrayList<Long> segmentAsNumbers;
-        BgpRouteEntry.PathSegment pathSegment;
-
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 1);
-        segmentAsNumbers.add((long) 2);
-        segmentAsNumbers.add((long) 3);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_CONFED_SET;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 4);
-        segmentAsNumbers.add((long) 5);
-        segmentAsNumbers.add((long) 6);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 7);
-        segmentAsNumbers.add((long) 8);
-        segmentAsNumbers.add((long) 9);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SET;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 10);
-        segmentAsNumbers.add((long) 11);
-        segmentAsNumbers.add((long) 12);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-
-        return pathSegments;
-    }
-
-    /**
-     * Generates an AS Path.
-     *
-     * @return a generated AS Path
-     */
-    private BgpRouteEntry.AsPath generateAsPath() {
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments =
-            generatePathSegments();
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-
-        return asPath;
-    }
-
-    /**
-     * Tests valid class constructor.
-     */
-    @Test
-    public void testConstructor() {
-        BgpRouteEntry.AsPath asPath = generateAsPath();
-
-        String expectedString =
-            "AsPath{pathSegments=[" +
-            "PathSegment{type=AS_CONFED_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
-            "PathSegment{type=AS_CONFED_SET, segmentAsNumbers=[4, 5, 6]}, " +
-            "PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[7, 8, 9]}, " +
-            "PathSegment{type=AS_SET, segmentAsNumbers=[10, 11, 12]}]}";
-        assertThat(asPath.toString(), is(expectedString));
-    }
-
-    /**
-     * Tests invalid class constructor for null Path Segments.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullPathSegments() {
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = null;
-        new BgpRouteEntry.AsPath(pathSegments);
-    }
-
-    /**
-     * Tests getting the fields of an AS Path.
-     */
-    @Test
-    public void testGetFields() {
-        // Create the fields to compare against
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments =
-            generatePathSegments();
-
-        // Generate the entry to test
-        BgpRouteEntry.AsPath asPath = generateAsPath();
-
-        assertThat(asPath.getPathSegments(), is(pathSegments));
-    }
-
-    /**
-     * Tests getting the AS Path Length.
-     */
-    @Test
-    public void testGetAsPathLength() {
-        //
-        // NOTE:
-        //  - AS_CONFED_SEQUENCE and AS_CONFED_SET are excluded
-        //  - AS_SET counts as a single hop
-        //
-        BgpRouteEntry.AsPath asPath = generateAsPath();
-        assertThat(asPath.getAsPathLength(), is(4));
-
-        // Create an empty AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        asPath = new BgpRouteEntry.AsPath(pathSegments);
-        assertThat(asPath.getAsPathLength(), is(0));
-    }
-
-    /**
-     * Tests equality of {@link BgpRouteEntry.AsPath}.
-     */
-    @Test
-    public void testEquality() {
-        BgpRouteEntry.AsPath asPath1 = generateAsPath();
-        BgpRouteEntry.AsPath asPath2 = generateAsPath();
-
-        assertThat(asPath1, is(asPath2));
-    }
-
-    /**
-     * Tests non-equality of {@link BgpRouteEntry.AsPath}.
-     */
-    @Test
-    public void testNonEquality() {
-        BgpRouteEntry.AsPath asPath1 = generateAsPath();
-
-        // Setup AS Path 2
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType;
-        ArrayList<Long> segmentAsNumbers;
-        BgpRouteEntry.PathSegment pathSegment;
-
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 1);
-        segmentAsNumbers.add((long) 2);
-        segmentAsNumbers.add((long) 3);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_CONFED_SET;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 4);
-        segmentAsNumbers.add((long) 5);
-        segmentAsNumbers.add((long) 6);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 7);
-        segmentAsNumbers.add((long) 8);
-        segmentAsNumbers.add((long) 9);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SET;
-        segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 10);
-        segmentAsNumbers.add((long) 111);                       // Different
-        segmentAsNumbers.add((long) 12);
-        pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-        pathSegments.add(pathSegment);
-        //
-        BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments);
-
-        assertThat(asPath1, is(not(asPath2)));
-    }
-
-    /**
-     * Tests object string representation.
-     */
-    @Test
-    public void testToString() {
-        BgpRouteEntry.AsPath asPath = generateAsPath();
-
-        String expectedString =
-            "AsPath{pathSegments=[" +
-            "PathSegment{type=AS_CONFED_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
-            "PathSegment{type=AS_CONFED_SET, segmentAsNumbers=[4, 5, 6]}, " +
-            "PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[7, 8, 9]}, " +
-            "PathSegment{type=AS_SET, segmentAsNumbers=[10, 11, 12]}]}";
-        assertThat(asPath.toString(), is(expectedString));
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpRouteEntryTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpRouteEntryTest.java
deleted file mode 100644
index d53eb59..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpRouteEntryTest.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-
-import java.util.ArrayList;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-
-/**
- * Unit tests for the BgpRouteEntry class.
- */
-public class BgpRouteEntryTest {
-    private BgpSession bgpSession;
-    private static final Ip4Address BGP_SESSION_BGP_ID =
-        Ip4Address.valueOf("10.0.0.1");
-    private static final Ip4Address BGP_SESSION_IP_ADDRESS =
-        Ip4Address.valueOf("20.0.0.1");
-
-    private BgpSession bgpSession2;
-    private static final Ip4Address BGP_SESSION_BGP_ID2 =
-        Ip4Address.valueOf("10.0.0.2");
-    private static final Ip4Address BGP_SESSION_IP_ADDRESS2 =
-        Ip4Address.valueOf("20.0.0.1");
-
-    private BgpSession bgpSession3;
-    private static final Ip4Address BGP_SESSION_BGP_ID3 =
-        Ip4Address.valueOf("10.0.0.1");
-    private static final Ip4Address BGP_SESSION_IP_ADDRESS3 =
-        Ip4Address.valueOf("20.0.0.2");
-
-    private final BgpSessionInfo localInfo = new BgpSessionInfo();
-    private final BgpSessionInfo remoteInfo = new BgpSessionInfo();
-
-    private final BgpSessionInfo localInfo2 = new BgpSessionInfo();
-    private final BgpSessionInfo remoteInfo2 = new BgpSessionInfo();
-
-    private final BgpSessionInfo localInfo3 = new BgpSessionInfo();
-    private final BgpSessionInfo remoteInfo3 = new BgpSessionInfo();
-
-    @Before
-    public void setUp() throws Exception {
-        // Mock objects for testing
-        bgpSession = createMock(BgpSession.class);
-        bgpSession2 = createMock(BgpSession.class);
-        bgpSession3 = createMock(BgpSession.class);
-
-        // Setup the BGP Sessions
-        remoteInfo.setIp4Address(BGP_SESSION_IP_ADDRESS);
-        remoteInfo2.setIp4Address(BGP_SESSION_IP_ADDRESS2);
-        remoteInfo3.setIp4Address(BGP_SESSION_IP_ADDRESS3);
-        remoteInfo.setBgpId(BGP_SESSION_BGP_ID);
-        remoteInfo2.setBgpId(BGP_SESSION_BGP_ID2);
-        remoteInfo3.setBgpId(BGP_SESSION_BGP_ID3);
-
-        expect(bgpSession.localInfo()).andReturn(localInfo).anyTimes();
-        expect(bgpSession.remoteInfo()).andReturn(remoteInfo).anyTimes();
-        expect(bgpSession2.localInfo()).andReturn(localInfo2).anyTimes();
-        expect(bgpSession2.remoteInfo()).andReturn(remoteInfo2).anyTimes();
-        expect(bgpSession3.localInfo()).andReturn(localInfo3).anyTimes();
-        expect(bgpSession3.remoteInfo()).andReturn(remoteInfo3).anyTimes();
-
-        replay(bgpSession);
-        replay(bgpSession2);
-        replay(bgpSession3);
-    }
-
-    /**
-     * Generates a BGP Route Entry.
-     *
-     * @return a generated BGP Route Entry
-     */
-    private BgpRouteEntry generateBgpRouteEntry() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 1);
-        segmentAsNumbers1.add((long) 2);
-        segmentAsNumbers1.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 4);
-        segmentAsNumbers2.add((long) 5);
-        segmentAsNumbers2.add((long) 6);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 100;
-        long multiExitDisc = 20;
-
-        BgpRouteEntry bgpRouteEntry =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
-
-        return bgpRouteEntry;
-    }
-
-    /**
-     * Tests valid class constructor.
-     */
-    @Test
-    public void testConstructor() {
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-
-        String expectedString =
-            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
-            "bgpId=10.0.0.1, origin=IGP, asPath=AsPath{pathSegments=" +
-            "[PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
-            "PathSegment{type=AS_SET, segmentAsNumbers=[4, 5, 6]}]}, " +
-            "localPref=100, multiExitDisc=20}";
-        assertThat(bgpRouteEntry.toString(), is(expectedString));
-    }
-
-    /**
-     * Tests invalid class constructor for null BGP Session.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullBgpSession() {
-        BgpSession bgpSessionNull = null;
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 100;
-
-        new BgpRouteEntry(bgpSessionNull, prefix, nextHop, origin, asPath,
-                    localPref);
-    }
-
-    /**
-     * Tests invalid class constructor for null AS Path.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullAsPath() {
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        BgpRouteEntry.AsPath asPath = null;
-        long localPref = 100;
-
-        new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                    localPref);
-    }
-
-    /**
-     * Tests getting the fields of a BGP route entry.
-     */
-    @Test
-    public void testGetFields() {
-        // Create the fields to compare against
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 1);
-        segmentAsNumbers1.add((long) 2);
-        segmentAsNumbers1.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 4);
-        segmentAsNumbers2.add((long) 5);
-        segmentAsNumbers2.add((long) 6);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 100;
-        long multiExitDisc = 20;
-
-        // Generate the entry to test
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-
-        assertThat(bgpRouteEntry.prefix(), is(prefix));
-        assertThat(bgpRouteEntry.nextHop(), is(nextHop));
-        assertThat(bgpRouteEntry.getBgpSession(), is(bgpSession));
-        assertThat(bgpRouteEntry.getOrigin(), is(origin));
-        assertThat(bgpRouteEntry.getAsPath(), is(asPath));
-        assertThat(bgpRouteEntry.getLocalPref(), is(localPref));
-        assertThat(bgpRouteEntry.getMultiExitDisc(), is(multiExitDisc));
-    }
-
-    /**
-     * Tests whether a BGP route entry is a local route.
-     */
-    @Test
-    public void testIsLocalRoute() {
-        //
-        // Test non-local route
-        //
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-        assertThat(bgpRouteEntry.isLocalRoute(), is(false));
-
-        //
-        // Test local route with AS Path that begins with AS_SET
-        //
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 1);
-        segmentAsNumbers1.add((long) 2);
-        segmentAsNumbers1.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 4);
-        segmentAsNumbers2.add((long) 5);
-        segmentAsNumbers2.add((long) 6);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 100;
-        long multiExitDisc = 20;
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
-        assertThat(bgpRouteEntry.isLocalRoute(), is(true));
-
-        //
-        // Test local route with empty AS Path
-        //
-        pathSegments = new ArrayList<>();
-        asPath = new BgpRouteEntry.AsPath(pathSegments);
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
-        assertThat(bgpRouteEntry.isLocalRoute(), is(true));
-    }
-
-    /**
-     * Tests getting the BGP Neighbor AS number for a route.
-     */
-    @Test
-    public void testGetNeighborAs() {
-        //
-        // Get neighbor AS for non-local route
-        //
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-        assertThat(bgpRouteEntry.getNeighborAs(), is((long) 1));
-
-        //
-        // Get neighbor AS for a local route
-        //
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 100;
-        long multiExitDisc = 20;
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
-        assertThat(bgpRouteEntry.getNeighborAs(), is(BgpConstants.BGP_AS_0));
-    }
-
-    /**
-     * Tests whether a BGP route entry has AS Path loop.
-     */
-    @Test
-    public void testHasAsPathLoop() {
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-
-        // Test for loops: test each AS number in the interval [1, 6]
-        for (int i = 1; i <= 6; i++) {
-            assertThat(bgpRouteEntry.hasAsPathLoop(i), is(true));
-        }
-
-        // Test for non-loops
-        assertThat(bgpRouteEntry.hasAsPathLoop(500), is(false));
-    }
-
-    /**
-     * Tests the BGP Decision Process comparison of BGP routes.
-     */
-    @Test
-    public void testBgpDecisionProcessComparison() {
-        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
-        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
-
-        //
-        // Compare two routes that are same
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
-
-        //
-        // Compare two routes with different LOCAL_PREF
-        //
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 1);
-        segmentAsNumbers1.add((long) 2);
-        segmentAsNumbers1.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 4);
-        segmentAsNumbers2.add((long) 5);
-        segmentAsNumbers2.add((long) 6);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 50;                                    // Different
-        long multiExitDisc = 20;
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
-        localPref = bgpRouteEntry1.getLocalPref();              // Restore
-
-        //
-        // Compare two routes with different AS_PATH length
-        //
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments2 = new ArrayList<>();
-        pathSegments2.add(pathSegment1);
-        // Different AS Path
-        BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments2);
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath2,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(false));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));
-
-        //
-        // Compare two routes with different ORIGIN
-        //
-        origin = BgpConstants.Update.Origin.EGP;                // Different
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
-        origin = bgpRouteEntry1.getOrigin();                    // Restore
-
-        //
-        // Compare two routes with different MULTI_EXIT_DISC
-        //
-        multiExitDisc = 10;                                     // Different
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
-        multiExitDisc = bgpRouteEntry1.getMultiExitDisc();      // Restore
-
-        //
-        // Compare two routes with different BGP ID
-        //
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession2, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
-
-        //
-        // Compare two routes with different BGP address
-        //
-        bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession3, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-        //
-        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
-        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
-    }
-
-    /**
-     * Tests equality of {@link BgpRouteEntry}.
-     */
-    @Test
-    public void testEquality() {
-        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
-        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();
-
-        assertThat(bgpRouteEntry1, is(bgpRouteEntry2));
-    }
-
-    /**
-     * Tests non-equality of {@link BgpRouteEntry}.
-     */
-    @Test
-    public void testNonEquality() {
-        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
-
-        // Setup BGP Route 2
-        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
-        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
-        byte origin = BgpConstants.Update.Origin.IGP;
-        // Setup the AS Path
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 1);
-        segmentAsNumbers1.add((long) 2);
-        segmentAsNumbers1.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 4);
-        segmentAsNumbers2.add((long) 5);
-        segmentAsNumbers2.add((long) 6);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
-        //
-        long localPref = 500;                                   // Different
-        long multiExitDisc = 20;
-        BgpRouteEntry bgpRouteEntry2 =
-            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
-                              localPref);
-        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
-
-        assertThat(bgpRouteEntry1, is(not(bgpRouteEntry2)));
-    }
-
-    /**
-     * Tests object string representation.
-     */
-    @Test
-    public void testToString() {
-        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
-
-        String expectedString =
-            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
-            "bgpId=10.0.0.1, origin=IGP, asPath=AsPath{pathSegments=" +
-            "[PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
-            "PathSegment{type=AS_SET, segmentAsNumbers=[4, 5, 6]}]}, " +
-            "localPref=100, multiExitDisc=20}";
-        assertThat(bgpRouteEntry.toString(), is(expectedString));
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpSessionManagerTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpSessionManagerTest.java
deleted file mode 100644
index 7ae8658..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/BgpSessionManagerTest.java
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-import org.jboss.netty.bootstrap.ClientBootstrap;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelFactory;
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.channel.ChannelPipelineFactory;
-import org.jboss.netty.channel.Channels;
-import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.junit.TestUtils;
-import org.onlab.junit.TestUtils.TestUtilsException;
-import org.onosproject.sdnip.RouteListener;
-import org.onosproject.sdnip.RouteUpdate;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-
-import com.google.common.net.InetAddresses;
-
-/**
- * Unit tests for the BgpSessionManager class.
- */
-public class BgpSessionManagerTest {
-    private static final Ip4Address IP_LOOPBACK_ID =
-        Ip4Address.valueOf("127.0.0.1");
-    private static final Ip4Address BGP_PEER1_ID =
-        Ip4Address.valueOf("10.0.0.1");
-    private static final Ip4Address BGP_PEER2_ID =
-        Ip4Address.valueOf("10.0.0.2");
-    private static final Ip4Address BGP_PEER3_ID =
-        Ip4Address.valueOf("10.0.0.3");
-    private static final Ip4Address NEXT_HOP1_ROUTER =
-        Ip4Address.valueOf("10.20.30.41");
-    private static final Ip4Address NEXT_HOP2_ROUTER =
-        Ip4Address.valueOf("10.20.30.42");
-    private static final Ip4Address NEXT_HOP3_ROUTER =
-        Ip4Address.valueOf("10.20.30.43");
-
-    private static final long DEFAULT_LOCAL_PREF = 10;
-    private static final long BETTER_LOCAL_PREF = 20;
-    private static final long DEFAULT_MULTI_EXIT_DISC = 20;
-    private static final long BETTER_MULTI_EXIT_DISC = 30;
-
-    BgpRouteEntry.AsPath asPathShort;
-    BgpRouteEntry.AsPath asPathLong;
-
-    // Timeout waiting for a message to be received
-    private static final int MESSAGE_TIMEOUT_MS = 5000; // 5s
-
-    // The BGP Session Manager to test
-    private BgpSessionManager bgpSessionManager;
-
-    // Remote Peer state
-    private final Collection<TestBgpPeer> peers = new LinkedList<>();
-    TestBgpPeer peer1;
-    TestBgpPeer peer2;
-    TestBgpPeer peer3;
-
-    // Local BGP per-peer session state
-    BgpSession bgpSession1;
-    BgpSession bgpSession2;
-    BgpSession bgpSession3;
-
-    // The socket that the remote peers should connect to
-    private InetSocketAddress connectToSocket;
-
-    private final DummyRouteListener dummyRouteListener =
-        new DummyRouteListener();
-
-    /**
-     * Dummy implementation for the RouteListener interface.
-     */
-    private class DummyRouteListener implements RouteListener {
-        @Override
-        public void update(Collection<RouteUpdate> routeUpdate) {
-            // Nothing to do
-        }
-    }
-
-    /**
-     * A class to capture the state for a BGP peer.
-     */
-    private final class TestBgpPeer {
-        private final Ip4Address peerId;
-        private ClientBootstrap peerBootstrap;
-        private TestBgpPeerChannelHandler peerChannelHandler;
-        private TestBgpPeerFrameDecoder peerFrameDecoder =
-            new TestBgpPeerFrameDecoder();
-
-        /**
-         * Constructor.
-         *
-         * @param peerId the peer ID
-         */
-        private TestBgpPeer(Ip4Address peerId) {
-            this.peerId = peerId;
-            peerChannelHandler = new TestBgpPeerChannelHandler(peerId);
-        }
-
-        /**
-         * Starts up the BGP peer and connects it to the tested SDN-IP
-         * instance.
-         *
-         * @param connectToSocket the socket to connect to
-         */
-        private void connect(InetSocketAddress connectToSocket)
-            throws InterruptedException {
-            //
-            // Setup the BGP Peer, i.e., the "remote" BGP router that will
-            // initiate the BGP connection, send BGP UPDATE messages, etc.
-            //
-            ChannelFactory channelFactory =
-                new NioClientSocketChannelFactory(
-                        Executors.newCachedThreadPool(),
-                        Executors.newCachedThreadPool());
-            ChannelPipelineFactory pipelineFactory =
-                new ChannelPipelineFactory() {
-                    @Override
-                    public ChannelPipeline getPipeline() throws Exception {
-                        // Setup the transmitting pipeline
-                        ChannelPipeline pipeline = Channels.pipeline();
-                        pipeline.addLast("TestBgpPeerFrameDecoder",
-                                         peerFrameDecoder);
-                        pipeline.addLast("TestBgpPeerChannelHandler",
-                                         peerChannelHandler);
-                        return pipeline;
-                    }
-                };
-
-            peerBootstrap = new ClientBootstrap(channelFactory);
-            peerBootstrap.setOption("child.keepAlive", true);
-            peerBootstrap.setOption("child.tcpNoDelay", true);
-            peerBootstrap.setPipelineFactory(pipelineFactory);
-            peerBootstrap.connect(connectToSocket);
-
-            boolean result;
-            // Wait until the OPEN message is received
-            result = peerFrameDecoder.receivedOpenMessageLatch.await(
-                MESSAGE_TIMEOUT_MS,
-                TimeUnit.MILLISECONDS);
-            assertThat(result, is(true));
-            // Wait until the KEEPALIVE message is received
-            result = peerFrameDecoder.receivedKeepaliveMessageLatch.await(
-                MESSAGE_TIMEOUT_MS,
-                TimeUnit.MILLISECONDS);
-            assertThat(result, is(true));
-
-            for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
-                if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER1_ID)) {
-                    bgpSession1 = bgpSession;
-                }
-                if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER2_ID)) {
-                    bgpSession2 = bgpSession;
-                }
-                if (bgpSession.remoteInfo().bgpId().equals(BGP_PEER3_ID)) {
-                    bgpSession3 = bgpSession;
-                }
-            }
-        }
-    }
-
-    /**
-     * Class that implements a matcher for BgpRouteEntry by considering
-     * the BGP peer the entry was received from.
-     */
-    private static final class BgpRouteEntryAndPeerMatcher
-        extends TypeSafeMatcher<Collection<BgpRouteEntry>> {
-        private final BgpRouteEntry bgpRouteEntry;
-
-        private BgpRouteEntryAndPeerMatcher(BgpRouteEntry bgpRouteEntry) {
-            this.bgpRouteEntry = bgpRouteEntry;
-        }
-
-        @Override
-        public boolean matchesSafely(Collection<BgpRouteEntry> entries) {
-            for (BgpRouteEntry entry : entries) {
-                if (bgpRouteEntry.equals(entry) &&
-                    bgpRouteEntry.getBgpSession() == entry.getBgpSession()) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void describeTo(Description description) {
-            description.appendText("BGP route entry lookup for entry \"").
-                appendText(bgpRouteEntry.toString()).
-                appendText("\"");
-        }
-    }
-
-    /**
-     * A helper method used for testing whether a collection of
-     * BGP route entries contains an entry from a specific BGP peer.
-     *
-     * @param bgpRouteEntry the BGP route entry to test
-     * @return an instance of BgpRouteEntryAndPeerMatcher that implements
-     * the matching logic
-     */
-    private static BgpRouteEntryAndPeerMatcher hasBgpRouteEntry(
-        BgpRouteEntry bgpRouteEntry) {
-        return new BgpRouteEntryAndPeerMatcher(bgpRouteEntry);
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        peer1 = new TestBgpPeer(BGP_PEER1_ID);
-        peer2 = new TestBgpPeer(BGP_PEER2_ID);
-        peer3 = new TestBgpPeer(BGP_PEER3_ID);
-        peers.clear();
-        peers.add(peer1);
-        peers.add(peer2);
-        peers.add(peer3);
-
-        //
-        // Setup the BGP Session Manager to test, and start listening for BGP
-        // connections.
-        //
-        bgpSessionManager = new BgpSessionManager(dummyRouteListener);
-        // NOTE: We use port 0 to bind on any available port
-        bgpSessionManager.start(0);
-
-        // Get the port number the BGP Session Manager is listening on
-        Channel serverChannel = TestUtils.getField(bgpSessionManager,
-                                                   "serverChannel");
-        SocketAddress socketAddress = serverChannel.getLocalAddress();
-        InetSocketAddress inetSocketAddress =
-            (InetSocketAddress) socketAddress;
-        InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
-        connectToSocket = new InetSocketAddress(connectToAddress,
-                                                inetSocketAddress.getPort());
-
-        //
-        // Setup the AS Paths
-        //
-        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
-        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
-        segmentAsNumbers1.add((long) 65010);
-        segmentAsNumbers1.add((long) 65020);
-        segmentAsNumbers1.add((long) 65030);
-        BgpRouteEntry.PathSegment pathSegment1 =
-            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
-        pathSegments.add(pathSegment1);
-        asPathShort = new BgpRouteEntry.AsPath(new ArrayList(pathSegments));
-        //
-        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
-        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
-        segmentAsNumbers2.add((long) 65041);
-        segmentAsNumbers2.add((long) 65042);
-        segmentAsNumbers2.add((long) 65043);
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
-        pathSegments.add(pathSegment2);
-        //
-        asPathLong = new BgpRouteEntry.AsPath(pathSegments);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        bgpSessionManager.stop();
-        bgpSessionManager = null;
-    }
-
-    /**
-     * Gets BGP RIB-IN routes by waiting until they are received.
-     * <p>
-     * NOTE: We keep checking once every 10ms the number of received routes,
-     * up to 5 seconds.
-     * </p>
-     *
-     * @param bgpSession the BGP session that is expected to receive the
-     * routes
-     * @param expectedRoutes the expected number of routes
-     * @return the BGP RIB-IN routes as received within the expected
-     * time interval
-     */
-    private Collection<BgpRouteEntry> waitForBgpRibIn(BgpSession bgpSession,
-                                                      long expectedRoutes)
-        throws InterruptedException {
-        Collection<BgpRouteEntry> bgpRibIn = bgpSession.getBgpRibIn4();
-
-        final int maxChecks = 500;              // Max wait of 5 seconds
-        for (int i = 0; i < maxChecks; i++) {
-            if (bgpRibIn.size() == expectedRoutes) {
-                break;
-            }
-            Thread.sleep(10);
-            bgpRibIn = bgpSession.getBgpRibIn4();
-        }
-
-        return bgpRibIn;
-    }
-
-    /**
-     * Gets BGP merged routes by waiting until they are received.
-     * <p>
-     * NOTE: We keep checking once every 10ms the number of received routes,
-     * up to 5 seconds.
-     * </p>
-     *
-     * @param expectedRoutes the expected number of routes
-     * @return the BGP Session Manager routes as received within the expected
-     * time interval
-     */
-    private Collection<BgpRouteEntry> waitForBgpRoutes(long expectedRoutes)
-        throws InterruptedException {
-        Collection<BgpRouteEntry> bgpRoutes =
-            bgpSessionManager.getBgpRoutes4();
-
-        final int maxChecks = 500;              // Max wait of 5 seconds
-        for (int i = 0; i < maxChecks; i++) {
-            if (bgpRoutes.size() == expectedRoutes) {
-                break;
-            }
-            Thread.sleep(10);
-            bgpRoutes = bgpSessionManager.getBgpRoutes4();
-        }
-
-        return bgpRoutes;
-    }
-
-    /**
-     * Gets a merged BGP route by waiting until it is received.
-     * <p>
-     * NOTE: We keep checking once every 10ms whether the route is received,
-     * up to 5 seconds.
-     * </p>
-     *
-     * @param expectedRoute the expected route
-     * @return the merged BGP route if received within the expected time
-     * interval, otherwise null
-     */
-    private BgpRouteEntry waitForBgpRoute(BgpRouteEntry expectedRoute)
-        throws InterruptedException {
-        Collection<BgpRouteEntry> bgpRoutes =
-            bgpSessionManager.getBgpRoutes4();
-
-        final int maxChecks = 500;              // Max wait of 5 seconds
-        for (int i = 0; i < maxChecks; i++) {
-            for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
-                if (bgpRouteEntry.equals(expectedRoute) &&
-                    bgpRouteEntry.getBgpSession() ==
-                    expectedRoute.getBgpSession()) {
-                    return bgpRouteEntry;
-                }
-            }
-            Thread.sleep(10);
-            bgpRoutes = bgpSessionManager.getBgpRoutes4();
-        }
-
-        return null;
-    }
-
-    /**
-     * Tests that the BGP OPEN messages have been exchanged, followed by
-     * KEEPALIVE.
-     * <p>
-     * The BGP Peer opens the sessions and transmits OPEN Message, eventually
-     * followed by KEEPALIVE. The tested BGP listener should respond by
-     * OPEN Message, followed by KEEPALIVE.
-     * </p>
-     *
-     * @throws TestUtilsException TestUtils error
-     */
-    @Test
-    public void testExchangedBgpOpenMessages()
-            throws InterruptedException, TestUtilsException {
-        // Initiate the connections
-        peer1.connect(connectToSocket);
-        peer2.connect(connectToSocket);
-        peer3.connect(connectToSocket);
-
-        //
-        // Test the fields from the BGP OPEN message:
-        // BGP version, AS number, BGP ID
-        //
-        for (TestBgpPeer peer : peers) {
-            assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
-                       is(BgpConstants.BGP_VERSION));
-            assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
-                       is(IP_LOOPBACK_ID));
-            assertThat(peer.peerFrameDecoder.remoteInfo.asNumber(),
-                       is(TestBgpPeerChannelHandler.PEER_AS));
-        }
-
-        //
-        // Test that the BgpSession instances have been created
-        //
-        assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
-        assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
-        assertThat(bgpSession1, notNullValue());
-        assertThat(bgpSession2, notNullValue());
-        assertThat(bgpSession3, notNullValue());
-        for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
-            long sessionAs = bgpSession.localInfo().asNumber();
-            assertThat(sessionAs, is(TestBgpPeerChannelHandler.PEER_AS));
-        }
-    }
-
-
-    /**
-     * Tests that the BGP OPEN with Capability messages have been exchanged,
-     * followed by KEEPALIVE.
-     * <p>
-     * The BGP Peer opens the sessions and transmits OPEN Message, eventually
-     * followed by KEEPALIVE. The tested BGP listener should respond by
-     * OPEN Message, followed by KEEPALIVE.
-     * </p>
-     *
-     * @throws TestUtilsException TestUtils error
-     */
-    @Test
-    public void testExchangedBgpOpenCapabilityMessages()
-            throws InterruptedException, TestUtilsException {
-        //
-        // Setup the BGP Capabilities for all peers
-        //
-        for (TestBgpPeer peer : peers) {
-            peer.peerChannelHandler.localInfo.setIpv4Unicast();
-            peer.peerChannelHandler.localInfo.setIpv4Multicast();
-            peer.peerChannelHandler.localInfo.setIpv6Unicast();
-            peer.peerChannelHandler.localInfo.setIpv6Multicast();
-            peer.peerChannelHandler.localInfo.setAs4OctetCapability();
-            peer.peerChannelHandler.localInfo.setAs4Number(
-                TestBgpPeerChannelHandler.PEER_AS4);
-        }
-
-        // Initiate the connections
-        peer1.connect(connectToSocket);
-        peer2.connect(connectToSocket);
-        peer3.connect(connectToSocket);
-
-        //
-        // Test the fields from the BGP OPEN message:
-        // BGP version, BGP ID
-        //
-        for (TestBgpPeer peer : peers) {
-            assertThat(peer.peerFrameDecoder.remoteInfo.bgpVersion(),
-                       is(BgpConstants.BGP_VERSION));
-            assertThat(peer.peerFrameDecoder.remoteInfo.bgpId(),
-                       is(IP_LOOPBACK_ID));
-        }
-
-        //
-        // Test that the BgpSession instances have been created,
-        // and contain the appropriate BGP session information.
-        //
-        assertThat(bgpSessionManager.getMyBgpId(), is(IP_LOOPBACK_ID));
-        assertThat(bgpSessionManager.getBgpSessions(), hasSize(3));
-        assertThat(bgpSession1, notNullValue());
-        assertThat(bgpSession2, notNullValue());
-        assertThat(bgpSession3, notNullValue());
-        for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) {
-            BgpSessionInfo localInfo = bgpSession.localInfo();
-            assertThat(localInfo.ipv4Unicast(), is(true));
-            assertThat(localInfo.ipv4Multicast(), is(true));
-            assertThat(localInfo.ipv6Unicast(), is(true));
-            assertThat(localInfo.ipv6Multicast(), is(true));
-            assertThat(localInfo.as4OctetCapability(), is(true));
-            assertThat(localInfo.asNumber(),
-                       is(TestBgpPeerChannelHandler.PEER_AS4));
-            assertThat(localInfo.as4Number(),
-                       is(TestBgpPeerChannelHandler.PEER_AS4));
-        }
-    }
-
-    /**
-     * Tests that the BGP UPDATE messages have been received and processed.
-     */
-    @Test
-    public void testProcessedBgpUpdateMessages() throws InterruptedException {
-        ChannelBuffer message;
-        BgpRouteEntry bgpRouteEntry;
-        Collection<BgpRouteEntry> bgpRibIn1;
-        Collection<BgpRouteEntry> bgpRibIn2;
-        Collection<BgpRouteEntry> bgpRibIn3;
-        Collection<BgpRouteEntry> bgpRoutes;
-
-        // Initiate the connections
-        peer1.connect(connectToSocket);
-        peer2.connect(connectToSocket);
-        peer3.connect(connectToSocket);
-
-        // Prepare routes to add/delete
-        Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
-        Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
-
-        //
-        // Add and delete some routes
-        //
-        addedRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
-        addedRoutes.add(Ip4Prefix.valueOf("40.0.0.0/24"));
-        addedRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("60.0.0.0/8"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("70.0.0.0/16"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("80.0.0.0/24"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("90.0.0.0/32"));
-        // Write the routes
-        message = peer1.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP1_ROUTER,
-                        DEFAULT_LOCAL_PREF,
-                        DEFAULT_MULTI_EXIT_DISC,
-                        asPathLong,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer1.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn1 = waitForBgpRibIn(bgpSession1, 5);
-        assertThat(bgpRibIn1, hasSize(5));
-        bgpRoutes = waitForBgpRoutes(5);
-        assertThat(bgpRoutes, hasSize(5));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("0.0.0.0/0"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("30.0.0.0/16"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("40.0.0.0/24"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("50.0.0.0/32"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-        //
-        // Delete some routes
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        withdrawnRoutes.add(Ip4Prefix.valueOf("0.0.0.0/0"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("50.0.0.0/32"));
-        // Write the routes
-        message = peer1.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP1_ROUTER,
-                        DEFAULT_LOCAL_PREF,
-                        DEFAULT_MULTI_EXIT_DISC,
-                        asPathLong,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer1.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn1 = waitForBgpRibIn(bgpSession1, 3);
-        assertThat(bgpRibIn1, hasSize(3));
-        bgpRoutes = waitForBgpRoutes(3);
-        assertThat(bgpRoutes, hasSize(3));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("30.0.0.0/16"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("40.0.0.0/24"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              DEFAULT_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-
-        // Close the channels and test there are no routes
-        peer1.peerChannelHandler.closeChannel();
-        peer2.peerChannelHandler.closeChannel();
-        peer3.peerChannelHandler.closeChannel();
-        bgpRoutes = waitForBgpRoutes(0);
-        assertThat(bgpRoutes, hasSize(0));
-    }
-
-    /**
-     * Tests the BGP route preference.
-     */
-    @Test
-    public void testBgpRoutePreference() throws InterruptedException {
-        ChannelBuffer message;
-        BgpRouteEntry bgpRouteEntry;
-        Collection<BgpRouteEntry> bgpRibIn1;
-        Collection<BgpRouteEntry> bgpRibIn2;
-        Collection<BgpRouteEntry> bgpRibIn3;
-        Collection<BgpRouteEntry> bgpRoutes;
-        Collection<Ip4Prefix> addedRoutes = new LinkedList<>();
-        Collection<Ip4Prefix> withdrawnRoutes = new LinkedList<>();
-
-        // Initiate the connections
-        peer1.connect(connectToSocket);
-        peer2.connect(connectToSocket);
-        peer3.connect(connectToSocket);
-
-        //
-        // Setup the initial set of routes to Peer1
-        //
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        addedRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
-        // Write the routes
-        message = peer1.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP1_ROUTER,
-                        DEFAULT_LOCAL_PREF,
-                        DEFAULT_MULTI_EXIT_DISC,
-                        asPathLong,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer1.peerChannelHandler.savedCtx.getChannel().write(message);
-        bgpRoutes = waitForBgpRoutes(2);
-        assertThat(bgpRoutes, hasSize(2));
-
-        //
-        // Add a route entry to Peer2 with a better LOCAL_PREF
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        // Write the routes
-        message = peer2.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP2_ROUTER,
-                        BETTER_LOCAL_PREF,
-                        DEFAULT_MULTI_EXIT_DISC,
-                        asPathLong,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer2.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
-        assertThat(bgpRibIn2, hasSize(1));
-        bgpRoutes = waitForBgpRoutes(2);
-        assertThat(bgpRoutes, hasSize(2));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession2,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP2_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathLong,
-                              BETTER_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-        //
-        // Add a route entry to Peer3 with a shorter AS path
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        // Write the routes
-        message = peer3.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP3_ROUTER,
-                        BETTER_LOCAL_PREF,
-                        DEFAULT_MULTI_EXIT_DISC,
-                        asPathShort,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer3.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn3 = waitForBgpRibIn(bgpSession3, 1);
-        assertThat(bgpRibIn3, hasSize(1));
-        bgpRoutes = waitForBgpRoutes(2);
-        assertThat(bgpRoutes, hasSize(2));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession3,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP3_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathShort,
-                              BETTER_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(DEFAULT_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn3, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-        //
-        // Cleanup in preparation for next test: delete old route entry from
-        // Peer2
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        withdrawnRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        // Write the routes
-        message = peer2.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP2_ROUTER,
-                        BETTER_LOCAL_PREF,
-                        BETTER_MULTI_EXIT_DISC,
-                        asPathShort,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer2.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn2 = waitForBgpRibIn(bgpSession2, 0);
-        assertThat(bgpRibIn2, hasSize(0));
-
-        //
-        // Add a route entry to Peer2 with a better MED
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        // Write the routes
-        message = peer2.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP2_ROUTER,
-                        BETTER_LOCAL_PREF,
-                        BETTER_MULTI_EXIT_DISC,
-                        asPathShort,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer2.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn2 = waitForBgpRibIn(bgpSession2, 1);
-        assertThat(bgpRibIn2, hasSize(1));
-        bgpRoutes = waitForBgpRoutes(2);
-        assertThat(bgpRoutes, hasSize(2));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession2,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP2_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathShort,
-                              BETTER_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn2, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-        //
-        // Add a route entry to Peer1 with a better (lower) BGP ID
-        //
-        addedRoutes = new LinkedList<>();
-        withdrawnRoutes = new LinkedList<>();
-        addedRoutes.add(Ip4Prefix.valueOf("20.0.0.0/8"));
-        withdrawnRoutes.add(Ip4Prefix.valueOf("30.0.0.0/16"));
-        // Write the routes
-        message = peer1.peerChannelHandler.prepareBgpUpdate(
-                        NEXT_HOP1_ROUTER,
-                        BETTER_LOCAL_PREF,
-                        BETTER_MULTI_EXIT_DISC,
-                        asPathShort,
-                        addedRoutes,
-                        withdrawnRoutes);
-        peer1.peerChannelHandler.savedCtx.getChannel().write(message);
-        //
-        // Check that the routes have been received, processed and stored
-        //
-        bgpRibIn1 = waitForBgpRibIn(bgpSession1, 1);
-        assertThat(bgpRibIn1, hasSize(1));
-        bgpRoutes = waitForBgpRoutes(1);
-        assertThat(bgpRoutes, hasSize(1));
-        //
-        bgpRouteEntry =
-            new BgpRouteEntry(bgpSession1,
-                              Ip4Prefix.valueOf("20.0.0.0/8"),
-                              NEXT_HOP1_ROUTER,
-                              (byte) BgpConstants.Update.Origin.IGP,
-                              asPathShort,
-                              BETTER_LOCAL_PREF);
-        bgpRouteEntry.setMultiExitDisc(BETTER_MULTI_EXIT_DISC);
-        assertThat(bgpRibIn1, hasBgpRouteEntry(bgpRouteEntry));
-        assertThat(waitForBgpRoute(bgpRouteEntry), notNullValue());
-
-
-        // Close the channels and test there are no routes
-        peer1.peerChannelHandler.closeChannel();
-        peer2.peerChannelHandler.closeChannel();
-        peer3.peerChannelHandler.closeChannel();
-        bgpRoutes = waitForBgpRoutes(0);
-        assertThat(bgpRoutes, hasSize(0));
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/PathSegmentTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/PathSegmentTest.java
deleted file mode 100644
index e8f2ddc..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/PathSegmentTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-
-import java.util.ArrayList;
-
-import org.junit.Test;
-
-/**
- * Unit tests for the BgpRouteEntry.PathSegment class.
- */
-public class PathSegmentTest {
-    /**
-     * Generates a Path Segment.
-     *
-     * @return a generated PathSegment
-     */
-    private BgpRouteEntry.PathSegment generatePathSegment() {
-        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 1);
-        segmentAsNumbers.add((long) 2);
-        segmentAsNumbers.add((long) 3);
-        BgpRouteEntry.PathSegment pathSegment =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-
-        return pathSegment;
-    }
-
-    /**
-     * Tests valid class constructor.
-     */
-    @Test
-    public void testConstructor() {
-        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
-
-        String expectedString =
-            "PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}";
-        assertThat(pathSegment.toString(), is(expectedString));
-    }
-
-    /**
-     * Tests invalid class constructor for null Segment AS Numbers.
-     */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullSegmentAsNumbers() {
-        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers = null;
-        new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-    }
-
-    /**
-     * Tests getting the fields of a Path Segment.
-     */
-    @Test
-    public void testGetFields() {
-        // Create the fields to compare against
-        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 1);
-        segmentAsNumbers.add((long) 2);
-        segmentAsNumbers.add((long) 3);
-
-        // Generate the entry to test
-        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
-
-        assertThat(pathSegment.getType(), is(pathSegmentType));
-        assertThat(pathSegment.getSegmentAsNumbers(), is(segmentAsNumbers));
-    }
-
-    /**
-     * Tests equality of {@link BgpRouteEntry.PathSegment}.
-     */
-    @Test
-    public void testEquality() {
-        BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
-        BgpRouteEntry.PathSegment pathSegment2 = generatePathSegment();
-
-        assertThat(pathSegment1, is(pathSegment2));
-    }
-
-    /**
-     * Tests non-equality of {@link BgpRouteEntry.PathSegment}.
-     */
-    @Test
-    public void testNonEquality() {
-        BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
-
-        // Setup Path Segment 2
-        byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
-        ArrayList<Long> segmentAsNumbers = new ArrayList<>();
-        segmentAsNumbers.add((long) 1);
-        segmentAsNumbers.add((long) 22);                        // Different
-        segmentAsNumbers.add((long) 3);
-        //
-        BgpRouteEntry.PathSegment pathSegment2 =
-            new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
-
-        assertThat(pathSegment1, is(not(pathSegment2)));
-    }
-
-    /**
-     * Tests object string representation.
-     */
-    @Test
-    public void testToString() {
-        BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
-
-        String expectedString =
-            "PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}";
-        assertThat(pathSegment.toString(), is(expectedString));
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerChannelHandler.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerChannelHandler.java
deleted file mode 100644
index 979a1ed..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerChannelHandler.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import java.util.Collection;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelStateEvent;
-import org.jboss.netty.channel.SimpleChannelHandler;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-
-/**
- * Class for handling the remote BGP Peer session.
- */
-class TestBgpPeerChannelHandler extends SimpleChannelHandler {
-    static final long PEER_AS = 65001;
-    static final long PEER_AS4 = 0x12345678;
-    static final int PEER_HOLDTIME = 120;       // 120 seconds
-
-    final BgpSessionInfo localInfo = new BgpSessionInfo();
-    ChannelHandlerContext savedCtx;
-
-    /**
-     * Constructor for given BGP ID.
-     *
-     * @param bgpId the BGP ID to use
-     */
-    TestBgpPeerChannelHandler(Ip4Address bgpId) {
-        this.localInfo.setBgpVersion(BgpConstants.BGP_VERSION);
-        this.localInfo.setBgpId(bgpId);
-        this.localInfo.setAsNumber(PEER_AS);
-        this.localInfo.setHoldtime(PEER_HOLDTIME);
-    }
-
-    /**
-     * Closes the channel.
-     */
-    void closeChannel() {
-        savedCtx.getChannel().close();
-    }
-
-    @Override
-    public void channelConnected(ChannelHandlerContext ctx,
-                                 ChannelStateEvent channelEvent) {
-        this.savedCtx = ctx;
-        // Prepare and transmit BGP OPEN message
-        ChannelBuffer message = BgpOpen.prepareBgpOpen(localInfo);
-        ctx.getChannel().write(message);
-
-        // Prepare and transmit BGP KEEPALIVE message
-        message = BgpKeepalive.prepareBgpKeepalive();
-        ctx.getChannel().write(message);
-    }
-
-    @Override
-    public void channelDisconnected(ChannelHandlerContext ctx,
-                                    ChannelStateEvent channelEvent) {
-        // Nothing to do
-    }
-
-    /**
-     * Prepares BGP UPDATE message.
-     *
-     * @param nextHopRouter the next-hop router address for the routes to add
-     * @param localPref the local preference for the routes to use
-     * @param multiExitDisc the MED value
-     * @param asPath the AS path for the routes to add
-     * @param addedRoutes the routes to add
-     * @param withdrawnRoutes the routes to withdraw
-     * @return the message to transmit (BGP header included)
-     */
-    ChannelBuffer prepareBgpUpdate(Ip4Address nextHopRouter,
-                                   long localPref,
-                                   long multiExitDisc,
-                                   BgpRouteEntry.AsPath asPath,
-                                   Collection<Ip4Prefix> addedRoutes,
-                                   Collection<Ip4Prefix> withdrawnRoutes) {
-        int attrFlags;
-        ChannelBuffer message =
-            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
-        ChannelBuffer pathAttributes =
-            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
-
-        // Encode the Withdrawn Routes
-        ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
-        message.writeShort(encodedPrefixes.readableBytes());
-        message.writeBytes(encodedPrefixes);
-
-        // Encode the Path Attributes
-        // ORIGIN: IGP
-        attrFlags = 0x40;                               // Transitive flag
-        pathAttributes.writeByte(attrFlags);
-        pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
-        pathAttributes.writeByte(1);                    // Data length
-        pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
-
-        // AS_PATH: asPath
-        attrFlags = 0x40;                               // Transitive flag
-        pathAttributes.writeByte(attrFlags);
-        pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
-        ChannelBuffer encodedAsPath = encodeAsPath(asPath);
-        pathAttributes.writeByte(encodedAsPath.readableBytes()); // Data length
-        pathAttributes.writeBytes(encodedAsPath);
-        // NEXT_HOP: nextHopRouter
-        attrFlags = 0x40;                               // Transitive flag
-        pathAttributes.writeByte(attrFlags);
-        pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
-        pathAttributes.writeByte(4);                    // Data length
-        pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
-        // LOCAL_PREF: localPref
-        attrFlags = 0x40;                               // Transitive flag
-        pathAttributes.writeByte(attrFlags);
-        pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
-        pathAttributes.writeByte(4);                    // Data length
-        pathAttributes.writeInt((int) localPref);       // Preference value
-        // MULTI_EXIT_DISC: multiExitDisc
-        attrFlags = 0x80;                               // Optional
-                                                        // Non-Transitive flag
-        pathAttributes.writeByte(attrFlags);
-        pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
-        pathAttributes.writeByte(4);                    // Data length
-        pathAttributes.writeInt((int) multiExitDisc);   // Preference value
-        // The NLRI prefixes
-        encodedPrefixes = encodePackedPrefixes(addedRoutes);
-
-        // Write the Path Attributes, beginning with its length
-        message.writeShort(pathAttributes.readableBytes());
-        message.writeBytes(pathAttributes);
-        message.writeBytes(encodedPrefixes);
-
-        return BgpMessage.prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE,
-                                            message);
-    }
-
-    /**
-     * Encodes a collection of IPv4 network prefixes in a packed format.
-     * <p>
-     * The IPv4 prefixes are encoded in the form:
-     * <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
-     * and Prefix is the IPv4 prefix (padded with trailing bits to the end
-     * of an octet).
-     *
-     * @param prefixes the prefixes to encode
-     * @return the buffer with the encoded prefixes
-     */
-    private ChannelBuffer encodePackedPrefixes(Collection<Ip4Prefix> prefixes) {
-        ChannelBuffer message =
-            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
-
-        // Write each of the prefixes
-        for (Ip4Prefix prefix : prefixes) {
-            int prefixBitlen = prefix.prefixLength();
-            int prefixBytelen = (prefixBitlen + 7) / 8;         // Round-up
-            message.writeByte(prefixBitlen);
-
-            Ip4Address address = prefix.address();
-            long value = address.toInt() & 0xffffffffL;
-            for (int i = 0; i < Ip4Address.BYTE_LENGTH; i++) {
-                if (prefixBytelen-- == 0) {
-                    break;
-                }
-                long nextByte =
-                    (value >> ((Ip4Address.BYTE_LENGTH - i - 1) * 8)) & 0xff;
-                message.writeByte((int) nextByte);
-            }
-        }
-
-        return message;
-    }
-
-    /**
-     * Encodes an AS path.
-     *
-     * @param asPath the AS path to encode
-     * @return the buffer with the encoded AS path
-     */
-    private ChannelBuffer encodeAsPath(BgpRouteEntry.AsPath asPath) {
-        ChannelBuffer message =
-            ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
-
-        for (BgpRouteEntry.PathSegment pathSegment : asPath.getPathSegments()) {
-            message.writeByte(pathSegment.getType());
-            message.writeByte(pathSegment.getSegmentAsNumbers().size());
-            for (Long asNumber : pathSegment.getSegmentAsNumbers()) {
-                message.writeShort(asNumber.intValue());
-            }
-        }
-
-        return message;
-    }
-}
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerFrameDecoder.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerFrameDecoder.java
deleted file mode 100644
index 4f39547..0000000
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/bgp/TestBgpPeerFrameDecoder.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * 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.sdnip.bgp;
-
-import java.util.concurrent.CountDownLatch;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.frame.FrameDecoder;
-import org.onlab.packet.Ip4Address;
-
-/**
- * Class for handling the decoding of the BGP messages at the remote
- * BGP peer session.
- */
-class TestBgpPeerFrameDecoder extends FrameDecoder {
-    final BgpSessionInfo remoteInfo = new BgpSessionInfo();
-
-    final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
-    final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
-
-    @Override
-    protected Object decode(ChannelHandlerContext ctx,
-                            Channel channel,
-                            ChannelBuffer buf) throws Exception {
-        // Test for minimum length of the BGP message
-        if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
-            // No enough data received
-            return null;
-        }
-
-        //
-        // Mark the current buffer position in case we haven't received
-        // the whole message.
-        //
-        buf.markReaderIndex();
-
-        //
-        // Read and check the BGP message Marker field: it must be all ones
-        //
-        byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
-        buf.readBytes(marker);
-        for (int i = 0; i < marker.length; i++) {
-            if (marker[i] != (byte) 0xff) {
-                // ERROR: Connection Not Synchronized. Close the channel.
-                ctx.getChannel().close();
-                return null;
-            }
-        }
-
-        //
-        // Read and check the BGP message Length field
-        //
-        int length = buf.readUnsignedShort();
-        if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
-            (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
-            // ERROR: Bad Message Length. Close the channel.
-            ctx.getChannel().close();
-            return null;
-        }
-
-        //
-        // Test whether the rest of the message is received:
-        // So far we have read the Marker (16 octets) and the
-        // Length (2 octets) fields.
-        //
-        int remainingMessageLen =
-            length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
-        if (buf.readableBytes() < remainingMessageLen) {
-            // No enough data received
-            buf.resetReaderIndex();
-            return null;
-        }
-
-        //
-        // Read the BGP message Type field, and process based on that type
-        //
-        int type = buf.readUnsignedByte();
-        remainingMessageLen--;      // Adjust after reading the type
-        ChannelBuffer message = buf.readBytes(remainingMessageLen);
-
-        //
-        // Process the remaining of the message based on the message type
-        //
-        switch (type) {
-        case BgpConstants.BGP_TYPE_OPEN:
-            processBgpOpen(ctx, message);
-            break;
-        case BgpConstants.BGP_TYPE_UPDATE:
-            // NOTE: Not used as part of the test, because ONOS does not
-            // originate UPDATE messages.
-            break;
-        case BgpConstants.BGP_TYPE_NOTIFICATION:
-            // NOTE: Not used as part of the testing (yet)
-            break;
-        case BgpConstants.BGP_TYPE_KEEPALIVE:
-            processBgpKeepalive(ctx, message);
-            break;
-        default:
-            // ERROR: Bad Message Type. Close the channel.
-            ctx.getChannel().close();
-            return null;
-        }
-
-        return null;
-    }
-
-    /**
-     * Processes BGP OPEN message.
-     *
-     * @param ctx the Channel Handler Context.
-     * @param message the message to process.
-     */
-    private void processBgpOpen(ChannelHandlerContext ctx,
-                                ChannelBuffer message) {
-        int minLength =
-            BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
-        if (message.readableBytes() < minLength) {
-            // ERROR: Bad Message Length. Close the channel.
-            ctx.getChannel().close();
-            return;
-        }
-
-        //
-        // Parse the OPEN message
-        //
-        remoteInfo.setBgpVersion(message.readUnsignedByte());
-        remoteInfo.setAsNumber(message.readUnsignedShort());
-        remoteInfo.setHoldtime(message.readUnsignedShort());
-        remoteInfo.setBgpId(Ip4Address.valueOf((int) message.readUnsignedInt()));
-        // Optional Parameters
-        int optParamLen = message.readUnsignedByte();
-        if (message.readableBytes() < optParamLen) {
-            // ERROR: Bad Message Length. Close the channel.
-            ctx.getChannel().close();
-            return;
-        }
-        message.readBytes(optParamLen);             // NOTE: data ignored
-
-        // BGP OPEN message successfully received
-        receivedOpenMessageLatch.countDown();
-    }
-
-    /**
-     * Processes BGP KEEPALIVE message.
-     *
-     * @param ctx the Channel Handler Context.
-     * @param message the message to process.
-     */
-    private void processBgpKeepalive(ChannelHandlerContext ctx,
-                                     ChannelBuffer message) {
-        if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
-            BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
-            // ERROR: Bad Message Length. Close the channel.
-            ctx.getChannel().close();
-            return;
-        }
-        // BGP KEEPALIVE message successfully received
-        receivedKeepaliveMessageLatch.countDown();
-    }
-}
