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})
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.
	 */
	@SuppressWarnings("serial")
	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
	 */
	@SuppressWarnings("serial")
	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
	 */
	@SuppressWarnings("serial")
	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);
	}
	
	// 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("0x0000000000000a03"), 3);
	}

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