/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.incubator.net.virtual.impl;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.osgi.TestServiceDirectory;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualLink;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.DisjointPath;
import org.onosproject.net.Link;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.TestDeviceParams;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.net.topology.LinkWeigherAdapter;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.store.service.TestStorageService;

import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

/**
 * Junit tests for VirtualNetworkTopologyService.
 */
public class VirtualNetworkTopologyManagerTest extends TestDeviceParams {

    private final String tenantIdValue1 = "TENANT_ID1";

    private VirtualNetworkManager manager;
    private DistributedVirtualNetworkStore virtualNetworkManagerStore;
    private CoreService coreService;
    private TestServiceDirectory testDirectory;

    @Before
    public void setUp() throws Exception {
        virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
        coreService = new VirtualNetworkTopologyManagerTest.TestCoreService();
        TestUtils.setField(virtualNetworkManagerStore, "coreService", coreService);
        TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
        virtualNetworkManagerStore.activate();

        manager = new VirtualNetworkManager();
        manager.store = virtualNetworkManagerStore;
        manager.coreService = coreService;
        NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());

        testDirectory = new TestServiceDirectory();
        TestUtils.setField(manager, "serviceDirectory", testDirectory);

        manager.activate();
    }

    @After
    public void tearDown() {
        virtualNetworkManagerStore.deactivate();
        manager.deactivate();
        NetTestTools.injectEventDispatcher(manager, null);
    }

    /**
     * Method to create the virtual network for further testing.
     *
     * @return virtual network
     */
    private VirtualNetwork setupVirtualNetworkTopology() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        VirtualDevice virtualDevice1 =
                manager.createVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice virtualDevice2 =
                manager.createVirtualDevice(virtualNetwork.id(), DID2);
        VirtualDevice virtualDevice3 =
                manager.createVirtualDevice(virtualNetwork.id(), DID3);
        VirtualDevice virtualDevice4 =
                manager.createVirtualDevice(virtualNetwork.id(), DID4);

        ConnectPoint cp1 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(1));
        manager.createVirtualPort(virtualNetwork.id(), cp1.deviceId(), cp1.port(), cp1);

        ConnectPoint cp2 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(2));
        manager.createVirtualPort(virtualNetwork.id(), cp2.deviceId(), cp2.port(), cp2);

        ConnectPoint cp3 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(3));
        manager.createVirtualPort(virtualNetwork.id(), cp3.deviceId(), cp3.port(), cp3);

        ConnectPoint cp4 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(4));
        manager.createVirtualPort(virtualNetwork.id(), cp4.deviceId(), cp4.port(), cp4);

        ConnectPoint cp5 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(5));
        manager.createVirtualPort(virtualNetwork.id(), cp5.deviceId(), cp5.port(), cp5);

        ConnectPoint cp6 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(6));
        manager.createVirtualPort(virtualNetwork.id(), cp6.deviceId(), cp6.port(), cp6);

        VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3);
        virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
        VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1);
        virtualNetworkManagerStore.updateLink(link2, link2.tunnelId(), Link.State.ACTIVE);
        VirtualLink link3 = manager.createVirtualLink(virtualNetwork.id(), cp4, cp5);
        virtualNetworkManagerStore.updateLink(link3, link3.tunnelId(), Link.State.ACTIVE);
        VirtualLink link4 = manager.createVirtualLink(virtualNetwork.id(), cp5, cp4);
        virtualNetworkManagerStore.updateLink(link4, link4.tunnelId(), Link.State.ACTIVE);
        VirtualLink link5 = manager.createVirtualLink(virtualNetwork.id(), cp2, cp6);
        virtualNetworkManagerStore.updateLink(link5, link5.tunnelId(), Link.State.ACTIVE);
        VirtualLink link6 = manager.createVirtualLink(virtualNetwork.id(), cp6, cp2);
        virtualNetworkManagerStore.updateLink(link6, link6.tunnelId(), Link.State.ACTIVE);

        return virtualNetwork;
    }

    /**
     * Tests the currentTopology() method.
     */
    @Test
    public void testCurrentTopology() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();
        assertNotNull("The topology should not be null.", topology);
    }

    /**
     * Test isLatest() method using a null topology.
     */
    @Test(expected = NullPointerException.class)
    public void testIsLatestByNullTopology() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);

        // test the isLatest() method with a null topology.
        topologyService.isLatest(null);
    }

    /**
     * Test isLatest() method.
     */
    @Test
    public void testIsLatest() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        // test the isLatest() method.
        assertTrue("This should be latest topology", topologyService.isLatest(topology));

        VirtualDevice srcVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice =
                manager.createVirtualDevice(virtualNetwork.id(), DID2);

        // test the isLatest() method where a new device has been added to the current topology.
        assertFalse("This should not be latest topology", topologyService.isLatest(topology));

        topology = topologyService.currentTopology();
        ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
        manager.createVirtualPort(virtualNetwork.id(), src.deviceId(), src.port(),
                                  new ConnectPoint(srcVirtualDevice.id(), src.port()));

        ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
        manager.createVirtualPort(virtualNetwork.id(), dst.deviceId(), dst.port(),
                                  new ConnectPoint(dstVirtualDevice.id(), dst.port()));
        VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst);

        // test the isLatest() method where a new link has been added to the current topology.
        assertFalse("This should not be latest topology", topologyService.isLatest(topology));
    }

    /**
     * Test getGraph() method.
     */
    @Test
    public void testGetGraph() {
        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        // test the getGraph() method.
        assertNotNull("The graph should not be null.", topologyService.getGraph(topology));
    }

    /**
     * Test getClusters() method.
     */
    @Test
    public void testGetClusters() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);

        Topology topology = topologyService.currentTopology();

        // test the getClusters() method.
        assertNotNull("The clusters should not be null.", topologyService.getClusters(topology));
        assertEquals("The clusters size did not match.", 2, topologyService.getClusters(topology).size());
    }

    /**
     * Test getCluster() method using a null cluster identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetClusterUsingNullClusterId() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        Set<TopologyCluster> clusters = topologyService.getClusters(topology);
        TopologyCluster cluster = clusters.stream().findFirst().get();

        // test the getCluster() method with a null cluster identifier
        TopologyCluster cluster1 = topologyService.getCluster(topology, null);
    }

    /**
     * Test getCluster() method.
     */
    @Test
    public void testGetCluster() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        Set<TopologyCluster> clusters = topologyService.getClusters(topology);
        assertNotNull("The clusters should not be null.", clusters);
        assertEquals("The clusters size did not match.", 2, clusters.size());

        // test the getCluster() method.
        TopologyCluster cluster = clusters.stream().findFirst().get();
        assertNotNull("The cluster should not be null.", cluster);
        TopologyCluster cluster1 = topologyService.getCluster(topology, cluster.id());
        assertNotNull("The cluster should not be null.", cluster1);
        assertEquals("The cluster ID did not match.", cluster.id(), cluster1.id());
    }

    /**
     * Test getClusterDevices() methods with a null cluster.
     */
    @Test(expected = NullPointerException.class)
    public void testGetClusterDevicesUsingNullCluster() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();
        Set<TopologyCluster> clusters = topologyService.getClusters(topology);

        // test the getClusterDevices() method using a null cluster.
        Object[] objects = clusters.stream().toArray();
        assertNotNull("The cluster should not be null.", objects);
        Set<DeviceId> clusterDevices = topologyService.getClusterDevices(topology, null);
    }

    /**
     * Test getClusterLinks() methods with a null cluster.
     */
    @Test(expected = NullPointerException.class)
    public void testGetClusterLinksUsingNullCluster() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();
        Set<TopologyCluster> clusters = topologyService.getClusters(topology);

        // test the getClusterLinks() method using a null cluster.
        Object[] objects = clusters.stream().toArray();
        assertNotNull("The cluster should not be null.", objects);
        Set<Link> clusterLinks = topologyService.getClusterLinks(topology, null);
    }

    /**
     * Test getClusterDevices() and getClusterLinks() methods.
     */
    @Test
    public void testGetClusterDevicesLinks() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        Set<TopologyCluster> clusters = topologyService.getClusters(topology);
        assertNotNull("The clusters should not be null.", clusters);
        assertEquals("The clusters size did not match.", 2, clusters.size());

        // test the getClusterDevices() method.
        Object[] objects = clusters.stream().toArray();
        assertNotNull("The cluster should not be null.", objects);
        Set<DeviceId> clusterDevices = topologyService.getClusterDevices(topology, (TopologyCluster) objects[0]);
        assertNotNull("The devices should not be null.", clusterDevices);
        assertEquals("The devices size did not match.", 3, clusterDevices.size());
        Set<DeviceId> clusterDevices1 = topologyService.getClusterDevices(topology, (TopologyCluster) objects[1]);
        assertNotNull("The devices should not be null.", clusterDevices1);
        assertEquals("The devices size did not match.", 1, clusterDevices1.size());

        // test the getClusterLinks() method.
        Set<Link> clusterLinks = topologyService.getClusterLinks(topology, (TopologyCluster) objects[0]);
        assertNotNull("The links should not be null.", clusterLinks);
        assertEquals("The links size did not match.", 6, clusterLinks.size());
        Set<Link> clusterLinks1 = topologyService.getClusterLinks(topology, (TopologyCluster) objects[1]);
        assertNotNull("The links should not be null.", clusterLinks1);
        assertEquals("The links size did not match.", 0, clusterLinks1.size());
    }

    /**
     * Test getPaths() method using a null src device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetPathsUsingNullSrcDeviceId() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getPaths() method using a null src device identifier.
        Set<Path> paths = topologyService.getPaths(topology, null, dstVirtualDevice.id());
    }

    /**
     * Test getPaths() method using a null dst device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetPathsUsingNullDstDeviceId() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getPaths() method using a null dst device identifier.
        Set<Path> paths = topologyService.getPaths(topology, srcVirtualDevice.id(), null);
    }

    /**
     * Test getPaths() method using a null weight.
     */
    @Test(expected = NullPointerException.class)
    public void testGetPathsUsingNullWeight() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getPaths() method using a null weight.
        Set<Path> paths = topologyService.getPaths(topology, srcVirtualDevice.id(),
                dstVirtualDevice.id(), (LinkWeigher) null);
    }

    /**
     * Test getPaths() and getPaths() by weight methods.
     */
    @Test
    public void testGetPaths() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getPaths() method.
        Set<Path> paths = topologyService.getPaths(topology, srcVirtualDevice.id(), dstVirtualDevice.id());
        assertNotNull("The paths should not be null.", paths);
        assertEquals("The paths size did not match.", 1, paths.size());

        // test the getPaths() by weight method.
        LinkWeigher weight = new LinkWeigherAdapter(1.0);
        Set<Path> paths1 = topologyService.getPaths(topology, srcVirtualDevice.id(), dstVirtualDevice.id(), weight);
        assertNotNull("The paths should not be null.", paths1);
        assertEquals("The paths size did not match.", 1, paths1.size());
        Path path = paths1.iterator().next();
        assertEquals("wrong path length", 1, path.links().size());
        assertEquals("wrong path cost", 1.0, path.cost(), 0.01);
    }

    /**
     * Test getDisjointPaths() methods using a null src device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDisjointPathsUsingNullSrcDeviceId() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getDisjointPaths() method using a null src device identifier.
        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology, null, dstVirtualDevice.id());
    }

    /**
     * Test getDisjointPaths() methods using a null dst device identifier.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDisjointPathsUsingNullDstDeviceId() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getDisjointPaths() method using a null dst device identifier.
        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology, srcVirtualDevice.id(), null);
    }

    /**
     * Test getDisjointPaths() methods using a null weight.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDisjointPathsUsingNullWeight() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getDisjointPaths() method using a null weight.
        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology, srcVirtualDevice.id(),
                                                                   dstVirtualDevice.id(), (LinkWeigher) null);
    }

    /**
     * Test getDisjointPaths() methods using a null risk profile.
     */
    @Test(expected = NullPointerException.class)
    public void testGetDisjointPathsUsingNullRiskProfile() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getDisjointPaths() method using a null risk profile.
        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology, srcVirtualDevice.id(),
                                                                   dstVirtualDevice.id(), (Map<Link, Object>) null);
    }

    /**
     * Test getDisjointPaths() methods.
     */
    @Test
    public void testGetDisjointPaths() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);

        // test the getDisjointPaths() method.
        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology, srcVirtualDevice.id(),
                                                                   dstVirtualDevice.id());
        assertNotNull("The paths should not be null.", paths);
        assertEquals("The paths size did not match.", 1, paths.size());

        // test the getDisjointPaths() method using a weight.
        LinkWeigher weight = new LinkWeigherAdapter(1.0);
        Set<DisjointPath> paths1 = topologyService.getDisjointPaths(topology, srcVirtualDevice.id(),
                                                                    dstVirtualDevice.id(), weight);
        assertNotNull("The paths should not be null.", paths1);
        assertEquals("The paths size did not match.", 1, paths1.size());
    }

    /**
     * Test isInfrastructure() method using a null connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testIsInfrastructureUsingNullConnectPoint() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        // test the isInfrastructure() method using a null connect point.
        Boolean isInfrastructure = topologyService.isInfrastructure(topology, null);
    }

    /**
     * Test isInfrastructure() method.
     */
    @Test
    public void testIsInfrastructure() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID4);
        ConnectPoint cp1 = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
        ConnectPoint cp2 = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));

        // test the isInfrastructure() method.
        Boolean isInfrastructure = topologyService.isInfrastructure(topology, cp1);
        assertTrue("The connect point should be infrastructure.", isInfrastructure);

        isInfrastructure = topologyService.isInfrastructure(topology, cp2);
        assertFalse("The connect point should not be infrastructure.", isInfrastructure);
    }

    /**
     * Test isBroadcastPoint() method using a null connect point.
     */
    @Test(expected = NullPointerException.class)
    public void testIsBroadcastUsingNullConnectPoint() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        // test the isInfrastructure() method using a null connect point.
        Boolean isInfrastructure = topologyService.isBroadcastPoint(topology, null);
    }

    /**
     * Test isBroadcastPoint() method.
     */
    @Test
    public void testIsBroadcastPoint() {
        VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();

        TopologyService topologyService = manager.get(virtualNetwork.id(), TopologyService.class);
        Topology topology = topologyService.currentTopology();

        VirtualDevice srcVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID1);
        ConnectPoint cp = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));

        // test the isBroadcastPoint() method.
        Boolean isBroadcastPoint = topologyService.isBroadcastPoint(topology, cp);
        assertTrue("The connect point should be a broadcast point.", isBroadcastPoint);
    }

    /**
     * Return the virtual device matching the device identifier.
     *
     * @param networkId virtual network identifier
     * @param deviceId  device identifier
     * @return virtual device
     */
    private VirtualDevice getVirtualDevice(NetworkId networkId, DeviceId deviceId) {
        Optional<VirtualDevice> foundDevice = manager.getVirtualDevices(networkId)
                .stream()
                .filter(device -> deviceId.equals(device.id()))
                .findFirst();
        if (foundDevice.isPresent()) {
            return foundDevice.get();
        }
        return null;
    }

    /**
     * Core service test class.
     */
    private class TestCoreService extends CoreServiceAdapter {

        ApplicationId appId;

        @Override
        public IdGenerator getIdGenerator(String topic) {
            return new IdGenerator() {
                private AtomicLong counter = new AtomicLong(0);

                @Override
                public long getNewId() {
                    return counter.getAndIncrement();
                }
            };
        }

        @Override
        public ApplicationId registerApplication(String name) {
            appId = new DefaultApplicationId(1, name);
            return appId;
        }

            @Override
        public ApplicationId getAppId(String name) {
            return appId;
        }
    }

}
