/*
 * Copyright 2017-present 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.incubator.net.routing.RouteAdminService;
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.createNiceMock;
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

    private RouteAdminService routeService;

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

    /**
     * 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 BgpSessionManager
         * 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 = () -> {
                // 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 void getDictionaryMock(ComponentContext componentContext) {
        Dictionary dictionary = createMock(Dictionary.class);
        expect(dictionary.get("bgpPort")).andReturn("0");
        replay(dictionary);
        expect(componentContext.getProperties()).andReturn(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();

        routeService = createNiceMock(RouteAdminService.class);
        replay(routeService);
        bgpSessionManager.routeService = routeService;

        // NOTE: We use port 0 to bind on any available port
        ComponentContext componentContext = createMock(ComponentContext.class);
        getDictionaryMock(componentContext);
        replay(componentContext);
        bgpSessionManager.activate(componentContext);

        // 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(65010L);
        segmentAsNumbers1.add(65020L);
        segmentAsNumbers1.add(65030L);
        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(65041L);
        segmentAsNumbers2.add(65042L);
        segmentAsNumbers2.add(65043L);
        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));
    }
}
