Renamed the intent package

net.onrc.onos.intent.* => net.onrc.onos.core.intent.*

Change-Id: Id61f79ed52acf3b91af4ebad2515ac5b7d6dc5e1
diff --git a/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
new file mode 100644
index 0000000..473b32b
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
@@ -0,0 +1,149 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.core.intent.ConstrainedBFSTree;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.PathIntent;
+import net.onrc.onos.core.intent.PathIntentMap;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ConstrainedBFSTreeTest {
+	static long LOCAL_PORT = 0xFFFEL;
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreate() {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L));
+		assertNotNull(tree);
+	}
+
+	@Test
+	public void testCreateConstrained() {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		PathIntentMap intents = new PathIntentMap();
+		ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 1000.0);
+		assertNotNull(tree);
+	}
+
+	@Test
+	public void testGetPath() {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L));
+		Path path11 = tree.getPath(graph.getSwitch(1L));
+		Path path12 = tree.getPath(graph.getSwitch(2L));
+		Path path13 = tree.getPath(graph.getSwitch(3L));
+		Path path14 = tree.getPath(graph.getSwitch(4L));
+
+		assertNotNull(path11);
+		assertEquals(0, path11.size());
+
+		assertNotNull(path12);
+		assertEquals(1, path12.size());
+		assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path12.get(0));
+
+		assertNotNull(path13);
+		assertEquals(2, path13.size());
+		if (path13.get(0).getDst().getDpid() == 2L) {
+			assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path13.get(0));
+			assertEquals(new LinkEvent(graph.getLink(2L, 23L)), path13.get(1));
+		}
+		else {
+			assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path13.get(0));
+			assertEquals(new LinkEvent(graph.getLink(4L, 43L)), path13.get(1));
+		}
+
+		assertNotNull(path14);
+		assertEquals(1, path14.size());
+		assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path14.get(0));
+	}
+
+	@Test
+	public void testGetPathNull() {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		graph.removeLink(1L, 12L, 2L, 21L);
+		graph.removeLink(1L, 14L, 4L, 41L);
+		// now, there is no path from switch 1, but to switch1
+
+		ConstrainedBFSTree tree1 = new ConstrainedBFSTree(graph.getSwitch(1L));
+		Path path12 = tree1.getPath(graph.getSwitch(2L));
+		Path path13 = tree1.getPath(graph.getSwitch(3L));
+		Path path14 = tree1.getPath(graph.getSwitch(4L));
+
+		ConstrainedBFSTree tree2 = new ConstrainedBFSTree(graph.getSwitch(2L));
+		Path path21 = tree2.getPath(graph.getSwitch(1L));
+
+		assertNull(path12);
+		assertNull(path13);
+		assertNull(path14);
+		assertNotNull(path21);
+		assertEquals(1, path21.size());
+		assertEquals(new LinkEvent(graph.getLink(2L, 21L)), path21.get(0));
+	}
+
+	@Test
+	public void testGetConstrainedPath() {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		PathIntentMap intents = new PathIntentMap();
+		IntentOperationList intentOps = new IntentOperationList();
+
+		// create constrained shortest path intents that have the same source destination ports
+		ConstrainedShortestPathIntent intent1 = new ConstrainedShortestPathIntent(
+				"1", 1L, LOCAL_PORT, 0x111L, 2L, LOCAL_PORT, 0x222L, 600.0);
+		ConstrainedShortestPathIntent intent2 = new ConstrainedShortestPathIntent(
+				"2", 1L, LOCAL_PORT, 0x333L, 2L, LOCAL_PORT, 0x444L, 600.0);
+
+		// calculate path of the intent1
+		ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+		Path path1 = tree.getPath(graph.getSwitch(2L));
+
+		assertNotNull(path1);
+		assertEquals(1, path1.size());
+		assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path1.get(0));
+
+		PathIntent pathIntent1 = new PathIntent("pi1", path1, 600.0, intent1);
+		intentOps.add(Operator.ADD, pathIntent1);
+		intents.executeOperations(intentOps);
+
+		// calculate path of the intent2
+		tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+		Path path2 = tree.getPath(graph.getSwitch(2L));
+
+		assertNotNull(path2);
+		assertEquals(2, path2.size());
+		assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path2.get(0));
+		assertEquals(new LinkEvent(graph.getLink(4L, 42L)), path2.get(1));
+
+		PathIntent pathIntent2 = new PathIntent("pi2", path2, 600.0, intent2);
+		intentOps.add(Operator.ADD, pathIntent2);
+		intents.executeOperations(intentOps);
+
+		// calculate path of the intent3
+		tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+		Path path3 = tree.getPath(graph.getSwitch(2L));
+
+		assertNull(path3);
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/core/intent/ConstrainedShortestPathIntentTest.java b/src/test/java/net/onrc/onos/core/intent/ConstrainedShortestPathIntentTest.java
new file mode 100644
index 0000000..b0a8afc
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/ConstrainedShortestPathIntentTest.java
@@ -0,0 +1,67 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.assertEquals;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ConstrainedShortestPathIntentTest {
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreate() {
+		ConstrainedShortestPathIntent intent1 =
+				new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+
+		assertEquals("1", intent1.getId());
+		assertEquals(2L, intent1.getSrcSwitchDpid());
+		assertEquals(3L, intent1.getSrcPortNumber());
+		assertEquals(4L, intent1.getSrcMac());
+		assertEquals(5L, intent1.getDstSwitchDpid());
+		assertEquals(6L, intent1.getDstPortNumber());
+		assertEquals(7L, intent1.getDstMac());
+		assertEquals(1000.0, intent1.getBandwidth(), 0.0);
+	}
+
+	@Test
+	public void testKryo() {
+		KryoFactory factory = new KryoFactory();
+		Kryo kryo = factory.newKryo();
+		Output output = new Output(1000);
+
+		ConstrainedShortestPathIntent intent1 =
+				new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+		kryo.writeObject(output, intent1);
+
+		output.close();
+		byte bytes[] = output.toBytes();
+
+		Input input = new Input(bytes);
+		ConstrainedShortestPathIntent intent2 = kryo.readObject(input, ConstrainedShortestPathIntent.class);
+		input.close();
+		assertEquals("1", intent2.getId());
+		assertEquals(2L, intent2.getSrcSwitchDpid());
+		assertEquals(3L, intent2.getSrcPortNumber());
+		assertEquals(4L, intent2.getSrcMac());
+		assertEquals(5L, intent2.getDstSwitchDpid());
+		assertEquals(6L, intent2.getDstPortNumber());
+		assertEquals(7L, intent2.getDstMac());
+		assertEquals(1000.0, intent2.getBandwidth(), 0.0);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/ErrorIntentTest.java b/src/test/java/net/onrc/onos/core/intent/ErrorIntentTest.java
new file mode 100644
index 0000000..9fbbd56
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/ErrorIntentTest.java
@@ -0,0 +1,40 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.core.intent.ErrorIntent;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.ErrorIntent.ErrorType;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for the ErrorIntent class.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ErrorIntentTest {
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Test the result of executing constructor of the ErrorIntent class.
+     * This test checks the fields of id, errorType, message and parentIntent.
+     */
+    @Test
+    public void testCreate() {
+        Intent parentIntent = new Intent("1");
+        ErrorIntent errorIntent = new ErrorIntent(ErrorType.PATH_NOT_FOUND, "path not found", parentIntent);
+
+        assertEquals("1", errorIntent.getId());
+        assertEquals(ErrorType.PATH_NOT_FOUND, errorIntent.errorType);
+        assertEquals("path not found", errorIntent.message);
+        assertEquals(parentIntent, errorIntent.parentIntent);
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/IntentMapTest.java b/src/test/java/net/onrc/onos/core/intent/IntentMapTest.java
new file mode 100644
index 0000000..b8ad6fb
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/IntentMapTest.java
@@ -0,0 +1,244 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.core.intent.ErrorIntent;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentMap;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.ShortestPathIntent;
+import net.onrc.onos.core.intent.ErrorIntent.ErrorType;
+import net.onrc.onos.core.intent.Intent.IntentState;
+import net.onrc.onos.core.intent.IntentMap.ChangedEventType;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+import net.onrc.onos.core.intent.runtime.IntentStateList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentMapTest {
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreate() {
+		IntentMap intents = new IntentMap();
+		assertEquals(0, intents.getAllIntents().size());
+	}
+
+	@Test
+	public void testChangedEventCreate() {
+		IntentMap intents = new IntentMap();
+		IntentMap.ChangedEvent event = intents.new ChangedEvent(
+				ChangedEventType.ADDED,
+				new Intent("id1"));
+		assertEquals(ChangedEventType.ADDED, event.eventType);
+		assertEquals("id1", event.intent.getId());
+	}
+
+	@Test
+	public void testAddOperations() {
+		IntentMap intents = new IntentMap();
+		assertEquals(0, intents.getAllIntents().size());
+
+		Intent intent1 = new Intent("1");
+		ShortestPathIntent intent2 =
+				new ShortestPathIntent("2", 21L, 22L, 23L, 24L, 25L, 26L);
+		ConstrainedShortestPathIntent intent3 =
+				new ConstrainedShortestPathIntent("3", 31L, 32L, 33L, 34L, 35L, 36L, 1000.0);
+
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		operations.add(Operator.ADD, intent3);
+		assertEquals(3, operations.size());
+
+		intents.executeOperations(operations);
+		assertEquals(3, intents.getAllIntents().size());
+		assertSame(intent1, intents.getIntent("1"));
+		assertSame(intent2, intents.getIntent("2"));
+		assertSame(intent3, intents.getIntent("3"));
+	}
+
+	@Test
+	public void testAddOperationsOverwrite() {
+		IntentMap intents = new IntentMap();
+
+		Intent intent1 = new Intent("1");
+		Intent intent2 = new Intent("2");
+		Intent intent3 = new Intent("3");
+		Intent intent4 = new Intent("1");
+		Intent intent5 = new Intent("2");
+		Intent intent6 = new Intent("4");
+
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		operations.add(Operator.ADD, intent3);
+		assertEquals(3, operations.size());
+
+		intents.executeOperations(operations);
+		assertEquals(3, intents.getAllIntents().size());
+		assertSame(intent1, intents.getIntent("1"));
+		assertSame(intent2, intents.getIntent("2"));
+		assertSame(intent3, intents.getIntent("3"));
+
+		operations.clear();
+		operations.add(Operator.ADD, intent4);
+		operations.add(Operator.ADD, intent5);
+		operations.add(Operator.ADD, intent6);
+		assertEquals(3, operations.size());
+
+		intents.executeOperations(operations);
+		assertEquals(4, intents.getAllIntents().size());
+		assertSame(intent4, intents.getIntent("1"));
+		assertSame(intent5, intents.getIntent("2"));
+		assertSame(intent3, intents.getIntent("3"));
+		assertSame(intent6, intents.getIntent("4"));
+	}
+
+	@Test
+	public void testRemoveOperation() {
+		IntentMap intents = new IntentMap();
+
+		Intent intent1 = new Intent("1");
+		ShortestPathIntent intent2 =
+				new ShortestPathIntent("2", 21L, 22L, 23L, 24L, 25L, 26L);
+		ConstrainedShortestPathIntent intent3 =
+				new ConstrainedShortestPathIntent("3", 31L, 32L, 33L, 34L, 35L, 36L, 1000.0);
+
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		operations.add(Operator.ADD, intent3);
+		intents.executeOperations(operations);
+		assertEquals(3, intents.getAllIntents().size());
+		assertSame(intent1, intents.getIntent("1"));
+		assertSame(intent2, intents.getIntent("2"));
+		assertSame(intent3, intents.getIntent("3"));
+
+		operations.clear();
+		operations.add(Operator.REMOVE, new Intent("1"));
+		operations.add(Operator.REMOVE, new Intent("3"));
+		intents.executeOperations(operations);
+		assertEquals(3, intents.getAllIntents().size());
+		assertSame(intent1, intents.getIntent("1"));
+		assertSame(intent2, intents.getIntent("2"));
+		assertSame(intent3, intents.getIntent("3"));
+		assertEquals(IntentState.DEL_REQ, intents.getIntent("1").getState());
+		assertEquals(IntentState.CREATED, intents.getIntent("2").getState());
+		assertEquals(IntentState.DEL_REQ, intents.getIntent("3").getState());
+	}
+
+	@Test
+	public void testErrorOperation() {
+		IntentMap intents = new IntentMap();
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, new Intent("1", IntentState.CREATED));
+		operations.add(Operator.ADD, new Intent("2", IntentState.INST_REQ));
+		operations.add(Operator.ADD, new Intent("3", IntentState.INST_ACK));
+		operations.add(Operator.ADD, new Intent("4", IntentState.INST_NACK));
+		operations.add(Operator.ADD, new Intent("5", IntentState.REROUTE_REQ));
+		operations.add(Operator.ADD, new Intent("6", IntentState.DEL_REQ));
+		operations.add(Operator.ADD, new Intent("7", IntentState.DEL_ACK));
+		operations.add(Operator.ADD, new Intent("8", IntentState.DEL_PENDING));
+		intents.executeOperations(operations);
+		assertEquals(8, intents.getAllIntents().size());
+
+		operations.clear();
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("1")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("2")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("3")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("4")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("5")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("6")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("7")));
+		operations.add(Operator.ERROR, new ErrorIntent(ErrorType.PATH_NOT_FOUND, "", new Intent("8")));
+		intents.executeOperations(operations);
+
+		assertEquals(IntentState.INST_NACK, intents.getIntent("1").getState());
+		assertEquals(IntentState.INST_NACK, intents.getIntent("2").getState());
+		assertEquals(IntentState.INST_NACK, intents.getIntent("3").getState());
+		assertEquals(IntentState.INST_NACK, intents.getIntent("4").getState());
+		assertEquals(IntentState.INST_NACK, intents.getIntent("5").getState());
+		assertEquals(IntentState.DEL_PENDING, intents.getIntent("6").getState());
+		assertEquals(IntentState.DEL_ACK, intents.getIntent("7").getState());
+		assertEquals(IntentState.DEL_PENDING, intents.getIntent("8").getState());
+	}
+
+	@Test
+	public void testPurge() {
+		IntentMap intents = new IntentMap();
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, new Intent("1", IntentState.CREATED));
+		operations.add(Operator.ADD, new Intent("2", IntentState.INST_REQ));
+		operations.add(Operator.ADD, new Intent("3", IntentState.INST_ACK));
+		operations.add(Operator.ADD, new Intent("4", IntentState.INST_NACK));
+		operations.add(Operator.ADD, new Intent("5", IntentState.REROUTE_REQ));
+		operations.add(Operator.ADD, new Intent("6", IntentState.DEL_REQ));
+		operations.add(Operator.ADD, new Intent("7", IntentState.DEL_ACK));
+		operations.add(Operator.ADD, new Intent("8", IntentState.DEL_PENDING));
+		intents.executeOperations(operations);
+		assertEquals(8, intents.getAllIntents().size());
+
+		intents.purge();
+
+		assertEquals(6, intents.getAllIntents().size());
+		assertEquals("1", intents.getIntent("1").getId());
+		assertEquals("2", intents.getIntent("2").getId());
+		assertEquals("3", intents.getIntent("3").getId());
+		assertNull(intents.getIntent("4"));
+		assertEquals("5", intents.getIntent("5").getId());
+		assertEquals("6", intents.getIntent("6").getId());
+		assertNull("7", intents.getIntent("7"));
+		assertEquals("8", intents.getIntent("8").getId());
+	}
+
+	@Test
+	public void testChangeStates() {
+		IntentMap intents = new IntentMap();
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, new Intent("1", IntentState.CREATED));
+		operations.add(Operator.ADD, new Intent("2", IntentState.INST_REQ));
+		operations.add(Operator.ADD, new Intent("3", IntentState.INST_ACK));
+		operations.add(Operator.ADD, new Intent("4", IntentState.INST_NACK));
+		operations.add(Operator.ADD, new Intent("5", IntentState.REROUTE_REQ));
+		operations.add(Operator.ADD, new Intent("6", IntentState.DEL_REQ));
+		operations.add(Operator.ADD, new Intent("7", IntentState.DEL_ACK));
+		operations.add(Operator.ADD, new Intent("8", IntentState.DEL_PENDING));
+		intents.executeOperations(operations);
+		assertEquals(8, intents.getAllIntents().size());
+
+		IntentStateList states = new IntentStateList();
+		states.put("8", IntentState.CREATED);
+		states.put("1", IntentState.INST_REQ);
+		states.put("2", IntentState.INST_ACK);
+		states.put("3", IntentState.INST_NACK);
+		states.put("4", IntentState.REROUTE_REQ);
+		states.put("5", IntentState.DEL_REQ);
+		states.put("6", IntentState.DEL_ACK);
+		states.put("7", IntentState.DEL_PENDING);
+		intents.changeStates(states);
+
+		assertEquals(IntentState.INST_REQ, intents.getIntent("1").getState());
+		assertEquals(IntentState.INST_ACK, intents.getIntent("2").getState());
+		assertEquals(IntentState.INST_NACK, intents.getIntent("3").getState());
+		assertEquals(IntentState.REROUTE_REQ, intents.getIntent("4").getState());
+		assertEquals(IntentState.DEL_REQ, intents.getIntent("5").getState());
+		assertEquals(IntentState.DEL_ACK, intents.getIntent("6").getState());
+		assertEquals(IntentState.DEL_PENDING, intents.getIntent("7").getState());
+		assertEquals(IntentState.CREATED, intents.getIntent("8").getState());
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/IntentOperationListTest.java b/src/test/java/net/onrc/onos/core/intent/IntentOperationListTest.java
new file mode 100644
index 0000000..aa1410d
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/IntentOperationListTest.java
@@ -0,0 +1,75 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.assertEquals;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentOperation;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.PathIntent;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentOperationListTest {
+
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void test() {
+		IntentOperationList opList = new IntentOperationList();
+
+		ConstrainedShortestPathIntent cspIntent1 =
+				new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+
+		Path path = new Path();
+		path.add(new LinkEvent(1L, 2L, 3L, 4L));
+		path.add(new LinkEvent(5L, 6L, 7L, 8L));
+		path.add(new LinkEvent(9L, 0L, 1L, 2L));
+
+		PathIntent pathIntent1 = new PathIntent("11", path, 123.45, cspIntent1);
+		opList.add(IntentOperation.Operator.ADD, pathIntent1);
+		opList.add(IntentOperation.Operator.REMOVE, new Intent("22"));
+
+		KryoFactory factory = new KryoFactory();
+		Kryo kryo = factory.newKryo();
+		Output output = new Output(1024);
+		kryo.writeObject(output, opList);
+		output.close();
+
+		byte[] bytes = output.toBytes();
+
+		Input input = new Input(bytes);
+		IntentOperationList rcvOpList = kryo.readObject(input, IntentOperationList.class);
+
+		assertEquals(2, rcvOpList.size());
+
+		IntentOperation op1 = rcvOpList.get(0);
+		IntentOperation op2 = rcvOpList.get(1);
+
+		assertEquals(IntentOperation.Operator.ADD, op1.operator);
+		PathIntent intent1 = (PathIntent) op1.intent;
+		assertEquals("11", intent1.getId());
+		assertEquals(3, intent1.getPath().size());
+
+		assertEquals(IntentOperation.Operator.REMOVE, op2.operator);
+		Intent intent2 = op2.intent;
+		assertEquals("22", intent2.getId());
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/IntentOperationTest.java b/src/test/java/net/onrc/onos/core/intent/IntentOperationTest.java
new file mode 100644
index 0000000..5dc960d
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/IntentOperationTest.java
@@ -0,0 +1,43 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentOperation;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for the IntentOperation class.
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentOperationTest {
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /**
+     * Test the result of executing constructor of the IntentOperation class.
+     * This test checks the id field and the operator field.
+     */
+    @Test
+    public void testCreate() {
+        IntentOperation op1 = new IntentOperation(Operator.ADD, new Intent("1"));
+        IntentOperation op2 = new IntentOperation(Operator.REMOVE, new Intent("2"));
+        IntentOperation op3 = new IntentOperation(Operator.ERROR, new Intent("3"));
+
+        assertEquals("1", op1.intent.getId());
+        assertEquals(Operator.ADD, op1.operator);
+        assertEquals("2", op2.intent.getId());
+        assertEquals(Operator.REMOVE, op2.operator);
+        assertEquals("3", op3.intent.getId());
+        assertEquals(Operator.ERROR, op3.operator);
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/IntentTest.java b/src/test/java/net/onrc/onos/core/intent/IntentTest.java
new file mode 100644
index 0000000..5b539dc
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/IntentTest.java
@@ -0,0 +1,79 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.*;
+
+import java.util.HashSet;
+
+import net.onrc.onos.core.intent.Intent;
+
+import org.junit.Test;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class IntentTest {
+	@Test
+	public void testCreateIntent() {
+		Intent intent = new Intent("id");
+		assertEquals("id", intent.getId());
+		assertEquals(Intent.IntentState.CREATED, intent.getState());
+	}
+
+	@Test
+	public void testCreateIntentWithState() {
+		Intent intent = new Intent("id", Intent.IntentState.INST_REQ);
+		assertEquals("id", intent.getId());
+		assertEquals(Intent.IntentState.INST_REQ, intent.getState());
+	}
+
+	@Test
+	public void testSetState() {
+		Intent intent = new Intent("id");
+
+		intent.setState(Intent.IntentState.INST_REQ);
+		assertEquals(Intent.IntentState.INST_REQ, intent.getState());
+
+		intent.setState(Intent.IntentState.DEL_REQ);
+		assertEquals(Intent.IntentState.DEL_REQ, intent.getState());
+	}
+
+	@Test
+	public void testEquals() {
+		Intent intent1 = new Intent("id1");
+		Intent intent2 = new Intent("id1");
+		Intent intent3 = new Intent("id2");
+		Intent intent4 = new Intent("id2");
+
+		assertEquals(intent1, intent2);
+		assertEquals(intent3, intent4);
+
+		assertFalse(intent1.equals(intent3));
+		assertFalse(intent3.equals(intent1));
+
+		intent1.setState(Intent.IntentState.INST_ACK);
+		intent2.setState(Intent.IntentState.INST_NACK);
+		assertEquals(intent1, intent2);
+	}
+
+	@Test
+	public void testHashCode() {
+		Intent intent1 = new Intent("id1");
+		intent1.setState(Intent.IntentState.INST_ACK);
+		Intent intent2 = new Intent("id1");
+		intent2.setState(Intent.IntentState.INST_NACK);
+		Intent intent3 = new Intent("id2");
+		Intent intent4 = new Intent("id2");
+
+		HashSet<Intent> intents = new HashSet<>();
+		intents.add(intent1);
+		intents.add(intent2);
+		intents.add(intent3);
+		intents.add(intent4);
+
+		assertEquals(2, intents.size());
+		assertTrue(intents.contains(intent1));
+		assertTrue(intents.contains(intent2));
+		assertTrue(intents.contains(intent3));
+		assertTrue(intents.contains(intent4));
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/MockNetworkGraph.java b/src/test/java/net/onrc/onos/core/intent/MockNetworkGraph.java
new file mode 100644
index 0000000..fce9cc2
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/MockNetworkGraph.java
@@ -0,0 +1,99 @@
+package net.onrc.onos.core.intent;
+
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraphImpl;
+import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.LinkImpl;
+import net.onrc.onos.ofcontroller.networkgraph.Port;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.networkgraph.SwitchImpl;
+
+/**
+ * A mock class of NetworkGraph.
+ * This class should be used only by test codes.
+ *
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class MockNetworkGraph extends NetworkGraphImpl {
+	public static Long LOCAL_PORT = 0xFFFEL;
+	public SwitchImpl sw1, sw2, sw3, sw4;
+
+	class DetachableLinkImpl extends LinkImpl {
+		public DetachableLinkImpl(NetworkGraph graph, Port srcPort, Port dstPort) {
+			super(graph, srcPort, dstPort);
+		}
+
+		public void detachFromGraph() {
+			unsetFromPorts();
+		}
+	}
+	public Switch addSwitch(Long switchId) {
+		SwitchImpl sw = new SwitchImpl(this, switchId);
+		this.putSwitch(sw);
+		return sw;
+	}
+
+	public Link addLink(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
+		return new DetachableLinkImpl(
+				this,
+				getSwitch(srcDpid).getPort(srcPortNo),
+				getSwitch(dstDpid).getPort(dstPortNo));
+	}
+
+	public Link[] addBidirectionalLinks(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
+		Link[] links = new Link[2];
+		links[0] = addLink(srcDpid, srcPortNo, dstDpid, dstPortNo);
+		links[1] = addLink(dstDpid, dstPortNo, srcDpid, srcPortNo);
+
+		return links;
+	}
+
+	/**
+	 * create sample topology of 4 switches and 5 bidirectional links.
+	 * <pre>
+	 * [1] --- [2]
+	 *  |    /  |
+	 *  |  /    |
+	 * [4] --- [3]
+	 * </pre>
+	 */
+	public void createSampleTopology1() {
+		sw1 = (SwitchImpl) addSwitch(1L);
+		sw1.addPort(LOCAL_PORT);
+		sw2 = (SwitchImpl) addSwitch(2L);
+		sw2.addPort(LOCAL_PORT);
+		sw3 = (SwitchImpl) addSwitch(3L);
+		sw3.addPort(LOCAL_PORT);
+		sw4 = (SwitchImpl) addSwitch(4L);
+		sw4.addPort(LOCAL_PORT);
+
+		sw1.addPort(12L); // sw1 -> sw2
+		sw1.addPort(14L); // sw1 -> sw4
+		sw2.addPort(21L); // sw2 -> sw1
+		sw2.addPort(23L); // sw2 -> sw3
+		sw2.addPort(24L); // sw2 -> sw4
+		sw3.addPort(32L); // sw3 -> sw2
+		sw3.addPort(34L); // sw3 -> sw4
+		sw4.addPort(41L); // sw4 -> sw1
+		sw4.addPort(42L); // sw4 -> sw2
+		sw4.addPort(43L); // sw4 -> sw3
+
+		addBidirectionalLinks(1L, 12L, 2L, 21L);
+		addBidirectionalLinks(2L, 23L, 3L, 32L);
+		addBidirectionalLinks(3L, 34L, 4L, 43L);
+		addBidirectionalLinks(4L, 41L, 1L, 14L);
+		addBidirectionalLinks(2L, 24L, 4L, 42L);
+
+		// set capacity of all links to 1000Mbps
+		for (Link link: getLinks()) {
+			((LinkImpl)link).setCapacity(1000.0);
+		}
+	}
+
+	public void removeLink(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
+		DetachableLinkImpl link = (DetachableLinkImpl)getSwitch(srcDpid).getPort(srcPortNo).getOutgoingLink();
+		if (link.getDstSwitch().getDpid().equals(dstDpid) && link.getDstPort().getNumber().equals(dstPortNo)) {
+			link.detachFromGraph();
+		}
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java b/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java
new file mode 100644
index 0000000..32f7e0f
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java
@@ -0,0 +1,201 @@
+package net.onrc.onos.core.intent;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.PathIntent;
+import net.onrc.onos.core.intent.PathIntentMap;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.networkgraph.Port;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PathIntentMapTest {
+	Link link12, link23, link24;
+	Switch sw1, sw2, sw3, sw4;
+	Port port11, port22, port21, port23, port31, port41;
+	Path path1, path2;
+	PathIntent intent1, intent2;
+
+	@Before
+	public void setUp() throws Exception {
+		sw1 = createMock(Switch.class);
+		sw2 = createMock(Switch.class);
+		sw3 = createMock(Switch.class);
+		sw4 = createMock(Switch.class);
+		expect(sw1.getDpid()).andReturn(1L).anyTimes();
+		expect(sw2.getDpid()).andReturn(2L).anyTimes();
+		expect(sw3.getDpid()).andReturn(3L).anyTimes();
+		expect(sw4.getDpid()).andReturn(4L).anyTimes();
+		replay(sw1);
+		replay(sw2);
+		replay(sw3);
+		replay(sw4);
+
+		port11 = createMock(Port.class);
+		port22 = createMock(Port.class);
+		port21 = createMock(Port.class);
+		port23 = createMock(Port.class);
+		port31 = createMock(Port.class);
+		port41 = createMock(Port.class);
+		expect(port11.getNumber()).andReturn(1L).anyTimes();
+		expect(port22.getNumber()).andReturn(2L).anyTimes();
+		expect(port21.getNumber()).andReturn(1L).anyTimes();
+		expect(port23.getNumber()).andReturn(3L).anyTimes();
+		expect(port31.getNumber()).andReturn(1L).anyTimes();
+		expect(port41.getNumber()).andReturn(1L).anyTimes();
+		replay(port11);
+		replay(port22);
+		replay(port21);
+		replay(port23);
+		replay(port31);
+		replay(port41);
+
+		link12 = createMock(Link.class);
+		link23 = createMock(Link.class);
+		link24 = createMock(Link.class);
+		expect(link12.getCapacity()).andReturn(1000.0).anyTimes();
+		expect(link23.getCapacity()).andReturn(1000.0).anyTimes();
+		expect(link24.getCapacity()).andReturn(1000.0).anyTimes();
+		expect(link12.getSrcSwitch()).andReturn(sw1).anyTimes();
+		expect(link23.getSrcSwitch()).andReturn(sw2).anyTimes();
+		expect(link24.getSrcSwitch()).andReturn(sw2).anyTimes();
+		expect(link12.getSrcPort()).andReturn(port11).anyTimes();
+		expect(link23.getSrcPort()).andReturn(port21).anyTimes();
+		expect(link24.getSrcPort()).andReturn(port23).anyTimes();
+		expect(link12.getDstSwitch()).andReturn(sw2).anyTimes();
+		expect(link23.getDstSwitch()).andReturn(sw3).anyTimes();
+		expect(link24.getDstSwitch()).andReturn(sw4).anyTimes();
+		expect(link12.getDstPort()).andReturn(port22).anyTimes();
+		expect(link23.getDstPort()).andReturn(port31).anyTimes();
+		expect(link24.getDstPort()).andReturn(port41).anyTimes();
+		replay(link12);
+		replay(link23);
+		replay(link24);
+
+		path1 = new Path();
+		path1.add(new LinkEvent(link12));
+		path1.add(new LinkEvent(link23));
+
+		path2 = new Path();
+		path2.add(new LinkEvent(link12));
+		path2.add(new LinkEvent(link24));
+
+		intent1 = new PathIntent("1", path1, 400.0, new Intent("_1"));
+		intent2 = new PathIntent("2", path2, 400.0, new Intent("_2"));
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreate() {
+		PathIntentMap intents = new PathIntentMap();
+		assertEquals(0, intents.getAllIntents().size());
+	}
+
+	@Test
+	public void testGetIntentsByDpid() {
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		assertEquals(2, operations.size());
+
+		PathIntentMap intents = new PathIntentMap();
+		intents.executeOperations(operations);
+		assertEquals(2, intents.getAllIntents().size());
+
+		Collection<PathIntent> pathIntents = intents.getIntentsByDpid(1L);
+		assertEquals(2, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+		assertTrue(pathIntents.contains(intent2));
+
+		pathIntents = intents.getIntentsByDpid(2L);
+		assertEquals(2, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+		assertTrue(pathIntents.contains(intent2));
+
+		pathIntents = intents.getIntentsByDpid(3L);
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+
+		pathIntents = intents.getIntentsByDpid(4L);
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent2));
+	}
+
+	@Test
+	public void testGetPathIntentsByPort() {
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		assertEquals(2, operations.size());
+
+		PathIntentMap intents = new PathIntentMap();
+		intents.executeOperations(operations);
+		assertEquals(2, intents.getAllIntents().size());
+
+		Collection<PathIntent> pathIntents = intents.getIntentsByPort(1L, 1L);
+		assertEquals(2, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+		assertTrue(pathIntents.contains(intent2));
+
+		pathIntents = intents.getIntentsByPort(2L, 1L);
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+
+		pathIntents = intents.getIntentsByPort(2L, 3L);
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent2));
+	}
+
+	@Test
+	public void testGetPathIntentsByLink() {
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		assertEquals(2, operations.size());
+
+		PathIntentMap intents = new PathIntentMap();
+		intents.executeOperations(operations);
+		assertEquals(2, intents.getAllIntents().size());
+
+		Collection<PathIntent> pathIntents = intents.getIntentsByLink(new LinkEvent(link12));
+		assertEquals(2, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+		assertTrue(pathIntents.contains(intent2));
+
+		pathIntents = intents.getIntentsByLink(new LinkEvent(link23));
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent1));
+
+		pathIntents = intents.getIntentsByLink(new LinkEvent(link24));
+		assertEquals(1, pathIntents.size());
+		assertTrue(pathIntents.contains(intent2));
+	}
+
+	@Test
+	public void testGetAvailableBandwidth() {
+		IntentOperationList operations = new IntentOperationList();
+		operations.add(Operator.ADD, intent1);
+		operations.add(Operator.ADD, intent2);
+		assertEquals(2, operations.size());
+
+		PathIntentMap intents = new PathIntentMap();
+		intents.executeOperations(operations);
+		assertEquals(2, intents.getAllIntents().size());
+
+		assertEquals(200.0, intents.getAvailableBandwidth(link12), 0.0);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java b/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java
new file mode 100644
index 0000000..9b4b255
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java
@@ -0,0 +1,103 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.assertEquals;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.core.intent.PathIntent;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class PathIntentTest {
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void testCreateFirstId() {
+		String id = PathIntent.createFirstId("100");
+		assertEquals("100___0", id);
+	}
+
+	@Test
+	public void testCreateNextId() {
+		String id = PathIntent.createNextId("100___999");
+		assertEquals("100___1000", id);
+	}
+
+	@Test
+	public void test() {
+		KryoFactory factory = new KryoFactory();
+		Kryo kryo = factory.newKryo();
+		Output output = new Output(1024);
+
+		ConstrainedShortestPathIntent cspIntent1 =
+				new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+
+		Path path = new Path();
+		path.add(new LinkEvent(1L, 1L, 2L, 2L));
+		path.add(new LinkEvent(2L, 1L, 3L, 2L));
+		path.add(new LinkEvent(3L, 1L, 4L, 2L));
+
+		PathIntent pathIntent1 = new PathIntent("11", path, 123.45, cspIntent1);
+
+		kryo.writeObject(output, pathIntent1);
+		output.close();
+
+		Input input = new Input(output.toBytes());
+
+		// create pathIntent from bytes
+
+		PathIntent pathIntent2 =
+				kryo.readObject(input, PathIntent.class);
+		input.close();
+
+		// check
+
+		assertEquals("11", pathIntent2.getId());
+		Path path2 = pathIntent2.getPath();
+
+		assertEquals(Long.valueOf(1L), path2.get(0).getSrc().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(0).getSrc().getNumber());
+		assertEquals(Long.valueOf(2L), path2.get(0).getDst().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(0).getDst().getNumber());
+
+		assertEquals(Long.valueOf(2L), path2.get(1).getSrc().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(1).getSrc().getNumber());
+		assertEquals(Long.valueOf(3L), path2.get(1).getDst().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(1).getDst().getNumber());
+
+		assertEquals(Long.valueOf(3L), path2.get(2).getSrc().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(2).getSrc().getNumber());
+		assertEquals(Long.valueOf(4L), path2.get(2).getDst().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(2).getDst().getNumber());
+
+		assertEquals(123.45, pathIntent2.getBandwidth(), 0.0);
+
+		ConstrainedShortestPathIntent cspIntent2 =
+				(ConstrainedShortestPathIntent) pathIntent2.getParentIntent();
+
+		assertEquals("1", cspIntent2.getId());
+		assertEquals(2L, cspIntent2.getSrcSwitchDpid());
+		assertEquals(3L, cspIntent2.getSrcPortNumber());
+		assertEquals(4L, cspIntent2.getSrcMac());
+		assertEquals(5L, cspIntent2.getDstSwitchDpid());
+		assertEquals(6L, cspIntent2.getDstPortNumber());
+		assertEquals(7L, cspIntent2.getDstMac());
+		assertEquals(1000.0, cspIntent2.getBandwidth(), 0.0);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/ShortestPathIntentTest.java b/src/test/java/net/onrc/onos/core/intent/ShortestPathIntentTest.java
new file mode 100644
index 0000000..1c34775
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/ShortestPathIntentTest.java
@@ -0,0 +1,50 @@
+package net.onrc.onos.core.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.core.intent.ShortestPathIntent;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ShortestPathIntentTest {
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void test() {
+		Kryo kryo = new Kryo();
+		Output output = new Output(1024);
+
+		ShortestPathIntent intent1 =
+				new ShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L);
+
+		kryo.writeObject(output, intent1);
+		output.close();
+
+		Input input = new Input(output.toBytes());
+		ShortestPathIntent intent2 =
+				kryo.readObject(input, ShortestPathIntent.class);
+		input.close();
+
+		assertEquals("1", intent2.getId());
+		assertEquals(2L, intent2.getSrcSwitchDpid());
+		assertEquals(3L, intent2.getSrcPortNumber());
+		assertEquals(4L, intent2.getSrcMac());
+		assertEquals(5L, intent2.getDstSwitchDpid());
+		assertEquals(6L, intent2.getDstPortNumber());
+		assertEquals(7L, intent2.getDstMac());
+	}
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java b/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java
new file mode 100644
index 0000000..be8ad9a
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java
@@ -0,0 +1,533 @@
+package net.onrc.onos.core.intent.runtime;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.onrc.onos.core.datagrid.IDatagridService;
+import net.onrc.onos.core.datagrid.IEventChannel;
+import net.onrc.onos.core.datagrid.IEventChannelListener;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentMap;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.MockNetworkGraph;
+import net.onrc.onos.core.intent.ShortestPathIntent;
+import net.onrc.onos.core.intent.Intent.IntentState;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+import net.onrc.onos.core.intent.runtime.IntentStateList;
+import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule;
+import net.onrc.onos.core.intent.runtime.PersistIntent;
+import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphListener;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
+import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.TypeSafeMatcher;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author Ray Milkey (ray@onlab.us)
+ *
+ * Unit tests for the Path Calculation Runtime module (PathCalcRuntimeModule).
+ * These test cases check the results of creating paths, deleting paths, and
+ * rerouting paths.  The network graph, controller registry, and data grid are
+ * mocked out.  The individual tests check the high level intents and the
+ * resulting operation lists to be sure they match the intended APIs.
+ *
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(PathCalcRuntimeModule.class)
+public class PathCalcRuntimeModuleTest {
+    private static final Long LOCAL_PORT = 0xFFFEL;
+
+    private FloodlightModuleContext modContext;
+    private IDatagridService datagridService;
+    private INetworkGraphService networkGraphService;
+    private IControllerRegistryService controllerRegistryService;
+    private PersistIntent persistIntent;
+    private MockNetworkGraph graph;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() throws Exception {
+        graph = new MockNetworkGraph();
+        graph.createSampleTopology1();
+
+        datagridService = createMock(IDatagridService.class);
+        networkGraphService = createMock(INetworkGraphService.class);
+        controllerRegistryService = createMock(IControllerRegistryService.class);
+        modContext = createMock(FloodlightModuleContext.class);
+        final IEventChannel eventChannel = createMock(IEventChannel.class);
+        persistIntent = PowerMock.createMock(PersistIntent.class);
+
+        PowerMock.expectNew(PersistIntent.class,
+                anyObject(IControllerRegistryService.class),
+                anyObject(INetworkGraphService.class)).andReturn(persistIntent);
+
+        expect(modContext.getServiceImpl(IDatagridService.class))
+                .andReturn(datagridService).once();
+        expect(modContext.getServiceImpl(INetworkGraphService.class))
+                .andReturn(networkGraphService).once();
+        expect(modContext.getServiceImpl(IControllerRegistryService.class))
+                .andReturn(controllerRegistryService).once();
+        expect(persistIntent.getKey()).andReturn(1L).anyTimes();
+        expect(persistIntent.persistIfLeader(eq(1L),
+                anyObject(IntentOperationList.class))).andReturn(true)
+                .anyTimes();
+
+        expect(networkGraphService.getNetworkGraph()).andReturn(graph)
+                .anyTimes();
+        networkGraphService.registerNetworkGraphListener(
+                anyObject(INetworkGraphListener.class));
+        expectLastCall();
+
+        expect(datagridService.createChannel("onos.pathintent",
+                Long.class, IntentOperationList.class))
+                .andReturn(eventChannel).once();
+
+        expect(datagridService.addListener(
+                eq("onos.pathintent_state"),
+                anyObject(IEventChannelListener.class),
+                eq(Long.class),
+                eq(IntentStateList.class)))
+                .andReturn(eventChannel).once();
+
+        replay(datagridService);
+        replay(networkGraphService);
+        replay(modContext);
+        replay(controllerRegistryService);
+        PowerMock.replay(persistIntent, PersistIntent.class);
+    }
+
+
+    /**
+     * Hamcrest matcher to check that a collection of Intents contains an
+     * Intent with the specified Intent Id.
+     */
+    public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
+        final private String id;
+
+        public EntryForIntentMatcher(String idValue) {
+            id = idValue;
+        }
+
+        @Override
+        public boolean matchesSafely(Collection<Intent> intents) {
+            assertThat(intents,
+                       hasItem(Matchers.<Intent>hasProperty("id", equalTo(id))));
+            return true;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("an intent with id \" ").
+                    appendText(id).
+                    appendText("\"");
+        }
+    }
+
+
+    /**
+     * Factory method to create an Intent entry Matcher.  Returns a matcher
+     * for the Intent with the given id.
+     * @param id id of the intent to match
+     * @return Matcher object
+     */
+    @Factory
+    public static Matcher<Collection<Intent>> hasIntentWithId(String id) {
+        return new EntryForIntentMatcher(id);
+    }
+
+
+    /**
+     * Matcher to determine if an IntentMap contains an entry with a given id,
+     * and that entry has a given state.
+     */
+    public static class IntentsHaveIntentWithStateMatcher extends TypeSafeMatcher<IntentMap> {
+        final private String id;
+        final private IntentState state;
+        private Intent intent;
+
+        public IntentsHaveIntentWithStateMatcher(String idValue,
+                                                 IntentState stateValue) {
+            id = idValue;
+            state = stateValue;
+        }
+
+        @Override
+        public boolean matchesSafely(IntentMap intents) {
+            intent = intents.getIntent(id);
+
+            return intent != null && intent.getState() == state;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            if (intent == null) {
+                description.appendText("intent lookup for id \"");
+                description.appendText(id);
+                description.appendText("\"");
+            } else {
+                description.appendText("state ");
+                description.appendText(state.toString());
+            }
+        }
+
+        @Override
+        public void describeMismatchSafely(IntentMap intents,
+                                           Description mismatchDescription) {
+            if (intent != null) {
+                mismatchDescription.appendText("was ").
+                                    appendText(intent.getState().toString());
+            } else {
+                mismatchDescription.appendText("that intent was not found");
+            }
+        }
+    }
+
+
+    /**
+     * Factory method to create a Matcher for an IntentMap that looks for an
+     * Intent with a given id and state.
+     *
+     * @param id id of the Intent to match
+     * @param state if the Intent is found, its state must match this
+     * @return Matcher object
+     */
+    @Factory
+    public static Matcher<IntentMap> hasIntentWithIdAndState(String id,
+                                                             IntentState state) {
+        return new IntentsHaveIntentWithStateMatcher(id, state);
+    }
+
+
+    @After
+    public void tearDown() {
+        verify(datagridService);
+        verify(networkGraphService);
+        verify(modContext);
+        verify(controllerRegistryService);
+        PowerMock.verify(persistIntent, PersistIntent.class);
+    }
+
+    /**
+     * Test the result of executing a path calculation on an
+     * Intent Operation List which contains a path that references a
+     * non-existent switch.
+     *
+     * A 3 path list is created where one of the paths references a switch
+     * that is not in the topology.  The test checks that the resulting
+     * Operation List has entries for the 2 correct paths, and that the
+     * high level intents contain a proper error entry for the bad path.
+     */
+    @Test
+    public void testInvalidSwitchName() throws FloodlightModuleException {
+        final String BAD_SWITCH_INTENT_NAME = "No Such Switch Intent";
+
+        // create shortest path intents
+        final IntentOperationList opList = new IntentOperationList();
+        opList.add(Operator.ADD,
+                new ShortestPathIntent(BAD_SWITCH_INTENT_NAME, 111L, 12L,
+                        LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
+                        LOCAL_PORT));
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
+                        LOCAL_PORT));
+
+        // compile high-level intent operations into low-level intent
+        // operations (calculate paths)
+        final PathCalcRuntimeModule runtime = new PathCalcRuntimeModule();
+        runtime.init(modContext);
+        runtime.startUp(modContext);
+        final IntentOperationList pathIntentOpList =
+                runtime.executeIntentOperations(opList);
+        assertThat(pathIntentOpList, notNullValue());
+
+        final IntentMap highLevelIntents = runtime.getHighLevelIntents();
+        assertThat(highLevelIntents, notNullValue());
+
+        final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
+        assertThat(allIntents, notNullValue());
+
+        //  One intent had an error and should not create a path list entry
+        assertThat(pathIntentOpList, hasSize(opList.size() - 1));
+
+        //  Should be a high level intent for each operation
+        assertThat(allIntents, hasSize(opList.size()));
+
+        // Check that we got a high level intent for each operation
+        assertThat(allIntents, hasIntentWithId("3"));
+        assertThat(allIntents, hasIntentWithId("2"));
+        assertThat(allIntents, hasIntentWithId(BAD_SWITCH_INTENT_NAME));
+
+        //  Check that the non existent switch was NACKed
+        assertThat(highLevelIntents, hasIntentWithIdAndState(BAD_SWITCH_INTENT_NAME, IntentState.INST_NACK));
+
+        //  Check that switch 2 was correctly processed
+        assertThat(highLevelIntents, hasIntentWithIdAndState("2", IntentState.INST_REQ));
+
+        //  Check that switch 3 was correctly processed
+        assertThat(highLevelIntents, hasIntentWithIdAndState("3", IntentState.INST_REQ));
+
+    }
+
+
+    /**
+     * Test the result of executing a path calculation on an
+     * Intent Operation List and then removing one of the switches.
+     *
+     * A 3 path list is created and then one of the paths is removed.
+     * The test checks that the resulting Operation List is correct,
+     * and that the high level intents contain a proper "delete requested"
+     * entry for the deleted path.
+     */
+    @Test
+    public void testIntentRemoval() throws FloodlightModuleException {
+
+        // create shortest path intents
+        final IntentOperationList opList = new IntentOperationList();
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
+                                       LOCAL_PORT));
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
+                                       LOCAL_PORT));
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
+                                       LOCAL_PORT));
+
+        // compile high-level intent operations into low-level intent
+        // operations (calculate paths)
+        final PathCalcRuntimeModule runtime = new PathCalcRuntimeModule();
+        runtime.init(modContext);
+        runtime.startUp(modContext);
+        final IntentOperationList pathIntentOpList =
+                runtime.executeIntentOperations(opList);
+        assertThat(pathIntentOpList, notNullValue());
+
+        final IntentMap highLevelIntents = runtime.getHighLevelIntents();
+        assertThat(highLevelIntents, notNullValue());
+
+        final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
+        assertThat(allIntents, notNullValue());
+
+        //  Should be one operation per path
+        assertThat(pathIntentOpList, hasSize(opList.size()));
+
+        //  Should be a high level intent for each operation
+        assertThat(allIntents, hasSize(opList.size()));
+
+        // Check that we got a high level intent for each operation
+        assertThat(allIntents, hasIntentWithId("3"));
+        assertThat(allIntents, hasIntentWithId("2"));
+        assertThat(allIntents, hasIntentWithId("1"));
+
+        //  Check that switch 1 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("1", IntentState.INST_REQ));
+
+        //  Check that switch 2 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("2", IntentState.INST_REQ));
+
+        //  Check that switch 3 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("3", IntentState.INST_REQ));
+
+        //  Now delete one path and check the results
+        final IntentOperationList opListForRemoval = new IntentOperationList();
+        opListForRemoval.add(Operator.REMOVE,
+                new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
+                        LOCAL_PORT));
+
+        final IntentOperationList pathIntentOpListAfterRemoval =
+                runtime.executeIntentOperations(opListForRemoval);
+        assertThat(pathIntentOpListAfterRemoval, notNullValue());
+        assertThat(pathIntentOpListAfterRemoval, hasSize(1));
+
+        //  Check the high level intents.
+        final IntentMap highLevelIntentsAfterRemoval = runtime.getHighLevelIntents();
+        assertThat(highLevelIntentsAfterRemoval, notNullValue());
+
+        final Collection<Intent> allIntentsAfterRemoval = highLevelIntentsAfterRemoval.getAllIntents();
+        assertThat(allIntentsAfterRemoval, notNullValue());
+        assertThat(allIntentsAfterRemoval, hasSize(3));
+
+        // Check that we got a high level intent for each operation
+        assertThat(allIntentsAfterRemoval, hasIntentWithId("3"));
+        assertThat(allIntentsAfterRemoval, hasIntentWithId("2"));
+        assertThat(allIntentsAfterRemoval, hasIntentWithId("1"));
+
+        //  Check the states of the high level intents
+        //  Check that switch 1 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("1", IntentState.DEL_REQ));
+
+        //  Check that switch 2 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("2", IntentState.INST_REQ));
+
+        //  Check that switch 3 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("3", IntentState.INST_REQ));
+    }
+
+    /**
+     * Test the result of executing a path calculation on an
+     * Intent Operation List and then forcing a reroute.
+     *
+     * A 3 path list is created and then one of the links is removed.
+     * The test checks that the resulting Operation List is correct,
+     * and that the high level intents contain a proper "reroute requested"
+     * entry for the deleted link.
+     */
+    @Test
+    public void testIntentReroute() throws FloodlightModuleException {
+
+        // create shortest path intents
+        final IntentOperationList opList = new IntentOperationList();
+        final ShortestPathIntent pathIntent1 =
+                new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
+                                       LOCAL_PORT);
+
+        opList.add(Operator.ADD, pathIntent1);
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
+                                       LOCAL_PORT));
+        opList.add(Operator.ADD,
+                new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
+                                       LOCAL_PORT));
+
+        // compile high-level intent operations into low-level intent
+        // operations (calculate paths)
+        final PathCalcRuntimeModule runtime = new PathCalcRuntimeModule();
+        runtime.init(modContext);
+        runtime.startUp(modContext);
+        final IntentOperationList pathIntentOpList =
+                runtime.executeIntentOperations(opList);
+        assertThat(pathIntentOpList, notNullValue());
+
+        final IntentMap highLevelIntents = runtime.getHighLevelIntents();
+        assertThat(highLevelIntents, notNullValue());
+
+        final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
+        assertThat(allIntents, notNullValue());
+
+        //  Should be one operation per path
+        assertThat(pathIntentOpList, hasSize(opList.size()));
+
+        //  Should be a high level intent for each operation
+        assertThat(allIntents, hasSize(opList.size()));
+
+        // Check that we got a high level intent for each operation
+        assertThat(allIntents, hasIntentWithId("3"));
+        assertThat(allIntents, hasIntentWithId("2"));
+        assertThat(allIntents, hasIntentWithId("1"));
+
+        //  Check that switch 1 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("1", IntentState.INST_REQ));
+
+        //  Check that switch 2 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("2", IntentState.INST_REQ));
+
+        //  Check that switch 3 was correctly processed
+        assertThat(highLevelIntents,
+                   hasIntentWithIdAndState("3", IntentState.INST_REQ));
+
+        //  Now add a different path to one of the switches path and check
+        //  the results
+        IntentStateList states = new IntentStateList();
+        states.put("1", IntentState.INST_ACK);
+        states.put("2", IntentState.INST_ACK);
+        states.put("3", IntentState.INST_ACK);
+        runtime.getHighLevelIntents().changeStates(states);
+        states.clear();
+        states.put("1___0", IntentState.INST_ACK);
+        states.put("2___0", IntentState.INST_ACK);
+        states.put("3___0", IntentState.INST_ACK);
+        runtime.getPathIntents().changeStates(states);
+
+        final List<SwitchEvent> emptySwitchEvents = new LinkedList<>();
+        final List<PortEvent> emptyPortEvents = new LinkedList<>();
+        final List<DeviceEvent> emptyDeviceEvents = new LinkedList<>();
+        final List<LinkEvent> addedLinkEvents = new LinkedList<>();
+        final List<LinkEvent> removedLinkEvents = new LinkedList<>();
+
+        graph.removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
+        graph.removeLink(2L, 21L, 1L, 12L);
+        LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
+        LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
+        removedLinkEvents.add(linkEvent1);
+        removedLinkEvents.add(linkEvent2);
+        runtime.networkGraphEvents(
+                emptySwitchEvents,
+                emptySwitchEvents,
+                emptyPortEvents,
+                emptyPortEvents,
+                addedLinkEvents,
+                removedLinkEvents,
+                emptyDeviceEvents,
+                emptyDeviceEvents);
+        final IntentOperationList opListForReroute = new IntentOperationList();
+        opListForReroute.add(Operator.ADD, pathIntent1);
+
+        final IntentOperationList pathIntentOpListAfterReroute =
+                runtime.executeIntentOperations(opListForReroute);
+        assertThat(pathIntentOpListAfterReroute, notNullValue());
+        assertThat(pathIntentOpListAfterReroute, hasSize(2));
+
+        //  Check the high level intents.
+        final IntentMap highLevelIntentsAfterReroute = runtime.getHighLevelIntents();
+        assertThat(highLevelIntentsAfterReroute, notNullValue());
+
+        final Collection<Intent> allIntentsAfterReroute = highLevelIntentsAfterReroute.getAllIntents();
+        assertThat(allIntentsAfterReroute, notNullValue());
+        assertThat(allIntentsAfterReroute, hasSize(3));
+
+        // Check that we got a high level intent for each operation
+        assertThat(allIntentsAfterReroute, hasIntentWithId("3"));
+        assertThat(allIntentsAfterReroute, hasIntentWithId("2"));
+        assertThat(allIntentsAfterReroute, hasIntentWithId("1"));
+
+        //  Check the states of the high level intents
+        //  Check that switch 1 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
+
+        //  Check that switch 2 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("2", IntentState.INST_ACK));
+
+        //  Check that switch 3 was correctly processed
+        assertThat(highLevelIntents,
+                hasIntentWithIdAndState("3", IntentState.INST_ACK));
+
+
+    }
+
+
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java b/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java
new file mode 100755
index 0000000..2505bb4
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java
@@ -0,0 +1,304 @@
+package net.onrc.onos.core.intent.runtime;
+
+import static org.easymock.EasyMock.*;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.onrc.onos.core.datagrid.IDatagridService;
+import net.onrc.onos.core.datagrid.IEventChannel;
+import net.onrc.onos.core.datagrid.IEventChannelListener;
+import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
+import net.onrc.onos.core.intent.FlowEntry;
+import net.onrc.onos.core.intent.Intent;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.MockNetworkGraph;
+import net.onrc.onos.core.intent.PathIntent;
+import net.onrc.onos.core.intent.PathIntentMap;
+import net.onrc.onos.core.intent.ShortestPathIntent;
+import net.onrc.onos.core.intent.Intent.IntentState;
+import net.onrc.onos.core.intent.IntentOperation.Operator;
+import net.onrc.onos.core.intent.runtime.IntentStateList;
+import net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule;
+import net.onrc.onos.core.intent.runtime.PersistIntent;
+import net.onrc.onos.core.intent.runtime.PlanCalcRuntime;
+import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphListener;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
+import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(PathCalcRuntimeModule.class)
+public class UseCaseTest {
+	private NetworkGraph g;
+	private FloodlightModuleContext modContext;
+	private IDatagridService datagridService;
+	private INetworkGraphService networkGraphService;
+	private IControllerRegistryService controllerRegistryService;
+	private PersistIntent persistIntent;
+	@SuppressWarnings("rawtypes")
+	private IEventChannel eventChannel;
+
+	private static Long LOCAL_PORT = 0xFFFEL;
+
+	@SuppressWarnings("unchecked")
+	@Before
+	public void setUp() throws Exception {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology1();
+		g = graph;
+
+		datagridService = createMock(IDatagridService.class);
+		networkGraphService = createMock(INetworkGraphService.class);
+		controllerRegistryService = createMock(IControllerRegistryService.class);
+		modContext = createMock(FloodlightModuleContext.class);
+		eventChannel = createMock(IEventChannel.class);
+		persistIntent = PowerMock.createMock(PersistIntent.class);
+
+		PowerMock.expectNew(PersistIntent.class,
+				anyObject(IControllerRegistryService.class),
+				anyObject(INetworkGraphService.class)).andReturn(persistIntent);
+
+		expect(modContext.getServiceImpl(IDatagridService.class))
+		.andReturn(datagridService).once();
+		expect(modContext.getServiceImpl(INetworkGraphService.class))
+		.andReturn(networkGraphService).once();
+		expect(modContext.getServiceImpl(IControllerRegistryService.class))
+		.andReturn(controllerRegistryService).once();
+		expect(persistIntent.getKey()).andReturn(1L).anyTimes();
+		expect(persistIntent.persistIfLeader(eq(1L),
+				anyObject(IntentOperationList.class))).andReturn(true).anyTimes();
+
+		expect(networkGraphService.getNetworkGraph()).andReturn(g).anyTimes();
+		networkGraphService.registerNetworkGraphListener(anyObject(INetworkGraphListener.class));
+		expectLastCall();
+
+		expect(datagridService.createChannel("onos.pathintent", Long.class, IntentOperationList.class))
+		.andReturn(eventChannel).once();
+
+		expect(datagridService.addListener(
+				eq("onos.pathintent_state"),
+				anyObject(IEventChannelListener.class),
+				eq(Long.class),
+				eq(IntentStateList.class)))
+		.andReturn(eventChannel).once();
+
+		replay(datagridService);
+		replay(networkGraphService);
+		replay(modContext);
+		replay(controllerRegistryService);
+		PowerMock.replay(persistIntent, PersistIntent.class);
+	}
+
+	@After
+	public void tearDown() {
+		verify(datagridService);
+		verify(networkGraphService);
+		verify(modContext);
+		verify(controllerRegistryService);
+		PowerMock.verify(persistIntent, PersistIntent.class);
+	}
+
+	private void showResult(PathIntentMap intents) {
+		for (Intent intent: intents.getAllIntents()) {
+			PathIntent pathIntent = (PathIntent)intent;
+			System.out.println("Path intent:" + pathIntent);
+			System.out.println("Parent intent: " + pathIntent.getParentIntent().toString());
+		}
+	}
+
+	@Test
+	public void createShortestPaths() throws FloodlightModuleException {
+		// create shortest path intents
+		IntentOperationList opList = new IntentOperationList();
+		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
+
+		// compile high-level intent operations into low-level intent operations (calculate paths)
+		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
+		runtime1.init(modContext);
+		runtime1.startUp(modContext);
+		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);
+
+		// compile low-level intents into flow entry installation plan
+		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
+		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);
+
+		// show results
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+	}
+
+	@Test
+	public void createConstrainedShortestPaths() throws FloodlightModuleException {
+		// create constrained shortest path intents
+		IntentOperationList opList = new IntentOperationList();
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));
+
+		// compile high-level intent operations into low-level intent operations (calculate paths)
+		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
+		runtime1.init(modContext);
+		runtime1.startUp(modContext);
+		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);
+
+		// compile low-level intents into flow entry installation plan
+		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
+		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);
+
+		// show results
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+	}
+
+	@Test
+	public void createMixedShortestPaths() throws FloodlightModuleException {
+		// create constrained & best effort shortest path intents
+		IntentOperationList opList = new IntentOperationList();
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
+		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));
+
+		// compile high-level intent operations into low-level intent operations (calculate paths)
+		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
+		runtime1.init(modContext);
+		runtime1.startUp(modContext);
+		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);
+
+		// compile low-level intents into flow entry installation plan
+		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
+		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);
+
+		// show results
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+	}
+
+	@Test
+	public void rerouteShortestPaths() throws FloodlightModuleException {
+		List<SwitchEvent> addedSwitchEvents = new LinkedList<>();
+		List<SwitchEvent> removedSwitchEvents = new LinkedList<>();
+		List<PortEvent> addedPortEvents = new LinkedList<>();
+		List<PortEvent> removedPortEvents = new LinkedList<>();
+		List<LinkEvent> addedLinkEvents = new LinkedList<>();
+		List<LinkEvent> removedLinkEvents = new LinkedList<>();
+		List<DeviceEvent> addedDeviceEvents = new LinkedList<>();
+		List<DeviceEvent> removedDeviceEvents = new LinkedList<>();
+
+		// create shortest path intents
+		IntentOperationList opList = new IntentOperationList();
+		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
+
+		// compile high-level intent operations into low-level intent operations (calculate paths)
+		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
+		runtime1.init(modContext);
+		runtime1.startUp(modContext);
+		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);
+
+		// compile low-level intents into flow entry installation plan
+		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
+		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);
+
+		// show results step1
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+
+		// TODO this state changes should be triggered by notification of plan module
+		IntentStateList states = new IntentStateList();
+		states.put("1", IntentState.INST_ACK);
+		states.put("2", IntentState.INST_ACK);
+		states.put("3", IntentState.INST_ACK);
+		runtime1.getHighLevelIntents().changeStates(states);
+		states.clear();
+		states.put("1___0", IntentState.INST_ACK);
+		states.put("2___0", IntentState.INST_ACK);
+		states.put("3___0", IntentState.INST_ACK);
+		runtime1.getPathIntents().changeStates(states);
+
+		// link down
+		((MockNetworkGraph)g).removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
+		((MockNetworkGraph)g).removeLink(2L, 21L, 1L, 12L);
+		LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
+		LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
+		removedLinkEvents.clear();
+		removedLinkEvents.add(linkEvent1);
+		removedLinkEvents.add(linkEvent2);
+		runtime1.networkGraphEvents(
+				addedSwitchEvents,
+				removedSwitchEvents,
+				addedPortEvents,
+				removedPortEvents,
+				addedLinkEvents,
+				removedLinkEvents,
+				addedDeviceEvents,
+				removedDeviceEvents);
+		System.out.println("Link goes down.");
+
+		// show results step2
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		// TODO: show results of plan computation
+	}
+
+
+	@Test
+	public void createAndRemoveShortestPaths() throws FloodlightModuleException {
+		// create shortest path intents
+		IntentOperationList opList = new IntentOperationList();
+		opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
+		opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
+
+		// compile high-level intent operations into low-level intent operations (calculate paths)
+		PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
+		runtime1.init(modContext);
+		runtime1.startUp(modContext);
+		IntentOperationList pathIntentOpList = runtime1.executeIntentOperations(opList);
+
+		// compile low-level intents into flow entry installation plan
+		PlanCalcRuntime runtime2 = new PlanCalcRuntime();
+		List<Set<FlowEntry>> plan = runtime2.computePlan(pathIntentOpList);
+
+		// show results
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+
+		// create remove operations
+		opList.clear();
+		opList.add(Operator.REMOVE, new Intent("1"));
+		opList.add(Operator.REMOVE, new Intent("2"));
+
+		// compile
+		runtime1.executeIntentOperations(opList);
+
+		// show results
+		showResult((PathIntentMap) runtime1.getPathIntents());
+		System.out.println(plan);
+	}
+
+}