Implement IntentInstallers

IntentInstallers for:
- PathFlowIntent
- SingleDstTreeFlowIntent
- SingleSrcTreeFlowIntent

This resolves ONOS-1884, ONOS-1885, and ONOS-1886.

Change-Id: Ie0eac4bab9a2898b582edf2e4291498f0a583d71
diff --git a/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentInstallerTest.java b/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentInstallerTest.java
new file mode 100644
index 0000000..99863d9
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentInstallerTest.java
@@ -0,0 +1,88 @@
+package net.onrc.onos.core.newintent;
+
+import net.onrc.onos.api.flowmanager.FakeFlowManagerService;
+import net.onrc.onos.api.flowmanager.FlowId;
+import net.onrc.onos.api.flowmanager.FlowLink;
+import net.onrc.onos.api.flowmanager.FlowManagerService;
+import net.onrc.onos.api.flowmanager.PacketPathFlow;
+import net.onrc.onos.api.flowmanager.Path;
+import net.onrc.onos.api.newintent.IntentId;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
+import net.onrc.onos.core.util.SwitchPort;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static net.onrc.onos.api.flowmanager.FlowState.COMPILED;
+import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED;
+import static net.onrc.onos.api.flowmanager.FlowState.SUBMITTED;
+import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWING;
+
+/**
+ * Suites of test of {@link PathFlowIntentInstaller}.
+ */
+public class PathFlowIntentInstallerTest {
+    private final FlowId flowId = new FlowId(1);
+    private final IntentId intentId = new IntentId(1);
+    private final PacketMatch match = new PacketMatchBuilder().build();
+    private SwitchPort src = new SwitchPort(1, (short) 1);
+    private SwitchPort dst = new SwitchPort(2, (short) 2);
+
+    /**
+     * Tests intent installation that the state is changed
+     * to SUBMITTED, COMPILED, then INSTALLED.
+     */
+    @Test
+    public void testNormalStateTransition() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, false, SUBMITTED, COMPILED, INSTALLED);
+        PathFlowIntentInstaller sut =
+                new PathFlowIntentInstaller(flowManager);
+
+        PacketPathFlow flow = createFlow();
+        PathFlowIntent intent = new PathFlowIntent(intentId, flow);
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent installation that addFlow() returns null.
+     */
+    @Test(expected = IntentInstallationException.class)
+    public void testInstallationFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, SUBMITTED);
+        PathFlowIntentInstaller sut =
+                new PathFlowIntentInstaller(flowManager);
+
+        PacketPathFlow flow = createFlow();
+        PathFlowIntent intent = new PathFlowIntent(intentId, flow);
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent removal that removeFlow() returns null.
+     */
+    @Test(expected = IntentRemovalException.class)
+    public void testRemovalFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, WITHDRAWING);
+        PathFlowIntentInstaller sut =
+                new PathFlowIntentInstaller(flowManager);
+
+        PacketPathFlow flow = createFlow();
+        PathFlowIntent intent = new PathFlowIntent(intentId, flow);
+
+        sut.remove(intent);
+    }
+
+    private PacketPathFlow createFlow() {
+        return new PacketPathFlow(flowId, match, src.getPortNumber(),
+                new Path(Arrays.asList(new FlowLink(src, dst))),
+                Collections.<Action>emptyList(), 0, 0);
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentInstallerTest.java b/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentInstallerTest.java
new file mode 100644
index 0000000..a653bdc
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentInstallerTest.java
@@ -0,0 +1,99 @@
+package net.onrc.onos.core.newintent;
+
+import net.onrc.onos.api.flowmanager.FakeFlowManagerService;
+import net.onrc.onos.api.flowmanager.FlowId;
+import net.onrc.onos.api.flowmanager.FlowLink;
+import net.onrc.onos.api.flowmanager.FlowManagerService;
+import net.onrc.onos.api.flowmanager.SingleDstTreeFlow;
+import net.onrc.onos.api.flowmanager.Tree;
+import net.onrc.onos.api.newintent.IntentId;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
+import net.onrc.onos.core.util.SwitchPort;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static net.onrc.onos.api.flowmanager.FlowState.COMPILED;
+import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED;
+import static net.onrc.onos.api.flowmanager.FlowState.SUBMITTED;
+import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWING;
+
+/**
+ * Suites of test of {@link SingleDstTreeFlowIntentInstaller}.
+ */
+public class SingleDstTreeFlowIntentInstallerTest {
+    private final SwitchPort port12 = new SwitchPort(1, (short) 1);
+    private final SwitchPort port13 = new SwitchPort(1, (short) 2);
+    private final SwitchPort port21 = new SwitchPort(2, (short) 2);
+    private final SwitchPort ingress1 = new SwitchPort(2, (short) 100);
+    private final SwitchPort ingress2 = new SwitchPort(3, (short) 101);
+    private final FlowId flowId = new FlowId(1);
+
+    /**
+     * Tests intent installation that the state is changed
+     * to SUBMITTED, COMPILED, then INSTALLED.
+     */
+    @Test
+    public void testNormalStateTransition() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, false, SUBMITTED, COMPILED, INSTALLED);
+        SingleDstTreeFlowIntentInstaller sut =
+                new SingleDstTreeFlowIntentInstaller(flowManager);
+
+        Tree tree = createTree();
+        SingleDstTreeFlowIntent intent = new SingleDstTreeFlowIntent(new IntentId(1), createFlow(tree));
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent installation that addFlow() returns null.
+     */
+    @Test(expected = IntentInstallationException.class)
+    public void testInstallationFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, SUBMITTED);
+        SingleDstTreeFlowIntentInstaller sut =
+                new SingleDstTreeFlowIntentInstaller(flowManager);
+
+        Tree tree = createTree();
+        SingleDstTreeFlowIntent intent = new SingleDstTreeFlowIntent(new IntentId(1), createFlow(tree));
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent removal that removeFlow() returns null.
+     */
+    @Test(expected = IntentRemovalException.class)
+    public void testRemovalFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, WITHDRAWING);
+        SingleDstTreeFlowIntentInstaller sut =
+                new SingleDstTreeFlowIntentInstaller(flowManager);
+
+        Tree tree = createTree();
+        SingleDstTreeFlowIntent intent = new SingleDstTreeFlowIntent(new IntentId(1), createFlow(tree));
+
+        sut.remove(intent);
+    }
+
+    private SingleDstTreeFlow createFlow(Tree tree) {
+        return new SingleDstTreeFlow(
+                flowId,
+                    new PacketMatchBuilder().build(),
+                    Arrays.asList(ingress1, ingress2),
+                    tree,
+                    Collections.<Action>emptyList()
+            );
+    }
+
+    private Tree createTree() {
+        Tree tree = new Tree();
+        tree.add(new FlowLink(port12, port21));
+        tree.add(new FlowLink(port13, port13));
+        return tree;
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/newintent/SingleSrcTreeFlowIntentInstallerTest.java b/src/test/java/net/onrc/onos/core/newintent/SingleSrcTreeFlowIntentInstallerTest.java
new file mode 100644
index 0000000..755fa87
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/newintent/SingleSrcTreeFlowIntentInstallerTest.java
@@ -0,0 +1,104 @@
+package net.onrc.onos.core.newintent;
+
+import net.onrc.onos.api.flowmanager.FakeFlowManagerService;
+import net.onrc.onos.api.flowmanager.FlowId;
+import net.onrc.onos.api.flowmanager.FlowLink;
+import net.onrc.onos.api.flowmanager.FlowManagerService;
+import net.onrc.onos.api.flowmanager.SingleSrcTreeFlow;
+import net.onrc.onos.api.flowmanager.Tree;
+import net.onrc.onos.api.newintent.IntentId;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.match.PacketMatchBuilder;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.Pair;
+import net.onrc.onos.core.util.SwitchPort;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static net.onrc.onos.api.flowmanager.FlowState.COMPILED;
+import static net.onrc.onos.api.flowmanager.FlowState.INSTALLED;
+import static net.onrc.onos.api.flowmanager.FlowState.SUBMITTED;
+import static net.onrc.onos.api.flowmanager.FlowState.WITHDRAWING;
+
+/**
+ * Suites of test of {@link SingleSrcTreeFlowIntentInstaller}.
+ */
+public class SingleSrcTreeFlowIntentInstallerTest {
+    private final FlowId flowId = new FlowId(1);
+    private final SwitchPort port12 = new SwitchPort(1, (short) 1);
+    private final SwitchPort port13 = new SwitchPort(1, (short) 3);
+    private final SwitchPort port21 = new SwitchPort(2, (short) 2);
+    private final SwitchPort port31 = new SwitchPort(3, (short) 3);
+    private final SwitchPort ingress1 = new SwitchPort(1, (short) 3);
+    private final SwitchPort egress1 = new SwitchPort(2, (short) 100);
+    private final SwitchPort egress2 = new SwitchPort(3, (short) 101);
+
+    /**
+     * Tests intent installation that the state is changed
+     * to SUBMITTED, COMPILED, then INSTALLED.
+     */
+    @Test
+    public void testNormalStateTransition() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, false, SUBMITTED, COMPILED, INSTALLED);
+        SingleSrcTreeFlowIntentInstaller sut =
+                new SingleSrcTreeFlowIntentInstaller(flowManager);
+
+        SingleSrcTreeFlow flow = createFlow();
+        SingleSrcTreeFlowIntent intent = new SingleSrcTreeFlowIntent(new IntentId(1), flow);
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent installation that addFlow() returns null.
+     */
+    @Test(expected = IntentInstallationException.class)
+    public void testInstallationFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, SUBMITTED);
+        SingleSrcTreeFlowIntentInstaller sut =
+                new SingleSrcTreeFlowIntentInstaller(flowManager);
+
+        SingleSrcTreeFlow flow = createFlow();
+        SingleSrcTreeFlowIntent intent = new SingleSrcTreeFlowIntent(new IntentId(1), flow);
+
+        sut.install(intent);
+    }
+
+    /**
+     * Tests intent removal that removeFlow() returns null.
+     */
+    @Test(expected = IntentRemovalException.class)
+    public void testRemovalFails() {
+        FlowManagerService flowManager =
+                new FakeFlowManagerService(flowId, true, WITHDRAWING);
+        SingleSrcTreeFlowIntentInstaller sut =
+                new SingleSrcTreeFlowIntentInstaller(flowManager);
+
+        SingleSrcTreeFlow flow = createFlow();
+        SingleSrcTreeFlowIntent intent = new SingleSrcTreeFlowIntent(new IntentId(1), flow);
+
+        sut.remove(intent);
+    }
+
+    private SingleSrcTreeFlow createFlow() {
+        Tree tree = new Tree();
+        tree.add(new FlowLink(port12, port21));
+        tree.add(new FlowLink(port13, port31));
+
+        Set<Pair<Dpid, OutputAction>> actions = new HashSet<>();
+        actions.add(new Pair<>(egress1.getDpid(), new OutputAction(egress1.getPortNumber())));
+        actions.add(new Pair<>(egress2.getDpid(), new OutputAction(egress2.getPortNumber())));
+
+        return new SingleSrcTreeFlow(
+                flowId,
+                new PacketMatchBuilder().build(),
+                ingress1,
+                tree,
+                actions
+        );
+    }
+}