ONOS-631 #Initial MPLS intent implementation

Change-Id: I6f906b953f06f395cc67e612648802e333c0e581
diff --git a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
index 2e18430..7099464 100644
--- a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
@@ -24,6 +24,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.DefaultApplicationId;
 import org.onosproject.core.DefaultGroupId;
@@ -162,7 +163,7 @@
                     .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                     .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                     .pushMpls()
-                    .setMpls(106);
+                    .setMpls(MplsLabel.mplsLabel(106));
             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                         tBuilder.build()));
         }
@@ -244,7 +245,7 @@
                     .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                     .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                     .pushMpls()
-                    .setMpls(106);
+                    .setMpls(MplsLabel.mplsLabel(106));
             addBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                         tBuilder.build()));
             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
@@ -280,7 +281,7 @@
                     .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                     .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                     .pushMpls()
-                    .setMpls(106);
+                    .setMpls(MplsLabel.mplsLabel(106));
             removeBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                         tBuilder.build()));
             buckets.remove(DefaultGroupBucket.createSelectGroupBucket(
@@ -338,7 +339,7 @@
                     .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                     .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                     .pushMpls()
-                    .setMpls(106);
+                    .setMpls(MplsLabel.mplsLabel(106));
             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
                     tBuilder.build()));
         }
@@ -411,7 +412,7 @@
                     .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
                     .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
                     .pushMpls()
-                    .setMpls(106);
+                    .setMpls(MplsLabel.mplsLabel(106));
             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
                                                         tBuilder.build()));
         }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/MplsIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/MplsIntentCompilerTest.java
new file mode 100644
index 0000000..1a81225
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/MplsIntentCompilerTest.java
@@ -0,0 +1,175 @@
+package org.onosproject.net.intent.impl;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+
+import org.onlab.packet.MplsLabel;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.MplsIntent;
+import org.onosproject.net.intent.MplsPathIntent;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+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.onosproject.net.DefaultEdgeLink.createEdgeLink;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
+
+/**
+ * Unit tests for the HostToHost intent compiler.
+ */
+public class MplsIntentCompilerTest extends AbstractIntentTest {
+
+    private static final ApplicationId APPID = new TestApplicationId("foo");
+
+    private TrafficSelector selector = new IntentTestsMocks.MockSelector();
+    private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
+
+    /**
+     * Creates a PointToPoint intent based on ingress and egress device Ids.
+     *
+     * @param ingressIdString string for id of ingress device
+     * @param egressIdString  string for id of egress device
+     * @return PointToPointIntent for the two devices
+     */
+    private MplsIntent makeIntent(String ingressIdString,  Optional<MplsLabel> ingressLabel,
+                                          String egressIdString, Optional<MplsLabel> egressLabel) {
+
+        return new MplsIntent(APPID, selector, treatment,
+                                      connectPoint(ingressIdString, 1),
+                                      ingressLabel,
+                                      connectPoint(egressIdString, 1),
+                                      egressLabel);
+    }
+    /**
+     * Creates a compiler for HostToHost intents.
+     *
+     * @param hops string array describing the path hops to use when compiling
+     * @return HostToHost intent compiler
+     */
+    private MplsIntentCompiler makeCompiler(String[] hops) {
+        MplsIntentCompiler compiler =
+                new MplsIntentCompiler();
+        compiler.pathService = new IntentTestsMocks.MockPathService(hops);
+        return compiler;
+    }
+
+
+    /**
+     * Tests a pair of devices in an 8 hop path, forward direction.
+     */
+    @Test
+    public void testForwardPathCompilation() {
+        Optional<MplsLabel> ingressLabel = Optional.ofNullable(MplsLabel.mplsLabel(10));
+        Optional<MplsLabel> egressLabel = Optional.ofNullable(MplsLabel.mplsLabel(20));
+
+        MplsIntent intent = makeIntent("d1", ingressLabel, "d8", egressLabel);
+        assertThat(intent, is(notNullValue()));
+
+        String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+        MplsIntentCompiler compiler = makeCompiler(hops);
+        assertThat(compiler, is(notNullValue()));
+
+        List<Intent> result = compiler.compile(intent, null, null);
+        assertThat(result, is(Matchers.notNullValue()));
+        assertThat(result, hasSize(1));
+        Intent forwardResultIntent = result.get(0);
+        assertThat(forwardResultIntent instanceof MplsPathIntent, is(true));
+
+        if (forwardResultIntent instanceof MplsIntent) {
+            MplsPathIntent forwardPathIntent = (MplsPathIntent) forwardResultIntent;
+            // 7 links for the hops, plus one default lnk on ingress and egress
+            assertThat(forwardPathIntent.path().links(), hasSize(hops.length + 1));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d1", "d2"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d2", "d3"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d3", "d4"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d4", "d5"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d5", "d6"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d6", "d7"));
+            assertThat(forwardPathIntent.path().links(), linksHasPath("d7", "d8"));
+            assertEquals(forwardPathIntent.egressLabel(), egressLabel);
+            assertEquals(forwardPathIntent.ingressLabel(), ingressLabel);
+        }
+    }
+
+    /**
+     * Tests a pair of devices in an 8 hop path, forward direction.
+     */
+    @Test
+    public void testReversePathCompilation() {
+        Optional<MplsLabel> ingressLabel = Optional.ofNullable(MplsLabel.mplsLabel(10));
+        Optional<MplsLabel> egressLabel = Optional.ofNullable(MplsLabel.mplsLabel(20));
+
+        MplsIntent intent = makeIntent("d8", ingressLabel, "d1", egressLabel);
+        assertThat(intent, is(notNullValue()));
+
+        String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+        MplsIntentCompiler compiler = makeCompiler(hops);
+        assertThat(compiler, is(notNullValue()));
+
+        List<Intent> result = compiler.compile(intent, null, null);
+        assertThat(result, is(Matchers.notNullValue()));
+        assertThat(result, hasSize(1));
+        Intent reverseResultIntent = result.get(0);
+        assertThat(reverseResultIntent instanceof MplsPathIntent, is(true));
+
+        if (reverseResultIntent instanceof MplsIntent) {
+            MplsPathIntent reversePathIntent = (MplsPathIntent) reverseResultIntent;
+            assertThat(reversePathIntent.path().links(), hasSize(hops.length + 1));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d2", "d1"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d3", "d2"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d4", "d3"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d5", "d4"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d6", "d5"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d7", "d6"));
+            assertThat(reversePathIntent.path().links(), linksHasPath("d8", "d7"));
+            assertEquals(reversePathIntent.egressLabel(), egressLabel);
+            assertEquals(reversePathIntent.ingressLabel(), ingressLabel);
+        }
+    }
+
+    /**
+     * Tests compilation of the intent which designates two different ports on the same switch.
+     */
+    @Test
+    public void testSameSwitchDifferentPortsIntentCompilation() {
+        ConnectPoint src = new ConnectPoint(deviceId("1"), portNumber(1));
+        ConnectPoint dst = new ConnectPoint(deviceId("1"), portNumber(2));
+        MplsIntent intent = new MplsIntent(APP_ID, selector, treatment, src, Optional.empty(), dst, Optional.empty());
+
+        String[] hops = {"1"};
+        MplsIntentCompiler sut = makeCompiler(hops);
+
+        List<Intent> compiled = sut.compile(intent, null, null);
+
+        assertThat(compiled, hasSize(1));
+        assertThat(compiled.get(0), is(instanceOf(MplsPathIntent.class)));
+        Path path = ((MplsPathIntent) compiled.get(0)).path();
+
+        assertThat(path.links(), hasSize(2));
+        Link firstLink = path.links().get(0);
+        assertThat(firstLink, is(createEdgeLink(src, true)));
+        Link secondLink = path.links().get(1);
+        assertThat(secondLink, is(createEdgeLink(dst, false)));
+    }
+}