/*
 * Copyright 2014-2015 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.bgp;

import com.google.common.net.InetAddresses;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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.Ignore;
import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.onosproject.bgp.controller.BgpCfg;
import org.onosproject.bgp.controller.BgpId;
import org.onosproject.bgp.controller.impl.AdjRibIn;
import org.onosproject.bgp.controller.impl.BgpControllerImpl;
import org.onosproject.bgp.controller.impl.BgpLocalRibImpl;
import org.onosproject.bgp.controller.impl.BgpPeerImpl;
import org.onosproject.bgp.controller.impl.VpnAdjRibIn;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetailsLocalRib;
import org.onosproject.bgpio.types.AutonomousSystemTlv;
import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
import org.onosproject.bgpio.types.IPReachabilityInformationTlv;
import org.onosproject.bgpio.types.IPv4AddressTlv;
import org.onosproject.bgpio.types.IsIsNonPseudonode;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.types.IsIsPseudonode;
import org.onosproject.bgpio.types.RouteDistinguisher;

/**
 * Test case for BGPControllerImpl.
 */
@Ignore("Tests are failing due to NPE and due to failure to bind port")
public class BgpControllerImplTest {

    protected static final Logger log = LoggerFactory
            .getLogger(BgpControllerImplTest.class);

    private static final String IP_LOOPBACK_ID1 = "127.0.0.1";

    private static final int MESSAGE_TIMEOUT_MS = 3000;
    public byte version;
    public short asNumber;
    public short holdTime;
    public int bgpId = InetAddresses.coerceToInteger(InetAddresses.forString(IP_LOOPBACK_ID1));
    public boolean isLargeAsCapabilitySet = false;
    public LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();

    @Before
    public void setUp() throws Exception {
        peer1 = new BgpPeerTest(version, asNumber,
                holdTime, bgpId, isLargeAsCapabilitySet,
                capabilityTlv);
        peer2 = new BgpPeerTest(version, asNumber,
                holdTime, bgpId, isLargeAsCapabilitySet,
                capabilityTlv);

        bgpControllerImpl = new BgpControllerImpl();

        // NOTE: We use port 0 to bind on any available port
        bgpControllerImpl.controller().setBgpPortNum();
        bgpControllerImpl.activate();

        Channel serverChannel = TestUtils.getField(bgpControllerImpl.controller(),
                                                  "serverChannel");
        SocketAddress socketAddress = serverChannel.getLocalAddress();
        InetSocketAddress inetSocketAddress =
           (InetSocketAddress) socketAddress;
        InetAddress connectToAddress = InetAddresses.forString("127.0.0.1");
        connectToSocket = new InetSocketAddress(connectToAddress,
                       inetSocketAddress.getPort());

        bgpControllerImpl.getConfig().setRouterId("1.1.1.1");
        bgpControllerImpl.getConfig().setAsNumber(200);
        bgpControllerImpl.getConfig().setHoldTime((short) 120);
        bgpControllerImpl.getConfig().setState(BgpCfg.State.IP_AS_CONFIGURED);

        bgpControllerImpl.getConfig().addPeer("127.0.0.1", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.9", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.33", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.10", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.20", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.30", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.40", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.50", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.60", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.70", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.80", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.90", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.91", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.92", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.99", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.94", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.95", 200);
        bgpControllerImpl.getConfig().addPeer("127.0.0.35", 200);
    }

    @After
    public void tearDown() throws Exception {
        bgpControllerImpl.deactivate();
        bgpControllerImpl = null;
    }

    private BgpControllerImpl bgpControllerImpl;

    BgpPeerTest peer1;
    BgpPeerTest peer2;
    // The socket that the remote peers should connect to
    private InetSocketAddress connectToSocket;

    @Test
    public void bgpOpenMessageTest1() throws InterruptedException {
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        peer1.connect(connectToSocket);
        boolean result;
        result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
        result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest2() throws InterruptedException {
        // Open message with as number which is not configured at peer
        peer1.peerChannelHandler.asNumber = 500;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest3() throws InterruptedException {
        // Open message with invalid hold time value
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 1;
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest4() throws InterruptedException {
        // Open message with invalid as number
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        peer1.peerChannelHandler.isLargeAsCapabilitySet = true;
        BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(766545);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv);
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedNotificationMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest5() throws InterruptedException {
        // Open message with LS capability
        short afi = 16388;
        byte res = 0;
        byte safi = 71;
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
        result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest6() throws InterruptedException {
        // Open message with as4 capability
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        peer1.peerChannelHandler.isLargeAsCapabilitySet = true;
        bgpControllerImpl.getConfig().setLargeASCapability(true);
        BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv);
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
        result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));

        result = peer1.peerFrameDecoder.receivedKeepaliveMessageLatch.await(
                MESSAGE_TIMEOUT_MS,
                TimeUnit.MILLISECONDS);
            assertThat(result, is(true));
    }

    @Test
    public void bgpOpenMessageTest7() throws InterruptedException {
        // Open message with both LS capability and as4 capability
        short afi = 16388;
        byte res = 0;
        byte safi = 71;
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        peer1.peerChannelHandler.isLargeAsCapabilitySet = true;
        bgpControllerImpl.getConfig().setLargeASCapability(true);
        BgpValueType tempTlv = new FourOctetAsNumCapabilityTlv(200);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv);

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer1.connect(connectToSocket);

        boolean result;
        result = peer1.peerFrameDecoder.receivedOpenMessageLatch.await(
            MESSAGE_TIMEOUT_MS,
            TimeUnit.MILLISECONDS);
        assertThat(result, is(true));
    }

    /**
     * Peer1 has Node NLRI (MpReach).
     */
    @Test
    public void testBgpUpdateMessage1() throws InterruptedException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.9", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.9"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contains specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, nodeTree should contains specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));
    }

    /**
     * Peer1 has Node NLRI (MpReach) and Peer2 has Node NLRI with same MpReach and MpUnReach.
     */
    @Test
    public void testBgpUpdateMessage2() throws InterruptedException, TestUtilsException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;
        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel = peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.95", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.95"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        TimeUnit.MILLISECONDS.sleep(500);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contains specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, nodeTree should contains specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.70", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.70"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);
        TimeUnit.MILLISECONDS.sleep(200);
        adj = peer.adjRib();

        //In Adj-RIB, nodetree should be empty
        assertThat(adj.nodeTree().isEmpty(), is(true));

        //Disconnect peer1
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        TimeUnit.MILLISECONDS.sleep(200);
        //In Local-RIB, nodetree should be empty
        assertThat(obj.nodeTree().isEmpty(), is(true));
    }

    /**
     * Peer1 has Link NLRI (MpReach).
     */
    @Test
    public void testBgpUpdateMessage3() throws InterruptedException, TestUtilsException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.10", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.10"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> localNodeSubTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteNodeSubTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2222);
        localNodeSubTlvs.add(tlv);
        remoteNodeSubTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        localNodeSubTlvs.add(tlv);
        remoteNodeSubTlvs.add(tlv);
        byte[] isoNodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21 };
        tlv = IsIsPseudonode.of(isoNodeID, (byte) 0x03);
        localNodeSubTlvs.add(tlv);
        isoNodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x02, 0x50, 0x21 };
        tlv = IsIsNonPseudonode.of(isoNodeID);
        remoteNodeSubTlvs.add(tlv);
        NodeDescriptors localNodeDes = new NodeDescriptors(localNodeSubTlvs, (short) 0x1b, (short) 256);
        NodeDescriptors remoteNodeDes = new NodeDescriptors(remoteNodeSubTlvs, (short) 0x1a, (short) 0x101);
        LinkedList<BgpValueType> linkDescriptor = new LinkedList<>();
        tlv = IPv4AddressTlv.of(Ip4Address.valueOf("2.2.2.2"), (short) 0x103);
        linkDescriptor.add(tlv);

        BgpLinkLSIdentifier key = new BgpLinkLSIdentifier(localNodeDes, remoteNodeDes, linkDescriptor);
        TimeUnit.MILLISECONDS.sleep(200);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, linkTree should contain specified key
        assertThat(adj.linkTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        TimeUnit.MILLISECONDS.sleep(200);

        //In Local-RIB, linkTree should contain specified key
        assertThat(obj.linkTree().containsKey(key), is(true));
    }

    /**
     * Peer1 has Node NLRI and Peer2 has Node NLRI with different MpReach and MpUnReach with VPN.
     */
    @Test
    public void testBgpUpdateMessage4() throws InterruptedException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = (byte) 0x80;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel =  peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.35", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        IpAddress ipAddress = IpAddress.valueOf("127.0.0.35");
        BgpId bgpId = new BgpId(ipAddress);
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);
        LinkedList<BgpValueType> subTlvs1 = new LinkedList<>();

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);

        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        RouteDistinguisher rd = new RouteDistinguisher((long) 0x0A);
        VpnAdjRibIn vpnAdj = peer.vpnAdjRib();

        //In Adj-RIB, vpnNodeTree should contain rd
        assertThat(vpnAdj.vpnNodeTree().containsKey(rd), is(true));

        Map<BgpNodeLSIdentifier, PathAttrNlriDetails> treeValue = vpnAdj.vpnNodeTree().get(rd);
        //In Adj-RIB, vpnNodeTree should contain rd key which contains specified value
        assertThat(treeValue.containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRibVpn();
        //In Local-RIB, vpnNodeTree should contain rd
        assertThat(obj.vpnNodeTree().containsKey(rd), is(true));

        Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> value = obj.vpnNodeTree().get(rd);
        //In Local-RIB, vpnNodeTree should contain rd key which contains specified value
        assertThat(value.containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.40", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.40"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        tlv = AutonomousSystemTlv.of(686);
        subTlvs1.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs1.add(tlv);
        nodeDes = new NodeDescriptors(subTlvs1, (short) 0x10, (short) 256);
        key = new BgpNodeLSIdentifier(nodeDes);
        vpnAdj = peer.vpnAdjRib();

        //In Adj-RIB, vpnNodeTree should contain rd
        assertThat(vpnAdj.vpnNodeTree().containsKey(rd), is(true));

        treeValue = vpnAdj.vpnNodeTree().get(rd);
        //In Adj-RIB, vpnNodeTree should contain rd key which contains specified value
        assertThat(treeValue.containsKey(key), is(true));

        //Disconnect peer1
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRibVpn();

        //In Local-RIB, vpnNodeTree should contain rd
        assertThat(obj.vpnNodeTree().containsKey(rd), is(true));

        value = obj.vpnNodeTree().get(rd);
        //In Local-RIB, vpnNodeTree should contain rd key which contains specified value
        assertThat(value.containsKey(key), is(true));
    }

    /**
     * Peer1 has Node NLRI and Peer2 has Node NLRI with different MpReach and MpUnReach.
     */
    @Test
    public void testBgpUpdateMessage5() throws InterruptedException, TestUtilsException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel = peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.99", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.99"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = null;
        tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        TimeUnit.MILLISECONDS.sleep(500);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contain specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, nodeTree should contain specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.92", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.92"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);
        adj = peer.adjRib();

        //In Adj-RIB, nodetree should be empty
        assertThat(adj.nodeTree().isEmpty(), is(true));

        //peer1 disconnects
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        TimeUnit.MILLISECONDS.sleep(200);

        //In Local-RIB, nodeTree should be empty
        assertThat(obj.nodeTree().isEmpty(), is(true));
    }

    /**
     * Peer2 has Prefix NLRI (MpReach).
     */
    @Test
    public void testBgpUpdateMessage6() throws InterruptedException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel = peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.94", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.94"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        TimeUnit.MILLISECONDS.sleep(500);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contain specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, nodeTree should contain specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.80", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.80"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);
        TimeUnit.MILLISECONDS.sleep(500);
        adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contain specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        //peer1 disconnects
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        TimeUnit.MILLISECONDS.sleep(200);

        //In Local-RIB, nodeTree should contain specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));
    }

    /**
     * Peer1 has Node NLRI (MpReach) and peer2 has Node NLRI with same MpReach and MpUnReach with IsIsNonPseudonode.
     */
    @Test
    public void testBgpUpdateMessage7() throws InterruptedException, TestUtilsException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel = peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.91", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.91"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        LinkedList<BgpValueType> subTlvs1 = new LinkedList<>();
        BgpValueType tlv = null;
        tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        subTlvs1.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contains specified key
        assertThat(adj.nodeTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, nodeTree should contains specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.90", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.90"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        tlv = AutonomousSystemTlv.of(2222);
        subTlvs1.add(tlv);
        byte[] isoNodeID = new byte[] {0x19, 0x00, (byte) 0x95, 0x01, (byte) 0x90, 0x58};
        tlv = IsIsNonPseudonode.of(isoNodeID);
        subTlvs1.add(tlv);
        nodeDes = new NodeDescriptors(subTlvs1, (short) 0x1a, (short) 256);
        key = new BgpNodeLSIdentifier(nodeDes);
        adj = peer.adjRib();

        //In Adj-RIB, nodeTree should contains specified key
        log.info("key " + key.toString());
        log.info("adj.nodeTree() " + adj.nodeTree().toString());
        assertThat(adj.nodeTree().containsKey(key), is(true));

        //peer1 disconnects
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        TimeUnit.MILLISECONDS.sleep(200);

        //In Local-RIB, nodeTree should contains specified key
        assertThat(obj.nodeTree().containsKey(key), is(true));
    }

    /**
     * Peer1 has Prefix NLRI (MpReach).
     */
    @Test
    public void testBgpUpdateMessage8() throws InterruptedException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 150;

        short afi = 16388;
        byte res = 0;
        byte safi = 71;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.20", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.20"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2222);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);
        byte[] isoNodeID = new byte[] {0x19, 0x21, 0x68, 0x07, 0x70, 0x01};
        tlv = IsIsNonPseudonode.of(isoNodeID);
        subTlvs.add(tlv);
        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x1a, (short) 256);
        LinkedList<BgpValueType> prefixDescriptor = new LinkedList<>();
        byte[] prefix = new byte[] {0x20, (byte) 0xc0, (byte) 0xa8, 0x4d, 0x01};
        ChannelBuffer tempCb = ChannelBuffers.dynamicBuffer();
        tempCb.writeBytes(prefix);
        tlv = IPReachabilityInformationTlv.read(tempCb, (short) 5);
        prefixDescriptor.add(tlv);
        BgpPrefixLSIdentifier key = new BgpPrefixLSIdentifier(nodeDes, prefixDescriptor);

        AdjRibIn adj = peer.adjRib();

        //In Adj-RIB, prefixTree should contain specified key
        assertThat(adj.prefixTree().containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRib();
        //In Local-RIB, prefixTree should contain specified key
        assertThat(obj.prefixTree().containsKey(key), is(true));
    }

    /**
     * Peer1 has Node NLRI (MpReach) and Peer2 has node NLRI with different MpReach
     * and MpUnReach with IsIsNonPseudonode.
     */
    @Test
    public void testBgpUpdateMessage9() throws InterruptedException {
        // Initiate the connections
        peer1.peerChannelHandler.asNumber = 200;
        peer1.peerChannelHandler.version = 4;
        peer1.peerChannelHandler.holdTime = 120;

        short afi = 16388;
        byte res = 0;
        byte safi = (byte) 0x80;

        bgpControllerImpl.getConfig().setLsCapability(true);
        BgpValueType tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer1.peerChannelHandler.capabilityTlv.add(tempTlv1);
        Channel channel = peer1.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.30", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer1
        BgpId bgpId = new BgpId(IpAddress.valueOf("127.0.0.30"));
        BgpPeerImpl peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);

        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = AutonomousSystemTlv.of(2478);
        subTlvs.add(tlv);
        tlv = BgpLSIdentifierTlv.of(33686018);
        subTlvs.add(tlv);

        NodeDescriptors nodeDes = new NodeDescriptors(subTlvs, (short) 0x10, (short) 256);
        BgpNodeLSIdentifier key = new BgpNodeLSIdentifier(nodeDes);
        RouteDistinguisher rd = new RouteDistinguisher((long) 0x0A);
        VpnAdjRibIn vpnAdj = peer.vpnAdjRib();

        //In Adj-RIB, vpnNodeTree should contain specified rd
        assertThat(vpnAdj.vpnNodeTree().containsKey(rd), is(true));

        Map<BgpNodeLSIdentifier, PathAttrNlriDetails> treeValue = vpnAdj.vpnNodeTree().get(rd);
        //In Adj-RIB, vpnNodeTree should contain specified rd with specified value
        assertThat(treeValue.containsKey(key), is(true));

        BgpLocalRibImpl obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRibVpn();
        //In Local-RIB, vpnNodeTree should contain specified rd
        assertThat(obj.vpnNodeTree().containsKey(rd), is(true));

        Map<BgpNodeLSIdentifier, PathAttrNlriDetailsLocalRib> value = obj.vpnNodeTree().get(rd);
        //In Local-RIB, vpnNodeTree should contain specified rd with specified value
        assertThat(value.containsKey(key), is(true));

        peer2.peerChannelHandler.asNumber = 200;
        peer2.peerChannelHandler.version = 4;
        peer2.peerChannelHandler.holdTime = 120;

        bgpControllerImpl.getConfig().setLsCapability(true);
        tempTlv1 = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
        peer2.peerChannelHandler.capabilityTlv.add(tempTlv1);
        peer2.connectFrom(connectToSocket, new InetSocketAddress("127.0.0.50", 0));
        TimeUnit.MILLISECONDS.sleep(1000);

        //Get peer2
        bgpId = new BgpId(IpAddress.valueOf("127.0.0.50"));
        peer = (BgpPeerImpl) bgpControllerImpl.getPeer(bgpId);
        key = new BgpNodeLSIdentifier(nodeDes);
        vpnAdj = peer.vpnAdjRib();

        //In Adj-RIB, vpnNodeTree should be empty
        assertThat(vpnAdj.vpnNodeTree().isEmpty(), is(true));

        //peer1 disconnects
        channel.disconnect();
        channel.close();

        obj = (BgpLocalRibImpl) bgpControllerImpl.bgpLocalRibVpn();
        TimeUnit.MILLISECONDS.sleep(200);

        //In Local-RIB, vpnNodeTree should be empty
        assertThat(obj.vpnNodeTree().isEmpty(), is(true));
    }

    /**
     * A class to capture the state for a BGP peer.
     */
    private final class BgpPeerTest {
        private ClientBootstrap peerBootstrap;
        private BgpPeerFrameDecoderTest peerFrameDecoder =
                new BgpPeerFrameDecoderTest();
        private BgpPeerChannelHandlerTest peerChannelHandler;

        private BgpPeerTest(byte version, short asNumber,
                short holdTime, int bgpId, boolean isLargeAsCapabilitySet,
                LinkedList<BgpValueType> capabilityTlv) {
            peerChannelHandler = new BgpPeerChannelHandlerTest(version,
                asNumber, holdTime, bgpId, isLargeAsCapabilitySet, capabilityTlv);
        }

        /**
         * Starts the BGP peer.
         *
         * @param connectToSocket the socket to connect to
         */
        private void connect(InetSocketAddress connectToSocket)
            throws InterruptedException {

            ChannelFactory channelFactory =
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool());
            ChannelPipelineFactory pipelineFactory = () -> {
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("BgpPeerFrameDecoderTest",
                        peerFrameDecoder);
                pipeline.addLast("BgpPeerChannelHandlerTest",
                        peerChannelHandler);
                return pipeline;
            };

            peerBootstrap = new ClientBootstrap(channelFactory);
            peerBootstrap.setOption("child.keepAlive", true);
            peerBootstrap.setOption("child.tcpNoDelay", true);
            peerBootstrap.setPipelineFactory(pipelineFactory);
            peerBootstrap.connect(connectToSocket);
       }

        private Channel connectFrom(InetSocketAddress connectToSocket, SocketAddress localAddress)
                throws InterruptedException {

                ChannelFactory channelFactory =
                    new NioClientSocketChannelFactory(
                            Executors.newCachedThreadPool(),
                            Executors.newCachedThreadPool());
                ChannelPipelineFactory pipelineFactory = () -> {
                    ChannelPipeline pipeline = Channels.pipeline();
                    pipeline.addLast("BgpPeerFrameDecoderTest",
                            peerFrameDecoder);
                    pipeline.addLast("BgpPeerChannelHandlerTest",
                            peerChannelHandler);
                    return pipeline;
                };

                peerBootstrap = new ClientBootstrap(channelFactory);
                peerBootstrap.setOption("child.keepAlive", true);
                peerBootstrap.setOption("child.tcpNoDelay", true);
                peerBootstrap.setPipelineFactory(pipelineFactory);
                Channel channel = peerBootstrap.connect(connectToSocket, localAddress).getChannel();
                return channel;
           }
    }
}