Adding more unit tests.
Made some classes abstract which should have been.
diff --git a/core/api/src/main/java/org/onlab/onos/net/AbstractAnnotated.java b/core/api/src/main/java/org/onlab/onos/net/AbstractAnnotated.java
index f29ad43..c329598 100644
--- a/core/api/src/main/java/org/onlab/onos/net/AbstractAnnotated.java
+++ b/core/api/src/main/java/org/onlab/onos/net/AbstractAnnotated.java
@@ -5,7 +5,7 @@
/**
* Base abstraction of an annotated entity.
*/
-public class AbstractAnnotated implements Annotated {
+public abstract class AbstractAnnotated implements Annotated {
private static final Annotations EMPTY = DefaultAnnotations.builder().build();
diff --git a/core/api/src/main/java/org/onlab/onos/net/AbstractDescription.java b/core/api/src/main/java/org/onlab/onos/net/AbstractDescription.java
index 5e5b117..5ebde83 100644
--- a/core/api/src/main/java/org/onlab/onos/net/AbstractDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/AbstractDescription.java
@@ -5,7 +5,7 @@
/**
* Base implementation of an annotated model description.
*/
-public class AbstractDescription implements Annotated {
+public abstract class AbstractDescription implements Annotated {
private static final SparseAnnotations EMPTY = DefaultAnnotations.builder().build();
diff --git a/core/api/src/main/java/org/onlab/onos/net/AbstractElement.java b/core/api/src/main/java/org/onlab/onos/net/AbstractElement.java
index 251d68a..f39469b 100644
--- a/core/api/src/main/java/org/onlab/onos/net/AbstractElement.java
+++ b/core/api/src/main/java/org/onlab/onos/net/AbstractElement.java
@@ -5,7 +5,7 @@
/**
* Base implementation of network elements, i.e. devices or hosts.
*/
-public class AbstractElement extends AbstractModel implements Element {
+public abstract class AbstractElement extends AbstractModel implements Element {
protected final ElementId id;
@@ -27,9 +27,4 @@
this.id = id;
}
- @Override
- public ElementId id() {
- return id;
- }
-
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/AbstractModel.java b/core/api/src/main/java/org/onlab/onos/net/AbstractModel.java
index 482ec68..f5f7689 100644
--- a/core/api/src/main/java/org/onlab/onos/net/AbstractModel.java
+++ b/core/api/src/main/java/org/onlab/onos/net/AbstractModel.java
@@ -5,7 +5,7 @@
/**
* Base implementation of a network model entity.
*/
-public class AbstractModel extends AbstractAnnotated implements Provided {
+public abstract class AbstractModel extends AbstractAnnotated implements Provided {
private final ProviderId providerId;
diff --git a/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java b/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
index 88eafb2..001518e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DefaultAnnotations.java
@@ -5,6 +5,8 @@
import java.util.Objects;
import java.util.Set;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Represents a set of simple annotations that can be used to add arbitrary
* attributes to various parts of the data model.
@@ -19,9 +21,9 @@
}
/**
- * Creates a new set of annotations using the specified immutable map.
+ * Creates a new set of annotations using clone of the specified hash map.
*
- * @param map immutable map of key/value pairs
+ * @param map hash map of key/value pairs
*/
private DefaultAnnotations(Map<String, String> map) {
this.map = map;
@@ -36,6 +38,38 @@
return new Builder();
}
+ /**
+ * Merges the specified base set of annotations and additional sparse
+ * annotations into new combined annotations. If the supplied sparse
+ * annotations are empty, the original base annotations are returned.
+ * Any keys tagged for removal in the sparse annotations will be omitted
+ * in the resulting merged annotations.
+ *
+ * @param annotations base annotations
+ * @param sparseAnnotations additional sparse annotations
+ * @return combined annotations or the original base annotations if there
+ * are not additional annotations
+ */
+ public static DefaultAnnotations merge(DefaultAnnotations annotations,
+ SparseAnnotations sparseAnnotations) {
+ checkNotNull(annotations, "Annotations cannot be null");
+ if (sparseAnnotations == null || sparseAnnotations.keys().isEmpty()) {
+ return annotations;
+ }
+
+ // Merge the two maps. Yes, this is not very efficient, but the
+ // use-case implies small maps and infrequent merges, so we opt for
+ // simplicity.
+ Map<String, String> merged = copy(annotations.map);
+ for (String key : sparseAnnotations.keys()) {
+ if (sparseAnnotations.isRemoved(key)) {
+ merged.remove(key);
+ } else {
+ merged.put(key, sparseAnnotations.value(key));
+ }
+ }
+ return new DefaultAnnotations(merged);
+ }
@Override
public Set<String> keys() {
@@ -53,15 +87,20 @@
return Objects.equals(Builder.REMOVED, map.get(key));
}
+ @SuppressWarnings("unchecked")
+ private static HashMap<String, String> copy(Map<String, String> original) {
+ if (original instanceof HashMap) {
+ return (HashMap) ((HashMap) original).clone();
+ }
+ throw new IllegalArgumentException("Expecting HashMap instance");
+ }
+
/**
* Facility for gradually building model annotations.
*/
public static final class Builder {
private static final String REMOVED = "~rEmOvEd~";
-
- // FIXME: Figure out whether and how to make this immutable and serializable
-// private final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
private final Map<String, String> builder = new HashMap<>();
// Private construction is forbidden.
@@ -99,8 +138,7 @@
* @return annotations
*/
public DefaultAnnotations build() {
-// return new DefaultAnnotations(builder.build());
- return new DefaultAnnotations(builder);
+ return new DefaultAnnotations(copy(builder));
}
}
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/DefaultDevice.java b/core/api/src/main/java/org/onlab/onos/net/DefaultDevice.java
index 2c6c4ff..8b3eee1 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DefaultDevice.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DefaultDevice.java
@@ -51,7 +51,7 @@
@Override
public DeviceId id() {
- return (DeviceId) super.id();
+ return (DeviceId) id;
}
@Override
diff --git a/core/api/src/main/java/org/onlab/onos/net/DefaultHost.java b/core/api/src/main/java/org/onlab/onos/net/DefaultHost.java
index efa876b..85712e8 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DefaultHost.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DefaultHost.java
@@ -45,7 +45,7 @@
@Override
public HostId id() {
- return (HostId) super.id();
+ return (HostId) id;
}
@Override
diff --git a/core/api/src/test/java/org/onlab/onos/net/ConnectPointTest.java b/core/api/src/test/java/org/onlab/onos/net/ConnectPointTest.java
new file mode 100644
index 0000000..ebb5217
--- /dev/null
+++ b/core/api/src/test/java/org/onlab/onos/net/ConnectPointTest.java
@@ -0,0 +1,37 @@
+package org.onlab.onos.net;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.onlab.onos.net.Device.Type.SWITCH;
+import static org.onlab.onos.net.DeviceId.deviceId;
+import static org.onlab.onos.net.PortNumber.portNumber;
+
+/**
+ * Test of the connetion point entity.
+ */
+public class ConnectPointTest {
+
+ public static final DeviceId DID1 = deviceId("1");
+ public static final DeviceId DID2 = deviceId("2");
+ public static final PortNumber P1 = portNumber(1);
+ public static final PortNumber P2 = portNumber(2);
+
+ @Test
+ public void basics() {
+ ConnectPoint p = new ConnectPoint(DID1, P2);
+ assertEquals("incorrect element id", DID1, p.deviceId());
+ assertEquals("incorrect element id", P2, p.port());
+ }
+
+
+ @Test
+ public void testEquality() {
+ new EqualsTester()
+ .addEqualityGroup(new ConnectPoint(DID1, P1), new ConnectPoint(DID1, P1))
+ .addEqualityGroup(new ConnectPoint(DID1, P2), new ConnectPoint(DID1, P2))
+ .addEqualityGroup(new ConnectPoint(DID2, P1), new ConnectPoint(DID2, P1))
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onlab/onos/net/DefaultAnnotationsTest.java b/core/api/src/test/java/org/onlab/onos/net/DefaultAnnotationsTest.java
new file mode 100644
index 0000000..274f4b8
--- /dev/null
+++ b/core/api/src/test/java/org/onlab/onos/net/DefaultAnnotationsTest.java
@@ -0,0 +1,68 @@
+package org.onlab.onos.net;
+
+import org.junit.Test;
+
+import static com.google.common.collect.ImmutableSet.of;
+import static org.junit.Assert.*;
+import static org.onlab.onos.net.DefaultAnnotations.builder;
+
+/**
+ * Tests of the default annotations.
+ */
+public class DefaultAnnotationsTest {
+
+ private DefaultAnnotations annotations;
+
+ @Test
+ public void basics() {
+ annotations = builder().set("foo", "1").set("bar", "2").build();
+ assertEquals("incorrect keys", of("foo", "bar"), annotations.keys());
+ assertEquals("incorrect value", "1", annotations.value("foo"));
+ assertEquals("incorrect value", "2", annotations.value("bar"));
+ }
+
+ @Test
+ public void empty() {
+ annotations = builder().build();
+ assertTrue("incorrect keys", annotations.keys().isEmpty());
+ }
+
+ @Test
+ public void remove() {
+ annotations = builder().remove("foo").set("bar", "2").build();
+ assertEquals("incorrect keys", of("foo", "bar"), annotations.keys());
+ assertNull("incorrect value", annotations.value("foo"));
+ assertEquals("incorrect value", "2", annotations.value("bar"));
+ }
+
+ @Test
+ public void merge() {
+ annotations = builder().set("foo", "1").set("bar", "2").build();
+ assertEquals("incorrect keys", of("foo", "bar"), annotations.keys());
+
+ SparseAnnotations updates = builder().remove("foo").set("bar", "3").set("goo", "4").build();
+
+ annotations = DefaultAnnotations.merge(annotations, updates);
+ assertEquals("incorrect keys", of("goo", "bar"), annotations.keys());
+ assertNull("incorrect value", annotations.value("foo"));
+ assertEquals("incorrect value", "3", annotations.value("bar"));
+ }
+
+ @Test
+ public void noopMerge() {
+ annotations = builder().set("foo", "1").set("bar", "2").build();
+ assertEquals("incorrect keys", of("foo", "bar"), annotations.keys());
+
+ SparseAnnotations updates = builder().build();
+ assertSame("same annotations expected", annotations,
+ DefaultAnnotations.merge(annotations, updates));
+ assertSame("same annotations expected", annotations,
+ DefaultAnnotations.merge(annotations, null));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void badMerge() {
+ DefaultAnnotations.merge(null, null);
+ }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onlab/onos/net/DefaultDeviceTest.java b/core/api/src/test/java/org/onlab/onos/net/DefaultDeviceTest.java
index ea1c8fd..f7bc617 100644
--- a/core/api/src/test/java/org/onlab/onos/net/DefaultDeviceTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/DefaultDeviceTest.java
@@ -40,6 +40,18 @@
@Test
public void basics() {
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
+ validate(device);
+ }
+
+ @Test
+ public void annotations() {
+ Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1,
+ DefaultAnnotations.builder().set("foo", "bar").build());
+ validate(device);
+ assertEquals("incorrect provider", "bar", device.annotations().value("foo"));
+ }
+
+ private void validate(Device device) {
assertEquals("incorrect provider", PID, device.providerId());
assertEquals("incorrect id", DID1, device.id());
assertEquals("incorrect type", SWITCH, device.type());
@@ -50,4 +62,4 @@
assertEquals("incorrect serial", SN1, device.serialNumber());
}
-}
+}
\ No newline at end of file