/*
 * 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.lldp.impl;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ONOSLLDP;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.cluster.ClusterMetadataServiceAdapter;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigEvent.Type;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.link.LinkProviderRegistryAdapter;
import org.onosproject.net.link.LinkProviderServiceAdapter;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.provider.lldpcommon.LinkDiscovery;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onlab.junit.TestTools.assertAfter;
import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;


public class LldpLinkProviderTest {

    private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
    private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
    private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
    private static final int EVENT_MS = 500;

    private static Port pd1;
    private static Port pd2;
    private static Port pd3;
    private static Port pd4;

    private final LldpLinkProvider provider = new LldpLinkProvider();
    private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter();
    private final TestLinkService linkService = new TestLinkService();
    private final TestPacketService packetService = new TestPacketService();
    private final TestDeviceService deviceService = new TestDeviceService();
    private final TestMasterShipService masterService = new TestMasterShipService();
    private final TestNetworkConfigRegistry configRegistry = new TestNetworkConfigRegistry();

    private CoreService coreService;
    private LinkProviderServiceAdapter providerService;

    private PacketProcessor testProcessor;
    private DeviceListener deviceListener;
    private NetworkConfigListener configListener;

    private ApplicationId appId =
            new DefaultApplicationId(100, "org.onosproject.provider.lldp");

    private TestSuppressionConfig cfg;

    private Set<DeviceId> deviceBlacklist;

    private Set<ConnectPoint> portBlacklist;

    @Before
    public void setUp() {
        deviceBlacklist = new HashSet<>();
        portBlacklist = new HashSet<>();
        cfg = new TestSuppressionConfig();
        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication(appId.name()))
                .andReturn(appId).anyTimes();
        replay(coreService);

        provider.cfgService = new ComponentConfigAdapter();
        provider.coreService = coreService;
        provider.cfgRegistry = configRegistry;

        provider.deviceService = deviceService;
        provider.linkService = linkService;
        provider.packetService = packetService;
        provider.providerRegistry = linkRegistry;
        provider.masterService = masterService;
        provider.clusterMetadataService = new ClusterMetadataServiceAdapter();

        provider.activate(null);

        provider.eventExecutor = MoreExecutors.newDirectExecutorService();

        providerService = linkRegistry.registeredProvider();
    }

    @Test
    public void basics() {
        assertNotNull("registration expected", providerService);
        assertEquals("incorrect provider", provider, providerService.provider());
    }

    @Test
    public void switchAdd() {
        DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1);
        deviceListener.event(de);

        assertFalse("Device not added", provider.discoverers.isEmpty());
    }

    @Test
    public void switchRemove() {
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));

        final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
        if (linkDiscovery != null) {
            // If LinkDiscovery helper is there after DEVICE_REMOVED,
            // it should be stopped
            assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
        }
        assertTrue("Device is not gone.", vanishedDpid(DID1));
    }

    /**
     * Checks that links on a reconfigured switch are properly removed.
     */
    @Test
    public void switchSuppressedByAnnotation() {

        // add device to stub DeviceService
        deviceService.putDevice(device(DID3));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        assertFalse("Device not added", provider.discoverers.isEmpty());

        // update device in stub DeviceService with suppression config
        deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
                .set(LldpLinkProvider.NO_LLDP, "true")
                .build()));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));

        // discovery on device is expected to be gone or stopped
        LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
        if (linkDiscovery != null) {
            assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
        }
    }

    @Test
    public void switchSuppressByBlacklist() {
        // add device in stub DeviceService
        deviceService.putDevice(device(DID3));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        // add deviveId to device blacklist
        deviceBlacklist.add(DID3);
        configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
                                                    DID3,
                                                    LinkDiscoveryFromDevice.class));

        assertAfter(EVENT_MS, () -> {
            // discovery helper for device is expected to be gone or stopped
            LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
            if (linkDiscovery != null) {
                assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
            }
        });
    }

    @Test
    public void portUp() {
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));

        assertTrue("Port not added to discoverer",
                   provider.discoverers.get(DID1).containsPort(3L));
    }

    @Test
    public void portDown() {

        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));

        assertFalse("Port added to discoverer",
                    provider.discoverers.get(DID1).containsPort(1L));
        assertTrue("Port is not gone.", vanishedPort(1L));
    }

    @Test
    public void portRemoved() {
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));

        assertTrue("Port is not gone.", vanishedPort(3L));
        assertFalse("Port was not removed from discoverer",
                    provider.discoverers.get(DID1).containsPort(3L));
    }

    /**
     * Checks that discovery on reconfigured switch are properly restarted.
     */
    @Test
    public void portSuppressedByDeviceAnnotationConfig() {

        /// When Device is configured with suppression:ON, Port also is same

        // add device in stub DeviceService with suppression configured
        deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
                .set(LldpLinkProvider.NO_LLDP, "true")
                .build()));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        // non-suppressed port added to suppressed device
        final long portno3 = 3L;
        deviceService.putPorts(DID3, port(DID3, portno3, true));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));

        // discovery on device is expected to be stopped
        LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
        if (linkDiscovery != null) {
            assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
        }

        /// When Device is reconfigured without suppression:OFF,
        /// Port should be included for discovery

        // update device in stub DeviceService without suppression configured
        deviceService.putDevice(device(DID3));
        // update the Port in stub DeviceService. (Port has reference to Device)
        deviceService.putPorts(DID3, port(DID3, portno3, true));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));

        // discovery should come back on
        assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
        assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
    }

    /**
     * Checks that discovery on reconfigured switch are properly restarted.
     */
    @Test
    public void portSuppressedByParentDeviceIdBlacklist() {

        /// When Device is configured without suppression:OFF,
        /// Port should be included for discovery

        // add device in stub DeviceService without suppression configured
        deviceService.putDevice(device(DID3));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        // non-suppressed port added to suppressed device
        final long portno3 = 3L;
        deviceService.putPorts(DID3, port(DID3, portno3, true));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));

        // discovery should succeed
        assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
        assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));

        // add suppression rule for "deviceId: "of:0000000000000003""
        deviceBlacklist.add(DID3);
        configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
                                                    DID3,
                                                    LinkDiscoveryFromDevice.class));


        /// When Device is reconfigured with suppression:ON, Port also is same

        // update device in stub DeviceService with suppression configured
        deviceService.putDevice(device(DID3));
        // update the Port in stub DeviceService. (Port has reference to Device)
        deviceService.putPorts(DID3, port(DID3, portno3, true));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));

        // discovery helper for device is expected to be gone or stopped
        LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
        if (linkDiscovery != null) {
            assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
        }
    }

    /**
     * Checks that discovery on reconfigured switch are properly restarted.
     */
    @Test
    public void portSuppressedByDeviceTypeConfig() {

        /// When Device is configured without suppression:OFF,
        /// Port should be included for discovery

        // add device in stub DeviceService without suppression configured
        deviceService.putDevice(device(DID1, Device.Type.SWITCH));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));

        // non-suppressed port added to suppressed device
        final long portno3 = 3L;
        deviceService.putPorts(DID1, port(DID1, portno3, true));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, portno3, true)));

        // add device in stub DeviceService with suppression configured
        deviceService.putDevice(device(DID2, Device.Type.ROADM));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));

        // non-suppressed port added to suppressed device
        final long portno4 = 4L;
        deviceService.putPorts(DID2, port(DID2, portno4, true));
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, portno4, true)));

        // discovery should succeed for this device
        assertFalse("Discoverer is expected to start", provider.discoverers.get(DID1).isStopped());
        assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID1).containsPort(portno3));

        // discovery on device is expected to be stopped for this device
        LinkDiscovery linkDiscovery = provider.discoverers.get(DID2);
        if (linkDiscovery != null) {
            assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
        }
    }

    /**
     * Checks that discovery on reconfigured port are properly restarted.
     */
    @Test
    public void portSuppressedByPortConfig() {

        // add device in stub DeviceService without suppression configured
        deviceService.putDevice(device(DID3));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        // suppressed port added to non-suppressed device
        final long portno3 = 3L;
        final Port port3 = port(DID3, portno3, true,
                                DefaultAnnotations.builder()
                                        .set(LldpLinkProvider.NO_LLDP, "true")
                                        .build());
        deviceService.putPorts(DID3, port3);
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));

        // discovery helper should be there turned on
        assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
        assertFalse("Discoverer should not contain the port there",
                    provider.discoverers.get(DID3).containsPort(portno3));
    }

    @Test
    public void portSuppressedByPortBlacklist() {

        // add device in stub DeviceService without suppression configured
        deviceService.putDevice(device(DID3));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));

        final long portno3 = 3L;
        final Port port3 = port(DID3, portno3, true);

        final ConnectPoint cpDid3no3 = new ConnectPoint(DID3, PortNumber.portNumber(portno3));
        portBlacklist.add(cpDid3no3);

        // suppressed port added to non-suppressed device
        deviceService.putPorts(DID3, port3);
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));

        configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
                                                    cpDid3no3,
                                                    LinkDiscoveryFromPort.class));

        // discovery helper should be there turned on
        assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
        // but port is not a discovery target
        assertFalse("Discoverer should not contain the port there",
                    provider.discoverers.get(DID3).containsPort(portno3));
    }

    @Test
    public void portUnknown() {
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        // Note: DID3 hasn't been added to TestDeviceService, but only port is added
        deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));


        assertNull("DeviceId exists",
                   provider.discoverers.get(DID3));
    }

    @Test
    public void unknownPktCtx() {

        // Note: DID3 hasn't been added to TestDeviceService
        PacketContext pktCtx = new TestPacketContext(device(DID3));

        testProcessor.process(pktCtx);
        assertFalse("Context should still be free", pktCtx.isHandled());
    }

    @Test
    public void knownPktCtx() {
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
        deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
        PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));


        testProcessor.process(pktCtx);

        assertTrue("Link not detected", detectedLink(DID1, DID2));

    }


    @After
    public void tearDown() {
        provider.deactivate();
        provider.coreService = null;
        provider.providerRegistry = null;
        provider.deviceService = null;
        provider.packetService = null;
    }

    private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) {
        return new DeviceEvent(type, deviceService.getDevice(did));

    }

    private DefaultDevice device(DeviceId did) {
        return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
                                 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
    }

    private DefaultDevice device(DeviceId did, Device.Type type) {
        return new DefaultDevice(ProviderId.NONE, did, type,
                                 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
    }

    private DefaultDevice device(DeviceId did, Annotations annotations) {
        return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
                                 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
    }

    @SuppressWarnings(value = {"unused"})
    private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
        return new DeviceEvent(type, deviceService.getDevice(did),
                               deviceService.getPort(did, port));
    }

    private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) {
        return new DeviceEvent(type, deviceService.getDevice(did), port);
    }

    private Port port(DeviceId did, long port, boolean enabled) {
        return new DefaultPort(deviceService.getDevice(did),
                               PortNumber.portNumber(port), enabled);
    }

    private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
        return new DefaultPort(deviceService.getDevice(did),
                               PortNumber.portNumber(port), enabled, annotations);
    }

    private boolean vanishedDpid(DeviceId... dids) {
        for (int i = 0; i < dids.length; i++) {
            if (!providerService.vanishedDpid().contains(dids[i])) {
                return false;
            }
        }
        return true;
    }

    private boolean vanishedPort(Long... ports) {
        for (int i = 0; i < ports.length; i++) {
            if (!providerService.vanishedPort().contains(ports[i])) {
                return false;
            }
        }
        return true;
    }

    private boolean detectedLink(DeviceId src, DeviceId dst) {
        for (DeviceId key : providerService.discoveredLinks().keySet()) {
            if (key.equals(src)) {
                return providerService.discoveredLinks().get(src).equals(dst);
            }
        }
        return false;
    }

    @Test
    public void addDeviceTypeRule() {
        Device.Type deviceType1 = Device.Type.ROADM;
        Device.Type deviceType2 = Device.Type.SWITCH;

        Set<Device.Type> deviceTypes = new HashSet<>();
        deviceTypes.add(deviceType1);

        cfg.deviceTypes(deviceTypes);

        configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);

        assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
        assertFalse(provider.rules().getSuppressedDeviceType().contains(deviceType2));
    }

    @Test
    public void updateDeviceTypeRule() {
        Device.Type deviceType1 = Device.Type.ROADM;
        Device.Type deviceType2 = Device.Type.SWITCH;
        Set<Device.Type> deviceTypes = new HashSet<>();

        deviceTypes.add(deviceType1);
        cfg.deviceTypes(deviceTypes);

        configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);

        deviceTypes.add(deviceType2);
        cfg.deviceTypes(deviceTypes);

        configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);

        assertAfter(EVENT_MS, () -> {
            assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
            assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType2));
        });
    }

    @Test
    public void addAnnotationRule() {
        final String key1 = "key1", key2 = "key2";
        final String value1 = "value1";

        Map<String, String> annotation = new HashMap<>();
        annotation.put(key1, value1);

        cfg.annotation(annotation);

        configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);

        assertAfter(EVENT_MS, () -> {
            assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
            assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
            assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
        });
    }

    @Test
    public void updateAnnotationRule() {
        final String key1 = "key1", key2 = "key2";
        final String value1 = "value1", value2 = "value2";
        Map<String, String> annotation = new HashMap<>();

        annotation.put(key1, value1);
        cfg.annotation(annotation);

        configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);

        assertAfter(EVENT_MS, () -> {
            assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
            assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
            assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
        });

        annotation.put(key2, value2);
        cfg.annotation(annotation);

        configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);

        assertAfter(EVENT_MS, () -> {
            assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
            assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
            assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key2));
            assertEquals(value2, provider.rules().getSuppressedAnnotation().get(key2));
        });
    }

    private void configEvent(NetworkConfigEvent.Type evType) {
        configListener.event(new NetworkConfigEvent(evType,
                                                    appId,
                                                    SuppressionConfig.class));
    }

    private class TestPacketContext implements PacketContext {

        protected Device device;
        protected boolean blocked = false;

        public TestPacketContext(Device dev) {
            device = dev;
        }

        @Override
        public long time() {
            return 0;
        }

        @Override
        public InboundPacket inPacket() {
            ONOSLLDP lldp = ONOSLLDP.onosLLDP(deviceService.getDevice(DID1).id().toString(),
                                              device.chassisId(),
                                              (int) pd1.number().toLong());

            Ethernet ethPacket = new Ethernet();
            ethPacket.setEtherType(Ethernet.TYPE_LLDP);
            ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
            ethPacket.setPayload(lldp);
            ethPacket.setPad(true);

            ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");

            ConnectPoint cp = new ConnectPoint(device.id(), pd3.number());

            return new DefaultInboundPacket(cp, ethPacket,
                                            ByteBuffer.wrap(ethPacket.serialize()));

        }

        @Override
        public OutboundPacket outPacket() {
            return null;
        }

        @Override
        public TrafficTreatment.Builder treatmentBuilder() {
            return null;
        }

        @Override
        public void send() {

        }

        @Override
        public boolean block() {
            blocked = true;
            return blocked;
        }

        @Override
        public boolean isHandled() {
            return blocked;
        }

    }

    private class TestPacketService extends PacketServiceAdapter {
        @Override
        public void addProcessor(PacketProcessor processor, int priority) {
            testProcessor = processor;
        }
    }

    private class TestDeviceService extends DeviceServiceAdapter {

        private final Map<DeviceId, Device> devices = new HashMap<>();
        private final ArrayListMultimap<DeviceId, Port> ports =
                ArrayListMultimap.create();

        public TestDeviceService() {
            Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
                                          "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
            Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH,
                                          "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
            devices.put(DID1, d1);
            devices.put(DID2, d2);
            pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
            pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
            pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
            pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true);

            ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
            ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
        }

        private void putDevice(Device device) {
            DeviceId deviceId = device.id();
            devices.put(deviceId, device);
        }

        private void putPorts(DeviceId did, Port... ports) {
            this.ports.putAll(did, Lists.newArrayList(ports));
        }

        @Override
        public int getDeviceCount() {
            return devices.values().size();
        }

        @Override
        public Iterable<Device> getDevices() {
            return ImmutableList.copyOf(devices.values());
        }

        @Override
        public Device getDevice(DeviceId deviceId) {
            return devices.get(deviceId);
        }

        @Override
        public MastershipRole getRole(DeviceId deviceId) {
            return MastershipRole.MASTER;
        }

        @Override
        public List<Port> getPorts(DeviceId deviceId) {
            return ports.get(deviceId);
        }

        @Override
        public Port getPort(DeviceId deviceId, PortNumber portNumber) {
            for (Port p : ports.get(deviceId)) {
                if (p.number().equals(portNumber)) {
                    return p;
                }
            }
            return null;
        }

        @Override
        public boolean isAvailable(DeviceId deviceId) {
            return true;
        }

        @Override
        public void addListener(DeviceListener listener) {
            deviceListener = listener;

        }

        @Override
        public void removeListener(DeviceListener listener) {

        }
    }

    private final class TestMasterShipService implements MastershipService {

        @Override
        public MastershipRole getLocalRole(DeviceId deviceId) {
            return MastershipRole.MASTER;
        }

        @Override
        public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
            return CompletableFuture.completedFuture(null);
        }

        @Override
        public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
            return null;
        }

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

        @Override
        public Set<DeviceId> getDevicesOf(NodeId nodeId) {
            return null;
        }

        @Override
        public void addListener(MastershipListener listener) {

        }

        @Override
        public void removeListener(MastershipListener listener) {

        }

        @Override
        public RoleInfo getNodesFor(DeviceId deviceId) {
            return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
        }
    }


    private class TestLinkService extends LinkServiceAdapter {
    }

    private final class TestNetworkConfigRegistry
            extends NetworkConfigRegistryAdapter {
        @SuppressWarnings("unchecked")
        @Override
        public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
            if (configClass == SuppressionConfig.class) {
                return (C) cfg;
            } else if (configClass == LinkDiscoveryFromDevice.class) {
                return (C) new LinkDiscoveryFromDevice() {
                    @Override
                    public boolean enabled() {
                        return !deviceBlacklist.contains(subj);
                    }
                };
            } else if (configClass == LinkDiscoveryFromPort.class) {
                return (C) new LinkDiscoveryFromPort() {
                    @Override
                    public boolean enabled() {
                        return !portBlacklist.contains(subj);
                    }
                };
            } else {
                return null;
            }
        }

        @Override
        public void addListener(NetworkConfigListener listener) {
            configListener = listener;
        }
    }

    private final class TestSuppressionConfig extends SuppressionConfig {
        private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
        private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());

        @Override
        public Set<Device.Type> deviceTypes() {
            return ImmutableSet.copyOf(deviceTypes);
        }

        @Override
        public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
            this.deviceTypes = ImmutableSet.copyOf(deviceTypes);
            return this;
        }

        @Override
        public Map<String, String> annotation() {
            return ImmutableMap.copyOf(annotation);
        }

        @Override
        public SuppressionConfig annotation(Map<String, String> annotation) {
            this.annotation = ImmutableMap.copyOf(annotation);
            return this;
        }
    }
}
