--- /dev/null
+/*
+ * Copyright (c) 2012 Big Switch Networks, Inc.
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
+ *
+ * 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.opendaylight.controller.hosttracker.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.opendaylight.controller.hosttracker.Entity;
+import org.opendaylight.controller.hosttracker.IDeviceService.DeviceField;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+
+/**
+ *
+ * @author gregor
+ *
+ */
+public class DeviceUniqueIndexTest extends TestCase {
+ protected Entity e1a;
+ protected Entity e1b;
+ protected Device d1;
+ protected Entity e2;
+ protected Entity e2alt;
+ protected Entity e3;
+ protected Entity e3_ip;
+ protected Entity e4;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Node n1 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(1L));
+ NodeConnector n1_1 = new NodeConnector(NodeConnectorIDType.OPENFLOW,
+ Short.valueOf((short) 1), n1);
+ e1a = new Entity(1L, (short) 1, 1, n1_1, new Date());
+ e1b = new Entity(1L, (short) 2, 1, n1_1, new Date());
+ List<Entity> d1Entities = new ArrayList<Entity>(2);
+ d1Entities.add(e1a);
+ d1Entities.add(e1b);
+ d1 = new Device(null, Long.valueOf(1), null, null, null, d1Entities,
+ null);
+
+ Node n2 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(2L));
+ NodeConnector n2_2 = new NodeConnector(NodeConnectorIDType.OPENFLOW,
+ Short.valueOf((short) 2), n2);
+ Node n3 = new Node(Node.NodeIDType.OPENFLOW, Long.valueOf(3L));
+ NodeConnector n3_3 = new NodeConnector(NodeConnectorIDType.OPENFLOW,
+ Short.valueOf((short) 3), n3);
+
+ // e2 and e2 alt match in MAC and VLAN
+ e2 = new Entity(2L, (short) 2, 2, n2_2, new Date());
+ e2alt = new Entity(2, (short) 2, null, null, null);
+
+ // IP is null
+ e3 = new Entity(3L, (short) 3, null, n3_3, new Date());
+ e3_ip = new Entity(3L, (short) 3, 3, n3_3, new Date());
+
+ // IP and switch and port are null
+ e4 = new Entity(4L, (short) 4, null, null, new Date());
+ }
+
+ /*
+ * Checks that the iterator it returns the elements in the Set expected
+ * Doesn't check how often an element is returned as long it's at least once
+ */
+ protected void verifyIterator(Set<Long> expected, Iterator<Long> it) {
+ HashSet<Long> actual = new HashSet<Long>();
+ while (it.hasNext()) {
+ actual.add(it.next());
+ }
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testDeviceUniqueIndex() {
+ DeviceUniqueIndex idx1 = new DeviceUniqueIndex(EnumSet.of(
+ DeviceField.MAC, DeviceField.VLAN));
+
+ idx1.updateIndex(d1, d1.getDeviceKey());
+ idx1.updateIndex(e2, 2L);
+
+ // -------------
+ // Test findByEntity lookups
+ assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a));
+ assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
+ assertEquals(Long.valueOf(2L), idx1.findByEntity(e2));
+ // we didn't add e2alt but since they key fields are the same we
+ // should find it
+ assertEquals(Long.valueOf(2L), idx1.findByEntity(e2alt));
+ assertEquals(null, idx1.findByEntity(e3));
+ assertEquals(null, idx1.findByEntity(e4));
+
+ // -------------
+ // Test getAll()
+ HashSet<Long> expectedKeys = new HashSet<Long>();
+ expectedKeys.add(1L);
+ expectedKeys.add(2L);
+ verifyIterator(expectedKeys, idx1.getAll());
+
+ // -------------
+ // Test queryByEntity()
+ verifyIterator(Collections.<Long> singleton(1L),
+ idx1.queryByEntity(e1a));
+ verifyIterator(Collections.<Long> singleton(1L),
+ idx1.queryByEntity(e1b));
+ verifyIterator(Collections.<Long> singleton(2L), idx1.queryByEntity(e2));
+ verifyIterator(Collections.<Long> singleton(2L),
+ idx1.queryByEntity(e2alt));
+ assertEquals(false, idx1.queryByEntity(e3).hasNext());
+ assertEquals(false, idx1.queryByEntity(e3).hasNext());
+
+ // -------------
+ // Test removal
+ idx1.removeEntity(e1a, 42L); // No-op. e1a isn't mapped to this key
+ assertEquals(Long.valueOf(1L), idx1.findByEntity(e1a));
+ idx1.removeEntity(e1a, 1L);
+ assertEquals(null, idx1.findByEntity(e1a));
+ assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
+ assertEquals(Long.valueOf(2L), idx1.findByEntity(e2));
+ idx1.removeEntity(e2);
+ assertEquals(null, idx1.findByEntity(e2));
+ assertEquals(Long.valueOf(1L), idx1.findByEntity(e1b));
+
+ // -------------
+ // Test null keys
+ DeviceUniqueIndex idx2 = new DeviceUniqueIndex(EnumSet.of(
+ DeviceField.IPV4, DeviceField.SWITCHPORT));
+ // only one key field is null
+ idx2.updateIndex(e3, 3L);
+ assertEquals(Long.valueOf(3L), idx2.findByEntity(e3));
+ assertEquals(null, idx2.findByEntity(e3_ip));
+ // all key fields are null
+ idx2.updateIndex(e4, 4L);
+ assertEquals(null, idx2.findByEntity(e4));
+ Device d4 = new Device(null, 4L, null, null, null,
+ Collections.<Entity> singleton(e4), null);
+ idx2.updateIndex(d4, 4L);
+ assertEquals(null, idx2.findByEntity(e4));
+
+ // -------------
+ // entity already exists with different deviceKey
+ DeviceUniqueIndex idx3 = new DeviceUniqueIndex(EnumSet.of(
+ DeviceField.MAC, DeviceField.VLAN));
+ idx3.updateIndex(e1a, 42L);
+ assertEquals(false, idx3.updateIndex(d1, 1L));
+ // TODO: shouldn't this fail as well so that the behavior
+ // is consistent?
+ idx3.updateIndex(e1a, 1L);
+ // anyways. We can now add d1 ;-)
+ assertEquals(true, idx3.updateIndex(d1, 1L));
+ }
+}