Unit tests for some Intent objects and compilers
Unit tests for HostToHost and MultiPointToSinglePoint intents
and intent compilers.
Made Intent classes final to make them immutable.
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
index f420fc2..7a894be6 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
@@ -12,7 +12,7 @@
/**
* Abstraction of end-station to end-station bidirectional connectivity.
*/
-public class HostToHostIntent extends ConnectivityIntent {
+public final class HostToHostIntent extends ConnectivityIntent {
private final HostId one;
private final HostId two;
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
index 78c95cf..9d0fde8 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
@@ -14,7 +14,7 @@
* Abstraction of a connectivity intent that is implemented by a set of path
* segments.
*/
-public class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
+public final class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
private final Set<Link> links;
@@ -46,6 +46,12 @@
return links;
}
+ /**
+ * Returns the set of links that represent the network connections needed
+ * by this intent.
+ *
+ * @return Set of links for the network hops needed by this intent
+ */
public Set<Link> links() {
return links;
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
index be8d309..8ee4a9e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
@@ -15,7 +15,7 @@
/**
* Abstraction of multiple source to single destination connectivity intent.
*/
-public class MultiPointToSinglePointIntent extends ConnectivityIntent {
+public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
private final Set<ConnectPoint> ingressPoints;
private final ConnectPoint egressPoint;
diff --git a/core/api/src/test/java/org/onlab/onos/net/NetTestTools.java b/core/api/src/test/java/org/onlab/onos/net/NetTestTools.java
index 379ec7a..bd2e3ee 100644
--- a/core/api/src/test/java/org/onlab/onos/net/NetTestTools.java
+++ b/core/api/src/test/java/org/onlab/onos/net/NetTestTools.java
@@ -47,10 +47,16 @@
new HashSet<IpPrefix>());
}
+ // Short-hand for creating a connection point.
+ public static ConnectPoint connectPoint(String id, int port) {
+ return new ConnectPoint(did(id), portNumber(port));
+ }
+
// Short-hand for creating a link.
public static Link link(String src, int sp, String dst, int dp) {
- return new DefaultLink(PID, new ConnectPoint(did(src), portNumber(sp)),
- new ConnectPoint(did(dst), portNumber(dp)),
+ return new DefaultLink(PID,
+ connectPoint(src, sp),
+ connectPoint(dst, dp),
Link.Type.DIRECT);
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
index de61e8e..50faf38 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
@@ -41,7 +41,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
- private IdGenerator<IntentId> intentIdGenerator;
+ protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java
index 68c55dd..aecd3ba 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java
@@ -37,7 +37,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
- private IdGenerator<IntentId> intentIdGenerator;
+ protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java b/core/net/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java
new file mode 100644
index 0000000..0f020a4
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/IntentTestsMocks.java
@@ -0,0 +1,86 @@
+package org.onlab.onos.net.intent;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.onlab.onos.net.ElementId;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.criteria.Criterion;
+import org.onlab.onos.net.flow.instructions.Instruction;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.PathService;
+
+import static org.onlab.onos.net.NetTestTools.createPath;
+
+/**
+ * Common mocks used by the intent framework tests.
+ */
+public class IntentTestsMocks {
+ /**
+ * Mock traffic selector class used for satisfying API requirements.
+ */
+ public static class MockSelector implements TrafficSelector {
+ @Override
+ public Set<Criterion> criteria() {
+ return new HashSet<>();
+ }
+ }
+
+ /**
+ * Mock traffic treatment class used for satisfying API requirements.
+ */
+ public static class MockTreatment implements TrafficTreatment {
+ @Override
+ public List<Instruction> instructions() {
+ return new ArrayList<>();
+ }
+ }
+
+ /**
+ * Mock path service for creating paths within the test.
+ */
+ public static class MockPathService implements PathService {
+
+ final String[] pathHops;
+ final String[] reversePathHops;
+
+ /**
+ * Constructor that provides a set of hops to mock.
+ *
+ * @param pathHops path hops to mock
+ */
+ public MockPathService(String[] pathHops) {
+ this.pathHops = pathHops;
+ String[] reversed = pathHops.clone();
+ Collections.reverse(Arrays.asList(reversed));
+ reversePathHops = reversed;
+ }
+
+ @Override
+ public Set<Path> getPaths(ElementId src, ElementId dst) {
+ Set<Path> result = new HashSet<>();
+
+ String[] allHops = new String[pathHops.length];
+
+ if (src.toString().endsWith(pathHops[0])) {
+ System.arraycopy(pathHops, 0, allHops, 0, pathHops.length);
+ } else {
+ System.arraycopy(reversePathHops, 0, allHops, 0, pathHops.length);
+ }
+
+ result.add(createPath(allHops));
+ return result;
+ }
+
+ @Override
+ public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
+ return getPaths(src, dst);
+ }
+ }
+}
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java b/core/net/src/test/java/org/onlab/onos/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java
new file mode 100644
index 0000000..869cefe
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java
@@ -0,0 +1,73 @@
+package org.onlab.onos.net.intent;
+
+import java.util.Collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.onlab.onos.net.Link;
+
+/**
+ * Matcher to determine if a Collection of Links contains a path between a source
+ * and a destination.
+ */
+public class LinksHaveEntryWithSourceDestinationPairMatcher extends
+ TypeSafeMatcher<Collection<Link>> {
+ private final String source;
+ private final String destination;
+
+ /**
+ * Creates a matcher for a given path represented by a source and
+ * a destination.
+ *
+ * @param source string identifier for the source of the path
+ * @param destination string identifier for the destination of the path
+ */
+ LinksHaveEntryWithSourceDestinationPairMatcher(String source,
+ String destination) {
+ this.source = source;
+ this.destination = destination;
+ }
+
+ @Override
+ public boolean matchesSafely(Collection<Link> links) {
+ for (Link link : links) {
+ if (link.src().elementId().toString().endsWith(source) &&
+ link.dst().elementId().toString().endsWith(destination)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("link lookup for source \"");
+ description.appendText(source);
+ description.appendText(" and destination ");
+ description.appendText(destination);
+ description.appendText("\"");
+ }
+
+ @Override
+ public void describeMismatchSafely(Collection<Link> links,
+ Description mismatchDescription) {
+ mismatchDescription.appendText("was ").
+ appendText(links.toString());
+ }
+
+ /**
+ * Creates a link has path matcher.
+ *
+ * @param source string identifier for the source of the path
+ * @param destination string identifier for the destination of the path
+ * @return matcher to match the path
+ */
+ public static LinksHaveEntryWithSourceDestinationPairMatcher linksHasPath(
+ String source,
+ String destination) {
+ return new LinksHaveEntryWithSourceDestinationPairMatcher(source,
+ destination);
+ }
+}
+
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/TestHostToHostIntent.java b/core/net/src/test/java/org/onlab/onos/net/intent/TestHostToHostIntent.java
new file mode 100644
index 0000000..f5e2551
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/TestHostToHostIntent.java
@@ -0,0 +1,112 @@
+package org.onlab.onos.net.intent;
+
+import org.junit.Test;
+import org.onlab.onos.net.HostId;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.onlab.onos.net.NetTestTools.hid;
+
+/**
+ * Unit tests for the HostToHostIntent class.
+ */
+public class TestHostToHostIntent {
+
+ private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+ private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+ private HostToHostIntent makeHostToHost(long id, HostId one, HostId two) {
+ return new HostToHostIntent(new IntentId(id),
+ one,
+ two,
+ selector,
+ treatment);
+ }
+
+ /**
+ * Tests the equals() method where two HostToHostIntents have references
+ * to the same hosts. These should compare equal.
+ */
+ @Test
+ public void testSameEquals() {
+
+ HostId one = hid("00:00:00:00:00:01/-1");
+ HostId two = hid("00:00:00:00:00:02/-1");
+ HostToHostIntent i1 = makeHostToHost(12, one, two);
+ HostToHostIntent i2 = makeHostToHost(12, one, two);
+
+ assertThat(i1, is(equalTo(i2)));
+ }
+
+ /**
+ * Tests the equals() method where two HostToHostIntents have references
+ * to different Hosts. These should compare not equal.
+ */
+ @Test
+ public void testLinksDifferentEquals() {
+
+ HostId one = hid("00:00:00:00:00:01/-1");
+ HostId two = hid("00:00:00:00:00:02/-1");
+ HostToHostIntent i1 = makeHostToHost(12, one, two);
+ HostToHostIntent i2 = makeHostToHost(12, two, one);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests the equals() method where two HostToHostIntents have different
+ * ids. These should compare not equal.
+ */
+
+ @Test
+ public void testBaseDifferentEquals() {
+ HostId one = hid("00:00:00:00:00:01/-1");
+ HostId two = hid("00:00:00:00:00:02/-1");
+ HostToHostIntent i1 = makeHostToHost(12, one, two);
+ HostToHostIntent i2 = makeHostToHost(11, one, two);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests that the hashCode() values for two equivalent HostToHostIntent
+ * objects are the same.
+ */
+
+ @Test
+ public void testHashCodeEquals() {
+ HostId one = hid("00:00:00:00:00:01/-1");
+ HostId two = hid("00:00:00:00:00:02/-1");
+ HostToHostIntent i1 = makeHostToHost(12, one, two);
+ HostToHostIntent i2 = makeHostToHost(12, one, two);
+
+ assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
+ }
+
+ /**
+ * Tests that the hashCode() values for two distinct LinkCollectionIntent
+ * objects are different.
+ */
+
+ @Test
+ public void testHashCodeDifferent() {
+ HostId one = hid("00:00:00:00:00:01/-1");
+ HostId two = hid("00:00:00:00:00:02/-1");
+ HostToHostIntent i1 = makeHostToHost(12, one, two);
+ HostToHostIntent i2 = makeHostToHost(112, one, two);
+
+ assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
+ }
+
+ /**
+ * Checks that the HostToHostIntent class is immutable.
+ */
+ @Test
+ public void checkImmutability() {
+ ImmutableClassChecker.assertThatClassIsImmutable(HostToHostIntent.class);
+ }
+}
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java b/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java
index ba67a6a..f781cf3 100644
--- a/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java
@@ -1,47 +1,145 @@
package org.onlab.onos.net.intent;
-import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
+import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
-import org.onlab.onos.net.flow.criteria.Criterion;
-import org.onlab.onos.net.flow.instructions.Instruction;
+import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
+import static org.onlab.onos.net.NetTestTools.link;
+/**
+ * Unit tests for the LinkCollectionIntent class.
+ */
public class TestLinkCollectionIntent {
- private static class MockSelector implements TrafficSelector {
- @Override
- public Set<Criterion> criteria() {
- return new HashSet<Criterion>();
- }
+ private Link link1 = link("dev1", 1, "dev2", 2);
+ private Link link2 = link("dev1", 1, "dev3", 2);
+ private Link link3 = link("dev2", 1, "dev3", 2);
+
+ private Set<Link> links1;
+ private Set<Link> links2;
+
+ private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+ private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+ private LinkCollectionIntent makeLinkCollection(long id, Set<Link> links) {
+ return new LinkCollectionIntent(new IntentId(id),
+ selector, treatment, links);
}
- private static class MockTreatment implements TrafficTreatment {
- @Override
- public List<Instruction> instructions() {
- return new ArrayList<>();
- }
+ @Before
+ public void setup() {
+ links1 = new HashSet<>();
+ links2 = new HashSet<>();
}
+ /**
+ * Tests the equals() method where two LinkCollectionIntents have references
+ * to the same Links in different orders. These should compare equal.
+ */
@Test
- public void testComparison() {
- TrafficSelector selector = new MockSelector();
- TrafficTreatment treatment = new MockTreatment();
- Set<Link> links = new HashSet<>();
- LinkCollectionIntent i1 = new LinkCollectionIntent(new IntentId(12),
- selector, treatment, links);
- LinkCollectionIntent i2 = new LinkCollectionIntent(new IntentId(12),
- selector, treatment, links);
+ public void testSameEquals() {
+ links1.add(link1);
+ links1.add(link2);
+ links1.add(link3);
- assertThat(i1.equals(i2), is(true));
+ links2.add(link3);
+ links2.add(link2);
+ links2.add(link1);
+
+ LinkCollectionIntent i1 = makeLinkCollection(12, links1);
+ LinkCollectionIntent i2 = makeLinkCollection(12, links2);
+
+ assertThat(i1, is(equalTo(i2)));
}
+ /**
+ * Tests the equals() method where two LinkCollectionIntents have references
+ * to different Links. These should compare not equal.
+ */
+ @Test
+ public void testLinksDifferentEquals() {
+ links1.add(link1);
+ links1.add(link2);
+
+ links2.add(link3);
+ links2.add(link1);
+
+ LinkCollectionIntent i1 = makeLinkCollection(12, links1);
+ LinkCollectionIntent i2 = makeLinkCollection(12, links2);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests the equals() method where two LinkCollectionIntents have different
+ * ids. These should compare not equal.
+ */
+ @Test
+ public void testBaseDifferentEquals() {
+ links1.add(link1);
+ links1.add(link2);
+
+ links2.add(link2);
+ links2.add(link1);
+
+ LinkCollectionIntent i1 = makeLinkCollection(1, links1);
+ LinkCollectionIntent i2 = makeLinkCollection(2, links2);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests that the hashCode() values for two equivalent LinkCollectionIntent
+ * objects are the same.
+ */
+ @Test
+ public void testHashCodeEquals() {
+ links1.add(link1);
+ links1.add(link2);
+ links1.add(link3);
+
+ links2.add(link3);
+ links2.add(link2);
+ links2.add(link1);
+
+ LinkCollectionIntent i1 = makeLinkCollection(1, links1);
+ LinkCollectionIntent i2 = makeLinkCollection(1, links2);
+
+ assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
+ }
+
+ /**
+ * Tests that the hashCode() values for two distinct LinkCollectionIntent
+ * objects are different.
+ */
+ @Test
+ public void testHashCodeDifferent() {
+ links1.add(link1);
+ links1.add(link2);
+
+ links2.add(link1);
+ links2.add(link3);
+
+ LinkCollectionIntent i1 = makeLinkCollection(1, links1);
+ LinkCollectionIntent i2 = makeLinkCollection(1, links2);
+
+ assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
+ }
+
+ /**
+ * Checks that the HostToHostIntent class is immutable.
+ */
+ @Test
+ public void checkImmutability() {
+ ImmutableClassChecker.assertThatClassIsImmutable(LinkCollectionIntent.class);
+ }
}
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/TestMultiPointToSinglePointIntent.java b/core/net/src/test/java/org/onlab/onos/net/intent/TestMultiPointToSinglePointIntent.java
new file mode 100644
index 0000000..e921907
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/TestMultiPointToSinglePointIntent.java
@@ -0,0 +1,157 @@
+package org.onlab.onos.net.intent;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.onos.net.NetTestTools.connectPoint;
+
+/**
+ * Unit tests for the MultiPointToSinglePointIntent class.
+ */
+public class TestMultiPointToSinglePointIntent {
+
+ private ConnectPoint point1 = connectPoint("dev1", 1);
+ private ConnectPoint point2 = connectPoint("dev2", 1);
+ private ConnectPoint point3 = connectPoint("dev3", 1);
+
+ private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+ private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+ Set<ConnectPoint> ingress1;
+ Set<ConnectPoint> ingress2;
+
+ /**
+ * Creates a MultiPointToSinglePointIntent object.
+ *
+ * @param id identifier to use for the new intent
+ * @param ingress set of ingress points
+ * @param egress egress point
+ * @return MultiPointToSinglePoint intent
+ */
+ private MultiPointToSinglePointIntent makeIntent(long id,
+ Set<ConnectPoint> ingress,
+ ConnectPoint egress) {
+ return new MultiPointToSinglePointIntent(new IntentId(id),
+ selector,
+ treatment,
+ ingress,
+ egress);
+ }
+
+ /**
+ * Initializes the ingress sets.
+ */
+ @Before
+ public void setup() {
+ ingress1 = new HashSet<>();
+ ingress2 = new HashSet<>();
+ }
+
+ /**
+ * Tests the equals() method where two MultiPointToSinglePoint have references
+ * to the same Links in different orders. These should compare equal.
+ */
+ @Test
+ public void testSameEquals() {
+
+ Set<ConnectPoint> ingress1 = new HashSet<>();
+ ingress1.add(point2);
+ ingress1.add(point3);
+
+ Set<ConnectPoint> ingress2 = new HashSet<>();
+ ingress2.add(point3);
+ ingress2.add(point2);
+
+ Intent i1 = makeIntent(12, ingress1, point1);
+ Intent i2 = makeIntent(12, ingress2, point1);
+
+ assertThat(i1, is(equalTo(i2)));
+ }
+
+ /**
+ * Tests the equals() method where two MultiPointToSinglePoint have references
+ * to different Links. These should compare not equal.
+ */
+ @Test
+ public void testLinksDifferentEquals() {
+ ingress1.add(point3);
+
+ ingress2.add(point3);
+ ingress2.add(point2);
+
+ Intent i1 = makeIntent(12, ingress1, point1);
+ Intent i2 = makeIntent(12, ingress2, point1);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests the equals() method where two MultiPointToSinglePoint have different
+ * ids. These should compare not equal.
+ */
+ @Test
+ public void testBaseDifferentEquals() {
+ ingress1.add(point3);
+ ingress2.add(point3);
+
+ Intent i1 = makeIntent(12, ingress1, point1);
+ Intent i2 = makeIntent(11, ingress2, point1);
+
+ assertThat(i1, is(not(equalTo(i2))));
+ }
+
+ /**
+ * Tests that the hashCode() values for two equivalent MultiPointToSinglePoint
+ * objects are the same.
+ */
+ @Test
+ public void testHashCodeEquals() {
+ ingress1.add(point2);
+ ingress1.add(point3);
+
+ ingress2.add(point3);
+ ingress2.add(point2);
+
+ Intent i1 = makeIntent(12, ingress1, point1);
+ Intent i2 = makeIntent(12, ingress2, point1);
+
+ assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
+ }
+
+ /**
+ * Tests that the hashCode() values for two distinct MultiPointToSinglePoint
+ * objects are different.
+ */
+ @Test
+ public void testHashCodeDifferent() {
+ ingress1.add(point2);
+
+ ingress2.add(point3);
+ ingress2.add(point2);
+
+ Intent i1 = makeIntent(12, ingress1, point1);
+ Intent i2 = makeIntent(12, ingress2, point1);
+
+
+ assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
+ }
+
+ /**
+ * Checks that the MultiPointToSinglePointIntent class is immutable.
+ */
+ @Test
+ public void checkImmutability() {
+ ImmutableClassChecker.
+ assertThatClassIsImmutable(MultiPointToSinglePointIntent.class);
+ }
+}
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestHostToHostIntentCompiler.java b/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestHostToHostIntentCompiler.java
new file mode 100644
index 0000000..bd61b7a
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestHostToHostIntentCompiler.java
@@ -0,0 +1,151 @@
+package org.onlab.onos.net.intent.impl;
+
+import java.util.List;
+
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.net.Host;
+import org.onlab.onos.net.HostId;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.host.HostService;
+import org.onlab.onos.net.intent.HostToHostIntent;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentTestsMocks;
+import org.onlab.onos.net.intent.PathIntent;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.onos.net.NetTestTools.hid;
+import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
+
+/**
+ * Unit tests for the HostToHost intent compiler.
+ */
+public class TestHostToHostIntentCompiler {
+ private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
+ private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
+ private static final String HOST_ONE_VLAN = "-1";
+ private static final String HOST_TWO_VLAN = "-1";
+ private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
+ private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
+
+ private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+ private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+ private HostId hostOneId = HostId.hostId(HOST_ONE);
+ private HostId hostTwoId = HostId.hostId(HOST_TWO);
+ private HostService mockHostService;
+
+ @Before
+ public void setup() {
+ Host hostOne = createMock(Host.class);
+ expect(hostOne.mac()).andReturn(new MacAddress(HOST_ONE_MAC.getBytes())).anyTimes();
+ expect(hostOne.vlan()).andReturn(VlanId.vlanId()).anyTimes();
+ replay(hostOne);
+
+ Host hostTwo = createMock(Host.class);
+ expect(hostTwo.mac()).andReturn(new MacAddress(HOST_TWO_MAC.getBytes())).anyTimes();
+ expect(hostTwo.vlan()).andReturn(VlanId.vlanId()).anyTimes();
+ replay(hostTwo);
+
+ mockHostService = createMock(HostService.class);
+ expect(mockHostService.getHost(eq(hostOneId))).andReturn(hostOne).anyTimes();
+ expect(mockHostService.getHost(eq(hostTwoId))).andReturn(hostTwo).anyTimes();
+ replay(mockHostService);
+ }
+
+ /**
+ * Creates a HostToHost intent based on two host Ids.
+ *
+ * @param oneIdString string for host one id
+ * @param twoIdString string for host two id
+ * @return HostToHostIntent for the two hosts
+ */
+ private HostToHostIntent makeIntent(String oneIdString, String twoIdString) {
+ return new HostToHostIntent(new IntentId(12),
+ hid(oneIdString),
+ hid(twoIdString),
+ selector,
+ treatment);
+ }
+
+ /**
+ * Creates a compiler for HostToHost intents.
+ *
+ * @param hops string array describing the path hops to use when compiling
+ * @return HostToHost intent compiler
+ */
+ private HostToHostIntentCompiler makeCompiler(String[] hops) {
+ HostToHostIntentCompiler compiler =
+ new HostToHostIntentCompiler();
+ compiler.pathService = new IntentTestsMocks.MockPathService(hops);
+ compiler.hostService = mockHostService;
+ IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
+ compiler.intentIdGenerator =
+ new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
+ return compiler;
+ }
+
+
+ /**
+ * Tests a pair of hosts with 8 hops between them.
+ */
+ @Test
+ public void testSingleLongPathCompilation() {
+
+ HostToHostIntent intent = makeIntent(HOST_ONE,
+ HOST_TWO);
+ assertThat(intent, is(notNullValue()));
+
+ String[] hops = {HOST_ONE, "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", HOST_TWO};
+ HostToHostIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent);
+ assertThat(result, is(Matchers.notNullValue()));
+ assertThat(result, hasSize(2));
+ Intent forwardResultIntent = result.get(0);
+ assertThat(forwardResultIntent instanceof PathIntent, is(true));
+ Intent reverseResultIntent = result.get(1);
+ assertThat(reverseResultIntent instanceof PathIntent, is(true));
+
+ if (forwardResultIntent instanceof PathIntent) {
+ PathIntent forwardPathIntent = (PathIntent) forwardResultIntent;
+ assertThat(forwardPathIntent.path().links(), hasSize(9));
+ assertThat(forwardPathIntent.path().links(), linksHasPath(HOST_ONE, "h1"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h1", "h2"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h2", "h3"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h3", "h4"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h4", "h5"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h5", "h6"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h6", "h7"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h7", "h8"));
+ assertThat(forwardPathIntent.path().links(), linksHasPath("h8", HOST_TWO));
+ }
+
+ if (reverseResultIntent instanceof PathIntent) {
+ PathIntent reversePathIntent = (PathIntent) reverseResultIntent;
+ assertThat(reversePathIntent.path().links(), hasSize(9));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h1", HOST_ONE));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h2", "h1"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h3", "h2"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h4", "h3"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h5", "h4"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h6", "h5"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h7", "h6"));
+ assertThat(reversePathIntent.path().links(), linksHasPath("h8", "h7"));
+ assertThat(reversePathIntent.path().links(), linksHasPath(HOST_TWO, "h8"));
+ }
+ }
+}
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestMultiPointToSinglePointIntentCompiler.java b/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestMultiPointToSinglePointIntentCompiler.java
new file mode 100644
index 0000000..8d286cf
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/impl/TestMultiPointToSinglePointIntentCompiler.java
@@ -0,0 +1,214 @@
+package org.onlab.onos.net.intent.impl;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.ElementId;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentTestsMocks;
+import org.onlab.onos.net.intent.LinkCollectionIntent;
+import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.PathService;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.onos.net.NetTestTools.connectPoint;
+import static org.onlab.onos.net.NetTestTools.createPath;
+import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
+
+/**
+ * Unit tests for the MultiPointToSinglePoint intent compiler.
+ */
+public class TestMultiPointToSinglePointIntentCompiler {
+
+ private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+ private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+ /**
+ * Mock path service for creating paths within the test.
+ */
+ private static class MockPathService implements PathService {
+
+ final String[] pathHops;
+
+ /**
+ * Constructor that provides a set of hops to mock.
+ *
+ * @param pathHops path hops to mock
+ */
+ MockPathService(String[] pathHops) {
+ this.pathHops = pathHops;
+ }
+
+ @Override
+ public Set<Path> getPaths(ElementId src, ElementId dst) {
+ Set<Path> result = new HashSet<>();
+
+ String[] allHops = new String[pathHops.length + 1];
+ allHops[0] = src.toString();
+ System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
+
+ result.add(createPath(allHops));
+ return result;
+ }
+
+ @Override
+ public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a MultiPointToSinglePoint intent for a group of ingress points
+ * and an egress point.
+ *
+ * @param ingressIds array of ingress device ids
+ * @param egressId device id of the egress point
+ * @return MultiPointToSinglePoint intent
+ */
+ private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+ ConnectPoint egressPoint = connectPoint(egressId, 1);
+
+ for (String ingressId : ingressIds) {
+ ingressPoints.add(connectPoint(ingressId, 1));
+ }
+
+ return new MultiPointToSinglePointIntent(
+ new IntentId(12),
+ selector,
+ treatment,
+ ingressPoints,
+ egressPoint);
+ }
+
+ /**
+ * Creates a compiler for MultiPointToSinglePoint intents.
+ *
+ * @param hops hops to use while computing paths for this intent
+ * @return MultiPointToSinglePoint intent
+ */
+ private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops) {
+ MultiPointToSinglePointIntentCompiler compiler =
+ new MultiPointToSinglePointIntentCompiler();
+ compiler.pathService = new MockPathService(hops);
+ IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
+ compiler.intentIdGenerator =
+ new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
+ return compiler;
+ }
+
+ /**
+ * Tests a single ingress point with 8 hops to its egress point.
+ */
+ @Test
+ public void testSingleLongPathCompilation() {
+
+ String[] ingress = {"ingress"};
+ String egress = "egress";
+
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+ assertThat(intent, is(notNullValue()));
+
+ String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8",
+ egress};
+ MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent);
+ assertThat(result, is(Matchers.notNullValue()));
+ assertThat(result, hasSize(1));
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(9));
+ assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
+ assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
+ assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
+ assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
+ assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
+ assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
+ assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
+ }
+ }
+
+ /**
+ * Tests a simple topology where two ingress points share some path segments
+ * and some path segments are not shared.
+ */
+ @Test
+ public void testTwoIngressCompilation() {
+ String[] ingress = {"ingress1", "ingress2"};
+ String egress = "egress";
+
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+ assertThat(intent, is(notNullValue()));
+
+ final String[] hops = {"inner1", "inner2", egress};
+ MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(4));
+ assertThat(linkIntent.links(), linksHasPath("ingress1", "inner1"));
+ assertThat(linkIntent.links(), linksHasPath("ingress2", "inner1"));
+ assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
+ assertThat(linkIntent.links(), linksHasPath("inner2", "egress"));
+ }
+ }
+
+ /**
+ * Tests a large number of ingress points that share a common path to the
+ * egress point.
+ */
+ @Test
+ public void testMultiIngressCompilation() {
+ String[] ingress = {"i1", "i2", "i3", "i4", "i5",
+ "i6", "i7", "i8", "i9", "i10"};
+ String egress = "e";
+
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+ assertThat(intent, is(notNullValue()));
+
+ final String[] hops = {"n1", egress};
+ MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(ingress.length + 1));
+ for (String ingressToCheck : ingress) {
+ assertThat(linkIntent.links(),
+ linksHasPath(ingressToCheck,
+ "n1"));
+ }
+ assertThat(linkIntent.links(), linksHasPath("n1", egress));
+ }
+ }
+}