Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS

Conflicts:
	src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
	src/main/java/net/onrc/onos/util/GraphDBConnection.java
	src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
index f8f50a3..5a9bce2 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
@@ -28,11 +28,21 @@
 	protected static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
 	protected GraphDBOperation dbop;
 
+	/**
+	 * Update a record in the LinkStorage in a way provided by op.
+	 * @param link Record of a link to be updated.
+	 * @param op Operation to be done.
+	 */
 	@Override
 	public void update(Link link, DM_OPERATION op) {
 		update(link, (LinkInfo)null, op);
 	}
 
+	/**
+	 * Update multiple records in the LinkStorage in a way provided by op.
+	 * @param links List of records to be updated.
+	 * @param op Operation to be done.
+	 */
 	@Override
 	public void update(List<Link> links, DM_OPERATION op) {
 		for (Link lt: links) {
@@ -40,6 +50,12 @@
 		}
 	}
 
+	/**
+	 * Update a record of link with meta-information in the LinkStorage in a way provided by op.
+	 * @param link Record of a link to update.
+	 * @param linkinfo Meta-information of a link to be updated.
+	 * @param op Operation to be done.
+	 */
 	@Override
 	public void update(Link link, LinkInfo linkinfo, DM_OPERATION op) {
 		switch (op) {
@@ -54,6 +70,12 @@
 		}
 	}
 	
+	/**
+	 * Perform INSERT/CREATE/UPDATE operation to update the LinkStorage.
+	 * @param lt Record of a link to be updated.
+	 * @param linkinfo Meta-information of a link to be updated.
+	 * @param op Operation to be done. (only INSERT/CREATE/UPDATE is acceptable)
+	 */
 	public void updateLink(Link lt, LinkInfo linkinfo, DM_OPERATION op) {
 		IPortObject vportSrc = null, vportDst = null;
 	
@@ -71,7 +93,6 @@
             vportDst = dbop.searchPort(dpid, port);
                         
             if (vportSrc != null && vportDst != null) {
-         	       	
             	// check if the link exists
             	
             	Iterable<IPortObject> currPorts = vportSrc.getLinkedPorts();
@@ -79,7 +100,7 @@
             	for (IPortObject V : currPorts) {
             		currLinks.add(V);
             	}
-            	
+
             	if (currLinks.contains(vportDst)) {
             		// TODO: update linkinfo
             		if (op.equals(DM_OPERATION.INSERT) || op.equals(DM_OPERATION.CREATE)) {
@@ -105,6 +126,10 @@
         }
 	}
 	
+	/**
+	 * Delete multiple records in the LinkStorage.
+	 * @param links List of records to be deleted.
+	 */
 	@Override
 	public void deleteLinks(List<Link> links) {
 
@@ -113,7 +138,10 @@
 		}
 	}
 	
-
+	/**
+	 * Delete a record in the LinkStorage.
+	 * @param link Record to be deleted.
+	 */
 	@Override
 	public void deleteLink(Link lt) {
 		IPortObject vportSrc = null, vportDst = null;
@@ -163,6 +191,12 @@
         }
 	}
 
+	/**
+	 * Get list of all links connected to the port specified by given DPID and port number.
+	 * @param dpid DPID of desired port.
+	 * @param port Port number of desired port.
+	 * @return List of links. Empty list if no port was found.
+	 */
 	// TODO: Fix me
 	@Override
 	public List<Link> getLinks(Long dpid, short port) {
@@ -172,34 +206,86 @@
     	
 		vportSrc = dbop.searchPort(HexString.toHexString(dpid), port);
 		if (vportSrc != null) {
-			
-     		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
-     			if (e.getLabel().equals("link")) {
-     				break;
-     			}
-     		}
+ 			
+			for (Edge e : vportSrc.asVertex().getEdges(Direction.IN)) {
+				if(e.getLabel().equals("link")) {
+					Vertex v = e.getVertex(Direction.OUT);
+					short dst_port = v.getProperty("number");
+					for(Edge e2 : v.getEdges(Direction.IN)) {
+						if(e2.getLabel().equals("on")) {
+							Vertex v2 = e2.getVertex(Direction.OUT);
+							long dst_dpid = HexString.toLong((String) v2.getProperty("dpid"));
+							
+			         		Link lt = new Link(dpid, port, dst_dpid, dst_port);
+			         		links.add(lt);
+						}
+					}
+				}
+			}
 		}
-     	return null;
+		// END: Trial code
+		
+     	return links;
 	}
 	
+	/**
+	 * Initialize the object. Open LinkStorage using given configuration file.
+	 * @param conf Path (absolute path for now) to configuration file.
+	 */
 	@Override
 	public void init(String conf) {
 		//TODO extract the DB location from properties
 		this.dbop = new GraphDBOperation(GraphDBConnection.getInstance(conf));
 	}
 
+	/**
+	 * Delete records of the links connected to the port specified by given DPID and port number.
+	 * @param dpid DPID of desired port.
+	 * @param port Port number of desired port.
+	 */
+	// TODO: Fix me
 	@Override
 	public void deleteLinksOnPort(Long dpid, short port) {
-		// TODO Auto-generated method stub
+		// BEGIN: Trial code
+		// author: Naoki Shiota
+		List<Link> linksToDelete = getLinks(dpid,port);
 		
+		for(Link l : linksToDelete) {
+			deleteLink(l);
+		}
+		// END: Trial code
 	}
 
+	/**
+	 * Get list of all links connected to the switch specified by given DPID.
+	 * @param dpid DPID of desired switch.
+	 * @return List of links. Empty list if no port was found.
+	 */
+	// TODO: Fix me
 	@Override
 	public List<Link> getLinks(String dpid) {
-		// TODO Auto-generated method stub
-		return null;
+		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
+		ISwitchObject vswitch;
+		List<Link> links = new ArrayList<Link>();
+
+		// BEGIN: Trial code
+		// author: Naoki Shiota
+		vswitch = conn.utils().searchSwitch(conn, dpid);
+
+		for(IPortObject vportSrc : vswitch.getPorts()) {
+			// array concatenation may be heavy...
+			List<Link> sublinks = getLinks(HexString.toLong(dpid), vportSrc.getNumber());
+			links.addAll(sublinks);
+		}
+		// END: Trial code
+
+		return links;
 	}
 
+	/**
+	 * Get list of all links whose state is ACTIVE.
+	 * @return List of active links. Empty list if no port was found.
+	 */
 	public List<Link> getActiveLinks() {
 		Iterable<ISwitchObject> switches = dbop.getActiveSwitches();
 
@@ -248,10 +334,16 @@
 		}
 	}
 	
+	/**
+	 * Finalize the object.
+	 */
 	public void finalize() {
 		close();
 	}
 
+	/**
+	 * Close LinkStorage.
+	 */
 	@Override
 	public void close() {
 		// TODO Auto-generated method stub
diff --git a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
index 3d5e03b..431db71 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
@@ -5,18 +5,25 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import junit.framework.Assert;
 
+import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
+
 import org.apache.commons.io.FileUtils;
 
 import com.thinkaurelius.titan.core.TitanFactory;
 import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Edge;
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
 import com.tinkerpop.blueprints.Vertex;
 import com.tinkerpop.blueprints.util.io.graphml.GraphMLReader;
+import com.tinkerpop.frames.FramedGraph;
 
 public class TestDatabaseManager {
 	private static final String testDbLocation = "/tmp/onos-testdb";
@@ -58,9 +65,20 @@
         Iterator<Vertex> it = titanGraph.getVertices("type", "port").iterator();
         while (it.hasNext()){
         	Vertex port = it.next();
-        	Integer portNum = (Integer) port.getProperty("number");
-        	port.setProperty("number", portNum.shortValue());
+        	if(port.getProperty("number").getClass() == Integer.class) {
+        		Integer portNum = port.getProperty("number");
+            	port.setProperty("number", portNum.shortValue());
+        	}
         }
+        
+		FramedGraph<TitanGraph> fg = new FramedGraph<TitanGraph>(titanGraph);
+		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
+		List<ISwitchObject> activeSwitches = new ArrayList<ISwitchObject>();
+
+		for (ISwitchObject sw: switches) {
+			sw.setState(SwitchState.ACTIVE.toString());
+		}
+
         titanGraph.stopTransaction(Conclusion.SUCCESS);
 	}
 	
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
index 6e99acd..0bf9ba0 100644
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
+++ b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
@@ -50,6 +50,8 @@
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.topology.TopologyManager;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
+import net.onrc.onos.registry.controller.StandaloneRegistry;
 
 /**
  *
@@ -58,6 +60,7 @@
 public class LinkDiscoveryManagerTest extends FloodlightTestCase {
 
     private TestLinkDiscoveryManager ldm;
+    private StandaloneRegistry srs;
     protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManagerTest.class);
     
     public class TestLinkDiscoveryManager extends LinkDiscoveryManager {
@@ -99,6 +102,7 @@
         ldm = new TestLinkDiscoveryManager();
         TopologyManager routingEngine = new TopologyManager();
         ldm.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
+        srs = new StandaloneRegistry();
         MockThreadPoolService tp = new MockThreadPoolService();
         RestApiServer restApi = new RestApiServer();
         cntx.addService(IRestApiService.class, restApi);
@@ -108,13 +112,17 @@
         cntx.addService(ITopologyService.class, ldm);
         cntx.addService(IStorageSourceService.class, new MemoryStorageSource());
         cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
+        cntx.addService(IControllerRegistryService.class, srs);
+
         restApi.init(cntx);
         tp.init(cntx);
         routingEngine.init(cntx);
+        srs.init(cntx);
         ldm.init(cntx);
         restApi.startUp(cntx);
         tp.startUp(cntx);
         routingEngine.startUp(cntx);
+        srs.startUp(cntx);
         ldm.startUp(cntx);
 
         IOFSwitch sw1 = createMockSwitch(1L);
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
index 857d091..fd1d7d0 100644
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
+++ b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
@@ -4,126 +4,637 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+
+import junit.framework.Assert;
 
 import net.floodlightcontroller.core.internal.TestDatabaseManager;
+import net.floodlightcontroller.linkdiscovery.ILinkStorage;
+import net.floodlightcontroller.linkdiscovery.LinkInfo;
 import net.floodlightcontroller.routing.Link;
 import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
 import net.onrc.onos.ofcontroller.linkdiscovery.ILinkStorage;
 
+import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.openflow.util.HexString;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
+import com.thinkaurelius.titan.core.TitanFactory;
 import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
 import com.tinkerpop.blueprints.Vertex;
 import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.PipeFunction;
+import com.tinkerpop.pipes.transform.PathPipe;
 
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class})
 public class LinkStorageImplTest {
 	private static ILinkStorage linkStorage;
 	private static TitanGraph titanGraph;
 	
-	//TODO Future ideas:
-	//Test add links with CREATE and UPDATE
-	//Test adding existing link again
-	
+	//private static IController
+
+	/**
+	 * Setup code called before each tests.
+	 * Read test graph data and replace DB access by test graph data.
+	 * @throws Exception
+	 */
 	@Before
 	public void setUp() throws Exception{
+		TestDatabaseManager.deleteTestDatabase();
+
 		titanGraph = TestDatabaseManager.getTestDatabase();
 		TestDatabaseManager.populateTestData(titanGraph);
+
+		// replace return value of TitanFactory.open() to dummy DB created above
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
 		
-		linkStorage = new TestableLinkStorageImpl(titanGraph);
+		linkStorage = new LinkStorageImpl();
+		
+		// initialize with dummy string
+		linkStorage.init("/dummy/path/to/db");
 	}
 	
+	/**
+	 * Closing code called after each tests.
+	 * Discard test graph data.
+	 * @throws Exception
+	 */
 	@After
-	public void tearDown() throws Exception {		
+	public void tearDown() throws Exception {
+		// finish code
+		linkStorage.close();
+		
 		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
 	}
 	
-	/*
-	 * Add a link between port 1.102 and 2.104
-	 * i.e SEA switch port 3 to LAX switch port 1
+	// TODO: remove @Ignore after UPDATE method is implemented
+	/**
+	 * Test if update() can correctly updates LinkInfo for a Link.
+	 */
+	@Ignore @Test
+	public void testUpdate_UpdateSingleLink() {
+		Link linkToUpdate= createExistingLink();
+		long currentTime = System.currentTimeMillis();
+		LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
+		LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
+
+		linkStorage.update(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
+		
+		doTestLinkHasStateOf(linkToUpdate, infoToVerify);
+	}
+	
+	/**
+	 * Test if update() can correctly creates a Link.
 	 */
 	@Test
-	public void testAddSingleLink(){
-		Link linkToAdd = new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a02"), 1);
+	public void testUpdate_CreateSingleLink() {
+		Link linkToCreate = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
 		
 		//Use the link storage API to add the link
-		linkStorage.update(linkToAdd, ILinkStorage.DM_OPERATION.INSERT);
+		linkStorage.update(linkToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		doTestLinkIsInGraph(linkToVerify);
+
+		// Add same link
+		Link linkToCreateTwice = createFeasibleLink();
+		linkStorage.update(linkToCreateTwice, ILinkStorage.DM_OPERATION.CREATE);
 		
-		//Test if it was added correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
+		// this occurs assertion failure if there are two links in titanGraph
+		doTestLinkIsInGraph(linkToVerify);
+	}
+
+	/**
+	 * Test if update() can correctly inserts a Link.
+	 */
+	@Test
+	public void testUpdate_InsertSingleLink(){
+		Link linkToInsert = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
 		
-		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
-		assertFalse(it.hasNext());
+		//Use the link storage API to add the link
+		linkStorage.update(linkToInsert, ILinkStorage.DM_OPERATION.INSERT);
+
+		doTestLinkIsInGraph(linkToVerify);
 		
-		pipe.start(sw1).out("on").has("number", (short)3).out("link").in("on");
-		
-		assertTrue(pipe.hasNext());
-		Vertex sw2 = pipe.next();
-		assertFalse(pipe.hasNext());
-		
-		//Check we ended up at the right vertex
-		assertEquals((String)sw2.getProperty("dpid"), "00:00:00:00:00:00:0a:02");
+		// Add same link
+		Link linkToInsertTwice = createFeasibleLink();
+		linkStorage.update(linkToInsertTwice, ILinkStorage.DM_OPERATION.INSERT);
+
+		// this occurs assertion failure if there are two links in titanGraph
+		doTestLinkIsInGraph(linkToVerify);
 	}
 	
-	//TODO enable once method is written
+	/**
+	 * Test if update() can correctly deletes a Link.
+	 */
+	@Test
+	public void testUpdate_DeleteSingleLink(){
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+
+		// Test deletion of existing link
+		linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
+		doTestLinkIsNotInGraph(linkToVerify);
+		
+		linkToDelete = createFeasibleLink();
+		linkToVerify = createFeasibleLink();
+
+		// Test deletion of not-existing link
+		linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
+		doTestLinkIsNotInGraph(linkToVerify);
+	}
+
+	/**
+	 * Test if update() can correctly creates multiple Links.
+	 */
+	@Test
+	public void testUpdate_CreateLinks(){
+		List<Link> linksToCreate = createFeasibleLinks();
+		List<Link> linksToVerify = createFeasibleLinks();
+
+		// Test creation of new links
+		linkStorage.update(linksToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		for(Link l : linksToVerify) {
+			doTestLinkIsInGraph(l);
+		}
+		
+		// Test creation of existing links
+		linksToCreate = createFeasibleLinks();
+		linkStorage.update(linksToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		for(Link l : linksToVerify) {
+			doTestLinkIsInGraph(l);
+		}
+	}
+	
+	/**
+	 * Test if update() can handle mixture of normal/abnormal input for creation of Links.
+	 */
+	@Test
+	public void testUpdate_CreateLinks_Mixuture(){
+		List<Link> linksToCreate = new ArrayList<Link>();
+		linksToCreate.add(createFeasibleLink());
+		linksToCreate.add(createExistingLink());
+		
+		// Test creation of mixture of new/existing links
+		linkStorage.update(linksToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		doTestLinkIsInGraph(createFeasibleLink());
+		doTestLinkIsInGraph(createExistingLink());
+	}
+
+	/**
+	 * Test if update() can correctly inserts multiple Links.
+	 */
+	@Test
+	public void testUpdate_InsertLinks(){
+		List<Link> linksToInsert = createFeasibleLinks();
+		List<Link> linksToVerify = createFeasibleLinks();
+		
+		// Test insertion of new links
+		linkStorage.update(linksToInsert, ILinkStorage.DM_OPERATION.INSERT);
+		for(Link l : linksToVerify) {
+			doTestLinkIsInGraph(l);
+		}
+		
+		// Test insertion of existing links
+		linksToInsert = createFeasibleLinks();
+		linkStorage.update(linksToInsert, ILinkStorage.DM_OPERATION.INSERT);
+		for(Link l : linksToVerify) {
+			doTestLinkIsInGraph(l);
+		}
+	}
+	
+	/**
+	 * Test if update() can handle mixture of normal/abnormal input for creation of Links.
+	 */
+	@Test
+	public void testUpdate_InsertLinks_Mixuture(){
+		List<Link> linksToInsert = new ArrayList<Link>();
+		linksToInsert.add(createFeasibleLink());
+		linksToInsert.add(createExistingLink());
+		
+		// Test insertion of mixture of new/existing links
+		linkStorage.update(linksToInsert, ILinkStorage.DM_OPERATION.INSERT);
+		doTestLinkIsInGraph(createFeasibleLink());
+		doTestLinkIsInGraph(createExistingLink());
+	}
+
+	/**
+	 * Test if update() can correctly deletes multiple Links.
+	 */
+	@Test
+	public void testUpdate_DeleteLinks(){
+		List<Link> linksToDelete = createExistingLinks();
+		List<Link> linksToVerify = createExistingLinks();
+		
+		// Test deletion of existing links
+		linkStorage.update(linksToDelete, ILinkStorage.DM_OPERATION.DELETE);
+		for(Link l : linksToVerify) {
+			doTestLinkIsNotInGraph(l);
+		}
+		
+		// Test deletion of not-existing links
+		linksToDelete = createExistingLinks();
+		linkStorage.update(linksToDelete, ILinkStorage.DM_OPERATION.DELETE);
+		for(Link l : linksToVerify) {
+			doTestLinkIsNotInGraph(l);
+		}
+	}
+	
+	/**
+	 * Test if update() can handle mixture of normal/abnormal input for deletion of Links.
+	 */
+	@Test
+	public void testUpdate_DeleteLinks_Mixuture(){
+		List<Link> linksToDelete = new ArrayList<Link>();
+		linksToDelete.add(createFeasibleLink());
+		linksToDelete.add(createExistingLink());
+		
+		// Test deletion of mixture of new/existing links
+		linkStorage.update(linksToDelete, ILinkStorage.DM_OPERATION.DELETE);
+		doTestLinkIsNotInGraph(createFeasibleLink());
+		doTestLinkIsNotInGraph(createExistingLink());
+	}
+	
+	// TODO: remove @Ignore after UPDATE method is implemented
+	/**
+	 * Test if updateLink() can correctly updates LinkInfo for a Link.
+	 */
 	@Ignore @Test
-	public void testGetLinks(){
-		//TODO Make sure this works when the implementation is written
-		List<Link> list = linkStorage.getLinks(Long.decode("0x0000000000000a01"), (short)2);
+	public void testUpdateLink_Update() {
+		Link linkToUpdate= createExistingLink();
+		long currentTime = System.currentTimeMillis();
+		LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
+		LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
+
+		linkStorage.updateLink(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
+		
+		doTestLinkHasStateOf(linkToUpdate, infoToVerify);
+	}
+	
+	/**
+	 * Test if updateLink() can correctly creates a Link.
+	 */
+	@Test
+	public void testUpdateLink_Create() {
+		Link linkToCreate = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.updateLink(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
+		doTestLinkIsInGraph(linkToVerify);
+
+		// Add same link
+		Link linkToCreateTwice = createFeasibleLink();
+		linkStorage.updateLink(linkToCreateTwice, null, ILinkStorage.DM_OPERATION.CREATE);
+		
+		// this occurs assertion failure if there are two links in titanGraph
+		doTestLinkIsInGraph(linkToVerify);
+	}
+	
+	/**
+	 * Test if updateLink() can correctly inserts a Link.
+	 */
+	@Test
+	public void testUpdateLink_Insert() {
+		Link linkToInsert = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.updateLink(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
+
+		doTestLinkIsInGraph(linkToVerify);
+		
+		// Add same link
+		Link linkToInsertTwice = createFeasibleLink();
+		linkStorage.updateLink(linkToInsertTwice, null, ILinkStorage.DM_OPERATION.INSERT);
+
+		// this occurs assertion failure if there are two links in titanGraph
+		doTestLinkIsInGraph(linkToVerify);
+	}
+	
+	// TODO: Check if addOrUpdateLink() should accept DELETE operation. If not, remove this test.
+	/**
+	 * Test if updateLink() can correctly deletes a Link.
+	 */
+	@Ignore @Test
+	public void testUpdateLink_Delete() {
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+
+		// Test deletion of existing link
+		linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
+		doTestLinkIsNotInGraph(linkToVerify);
+		
+		linkToDelete = createFeasibleLink();
+		linkToVerify = createFeasibleLink();
+
+		// Test deletion of not-existing link
+		linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
+		doTestLinkIsNotInGraph(linkToVerify);
+	}
+	
+	/**
+	 * Test if getLinks() can correctly return Links connected to specific DPID and port.
+	 */
+	@Test
+	public void testGetLinks_ByDpidPort(){
+		Link linkToVerify = createExistingLink();
+		Long dpid = linkToVerify.getSrc();
+		short port = (short)linkToVerify.getSrcPort();
+		
+		List<Link> list = linkStorage.getLinks(dpid, port);
 		
 		assertEquals(list.size(), 1);
 		
 		Link l = list.get(0);
-		assertEquals(l.getSrc(), 2561L);
-		assertEquals(l.getSrcPort(), (short)2);
-		assertEquals(l.getDst(), 2563L);
-		assertEquals(l.getDstPort(), (short)1);
+		assertEquals(l.getSrc(), linkToVerify.getSrc());
+		assertEquals(l.getSrcPort(), linkToVerify.getSrcPort());
+		assertEquals(l.getDst(), linkToVerify.getDst());
+		assertEquals(l.getDstPort(), linkToVerify.getDstPort());
+		
+		Link linkToVerifyNot = createFeasibleLink();
+		
+		List<Link> list2 = linkStorage.getLinks(linkToVerifyNot.getSrc(), (short)linkToVerifyNot.getSrcPort());
+		
+		assertEquals(list2.size(), 0);
 	}
 	
-	//TODO enable once method is written
-	@Ignore @Test
-	public void testUpdateDelete(){
-		Link linkToDelete = new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a03"), 1);
+	/**
+	 * Test if getLinks() can correctly return Links connected to specific MAC address.
+	 */
+	@Test
+	public void testGetLinks_ByString() {
+		Link linkToVeryfy = createExistingLink();
+		String dpid = HexString.toHexString(linkToVeryfy.getSrc());
 		
-		linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
-		
-		//Test if it was deleted correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
-		
-		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
-		assertFalse(it.hasNext());
-		
-		pipe.start(sw1).out("on").has("number", 2).out("link");
-		
-		assertFalse(pipe.hasNext());
+		List<Link> links = linkStorage.getLinks(dpid);
+		assertTrue(links.contains(linkToVeryfy));
+
+		Link linkToVerifyNot = createFeasibleLink();
+		assertFalse(links.contains(linkToVerifyNot));
 	}
 	
-	//TODO enable once method is written
-	@Ignore @Test
+	/**
+	 * Test if deleteLink() can correctly delete a Link.
+	 */
+	@Test
+	public void testDeleteLink() {
+		// Deletion of existing link
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+		
+		linkStorage.deleteLink(linkToDelete);
+		doTestLinkIsNotInGraph(linkToVerify);
+		
+		// Deletion of not existing link
+		linkToDelete = createFeasibleLink();
+		linkToVerify = createFeasibleLink();
+		
+		linkStorage.deleteLink(linkToDelete);
+		doTestLinkIsNotInGraph(linkToVerify);
+	}
+	
+	/**
+	 * Test if deleteLinks() can correctly delete Links.
+	 */
+	@Test
 	public void testDeleteLinks(){
-		//TODO Make sure this works when the implementation is written
+		List<Link> linksToDelete = createExistingLinks();
+		List<Link> linksToVerify = createExistingLinks();
 		
-		linkStorage.deleteLinksOnPort(Long.decode("0x0000000000000a01"), (short)2);
+		linkStorage.deleteLinks(linksToDelete);
+		for(Link l : linksToVerify) {
+			doTestLinkIsNotInGraph(l);
+		}
+	}
+	
+	/**
+	 * Test if deleteLinks() can handle mixture of normal/abnormal input.
+	 */
+	@Test
+	public void testDeleteLinks_Mixture(){
+		List<Link> linksToDelete = new ArrayList<Link>();
+		linksToDelete.add(createFeasibleLink());
+		linksToDelete.add(createExistingLink());
 		
-		//Test if it was deleted correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
+		// Test deletion of mixture of new/existing links
+		linkStorage.deleteLinks(linksToDelete);
+		doTestLinkIsNotInGraph(createFeasibleLink());
+		doTestLinkIsNotInGraph(createExistingLink());
+	}
+
+	/**
+	 * Test if getActiveLinks() can correctly return active Links.
+	 */
+	@Test
+	public void testGetActiveLinks() {
+		Link existingLink = createExistingLink();
+		Link notExistingLink = createFeasibleLink();
+
+		List<Link> links = linkStorage.getActiveLinks();
 		
+		assertTrue(links.contains(existingLink));
+		assertFalse(links.contains(notExistingLink));
+	}
+	
+	/**
+	 * Test if deleteLinksOnPort() can delete Links.
+	 */
+	@Test
+	public void testDeleteLinksOnPort() {
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+		
+		linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
+		
+		doTestLinkIsNotInGraph(linkToVerify);
+	}
+
+	/**
+	 * Test if titanGraph has specific link
+	 * @param link 
+	 */
+	private void doTestLinkIsInGraph(Link link) {
+		String src_dpid = HexString.toHexString(link.getSrc());
+		String dst_dpid = HexString.toHexString(link.getDst());
+		short src_port = link.getSrcPort();
+		short dst_port = link.getDstPort();
+		
+		Iterator<Vertex> it = titanGraph.getVertices("dpid", src_dpid).iterator();
+		
+		// Test if just one switch is found in the graph
 		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
+		Vertex sw = it.next();
 		assertFalse(it.hasNext());
 		
-		pipe.start(sw1).out("on").has("number", 2).out("link");
+		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
+		pipe.start(sw).out("on").has("number", src_port).out("link").has("number", dst_port).in("on").has("dpid", dst_dpid);
 		
+		// Test if just one link is found in the graph
+		assertTrue(pipe.hasNext());
+		pipe.next();
 		assertFalse(pipe.hasNext());
 	}
 	
+	/**
+	 * Test if titanGraph doesn't have specific link
+	 * @param link
+	 */
+	private void doTestLinkIsNotInGraph(Link link) {
+		String src_dpid = HexString.toHexString(link.getSrc());
+		String dst_dpid = HexString.toHexString(link.getDst());
+		short src_port = link.getSrcPort();
+		short dst_port = link.getDstPort();
+		
+		Iterator<Vertex> it = titanGraph.getVertices("dpid", src_dpid).iterator();
+		
+		// Test if just one switch is found in the graph
+		assertTrue(it.hasNext());
+		Vertex sw = it.next();
+		assertFalse(it.hasNext());
+		
+		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
+		pipe.start(sw).out("on").has("number", src_port).out("link").has("number", dst_port).in("on").has("dpid", dst_dpid);
+		
+		// Test if no link is found in the graph
+		assertFalse(pipe.hasNext());
+	}
+	
+	/**
+	 * Test if titanGraph has specific Link with specific LinkInfo
+	 * @param link 
+	 */
+	private void doTestLinkHasStateOf(Link link, LinkInfo info) {
+		String src_dpid = HexString.toHexString(link.getSrc());
+		String dst_dpid = HexString.toHexString(link.getDst());
+		short src_port = link.getSrcPort();
+		short dst_port = link.getDstPort();
+		
+		Iterator<Vertex> it = titanGraph.getVertices("dpid", src_dpid).iterator();
+		
+		// Test if just one switch is found in the graph
+		assertTrue(it.hasNext());
+		Vertex sw = it.next();
+		assertFalse(it.hasNext());
+		
+		GremlinPipeline<Vertex, Edge> pipe = new GremlinPipeline<Vertex, Edge>();
+		pipe.start(sw);
+		pipe.enablePath();
+		pipe.out("on").has("number", src_port).out("link").has("number", dst_port).in("on").has("dpid", dst_dpid)
+			.path().step(new PipeFunction<PathPipe<Vertex>, Edge>() {
+			@Override
+			public Edge compute(PathPipe<Vertex> pipepath) {
+				List<Vertex> V = pipepath.next();
+
+				Vertex port_src = V.get(1);
+				Vertex port_dst = V.get(2);
+				
+				for(Edge e : port_src.getEdges(Direction.OUT)) {
+					if(e.getVertex(Direction.IN).equals(port_dst)) {
+						return e;
+					}
+				}
+				
+				return null;
+			}
+		});
+		
+		// Test if just one link is found in the graph
+		assertTrue(pipe.hasNext());
+		Edge edge = pipe.next();
+		assertTrue(edge != null);
+		assertFalse(pipe.hasNext());
+
+		// TODO: implement test code to check if update is correctly done.
+		assertTrue(false);
+	}
+
+
+	//----------------- Creation of test data -----------------------
+	/**
+	 * Returns new Link object which has information of existing link in titanGraph
+	 * @return new Link object
+	 */
+	private Link createExistingLink() {
+		// Link from SEA switch port 2 to CHI switch port 1
+		return new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a03"), 1);
+	}
+	
+	/**
+	 * Returns new Link object which has information of not-existing but feasible link in titanGraph
+	 * @return new Link object
+	 */
+	private Link createFeasibleLink() {
+		// Link from SEA switch port 1 to LAX switch port 1
+		return new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a02"), 1);
+	}
+	
+	// make NO sense while test-network data doesn't define physical network (i.e. any link is feasible)
+	@SuppressWarnings("unused")
+	private Link createInfeasibleLink() {
+		return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
+	}
+
+	/**
+	 * Returns list of Link objects which all has information of existing link in titanGraph
+	 * @return ArrayList of new Link objects
+	 */
+	private List<Link> createExistingLinks() {
+		List<Link> links = new ArrayList<Link>();
+		// Link from SEA switch port 2 to CHI switch port 1
+		links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a03"), 1));
+		// Link from LAX switch port 1 to SEA switch port 3
+		links.add(new Link(Long.decode("0x0000000000000a02"), 1, Long.decode("0x0000000000000a01"), 3));
+		return links;
+	}
+	
+	/**
+	 * Returns list of Link objects which all has information of not-existing but feasible link
+	 * @return ArrayList of new Link objects
+	 */
+	private List<Link> createFeasibleLinks() {
+		List<Link> links = new ArrayList<Link>();
+		// Link from CHI switch port 4 to NYC switch port 3
+		links.add(new Link(Long.decode("0x0000000000000a03"), 4, Long.decode("0x0000000000000a05"), 3));
+		// Link from SEA switch port 4 to LAX switch port 1
+		links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a02"), 1));
+		return links;
+	}
+	
+	/**
+	 * Returns new LinkInfo object with convenient values.
+	 * @return LinkInfo object
+	 */
+	private LinkInfo createFeasibleLinkInfo(long time) {
+		long time_first = time;
+		long time_last_lldp = time + 50;
+		long time_last_bddp = time + 100;
+		int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
+		int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
+
+		return new LinkInfo(time_first,
+				time_last_lldp,
+				time_last_bddp,
+				state_src,
+				state_dst);
+	}
+	//---------------------------------------------------------------
 }