/*
 * Copyright 2015-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.provider.bgp.topology.impl;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNot.not;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.hamcrest.Matchers.nullValue;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

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.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onlab.util.Bandwidth;
import org.onosproject.bgp.controller.BgpLinkListener;
import org.onosproject.bgp.controller.BgpNodeListener;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4.ProtocolType;
import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
import org.onosproject.bgpio.types.AutonomousSystemTlv;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.IsIsNonPseudonode;
import org.onosproject.bgpio.types.LinkStateAttributes;
import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.resource.label.LabelResourcePool;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.mastership.MastershipEvent.Type;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv;
import org.onosproject.bgpio.types.attr.BgpAttrNodeIsIsAreaId;
import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV4;
import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric;
import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth;
import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.ConfigApplyDelegate;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.config.basics.BandwidthCapacity;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceAdminService;
import org.onosproject.net.resource.ResourceId;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * Test for BGP topology provider.
 */
public class BgpTopologyProviderTest {
    private static final DeviceId DID2 = DeviceId.deviceId("l3:rd=0::routinguniverse=0:asn=10");
    private static final String UNKNOWN = new String("unknown");
    public static ProviderId providerId = new ProviderId("l3", "foo");
    private static final NodeId NODE1 = new NodeId("Master1");

    private final BgpTopologyProvider provider = new BgpTopologyProvider();
    private final TestDeviceRegistry nodeRegistry = new TestDeviceRegistry();
    private final TestLinkRegistry linkRegistry = new TestLinkRegistry();
    private final MockBgpController controller = new MockBgpController();
    private MockDeviceService deviceService = new MockDeviceService();
    private MockLinkService linkService = new MockLinkService();
    private MockMastershipService mastershipService = new MockMastershipService();
    private MockNetConfigRegistryAdapter networkConfigService = new MockNetConfigRegistryAdapter();
    private MockLabelResourceService labelResourceAdminService = new MockLabelResourceService();
    private Map<DeviceId, Device> deviceMap = new HashMap<>();
    private MastershipListener listener;

    @Before
    public void startUp() throws TestUtilsException {
        provider.deviceProviderRegistry = nodeRegistry;
        provider.linkProviderRegistry = linkRegistry;
        provider.controller = controller;
        provider.deviceService = deviceService;
        provider.linkService = linkService;
        provider.labelResourceAdminService = labelResourceAdminService;
        provider.mastershipService = mastershipService;
        provider.networkConfigService = networkConfigService;
        listener = TestUtils.getField(provider, "masterListener");
        provider.activate();
        assertThat("device provider should be registered", not(nodeRegistry.provider));
        assertThat("link provider should be registered", not(linkRegistry.linkProvider));
        assertThat("node listener should be registered", not(controller.nodeListener));
        assertThat("link listener should be registered", not(controller.linkListener));
    }

    @After
    public void tearDown() {
        provider.deactivate();
        provider.controller = null;
        provider.deviceService = null;
        provider.deviceProviderRegistry = null;
        provider.linkService = null;
        provider.mastershipService = null;
        provider.networkConfigService = null;
        provider.labelResourceAdminService = null;
        assertThat(controller.nodeListener, is(new HashSet<BgpNodeListener>()));
        assertThat(controller.linkListener, is(new HashSet<BgpLinkListener>()));
    }

    private class MockLabelResourceService implements LabelResourceAdminService {

        Map<DeviceId, LabelResourcePool> resourcePool = new HashMap<>();

        @Override
        public boolean createDevicePool(DeviceId deviceId, LabelResourceId beginLabel, LabelResourceId endLabel) {
            LabelResourcePool labelResource = new LabelResourcePool(deviceId.toString(),
                    beginLabel.labelId(),
                    endLabel.labelId());
            if (resourcePool.containsValue(labelResource)) {
                return false;
            }

            resourcePool.put(deviceId, labelResource);
            return true;
        }

        @Override
        public boolean createGlobalPool(LabelResourceId beginLabel, LabelResourceId endLabel) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean destroyDevicePool(DeviceId deviceId) {
            LabelResourcePool devicePool = resourcePool.get(deviceId);

            if (devicePool == null) {
                return false;
            }

            resourcePool.remove(deviceId);
            return true;
        }

        @Override
        public boolean destroyGlobalPool() {
            // TODO Auto-generated method stub
            return false;
        }
    }

    /* Mock test for device service */
    private class MockNetConfigRegistryAdapter extends NetworkConfigRegistryAdapter {
        private ConfigFactory cfgFactory;
        private Map<ConnectPoint, BandwidthCapacity> classConfig = new HashMap<>();

        @Override
        public void registerConfigFactory(ConfigFactory configFactory) {
            cfgFactory = configFactory;
        }

        @Override
        public void unregisterConfigFactory(ConfigFactory configFactory) {
            cfgFactory = null;
        }

        @Override
        public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
            if (configClass == BandwidthCapacity.class) {
                BandwidthCapacity devCap = new BandwidthCapacity();
                classConfig.put((ConnectPoint) subject, devCap);

                JsonNode node = new ObjectNode(new MockJsonNode());
                ObjectMapper mapper = new ObjectMapper();
                ConfigApplyDelegate delegate = new InternalApplyDelegate();
                devCap.init((ConnectPoint) subject, null, node, mapper, delegate);
                return (C) devCap;
            }

            return null;
        }

        @Override
        public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
            classConfig.remove(subject);
        }

        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
            if (configClass == BandwidthCapacity.class) {
                return (C) classConfig.get(subject);
            }
            return null;
        }

        private class MockJsonNode extends JsonNodeFactory {
        }

        // Auxiliary delegate to receive notifications about changes applied to
        // the network configuration - by the apps.
        private class InternalApplyDelegate implements ConfigApplyDelegate {
            @Override
            public void onApply(Config config) {
            }
        }
    }

    private class MockMastershipService extends MastershipServiceAdapter {
        @Override
        public MastershipRole getLocalRole(DeviceId deviceId) {
            return MASTER;
        }

        @Override
        public boolean isLocalMaster(DeviceId deviceId) {
            return getLocalRole(deviceId) == MASTER;
        }

        @Override
        public NodeId getMasterFor(DeviceId deviceId) {
            return NODE1;
        }
    }

    private class MockResourceAdminService implements ResourceAdminService {
        Map<ResourceId, List<Resource>> registeredRes = new HashMap<>();

        @Override
        public boolean register(List<Resource> resources) {
            for (Resource res : resources) {
                List<Resource> resource = new LinkedList<>();
                resource.add(res);
                if (registeredRes.containsKey(res.id())) {
                    resource.addAll(registeredRes.get(res.id()));
                }
                registeredRes.put(res.id(), resource);
            }
            return true;
        }

        @Override
        public boolean unregister(List<ResourceId> ids) {
            for (ResourceId id : ids) {
                if (registeredRes.containsKey(id)) {
                    registeredRes.remove(id);
                } else {
                    return false;
                }
            }
            return true;
        }
    }

    private class MockLinkService extends LinkServiceAdapter {

        @Override
        public Link getLink(ConnectPoint src, ConnectPoint dst) {
            for (Link link : linkRegistry.links) {
                if (link.src().equals(src) && link.dst().equals(dst)) {
                    return link;
                }
            }
            return null;
        }
    }

    /* Class implement device test registry */
    private class TestDeviceRegistry implements DeviceProviderRegistry {
        DeviceProvider provider;

        Set<DeviceId> connected = new HashSet<>();
        Map<DeviceId, List<PortDescription>> portUpdated = new HashMap<>();

        @Override
        public DeviceProviderService register(DeviceProvider provider) {
            this.provider = provider;
            return new TestProviderService();
        }

        @Override
        public void unregister(DeviceProvider provider) {
        }

        @Override
        public Set<ProviderId> getProviders() {
            return null;
        }

        private class TestProviderService implements DeviceProviderService {

            @Override
            public DeviceProvider provider() {
                return null;
            }

            @Override
            public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) {
                if (!deviceId.equals(DID2)) {
                    connected.add(deviceId);
                    Device device = new DefaultDevice(BgpTopologyProviderTest.providerId, deviceId, Device.Type.ROUTER,
                            UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, new ChassisId(), deviceDescription.annotations());
                    deviceMap.put(deviceId, device);
                }
            }

            @Override
            public void deviceDisconnected(DeviceId deviceId) {
                if (!deviceId.equals(DID2)) {
                    connected.remove(deviceId);
                    deviceMap.remove(deviceId);
                }
            }

            @Override
            public void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) {
                portUpdated.put(deviceId, portDescriptions);
            }

            @Override
            public void portStatusChanged(DeviceId deviceId, PortDescription portDescription) {
                // TODO Auto-generated method stub

            }

            @Override
            public void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response) {
                // TODO Auto-generated method stub

            }

            @Override
            public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) {
                // TODO Auto-generated method stub

            }
        }
    }

    /* Class implement device test registry */
    private class TestLinkRegistry implements LinkProviderRegistry {
        LinkProvider linkProvider;
        Set<Link> links = new HashSet<>();

        @Override
        public LinkProviderService register(LinkProvider provider) {
            this.linkProvider = provider;
            return new TestProviderService();
        }

        @Override
        public void unregister(LinkProvider provider) {
            // TODO Auto-generated method stub
        }

        @Override
        public Set<ProviderId> getProviders() {
            return null;
        }

        private class TestProviderService implements LinkProviderService {

            @Override
            public void linkDetected(LinkDescription linkDescription) {
                links.add(DefaultLink.builder()
                        .src(linkDescription.src())
                        .dst(linkDescription.dst())
                        .state(ACTIVE)
                        .type(linkDescription.type())
                        .providerId(BgpTopologyProviderTest.providerId)
                        .annotations(linkDescription.annotations())
                        .build());
            }

            @Override
            public void linkVanished(LinkDescription linkDescription) {
                links.remove(DefaultLink.builder().src(linkDescription.src())
                        .dst(linkDescription.dst()).state(ACTIVE).type(linkDescription.type())
                        .providerId(BgpTopologyProviderTest.providerId).build());
            }

            @Override
            public void linksVanished(ConnectPoint connectPoint) {
                // TODO Auto-generated method stub
            }

            @Override
            public void linksVanished(DeviceId deviceId) {
                // TODO Auto-generated method stub
            }

            @Override
            public LinkProvider provider() {
                // TODO Auto-generated method stub
                return null;
            }
        }
    }

    /* Test class for BGP controller */
    private class MockBgpController extends BgpControllerAdapter {
        protected Set<BgpNodeListener> nodeListener = new CopyOnWriteArraySet<>();
        protected Set<BgpLinkListener> linkListener = new CopyOnWriteArraySet<>();

        @Override
        public void addListener(BgpNodeListener nodeListener) {
            this.nodeListener.add(nodeListener);
        }

        @Override
        public void removeListener(BgpNodeListener nodeListener) {
            this.nodeListener.remove(nodeListener);
        }

        @Override
        public void addLinkListener(BgpLinkListener linkListener) {
            this.linkListener.add(linkListener);
        }

        @Override
        public void removeLinkListener(BgpLinkListener linkListener) {
            this.linkListener.remove(linkListener);
        }
    }

    /* Mock test for device service */
    private class MockDeviceService extends DeviceServiceAdapter {
        @Override
        public Device getDevice(DeviceId deviceId) {
            return deviceMap.get(deviceId);
        }
    }

    /**
     * Validate node is added to the device validating URI, RIB should get updated properly.
     */
    @Test
    public void bgpTopologyProviderTestAddDevice1() {
        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(100);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(0));
        }
    }

    /**
     * Validate node is not added to the device for invalid URI, RIB count should be zero.
     */
    @Test
    public void bgpTopologyProviderTestAddDevice2() {
        LinkedList<BgpValueType> subTlvs;
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        subTlvs = new LinkedList<>();
        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());


        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(0));
        }
    }

    /**
     * Delete node when node does not exist, RIB count should be zero.
     */
    @Test
    public void bgpTopologyProviderTestAddDevice3() {
        LinkedList<BgpValueType> subTlvs;
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        subTlvs = new LinkedList<>();
        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        for (BgpNodeListener l : controller.nodeListener) {
            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(0));
        }
    }


    /**
     * Validate node is added to the device with all device annotations.
     */
    @Test
    public void bgpTopologyProviderTestAddDevice4() {
        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(100);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttr = new LinkedList<>();
        tlv = BgpAttrNodeFlagBitTlv.of(true, true, true, false);
        linkStateAttr.add(tlv);
        tlv = BgpAttrNodeIsIsAreaId.of(new byte[] {01, 01, 01, 01});
        linkStateAttr.add(tlv);
        tlv = BgpAttrRouterIdV4.of(Ip4Address.valueOf("1.1.1.1"), LinkStateAttributes.ATTR_NODE_IPV4_LOCAL_ROUTER_ID);
        linkStateAttr.add(tlv);
        pathAttributes.add(new LinkStateAttributes(linkStateAttr));
        details.setPathAttribute(pathAttributes);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);

            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.ABR_BIT),
                    is("false"));
            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.EXTERNAL_BIT),
                    is("true"));
            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.INTERNAL_BIT),
                    is("false"));
            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.PSEUDO),
                    is("false"));
            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.AREAID).getBytes(),
                    is(new byte[] {01, 01, 01, 01}));
            assertThat(deviceMap.values().iterator().next().annotations().value(BgpTopologyProvider.LSRID),
                    is("1.1.1.1"));

            assertThat(nodeRegistry.connected.size(), is(1));
            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(0));
        }
    }

    /**
     * Add a link and two devices.
     *
     * @throws BgpParseException while adding a link.
     */
    @Test
    public void bgpTopologyProviderTestAddLink1() throws BgpParseException {
        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
        LinkedList<BgpValueType> linkdes = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        localTlvs.add(tlv);
        remoteTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
        localTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
        remoteTlvs.add(tlv);
        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
        linkdes.add(tlv);
        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
                new RouteDistinguisher(), false);
        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            l.addNode(remNodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(2));
        }
        for (BgpLinkListener l : controller.linkListener) {
            l.addLink(linkNlri, details);
            assertThat(linkRegistry.links.size(), is(1));
        }
    }

    /**
     * Add a link and delete a link.
     *
     * @throws BgpParseException while adding or removing the link
     */
    @Test
    public void bgpTopologyProviderTestAddLink2() throws BgpParseException {
        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
        LinkedList<BgpValueType> linkdes = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        localTlvs.add(tlv);
        remoteTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
        localTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
        remoteTlvs.add(tlv);
        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
        linkdes.add(tlv);
        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
                new RouteDistinguisher(), false);
        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            l.addNode(remNodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(2));
            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(1));
        }
        for (BgpLinkListener l : controller.linkListener) {
            l.addLink(linkNlri, details);
            assertThat(linkRegistry.links.size(), is(1));
            l.deleteLink(linkNlri);
            assertThat(linkRegistry.links.size(), is(0));
        }
    }

    /**
     * Add a link and delete a link with registering/unregistering bandwidth.
     *
     * @throws BgpParseException while adding or removing the link
     * @throws InterruptedException while registering for bandwidth
     */
    @Test
    public void bgpTopologyProviderTestAddLink3() throws BgpParseException, InterruptedException {
        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
        LinkedList<BgpValueType> linkdes = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        localTlvs.add(tlv);
        remoteTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
        localTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
        remoteTlvs.add(tlv);
        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
        linkdes.add(tlv);
        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
                new RouteDistinguisher(), false);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            l.addNode(remNodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(2));
            l.deleteNode(remNodeNlri);
            assertThat(nodeRegistry.connected.size(), is(1));
        }

        List<BgpValueType> linkPathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttr = new LinkedList<>();
        tlv = BgpLinkAttrIgpMetric.of(10, 4);
        linkStateAttr.add(tlv);
        tlv = BgpLinkAttrTeDefaultMetric.of(20);
        linkStateAttr.add(tlv);
        tlv = BgpLinkAttrMaxLinkBandwidth.of(30, LinkStateAttributes.ATTR_LINK_MAX_RES_BANDWIDTH);
        linkStateAttr.add(tlv);
        linkPathAttributes.add(new LinkStateAttributes(linkStateAttr));
        details.setPathAttribute(linkPathAttributes);

        for (BgpLinkListener l : controller.linkListener) {
            l.addLink(linkNlri, details);
            assertThat(linkRegistry.links.size(), is(1));
            assertThat(linkRegistry.links.iterator().next().annotations().value(BgpTopologyProvider.COST),
                    is("10"));
            assertThat(linkRegistry.links.iterator().next().annotations().value(BgpTopologyProvider.TE_COST),
                    is("20"));

            l.deleteLink(linkNlri);
            assertThat(linkRegistry.links.size(), is(0));
        }
    }

    /**
     * Invalid link.
     *
     * @throws BgpParseException while adding or deleting a link
     */
    @Test
    public void bgpTopologyProviderTestDeleteLink3() throws BgpParseException {
        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
        LinkedList<BgpValueType> linkdes = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        localTlvs.add(tlv);
        remoteTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
        localTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
        remoteTlvs.add(tlv);
        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        details.setPathAttribute(pathAttributes);

        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
        linkdes.add(tlv);
        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
                new RouteDistinguisher(), false);
        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            l.addNode(remNodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(2));
            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(1));
        }
        for (BgpLinkListener l : controller.linkListener) {
            l.deleteLink(linkNlri);
            assertThat(linkRegistry.links.size(), is(0));
        }
    }

    /**
     * Add device check label registration is done.
     *
     * @throws BgpParseException while adding a device
     */
    @Test
    public void bgpTopologyProviderDeviceTestLabel1() throws BgpParseException {
        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(100);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttributes = new LinkedList<>();
        tlv = BgpAttrRouterIdV4.of(Ip4Address.valueOf("1.1.1.1"), LinkStateAttributes.ATTR_NODE_IPV4_LOCAL_ROUTER_ID);
        linkStateAttributes.add(tlv);
        pathAttributes.add(new LinkStateAttributes(linkStateAttributes));
        details.setPathAttribute(pathAttributes);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
        }

        MastershipEvent event = new MastershipEvent(Type.MASTER_CHANGED, nodeRegistry.connected.iterator().next(),
                new RoleInfo(NodeId.nodeId("Node1"), new LinkedList<>()));

        listener.event(event);
        assertThat(labelResourceAdminService.resourcePool.keySet().size(), is(1));
    }

    /**
     * Add device check label registration is done and delete node destroy label pool.
     *
     * @throws BgpParseException while adding a device
     */
    @Test
    public void bgpTopologyProviderDeviceTestLabel2() throws BgpParseException {
        LinkedList<BgpValueType> subTlvs = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(100);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        subTlvs.add(tlv);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(new NodeDescriptors(subTlvs, deslength,
                                                                                               desType));
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttributes = new LinkedList<>();
        tlv = BgpAttrRouterIdV4.of(Ip4Address.valueOf("1.1.1.1"), LinkStateAttributes.ATTR_NODE_IPV4_LOCAL_ROUTER_ID);
        linkStateAttributes.add(tlv);
        pathAttributes.add(new LinkStateAttributes(linkStateAttributes));
        details.setPathAttribute(pathAttributes);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            // Check label resource reserved for that device
            MastershipEvent event = new MastershipEvent(Type.MASTER_CHANGED, nodeRegistry.connected.iterator().next(),
                    new RoleInfo(NodeId.nodeId("Node1"), new LinkedList<>()));
            listener.event(event);
            assertThat(labelResourceAdminService.resourcePool.keySet().size(), is(1));

            l.deleteNode(nodeNlri);
            assertThat(nodeRegistry.connected.size(), is(0));
            assertThat(labelResourceAdminService.resourcePool.keySet().size(), is(0));
        }
    }

    /**
     * Add a link register bandwidth and remove link unregister bandwidth.
     *
     * @throws BgpParseException while registering/unregistering bandwidth
     */
    @Test
    public void bgpTopologyProviderDeviceTestLabel3() throws BgpParseException {
        LinkedList<BgpValueType> localTlvs = new LinkedList<>();
        LinkedList<BgpValueType> remoteTlvs = new LinkedList<>();
        LinkedList<BgpValueType> linkdes = new LinkedList<>();
        BgpValueType tlv = new AutonomousSystemTlv(10);
        short deslength = AutonomousSystemTlv.LENGTH;
        short desType = AutonomousSystemTlv.TYPE;

        localTlvs.add(tlv);
        remoteTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {20, 20, 20, 20, 00, 20});
        localTlvs.add(tlv);
        tlv = IsIsNonPseudonode.of(new byte[] {30, 30, 30, 30, 00, 30});
        remoteTlvs.add(tlv);
        NodeDescriptors localNode = new NodeDescriptors(localTlvs, deslength, desType);
        NodeDescriptors remoteNode = new NodeDescriptors(remoteTlvs, deslength, desType);
        BgpNodeLSIdentifier localNodeDescriptors = new BgpNodeLSIdentifier(localNode);
        BgpNodeLSNlriVer4 nodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, localNodeDescriptors, false,
                                                           new RouteDistinguisher());

        BgpNodeLSIdentifier remoteNodeDescriptors = new BgpNodeLSIdentifier(remoteNode);
        BgpNodeLSNlriVer4 remNodeNlri = new BgpNodeLSNlriVer4(0, (byte) Constants.DIRECT, remoteNodeDescriptors, false,
                                                           new RouteDistinguisher());

        PathAttrNlriDetails details = new PathAttrNlriDetails();
        details.setIdentifier(0);
        details.setProtocolID(ProtocolType.DIRECT);
        List<BgpValueType> pathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttributes = new LinkedList<>();
        tlv = BgpAttrRouterIdV4.of(Ip4Address.valueOf("1.1.1.1"), LinkStateAttributes.ATTR_NODE_IPV4_LOCAL_ROUTER_ID);
        linkStateAttributes.add(tlv);
        pathAttributes.add(new LinkStateAttributes(linkStateAttributes));
        details.setPathAttribute(pathAttributes);

        tlv = LinkLocalRemoteIdentifiersTlv.of(99, 100);
        linkdes.add(tlv);
        BgpLinkLSIdentifier linkId = new BgpLinkLSIdentifier(localNode, remoteNode, linkdes);
        BgpLinkLsNlriVer4 linkNlri = new BgpLinkLsNlriVer4((byte) Constants.DIRECT, 0, linkId,
                new RouteDistinguisher(), false);

        for (BgpNodeListener l : controller.nodeListener) {
            l.addNode(nodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(1));
            //Check label resource reserved for that device
            MastershipEvent event = new MastershipEvent(Type.MASTER_CHANGED, nodeRegistry.connected.iterator().next(),
                    new RoleInfo(NodeId.nodeId("Node1"), new LinkedList<>()));
            listener.event(event);
            assertThat(labelResourceAdminService.resourcePool.keySet().size(), is(1));
            l.addNode(remNodeNlri, details);
            assertThat(nodeRegistry.connected.size(), is(2));
            l.deleteNode(remNodeNlri);
            assertThat(nodeRegistry.connected.size(), is(1));
            assertThat(labelResourceAdminService.resourcePool.keySet().size(), is(1));
        }

        List<BgpValueType> linkPathAttributes = new LinkedList<>();
        List<BgpValueType> linkStateAttr = new LinkedList<>();
        tlv = BgpLinkAttrIgpMetric.of(10, 4);
        linkStateAttr.add(tlv);
        tlv = BgpLinkAttrTeDefaultMetric.of(20);
        linkStateAttr.add(tlv);
        tlv = BgpLinkAttrMaxLinkBandwidth.of(70, LinkStateAttributes.ATTR_LINK_MAX_RES_BANDWIDTH);
        linkStateAttr.add(tlv);
        linkPathAttributes.add(new LinkStateAttributes(linkStateAttr));
        details.setPathAttribute(linkPathAttributes);

        for (BgpLinkListener l : controller.linkListener) {
            l.addLink(linkNlri, details);
            assertThat(linkRegistry.links.size(), is(1));
            assertThat(linkRegistry.links.iterator().next().annotations().value(BgpTopologyProvider.COST),
                    is("10"));
            assertThat(linkRegistry.links.iterator().next().annotations().value(BgpTopologyProvider.TE_COST),
                    is("20"));

            ConnectPoint src = new ConnectPoint(
                    DeviceId.deviceId("l3:rd=0::routinguniverse=0:asn=10:isoid=1414.1414.0014"),
                    PortNumber.portNumber(4294967395L));
            ConnectPoint dst = new ConnectPoint(
                    DeviceId.deviceId("l3:rd=0::routinguniverse=0:asn=10:isoid=1e1e.1e1e.001e"),
                    PortNumber.portNumber(4294967396L));
            BandwidthCapacity bandwidth = networkConfigService.getConfig(src, BandwidthCapacity.class);
            assertThat(bandwidth.capacity().bps(), is(70.0 * 1_000_000L));

            bandwidth = networkConfigService.getConfig(dst, BandwidthCapacity.class);
            assertThat(bandwidth.capacity(), is(Bandwidth.bps(70.0 * 1_000_000L)));

            l.deleteLink(linkNlri);
            assertThat(linkRegistry.links.size(), is(0));
            bandwidth = networkConfigService.getConfig(src, BandwidthCapacity.class);
            assertThat(bandwidth, is(nullValue()));
            bandwidth = networkConfigService.getConfig(dst, BandwidthCapacity.class);
            assertThat(bandwidth, is(nullValue()));
        }
    }
}
