/*
 * 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
    TestBgpPeer peer1 = new TestBgpPeer(BGP_PEER1_ID);
    TestBgpPeer peer2 = new TestBgpPeer(BGP_PEER2_ID);
    TestBgpPeer peer3 = new TestBgpPeer(BGP_PEER3_ID);

    // 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 {
        //
        // 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.
     *
     * @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.
     *
     * @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;
    }

    /**
     * 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.
     *
     * @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
        //
        assertThat(peer1.peerFrameDecoder.remoteBgpVersion,
                   is(BgpConstants.BGP_VERSION));
        assertThat(peer1.peerFrameDecoder.remoteAs,
                   is(TestBgpPeerChannelHandler.PEER_AS));
        assertThat(peer1.peerFrameDecoder.remoteBgpIdentifier,
                   is(IP_LOOPBACK_ID));
        assertThat(peer2.peerFrameDecoder.remoteBgpVersion,
                   is(BgpConstants.BGP_VERSION));
        assertThat(peer2.peerFrameDecoder.remoteAs,
                   is(TestBgpPeerChannelHandler.PEER_AS));
        assertThat(peer2.peerFrameDecoder.remoteBgpIdentifier,
                   is(IP_LOOPBACK_ID));
        assertThat(peer3.peerFrameDecoder.remoteBgpVersion,
                   is(BgpConstants.BGP_VERSION));
        assertThat(peer3.peerFrameDecoder.remoteAs,
                   is(TestBgpPeerChannelHandler.PEER_AS));
        assertThat(peer3.peerFrameDecoder.remoteBgpIdentifier,
                   is(IP_LOOPBACK_ID));

        //
        // 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 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));

        //
        // 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));
        //
        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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));


        // 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));

        //
        // 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));

        //
        // 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));

        //
        // 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(bgpRoutes, hasBgpRouteEntry(bgpRouteEntry));


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