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("/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);
	}
	//---------------------------------------------------------------
}
