/*
 * Copyright 2014-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.provider.host.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestTools;
import org.onlab.junit.TestUtils;
import org.onlab.osgi.ComponentContextAdapter;
import org.onlab.packet.ARP;
import org.onlab.packet.ChassisId;
import org.onlab.packet.DHCP;
import org.onlab.packet.DHCP6;
import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
import org.onlab.packet.dhcp.Dhcp6Duid;
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaNaOption;
import org.onlab.packet.dhcp.Dhcp6Option;
import org.onlab.packet.dhcp.DhcpOption;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.packet.ndp.RouterAdvertisement;
import org.onlab.packet.ndp.RouterSolicitation;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceListener;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContextAdapter;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyServiceAdapter;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.onlab.packet.VlanId.vlanId;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;

public class HostLocationProviderTest {
    private static final ProviderId PROVIDER_ID =
            new ProviderId("of", "org.onosproject.provider.host");

    private static final int ASSERTION_DELAY = 100; // millis

    private static final Integer INPORT = 10;
    private static final Integer INPORT2 = 11;
    private static final String DEV1 = "of:1";
    private static final String DEV2 = "of:2";
    private static final String DEV3 = "of:3";
    private static final String DEV4 = "of:4";
    private static final String DEV5 = "of:5";
    private static final String DEV6 = "of:6";

    private static final VlanId VLAN = vlanId();
    private static final VlanId VLAN_100 = VlanId.vlanId("100");

    // IPv4 Host
    private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
    private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
    private static final byte[] IP = new byte[]{10, 0, 0, 1};
    private static final IpAddress IP_ADDRESS =
            IpAddress.valueOf(IpAddress.Version.INET, IP);
    private static final HostLocation LOCATION =
            new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
    private static final DefaultHost HOST =
            new DefaultHost(PROVIDER_ID, hostId(MAC), MAC,
                    VLAN, LOCATION,
                    ImmutableSet.of(IP_ADDRESS));
    private static final DefaultHost HOST_VLAN_100 =
            new DefaultHost(PROVIDER_ID, hostId(MAC, VLAN_100), MAC,
                            VLAN_100, LOCATION,
                            ImmutableSet.of(IP_ADDRESS));

    // IPv6 Host
    private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
    private static final MacAddress BCMAC2 = MacAddress.valueOf("33:33:00:00:00:01");
    private static final byte[] IP2 = Ip6Address.valueOf("1000::1").toOctets();
    private static final byte[] LLIP2 = IPv6.getLinkLocalAddress(MAC2.toBytes());
    private static final IpAddress IP_ADDRESS2 =
            IpAddress.valueOf(IpAddress.Version.INET6, IP2);
    private static final IpAddress LLIP_ADDRESS2 =
            IpAddress.valueOf(IpAddress.Version.INET6, LLIP2);
    private static final HostLocation LOCATION2 =
            new HostLocation(deviceId(DEV4), portNumber(INPORT), 0L);
    private static final DefaultHost HOST2 =
            new DefaultHost(PROVIDER_ID, hostId(MAC2), MAC2,
                    VLAN, LOCATION2,
                    ImmutableSet.of(IP_ADDRESS2));

    // DHCP Server
    private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
    private static final byte[] IP3 = new byte[]{10, 0, 0, 2};
    private static final IpAddress IP_ADDRESS3 =
            IpAddress.valueOf(IpAddress.Version.INET, IP3);
    private static final HostLocation LOCATION3 =
            new HostLocation(deviceId(DEV1), portNumber(INPORT2), 0L);
    private static final DefaultHost HOST3 =
            new DefaultHost(PROVIDER_ID, hostId(MAC3), MAC3,
                    VLAN, LOCATION3,
                    ImmutableSet.of(IP_ADDRESS3));

    // DHCP6 Server
    private static final MacAddress DHCP6_SERVER_MAC = MacAddress.valueOf("00:00:44:00:00:04");
    private static final IpAddress DHCP6_SERVER_IP =
            IpAddress.valueOf("2000::1:1000");

    // Gateway information for relay agent
    private static final InterfaceIpAddress GW_IFACE_ADDR = InterfaceIpAddress.valueOf("10.0.1.1/32");
    private static final Interface GW_IFACE = new Interface("gateway",
                                                                    LOCATION,
                                                                    ImmutableList.of(GW_IFACE_ADDR),
                                                                    null,
                                                                    VLAN_100);

    private static final ComponentContextAdapter CTX_FOR_REMOVE =
            new ComponentContextAdapter() {
                @Override
                public Dictionary getProperties() {
                    Hashtable<String, String> props = new Hashtable<>();
                    props.put("hostRemovalEnabled", "true");
                    return props;
                }
            };

    public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
            new ComponentContextAdapter() {
                @Override
                public Dictionary getProperties() {
                    return new Hashtable();
                }
            };

    private final HostLocationProvider provider = new HostLocationProvider();
    private final TestHostRegistry hostRegistry = new TestHostRegistry();
    private final TestTopologyService topoService = new TestTopologyService();
    private final TestDeviceService deviceService = new TestDeviceService();
    private final TestHostService hostService = new TestHostService();
    private final TestPacketService packetService = new TestPacketService();
    private final TestInterfaceService interfaceService = new TestInterfaceService();

    private PacketProcessor testProcessor;
    private CoreService coreService;
    private TestHostProviderService providerService;

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

    @Before
    public void setUp() {
        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication(appId.name()))
                .andReturn(appId).anyTimes();
        replay(coreService);

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

        provider.providerRegistry = hostRegistry;
        provider.topologyService = topoService;
        provider.packetService = packetService;
        provider.deviceService = deviceService;
        provider.hostService = hostService;
        provider.interfaceService = interfaceService;

        provider.activate(CTX_FOR_NO_REMOVE);

        provider.deviceEventHandler = MoreExecutors.newDirectExecutorService();
    }

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

    @Test
    public void events() {
        // New host. Expect one additional host description.
        testProcessor.process(new TestArpPacketContext(DEV1));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("New host expected",
                providerService.descriptions.size(), is(1)));

        // The host moved to new switch. Expect one additional host description.
        // The second host description should have a different location.
        testProcessor.process(new TestArpPacketContext(DEV2));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("Host motion expected",
                providerService.descriptions.size(), is(2)));
        final HostLocation loc11 = providerService.descriptions.get(0).location();
        final HostLocation loc12 = providerService.descriptions.get(1).location();
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertNotEquals("Host location should be different",
                loc11, loc12));

        // The host was misheard on a spine. Expect no additional host description.
        testProcessor.process(new TestArpPacketContext(DEV3));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("Host misheard on spine switch",
                providerService.descriptions.size(), is(2)));

        providerService.clear();

        // New host. Expect two additional host descriptions. One for target IP. One for dest IP.
        testProcessor.process(new TestNaPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("New host expected",
                providerService.descriptions.size(), is(2)));

        // The host moved to new switch. Expect two additional host descriptions.
        // The 3rd and 4th host description should have a different location.
        testProcessor.process(new TestNaPacketContext(DEV5));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("Host motion expected",
                providerService.descriptions.size(), is(4)));
        final HostLocation loc21 = providerService.descriptions.get(0).location();
        final HostLocation loc22 = providerService.descriptions.get(1).location();
        final HostLocation loc23 = providerService.descriptions.get(2).location();
        final HostLocation loc24 = providerService.descriptions.get(3).location();
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertEquals("1st and 2nd location should be equal",
                loc21, loc22));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertEquals("3rd and 4th location should be equal",
                loc23, loc24));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertNotEquals("1st and 3rd location should be different",
                loc21, loc23));

        // The host was misheard on a spine. Expect no additional host description.
        testProcessor.process(new TestNaPacketContext(DEV6));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("Host misheard on spine switch",
                providerService.descriptions.size(), is(4)));
    }

    @Test
    public void removeHostByDeviceRemove() {
        provider.modified(CTX_FOR_REMOVE);
        testProcessor.process(new TestArpPacketContext(DEV1));
        testProcessor.process(new TestNaPacketContext(DEV4));

        Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
        assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);

        device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
        assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
    }

    @Test
    public void removeHostByDeviceOffline() {
        provider.modified(CTX_FOR_REMOVE);
        testProcessor.process(new TestArpPacketContext(DEV1));
        testProcessor.process(new TestArpPacketContext(DEV4));

        Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
        assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);

        device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
        assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
    }

    @Test
    public void removeHostByDevicePortDown() {
        provider.modified(CTX_FOR_REMOVE);
        testProcessor.process(new TestArpPacketContext(DEV1));
        testProcessor.process(new TestArpPacketContext(DEV4));

        Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
                new DefaultPort(device, portNumber(INPORT), false)));
        assertEquals("incorrect remove count", 1, providerService.locationRemoveCount);

        device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
                                          "m", "h", "s", "n", new ChassisId(0L));
        deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
                new DefaultPort(device, portNumber(INPORT), false)));
        assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
    }

    /**
     * When receiving ARP, updates location and IP.
     */
    @Test
    public void receiveArp() {
        testProcessor.process(new TestArpPacketContext(DEV1));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveArp. One host description expected",
                providerService.descriptions.size(), is(1)));
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));
    }

    /**
     * When receiving IPv4, updates location only.
     */
    @Test
    public void receiveIpv4() {
        testProcessor.process(new TestIpv4PacketContext(DEV1));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveIpv4. One host description expected",
                providerService.descriptions.size(), is(1)));
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));
    }

    /**
     * When receiving DHCP REQUEST, update MAC, location of client.
     * When receiving DHCP ACK, update MAC, location of server and IP of client.
     */
    @Test
    public void receiveDhcp() {
        TestUtils.setField(provider, "useDhcp", true);
        // DHCP Request
        testProcessor.process(new TestDhcpRequestPacketContext(DEV1, VLAN));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveDhcpRequest. One host description expected",
                providerService.descriptions.size(), is(1)));
        // Should learn the MAC and location of DHCP client
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));

        // DHCP Ack
        testProcessor.process(new TestDhcpAckPacketContext(DEV1));
        TestTools.assertAfter(ASSERTION_DELAY, () ->
                assertThat("receiveDhcpAck. Two additional host descriptions expected",
                providerService.descriptions.size(), is(3)));

        // Should also learn the MAC, location of DHCP server
        HostDescription descr2 = providerService.descriptions.get(1);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.location(), is(LOCATION3)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.hwAddress(), is(MAC3)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.vlan(), is(VLAN)));

        // Should update the IP address of the client.
        HostDescription descr3 = providerService.descriptions.get(2);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.location(), is(LOCATION)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.hwAddress(), is(MAC)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.ipAddress().size(), is(1)));
        IpAddress ip = descr3.ipAddress().iterator().next();
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(ip, is(IP_ADDRESS.getIp4Address())));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.vlan(), is(VLAN)));
    }

    /**
     * When receiving DHCPv6 REQUEST, update MAC, location of client.
     * When receiving DHCPv6 ACK, update MAC, location of server and IP of client.
     */
    @Test
    public void receiveDhcp6() {
        TestUtils.setField(provider, "useDhcp6", true);
        // DHCP Request
        testProcessor.process(new TestDhcp6RequestPacketContext(DEV4, VLAN));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveDhcpRequest. One host description expected",
                   providerService.descriptions.size(), is(1)));
        // Should learn the MAC and location of DHCP client
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));

        // DHCP Ack
        testProcessor.process(new TestDhcp6AckPacketContext(DEV1));
        TestTools.assertAfter(ASSERTION_DELAY, () ->
                assertThat("receiveDhcpAck. Two additional host descriptions expected",
                   providerService.descriptions.size(), is(3)));

        // Should also learn the MAC, location of DHCP server
        HostDescription descr2 = providerService.descriptions.get(1);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.location(), is(LOCATION3)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.hwAddress(), is(DHCP6_SERVER_MAC)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr2.vlan(), is(VLAN)));

        // Should update the IP address of the DHCP client.
        HostDescription descr3 = providerService.descriptions.get(2);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.ipAddress().size(), is(1)));
        IpAddress ip = descr3.ipAddress().iterator().next();
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(ip, is(IP_ADDRESS2.getIp6Address())));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr3.vlan(), is(VLAN)));
    }

    /**
     * When receiving NeighborAdvertisement, updates location and IP.
     * We should also expect that target IP is learnt.
     */
    @Test
    public void receiveNa() {
        testProcessor.process(new TestNaPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveNa. One host description expected",
                providerService.descriptions.size(), is(2)));
        final HostDescription descr0 = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr0.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr0.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertTrue(descr0.ipAddress().contains(LLIP_ADDRESS2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr0.vlan(), is(VLAN)));

        final HostDescription descr1 = providerService.descriptions.get(1);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr1.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr1.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertTrue(descr1.ipAddress().contains(IP_ADDRESS2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr1.vlan(), is(VLAN)));
    }

    /**
     * When receiving NeighborSolicitation, updates location and IP.
     */
    @Test
    public void receiveNs() {
        testProcessor.process(new TestNsPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveNs. One host description expected",
                providerService.descriptions.size(), is(1)));
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));
    }

    /**
     * When receiving RouterAdvertisement, ignores it.
     */
    @Test
    public void receivesRa() {
        testProcessor.process(new TestRAPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receivesRa. No host description expected",
                providerService.descriptions.size(), is(0)));
    }

    /**
     * When receiving RouterSolicitation, ignores it.
     */
    @Test
    public void receiveRs() {
        testProcessor.process(new TestRSPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveRs. No host description expected",
                providerService.descriptions.size(), is(0)));
    }

    /**
     * When receiving Duplicate Address Detection (DAD), ignores it.
     */
    @Test
    public void receiveDad() {
        testProcessor.process(new TestDadPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveDad. No host description expected",
                providerService.descriptions.size(), is(0)));
    }

    /**
     * When receiving IPv6 multicast packet, ignores it.
     */
    @Test
    public void receiveIpv6Multicast() {
        testProcessor.process(new TestIpv6McastPacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveIpv6Multicast. No host description expected",
                providerService.descriptions.size(), is(0)));
    }

    /**
     * When receiving IPv6 unicast packet, updates location only.
     */
    @Test
    public void receiveIpv6Unicast() {
        testProcessor.process(new TestIpv6PacketContext(DEV4));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat("receiveIpv6Unicast. One host description expected",
                providerService.descriptions.size(), is(1)));
        HostDescription descr = providerService.descriptions.get(0);
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.location(), is(LOCATION2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.hwAddress(), is(MAC2)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.ipAddress().size(), is(0)));
        TestTools.assertAfter(ASSERTION_DELAY, () -> assertThat(descr.vlan(), is(VLAN)));
    }

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

    private class TestHostRegistry implements HostProviderRegistry {

        @Override
        public HostProviderService register(HostProvider provider) {
            providerService = new TestHostProviderService(provider);
            return providerService;
        }

        @Override
        public void unregister(HostProvider provider) {
        }

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

    }

    private class TestHostProviderService
            extends AbstractProviderService<HostProvider>
            implements HostProviderService {

        List<HostDescription> descriptions = Lists.newArrayList();
        int hostRemoveCount;
        int ipRemoveCount;
        int locationRemoveCount;

        public void clear() {
            descriptions.clear();
            hostRemoveCount = 0;
            ipRemoveCount = 0;
            locationRemoveCount = 0;
        }

        protected TestHostProviderService(HostProvider provider) {
            super(provider);
        }

        @Override
        public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
            descriptions.add(hostDescription);
        }

        @Override
        public void hostVanished(HostId hostId) {
            hostRemoveCount++;
        }

        @Override
        public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
            ipRemoveCount++;
        }

        @Override
        public void removeLocationFromHost(HostId hostId, HostLocation location) {
            locationRemoveCount++;
        }

    }

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

    private class TestTopologyService extends TopologyServiceAdapter {
        @Override
        public boolean isInfrastructure(Topology topology,
                                        ConnectPoint connectPoint) {
            //simulate DPID3 as an infrastructure switch
            if ((connectPoint.deviceId()).equals(deviceId(DEV3)) ||
                    connectPoint.deviceId().equals(deviceId(DEV6))) {
                return true;
            }
            return false;
        }
    }

    /**
     * Generates ARP packet.
     */
    private class TestArpPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestArpPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            ARP arp = new ARP();
            arp.setSenderProtocolAddress(IP)
                    .setSenderHardwareAddress(MAC.toBytes())
                    .setTargetHardwareAddress(BCMAC.toBytes())
                    .setTargetProtocolAddress(IP);

            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_ARP)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC.toBytes())
                    .setDestinationMACAddress(BCMAC)
                    .setPayload(arp);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates IPv4 Unicast packet.
     */
    private class TestIpv4PacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestIpv4PacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            IPv4 ipv4 = new IPv4();
            ipv4.setDestinationAddress("10.0.0.1");
            ipv4.setSourceAddress(IP_ADDRESS.toString());
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV4)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC)
                    .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
                    .setPayload(ipv4);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates DHCP REQUEST packet.
     */
    private class TestDhcpRequestPacketContext extends PacketContextAdapter {
        private final String deviceId;
        private final VlanId vlanId;

        public TestDhcpRequestPacketContext(String deviceId, VlanId vlanId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
            this.vlanId = vlanId;
        }

        @Override
        public InboundPacket inPacket() {
            byte[] dhcpMsgType = new byte[1];
            dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();

            DhcpOption dhcpOption = new DhcpOption();
            dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
            dhcpOption.setData(dhcpMsgType);
            dhcpOption.setLength((byte) 1);
            DHCP dhcp = new DHCP();
            dhcp.setOptions(Collections.singletonList(dhcpOption));
            dhcp.setClientHardwareAddress(MAC.toBytes());
            UDP udp = new UDP();
            udp.setPayload(dhcp);
            udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
            udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
            IPv4 ipv4 = new IPv4();
            ipv4.setPayload(udp);
            ipv4.setDestinationAddress(IP_ADDRESS3.toString());
            ipv4.setSourceAddress(IP_ADDRESS.toString());
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV4)
                    .setVlanID(this.vlanId.toShort())
                    .setSourceMACAddress(MAC)
                    .setDestinationMACAddress(MAC3)
                    .setPayload(ipv4);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                    portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                    ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates DHCP ACK packet.
     */
    private class TestDhcpAckPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestDhcpAckPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            byte[] dhcpMsgType = new byte[1];
            dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();

            DhcpOption dhcpOption = new DhcpOption();
            dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
            dhcpOption.setData(dhcpMsgType);
            dhcpOption.setLength((byte) 1);

            DHCP dhcp = new DHCP();
            dhcp.setOptions(ImmutableList.of(dhcpOption));

            dhcp.setClientHardwareAddress(MAC.toBytes());
            dhcp.setYourIPAddress(IP_ADDRESS.getIp4Address().toInt());

            UDP udp = new UDP();
            udp.setPayload(dhcp);
            udp.setSourcePort(UDP.DHCP_SERVER_PORT);
            udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
            IPv4 ipv4 = new IPv4();
            ipv4.setPayload(udp);
            ipv4.setDestinationAddress(IP_ADDRESS.toString());
            ipv4.setSourceAddress(IP_ADDRESS3.toString());
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV4)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC3)
                    .setDestinationMACAddress(MAC)
                    .setPayload(ipv4);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                    portNumber(INPORT2));
            return new DefaultInboundPacket(receivedFrom, eth,
                    ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates DHCPv6 REQUEST packet.
     */
    private class TestDhcp6RequestPacketContext extends PacketContextAdapter {
        private final String deviceId;
        private final VlanId vlanId;

        public TestDhcp6RequestPacketContext(String deviceId, VlanId vlanId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
            this.vlanId = vlanId;
        }

        @Override
        public InboundPacket inPacket() {

            DHCP6 dhcp6 = new DHCP6();
            dhcp6.setMsgType(DHCP6.MsgType.REQUEST.value());
            List<Dhcp6Option> options = Lists.newArrayList();

            // IA address
            Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
            iaAddressOption.setIp6Address(IP_ADDRESS2.getIp6Address());

            // IA NA
            Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
            iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
            options.add(iaNaOption);

            dhcp6.setOptions(options);

            UDP udp = new UDP();
            udp.setPayload(dhcp6);
            udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
            udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(udp);
            ipv6.setDestinationAddress(Ip6Address.ZERO.toOctets());
            ipv6.setSourceAddress(Ip6Address.ZERO.toOctets());
            ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(this.vlanId.toShort())
                    .setSourceMACAddress(MAC2)
                    .setDestinationMACAddress(DHCP6_SERVER_MAC)
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates DHCPv6 ACK packet.
     */
    private class TestDhcp6AckPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestDhcp6AckPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            DHCP6 dhcp6 = new DHCP6();
            dhcp6.setMsgType(DHCP6.MsgType.REPLY.value());
            List<Dhcp6Option> options = Lists.newArrayList();

            // IA address
            Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
            iaAddressOption.setIp6Address(IP_ADDRESS2.getIp6Address());

            // IA NA
            Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
            iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
            options.add(iaNaOption);

            // Client ID
            Dhcp6Duid duid = new Dhcp6Duid();
            duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
            duid.setHardwareType((short) 1);
            duid.setDuidTime(0);
            duid.setLinkLayerAddress(MAC2.toBytes());
            Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
            clientIdOption.setDuid(duid);
            options.add(clientIdOption);
            dhcp6.setOptions(options);

            UDP udp = new UDP();
            udp.setPayload(dhcp6);
            udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
            udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(udp);
            ipv6.setDestinationAddress(Ip6Address.ZERO.toOctets());
            ipv6.setSourceAddress(Ip6Address.ZERO.toOctets());
            ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(DHCP6_SERVER_MAC)
                    .setDestinationMACAddress(MAC2)
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT2));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates NeighborAdvertisement packet.
     */
    private class TestNaPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestNaPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            NeighborAdvertisement na = new NeighborAdvertisement();
            na.setTargetAddress(IP2);
            ICMP6 icmp6 = new ICMP6();
            icmp6.setPayload(na);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(icmp6);
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
            ipv6.setSourceAddress(LLIP2);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(BCMAC2)
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates NeighborSolicitation packet.
     */
    private class TestNsPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestNsPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            NeighborSolicitation ns = new NeighborSolicitation();
            ICMP6 icmp6 = new ICMP6();
            icmp6.setPayload(ns);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(icmp6);
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1:ff00:0000").toOctets());
            ipv6.setSourceAddress(IP2);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(BCMAC2)
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates Duplicate Address Detection packet.
     */
    private class TestDadPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestDadPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            NeighborSolicitation ns = new NeighborSolicitation();
            ICMP6 icmp6 = new ICMP6();
            icmp6.setPayload(ns);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(icmp6);
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
            ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(BCMAC2)
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates Router Solicitation packet.
     */
    private class TestRSPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestRSPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            RouterSolicitation ns = new RouterSolicitation();
            ICMP6 icmp6 = new ICMP6();
            icmp6.setPayload(ns);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(icmp6);
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::2").toOctets());
            ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:02"))
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates Router Advertisement packet.
     */
    private class TestRAPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestRAPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            RouterAdvertisement ns = new RouterAdvertisement();
            ICMP6 icmp6 = new ICMP6();
            icmp6.setPayload(ns);
            IPv6 ipv6 = new IPv6();
            ipv6.setPayload(icmp6);
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
            ipv6.setSourceAddress(IP2);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates IPv6 Multicast packet.
     */
    private class TestIpv6McastPacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestIpv6McastPacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            IPv6 ipv6 = new IPv6();
            ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
            ipv6.setSourceAddress(IP2);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2.toBytes())
                    .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    /**
     * Generates IPv6 Unicast packet.
     */
    private class TestIpv6PacketContext extends PacketContextAdapter {
        private final String deviceId;

        public TestIpv6PacketContext(String deviceId) {
            super(0, null, null, false);
            this.deviceId = deviceId;
        }

        @Override
        public InboundPacket inPacket() {
            IPv6 ipv6 = new IPv6();
            ipv6.setDestinationAddress(Ip6Address.valueOf("1000::1").toOctets());
            ipv6.setSourceAddress(IP2);
            Ethernet eth = new Ethernet();
            eth.setEtherType(Ethernet.TYPE_IPV6)
                    .setVlanID(VLAN.toShort())
                    .setSourceMACAddress(MAC2)
                    .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
                    .setPayload(ipv6);
            ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
                                                         portNumber(INPORT));
            return new DefaultInboundPacket(receivedFrom, eth,
                                            ByteBuffer.wrap(eth.serialize()));
        }
    }

    private class TestDeviceService extends DeviceServiceAdapter {
        private DeviceListener listener;

        @Override
        public void addListener(DeviceListener listener) {
            this.listener = listener;
        }

        @Override
        public Iterable<Device> getDevices() {
            return Collections.emptyList();
        }
    }

    private class TestHostService extends HostServiceAdapter {
        @Override
        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
            ConnectPoint cp1 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT));
            ConnectPoint cp2 = new ConnectPoint(deviceId(DEV4), portNumber(INPORT));
            ConnectPoint cp3 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT2));
            if (connectPoint.equals(cp1)) {
                return ImmutableSet.of(HOST);
            } else if (connectPoint.equals(cp2)) {
                return ImmutableSet.of(HOST2);
            } else if (connectPoint.equals(cp3)) {
                return ImmutableSet.of(HOST3);
            } else {
                return ImmutableSet.of();
            }
        }

        @Override
        public Set<Host> getConnectedHosts(DeviceId deviceId) {
            if (deviceId.equals(deviceId(DEV1))) {
                return ImmutableSet.of(HOST, HOST3);
            } else if (deviceId.equals(deviceId(DEV4))) {
                return ImmutableSet.of(HOST2);
            } else {
                return ImmutableSet.of();
            }
        }

        @Override
        public Host getHost(HostId hostId) {
            if (hostId.equals(HostId.hostId(MAC, VLAN))) {
                return HOST;
            } else if (hostId.equals(HostId.hostId(MAC2, VLAN))) {
                return HOST2;
            } else if (hostId.equals(HostId.hostId(MAC3, VLAN))) {
                return HOST3;
            } else if (hostId.equals(HostId.hostId(MAC, VLAN_100))) {
                return HOST_VLAN_100;
            }
            return null;
        }
    }

    private class TestInterfaceService implements InterfaceService {
        @Override
        public Set<Interface> getInterfaces() {
            return null;
        }

        @Override
        public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
            return null;
        }

        @Override
        public Set<Interface> getInterfacesByPort(ConnectPoint port) {
            return null;
        }

        @Override
        public Set<Interface> getInterfacesByIp(IpAddress ip) {
            if (ip.equals(GW_IFACE_ADDR.ipAddress())) {
                return ImmutableSet.of(GW_IFACE);
            } else {
                return ImmutableSet.of();
            }
        }

        @Override
        public Set<Interface> getInterfacesByVlan(VlanId vlan) {
            return null;
        }

        @Override
        public Interface getMatchingInterface(IpAddress ip) {
            return null;
        }

        @Override
        public Set<Interface> getMatchingInterfaces(IpAddress ip) {
            return null;
        }

        @Override
        public void addListener(InterfaceListener listener) {

        }

        @Override
        public void removeListener(InterfaceListener listener) {

        }

        @Override
        public boolean isConfigured(ConnectPoint connectPoint) {
            return false;
        }
    }
}
