package net.onrc.onos.ofcontroller.core.internal;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.floodlightcontroller.routing.Link;
import net.onrc.onos.graph.GraphDBConnection;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.ofcontroller.core.ILinkStorage;
import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;

import org.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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Unit test for {@link LinkStorageImpl}.
 * @author Naoki Shiota
 *
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({LinkStorageImpl.class, GraphDBConnection.class, GraphDBOperation.class})
@SuppressWarnings("serial")
public class LinkStorageImplTest {
	protected final static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);

	private static ILinkStorage linkStorage;
	
	// Mock GraphDBConnection (do nothing)
	private static GraphDBConnection conn;
	
	// Mock GraphDBOperation (mocks port-related methods only)
	private static GraphDBOperation ope;
	
	// Uncommitted actions executed in LinkStorageImpl
	private static ArrayList<LinkEvent> actions;
	
	// Dictionary of mock IPortObject to information of port
	// -> Used to refer DPID from IPortObject
	private static Map<IPortObject,PortInfo> mockToPortInfoMap;
	
	
	// Links existing in virtual graph
	private List<Link> links;
	
	//================ Utility classes for logging actions in LinkStorageImpl ===========
	private enum LinkEventType {
		ADD, DELETE
	}
	
	private class LinkEvent {
		private Long src_dpid = null;
		private Long dst_dpid = null;
		private Short src_port = null;
		private Short dst_port = null;
		
		public LinkEventType type;
		
		public LinkEvent(Link link, LinkEventType type) {
			this.src_dpid = link.getSrc();
			this.src_port = link.getSrcPort();
			this.dst_dpid = link.getDst();
			this.dst_port = link.getDstPort();
			
			this.type = type;
		}

		public Long getSrcDpid() { return src_dpid; }
		public Short getSrcPort() { return src_port; }
		public Long getDstDpid() { return dst_dpid; }
		public Short getDstPort() { return dst_port; }
		public LinkEventType getType() { return type; }
	}
	
	private class PortInfo {
		public Long dpid = null;
		public Short port = null;
		
		public PortInfo(Long dpid, Short port) { this.dpid = dpid; this.port = port; }
	}

	/**
	 * 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{
		// Create mock GraphDBConnection (replace Singleton object to mock one)
		PowerMock.mockStatic(GraphDBConnection.class);
		PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
		conn = PowerMock.createMock(GraphDBConnection.class);
		EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(conn).anyTimes();
		PowerMock.replay(GraphDBConnection.class);
		
		// Create mock GraphDBOperation
		ope = createMockGraphDBOperation();
		PowerMock.expectNew(GraphDBOperation.class, new Class<?>[] {GraphDBConnection.class}, EasyMock.anyObject(GraphDBConnection.class)).andReturn(ope).anyTimes();
		PowerMock.replay(GraphDBOperation.class);
		
		actions = new ArrayList<LinkEvent>();
		mockToPortInfoMap = new HashMap<IPortObject,PortInfo>();
		
		linkStorage = new LinkStorageImpl();
		linkStorage.init("dummyStore", "/dummy/path/to/conf");
		
		initLinks();
	}
	
	/**
	 * Closing code called after each tests.
	 * @throws Exception
	 */
	@After
	public void tearDown() throws Exception {
		linkStorage.close();
	}
	

	/**
	 * Test if {@link LinkStorageImpl#addLink(Link)} can correctly creates a Link.
	 */
	@Test
	public void testAddLink() {
		Link linkToCreate = createFeasibleLink();
		Link linkToVerify = createFeasibleLink();
		
		//Use the link storage API to add the link
		linkStorage.addLink(linkToCreate);
		doTestLinkExist(linkToVerify);
	}
	
	/**
	 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly creates multiple Links.
	 */
	@Test
	public void testAddLinks() {
		List<Link> linksToCreate = createFeasibleLinks();
		List<Link> linksToVerify = createFeasibleLinks();
	
		// Test creation of new links
		linkStorage.addLinks(linksToCreate);
		for(Link l : linksToVerify) {
			doTestLinkExist(l);
		}
	}

	// TODO: remove @Ignore after UPDATE method is implemented
	/**
	 * Test if {@link LinkStorageImpl#updateLinkInfo(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
	 */
	@Ignore @Test
	public void testUpdate_Update() {
		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 {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly creates a Link.
	 */
	@Test
	public void testUpdate_Create() {
		Link linkToCreate = createFeasibleLink();
		Link linkToVerify = createFeasibleLink();
		
		//Use the link storage API to add the link
		linkStorage.update(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
		doTestLinkExist(linkToVerify);
	}

	/**
	 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)}can correctly inserts a Link.
	 */
	@Test
	public void testUpdate_Insert(){
		Link linkToInsert = createFeasibleLink();
		Link linkToVerify = createFeasibleLink();
		
		//Use the link storage API to add the link
		linkStorage.update(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
		doTestLinkExist(linkToVerify);
	}
	
	/**
	 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly deletes a Link.
	 */
	@Test
	public void testUpdate_Delete(){
		Link linkToDelete = createExistingLink();
		Link linkToVerify = createExistingLink();

		// Test deletion of existing link
		linkStorage.update(linkToDelete, null, DM_OPERATION.DELETE);
		doTestLinkNotExist(linkToVerify);
	}

	/**
	 * Test if {@link LinkStorageImpl#getLinks(Long, short)} 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(1, list.size());
		
		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(0, list2.size());
	}
	
	/**
	 * Test if {@link LinkStorageImpl#getLinks(String)} 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 {@link LinkStorageImpl#getReverseLinks(String)} can correctly return Links connected to specific MAC address.
	 */
	@Test
	public void testGetReverseLinks_ByString() {
		Link linkToVeryfy = createExistingLink();
		String dpid = HexString.toHexString(linkToVeryfy.getDst());
		
		List<Link> links = linkStorage.getReverseLinks(dpid);
		assertTrue(links.contains(linkToVeryfy));

		Link linkToVerifyNot = createFeasibleLink();
		assertFalse(links.contains(linkToVerifyNot));
	}
	
	/**
	 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
	 */
	@Test
	public void testDeleteLink() {
		// Deletion of existing link
		Link linkToDelete = createExistingLink();
		Link linkToVerify = createExistingLink();
		
		linkStorage.deleteLink(linkToDelete);
		doTestLinkNotExist(linkToVerify);
	}
	
	/**
	 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
	 */
	@Test
	public void testDeleteLinks(){
		List<Link> linksToDelete = createExistingLinks();
		List<Link> linksToVerify = createExistingLinks();
		
		linkStorage.deleteLinks(linksToDelete);
		for(Link l : linksToVerify) {
			doTestLinkNotExist(l);
		}
	}

	/**
	 * Test if {@link LinkStorageImpl#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 {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
	 */
	@Test
	public void testDeleteLinksOnPort() {
		Link linkToDelete = createExistingLink();
		Link linkToVerify = createExistingLink();
		
		linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
		
		doTestLinkNotExist(linkToVerify);
	}
	
	/**
	 * Test if {@link LinkStorageImpl#getLinkInfo(Link)} can delete Links.
	 */
	@Ignore @Test
	public void testGetLinkInfo() {
		fail("not yet implemented");
	}

	/**
	 * Test if specific link exists
	 * @param link 
	 */
	private void doTestLinkExist(Link link) {
		int count = 0;
		for(Link lt : links) {
			if(lt.equals(link)) {
				++count;
			}
		}
		
		assertTrue(count == 1);
	}
	
	/**
	 * Test if specific link doesn't exist
	 * @param link
	 */
	private void doTestLinkNotExist(Link link) {
		assertFalse(links.contains(link));
	}
	
	/**
	 * Test if titanGraph has specific Link with specific LinkInfo
	 * @param link 
	 */
	// TODO: Fix me
	private void doTestLinkHasStateOf(Link link, LinkInfo info) {
	}
	
	/**
	 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
	 * @author Naoki Shiota
	 *
	 */
	private class RemoveLinkCallback implements IAnswer<Object> {
		private long dpid;
		private short port;
		public RemoveLinkCallback(long dpid, short port) {
			this.dpid = dpid; this.port = port;
		}
		
		@Override
		public Object answer() throws Throwable {
			IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
			PortInfo dst = mockToPortInfoMap.get(dstPort);

			Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
			actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
			
			return null;
		}
	}
	
	/**
	 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
	 * @author Naoki Shiota
	 */
	private class SetLinkPortCallback implements IAnswer<Object> {
		private long dpid;
		private short port;
		public SetLinkPortCallback(long dpid, short port) {
			this.dpid = dpid; this.port = port;
		}

		@Override
		public Object answer() throws Throwable {
			IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
			PortInfo dst = mockToPortInfoMap.get(dstPort);

			Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
			actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));

			return null;
		}
		
	}
	
	/**
	 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
	 * @author Naoki Shiota
	 *
	 */
	private class GetSwitchCallback implements IAnswer<ISwitchObject> {
		private long dpid;
		
		public GetSwitchCallback(long dpid) {
			this.dpid = dpid;
		}

		@Override
		public ISwitchObject answer() throws Throwable {
			ISwitchObject sw = createMockSwitch(dpid);
			return sw;
		}
	}
	
	/**
	 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
	 * @author Naoki Shiota
	 *
	 */
	private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
		private long dpid;
		private short port;
		
		public GetLinkedPortsCallback(long dpid, short port) {
			this.dpid = dpid;
			this.port = port;
		}

		@Override
		public Iterable<IPortObject> answer() throws Throwable {
			List<IPortObject> ports = new ArrayList<IPortObject>();

			for(Link lk : links) {
				if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
					ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
				}
			}

			return ports;
		}
		
	}

	/**
	 * Class defines a function called back when {@link IPortObject#getReverseLinkedPorts()} is called.
	 * @author Naoki Shiota
	 *
	 */
	private class GetReverseLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
		private long dpid;
		private short port;
		
		public GetReverseLinkedPortsCallback(long dpid, short port) {
			this.dpid = dpid;
			this.port = port;
		}

		@Override
		public Iterable<IPortObject> answer() throws Throwable {
			List<IPortObject> ports = new ArrayList<IPortObject>();

			for(Link lk : links) {
				if(lk.getDst() == dpid && lk.getDstPort() == port) {
					ports.add(createMockPort(lk.getSrc(), lk.getSrcPort()));
				}
			}

			return ports;
		}
		
	}

	/**
	 * Class defines a function called back when {@link LinkStorageImplTest} is called.
	 * @author Naoki Shiota
	 *
	 */
	private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
		private long dpid;
		
		public GetPortsCallback(long dpid) {
			this.dpid = dpid;
		}
		
		@Override
		public Iterable<IPortObject> answer() throws Throwable {
			List<IPortObject> ports = new ArrayList<IPortObject>();
			
			for(Short number : getPorts(dpid)) {
				ports.add(createMockPort(dpid, number));
			}

			return ports;
		}
	}

	// ------------------------Creation of Mock-----------------------------
	/**
	 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
	 * @return EasyMock-wrapped GraphDBOperation object.
	 */
	private GraphDBOperation createMockGraphDBOperation() {
		GraphDBOperation mockDBOpe = EasyMock.createNiceMock(GraphDBOperation.class);
		
		// Mock searchPort() method to create new mock IPortObject.
		EasyMock.expect(mockDBOpe.searchPort((String)EasyMock.anyObject(), EasyMock.anyShort())).
			andAnswer(new IAnswer<IPortObject>() {
			@Override
			public IPortObject answer() throws Throwable {
				long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
				short port = (Short) EasyMock.getCurrentArguments()[1];
				IPortObject ret = createMockPort(dpid,port);
				
				return ret;
			}
		}).anyTimes();
		
		// Mock searchSwitch() method to create new mock ISwitchObject.
		EasyMock.expect(mockDBOpe.searchSwitch((String)EasyMock.anyObject())).
			andAnswer(new IAnswer<ISwitchObject>() {
			@Override
			public ISwitchObject answer() throws Throwable {
				long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
				ISwitchObject ret = createMockSwitch(dpid);
				
				return ret;
			}
		}).anyTimes();
		
		// Mock getActiveSwitches() method to create list of mock ISwitchObject.
		EasyMock.expect(mockDBOpe.getActiveSwitches()).andReturn(new ArrayList<ISwitchObject> () {{
			for(Long dpid : getDpids()) {
				add(createMockSwitch(dpid));
			}
		}}).anyTimes();

		// Mock commit() method to commit change of link information
		mockDBOpe.commit();
		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
			@Override
			public Object answer() throws Throwable {
				for(LinkEvent action : actions) {
					if(action.getType().equals(LinkEventType.ADD)) {
						Link linkToAdd = new Link(
								action.getSrcDpid(),
								action.getSrcPort(),
								action.getDstDpid(),
								action.getDstPort());
						links.add(linkToAdd);
					} else if(action.getType().equals(LinkEventType.DELETE)) {
						Link linkToRemove = new Link(
								action.getSrcDpid(),
								action.getSrcPort(),
								action.getDstDpid(),
								action.getDstPort());
						links.remove(linkToRemove);
					} else {
						log.error("mock commit(): unexpected action {}", new Object[]{action.getType()});
					}
				}
				actions.clear();
				return null;
			}
		}).atLeastOnce();
		
		EasyMock.replay(mockDBOpe);
		return mockDBOpe;
	}
	
	/**
	 * Create a mock {@link IPortObject} using given DPID and port number.
	 * {@link IPortObject} can't store DPID, so DPID is stored to mockToPortInfoMap for later use.
	 * Duplication is not checked.
	 * @param dpid DPID of a port
	 * @param number Port Number
	 * @return EasyMock-wrapped IPortObject
	 */
	private IPortObject createMockPort(long dpid, short number) {
		IPortObject mockPort = EasyMock.createNiceMock(IPortObject.class);
		
		EasyMock.expect(mockPort.getNumber()).andReturn(number);
		
		// Mock removeLink() method
		mockPort.removeLink((IPortObject) EasyMock.anyObject());
		EasyMock.expectLastCall().andAnswer(new RemoveLinkCallback(dpid, number)).anyTimes();
		
		// Mock setLinkPort() method
		mockPort.setLinkPort((IPortObject) EasyMock.anyObject());
		EasyMock.expectLastCall().andAnswer(new SetLinkPortCallback(dpid, number)).anyTimes();
		
		// Mock getLinkPorts() method
		EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();

		// Mock getReverseLinkPorts() method
		EasyMock.expect(mockPort.getReverseLinkedPorts()).andAnswer(new GetReverseLinkedPortsCallback(dpid, number)).anyTimes();
		
		// Mock getSwitch() method
		EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
		
		mockToPortInfoMap.put(mockPort, new PortInfo(dpid,number));
		EasyMock.replay(mockPort);
		
		return mockPort;
	}
	
	/**
	 * Create a mock {@link ISwitchObject} using given DPID number.
	 * Duplication is not checked.
	 * @param dpid DPID of a switch
	 * @return EasyMock-wrapped ISwitchObject
	 */
	private ISwitchObject createMockSwitch(long dpid) {
		ISwitchObject mockSw = EasyMock.createNiceMock(ISwitchObject.class);
		
		EasyMock.expect(mockSw.getPorts()).andAnswer(new GetPortsCallback(dpid)).anyTimes();
		EasyMock.expect(mockSw.getDPID()).andReturn(HexString.toHexString(dpid)).anyTimes();
		EasyMock.expect(mockSw.getState()).andReturn("ACTIVE").anyTimes();
		
		EasyMock.replay(mockSw);
		return mockSw;
	}


	//----------------- Creation of test data -----------------------
	// Assume a network shown below.
	//
	// [dpid1]--+--[port:1]----[port:1]--+--[dpid2]
	//          |                        |
	//          +--[port:2]    [port:2]--+
	//          |
	//          +--[port:3]    [port:1]--+--[dpid3]
	//          |                        |
	//          +--[port:4]----[port:2]--+
	//
	// dpid1 : 00:00:00:00:0a:01
	// dpid2 : 00:00:00:00:0a:02
	// dpid3 : 00:00:00:00:0a:03
	
	/**
	 * Initialize links member to represent test topology above.
	 */
	private void initLinks() {
		links = new ArrayList<Link>();
		
		links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
		links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
	}
	
	/**
	 * Returns list of port number attached to the switch specified by given DPID.
	 * @param dpid DPID of the switch
	 * @return List of port number
	 */
	private List<Short> getPorts(long dpid) {
		List<Short> ports;
		
		if(dpid == Long.decode("0x0000000000000a01")) {
			ports = new ArrayList<Short>() {{
				add((short)1);
				add((short)2);
				add((short)3);
				add((short)4);
			}};
		} else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
			ports = new ArrayList<Short>() {{
				add((short)1);
				add((short)2);
			}};
		} else {
			ports = new ArrayList<Short>();
		}
		
		return ports;
	}
	
	/**
	 * Returns list of DPIDs in test topology.
	 * @return List of DPIDs
	 */
	private List<Long> getDpids() {
		List<Long> dpids = new ArrayList<Long>() {{
			add(Long.decode("0x0000000000000a01"));
			add(Long.decode("0x0000000000000a02"));
			add(Long.decode("0x0000000000000a03"));
		}};
		
		return dpids;
	}
	
	/**
	 * Returns new {@link Link} object of an existing link
	 * @return new Link object
	 */
	private Link createExistingLink() {
		return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
	}
	
	/**
	 * Returns new {@link Link} object of a not-existing but feasible link
	 * @return new Link object
	 */
	private Link createFeasibleLink() {
		return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
	}
	
	/**
	 * Returns list of existing {@link Link} objects
	 * @return ArrayList of new Link objects
	 */
	private List<Link> createExistingLinks() {
		List<Link> links = new ArrayList<Link>();
		links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
		links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
		return links;
	}
	
	/**
	 * Returns list of {@link Link} objects that are all not-existing but feasible
	 * @return ArrayList of new Link objects
	 */
	private List<Link> createFeasibleLinks() {
		List<Link> links = new ArrayList<Link>();
		links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
		links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
		return links;
	}
	
	/**
	 * Returns new {@link 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);
	}
	//---------------------------------------------------------------
}
