added tests for HostManager/service

Change-Id: Iae1ae753b7d4ca6be1759ce13308313ce49b57d3
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManager.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManager.java
index 3e43dfd..07e1e31 100644
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManager.java
+++ b/core/trivial/src/main/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManager.java
@@ -50,7 +50,7 @@
     private final SimpleHostStore store = new SimpleHostStore();
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    private EventDeliveryService eventDispatcher;
+    protected EventDeliveryService eventDispatcher;
 
 
     @Activate
diff --git a/core/trivial/src/test/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManagerTest.java b/core/trivial/src/test/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManagerTest.java
new file mode 100644
index 0000000..0524f0f
--- /dev/null
+++ b/core/trivial/src/test/java/org/onlab/onos/net/trivial/host/impl/SimpleHostManagerTest.java
@@ -0,0 +1,197 @@
+package org.onlab.onos.net.trivial.host.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.event.Event;
+import org.onlab.onos.event.impl.TestEventDispatcher;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Host;
+import org.onlab.onos.net.HostId;
+import org.onlab.onos.net.HostLocation;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.host.DefaultHostDescription;
+import org.onlab.onos.net.host.HostDescription;
+import org.onlab.onos.net.host.HostEvent;
+import org.onlab.onos.net.host.HostListener;
+import org.onlab.onos.net.host.HostProvider;
+import org.onlab.onos.net.host.HostProviderRegistry;
+import org.onlab.onos.net.host.HostProviderService;
+import org.onlab.onos.net.provider.AbstractProvider;
+import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.packet.IPAddress;
+import org.onlab.packet.MACAddress;
+import org.onlab.packet.VLANID;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import static org.onlab.onos.net.host.HostEvent.Type.*;
+
+/**
+ * Test codifying the host service & host provider service contracts.
+ */
+public class SimpleHostManagerTest {
+
+    private static final ProviderId PID = new ProviderId("foo");
+
+    private static final VLANID VLAN1 = VLANID.vlanId((short) 1);
+    private static final VLANID VLAN2 = VLANID.vlanId((short) 2);
+    private static final MACAddress MAC1 = MACAddress.valueOf("00:00:11:00:00:01");
+    private static final MACAddress MAC2 = MACAddress.valueOf("00:00:22:00:00:02");
+    private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
+    private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
+
+    private static final IPAddress IP1 = IPAddress.valueOf("10.0.0.1");
+    private static final IPAddress IP2 = IPAddress.valueOf("10.0.0.2");
+    private static final Set<IPAddress> IPSET1 = Sets.newHashSet(IP1);
+    private static final Set<IPAddress> IPSET2 = Sets.newHashSet(IP2);
+
+    private static final DeviceId DID1 = DeviceId.deviceId("of:001");
+    private static final DeviceId DID2 = DeviceId.deviceId("of:002");
+    private static final PortNumber P1 = PortNumber.portNumber(100);
+    private static final PortNumber P2 = PortNumber.portNumber(200);
+    private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
+    private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
+
+    private SimpleHostManager mgr;
+
+    protected TestListener listener = new TestListener();
+    protected HostProviderRegistry registry;
+    protected TestHostProvider provider;
+    protected HostProviderService providerService;
+
+    @Before
+    public void setUp() {
+        mgr = new SimpleHostManager();
+        mgr.eventDispatcher = new TestEventDispatcher();
+        registry = mgr;
+        mgr.activate();
+
+        mgr.addListener(listener);
+
+        provider = new TestHostProvider();
+        providerService = registry.register(provider);
+        assertTrue("provider should be registered",
+                registry.getProviders().contains(provider.id()));
+    }
+
+    @After
+    public void tearDown() {
+        registry.unregister(provider);
+        assertFalse("provider should not be registered",
+                registry.getProviders().contains(provider.id()));
+
+        mgr.removeListener(listener);
+        mgr.deactivate();
+        mgr.eventDispatcher = null;
+    }
+
+    private void detect(HostId hid, MACAddress mac, VLANID vlan,
+            HostLocation loc, Set<IPAddress> ips) {
+        HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ips);
+        providerService.hostDetected(hid, descr);
+        assertNotNull("host should be found", mgr.getHost(hid));
+    }
+
+    private void validateEvents(Enum... types) {
+        int i = 0;
+        assertEquals("wrong events received", types.length, listener.events.size());
+        for (Event event : listener.events) {
+            assertEquals("incorrect event type", types[i], event.type());
+            i++;
+        }
+        listener.events.clear();
+    }
+
+    @Test
+    public void hostDetected() {
+        assertNull("host shouldn't be found", mgr.getHost(HID1));
+
+        // host addition
+        detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
+        assertEquals("exactly one should be found", 1, mgr.getHostCount());
+        detect(HID2, MAC2, VLAN2, LOC2, IPSET1);
+        assertEquals("two hosts should be found", 2, mgr.getHostCount());
+        validateEvents(HOST_ADDED, HOST_ADDED);
+
+        // host motion
+        detect(HID1, MAC1, VLAN1, LOC2, IPSET1);
+        validateEvents(HOST_MOVED);
+        assertEquals("only two hosts should be found", 2, mgr.getHostCount());
+
+        // host update
+        detect(HID1, MAC1, VLAN1, LOC2, IPSET2);
+        validateEvents(HOST_UPDATED);
+        assertEquals("only two hosts should be found", 2, mgr.getHostCount());
+    }
+
+    @Test
+    public void hostVanished() {
+        detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
+        providerService.hostVanished(HID1);
+        validateEvents(HOST_ADDED, HOST_REMOVED);
+
+        assertNull("host should have been removed", mgr.getHost(HID1));
+    }
+
+    private void validateHosts(
+            String msg, Iterable<Host> hosts, HostId ... ids) {
+        Set<HostId> hids = Sets.newHashSet(ids);
+        for (Host h : hosts) {
+            assertTrue(msg, hids.remove(h.id()));
+        }
+        assertTrue("expected hosts not fetched from store", hids.isEmpty());
+    }
+
+    @Test
+    public void getHosts() {
+        detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
+        detect(HID2, MAC2, VLAN1, LOC2, IPSET2);
+
+        validateHosts("host not properly stored", mgr.getHosts(), HID1, HID2);
+        validateHosts("can't get hosts by VLAN", mgr.getHostsByVlan(VLAN1), HID1, HID2);
+        validateHosts("can't get hosts by MAC", mgr.getHostsByMac(MAC1), HID1);
+        validateHosts("can't get hosts by IP", mgr.getHostsByIp(IP1), HID1);
+        validateHosts("can't get hosts by location", mgr.getConnectedHosts(LOC1), HID1);
+        assertTrue("incorrect host location", mgr.getConnectedHosts(DID2).isEmpty());
+    }
+
+    private static class TestHostProvider extends AbstractProvider
+            implements HostProvider {
+
+        protected TestHostProvider() {
+            super(PID);
+        }
+
+        @Override
+        public ProviderId id() {
+            return PID;
+        }
+
+        @Override
+        public void triggerProbe(Host host) {
+        }
+
+    }
+
+    private static class TestListener implements HostListener {
+
+        protected List<HostEvent> events = Lists.newArrayList();
+
+        @Override
+        public void event(HostEvent event) {
+            events.add(event);
+        }
+
+    }
+}