Ray Milkey

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.
......@@ -12,7 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* 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;
......
......@@ -14,7 +14,7 @@ import com.google.common.base.MoreObjects;
* 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 @@ public class LinkCollectionIntent extends ConnectivityIntent implements Installa
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;
}
......
......@@ -15,7 +15,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* 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;
......
......@@ -47,10 +47,16 @@ public final class NetTestTools {
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);
}
......
......@@ -41,7 +41,7 @@ public class HostToHostIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
private IdGenerator<IntentId> intentIdGenerator;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
......
......@@ -37,7 +37,7 @@ public class MultiPointToSinglePointIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
private IdGenerator<IntentId> intentIdGenerator;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
......
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);
}
}
}
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);
}
}
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);
}
}
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);
}
@Before
public void setup() {
links1 = new HashSet<>();
links2 = new HashSet<>();
}
private static class MockTreatment implements TrafficTreatment {
@Override
public List<Instruction> instructions() {
return new ArrayList<>();
/**
* Tests the equals() method where two LinkCollectionIntents have references
* to the same Links in different orders. These should compare equal.
*/
@Test
public void testSameEquals() {
links1.add(link1);
links1.add(link2);
links1.add(link3);
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 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 testBaseDifferentEquals() {
links1.add(link1);
links1.add(link2);
assertThat(i1.equals(i2), is(true));
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);
}
}
......
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);
}
}
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"));
}
}
}
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));
}
}
}