/*
 * 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.routing.bgp;

import com.google.common.net.InetAddresses;
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.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onosproject.routing.RouteListener;
import org.onosproject.routing.RouteUpdate;
import org.osgi.service.component.ComponentContext;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;

/**
 * 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);
    }

    @SuppressWarnings("unchecked")
    private Dictionary<String, String>
            getDictionaryMock(ComponentContext componentContext) {
        Dictionary<String, String> dictionary = createMock(Dictionary.class);
        expect(dictionary.get("bgpPort")).andReturn("0");
        replay(dictionary);
        expect(componentContext.getProperties()).andReturn(dictionary);
        return dictionary;
    }

    @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();
        // NOTE: We use port 0 to bind on any available port
        ComponentContext componentContext = createMock(ComponentContext.class);
        Dictionary<String, String> dictionary = getDictionaryMock(componentContext);
        replay(componentContext);
        bgpSessionManager.activate(componentContext);
        bgpSessionManager.start(dummyRouteListener);

        // 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));
    }
}
