blob: 0968fefae5435da11666b5ad9c5e273dfdbe867e [file] [log] [blame]
package net.floodlightcontroller.linkdiscovery.internal;
import static org.junit.Assert.assertEquals;
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 net.floodlightcontroller.core.internal.TestDatabaseManager;
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.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;
//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 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 {
// finish code
linkStorage.close();
titanGraph.shutdown();
TestDatabaseManager.deleteTestDatabase();
}
// 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 testUpdate_CreateSingleLink() {
Link linkToCreate = createFeasibleLink();
Link linkToVerify = createFeasibleLink();
//Use the link storage API to add the link
linkStorage.update(linkToCreate, ILinkStorage.DM_OPERATION.CREATE);
doTestLinkIsInGraph(linkToVerify);
// Add same link
Link linkToCreateTwice = createFeasibleLink();
linkStorage.update(linkToCreateTwice, ILinkStorage.DM_OPERATION.CREATE);
// 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();
//Use the link storage API to add the link
linkStorage.update(linkToInsert, ILinkStorage.DM_OPERATION.INSERT);
doTestLinkIsInGraph(linkToVerify);
// 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);
}
/**
* 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 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(), 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);
}
/**
* 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());
List<Link> links = linkStorage.getLinks(dpid);
assertTrue(links.contains(linkToVeryfy));
Link linkToVerifyNot = createFeasibleLink();
assertFalse(links.contains(linkToVerifyNot));
}
/**
* 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(){
List<Link> linksToDelete = createExistingLinks();
List<Link> linksToVerify = createExistingLinks();
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 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 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 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);
}
//---------------------------------------------------------------
}