Merge in changes from master
diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
index 48dfcfb..b790a8e 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
@@ -57,8 +57,6 @@
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPacket;
 import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
-import net.floodlightcontroller.perfmon.PktInProcessingTime;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.restserver.RestApiServer;
 import net.floodlightcontroller.test.FloodlightTestCase;
@@ -66,6 +64,8 @@
 import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
 import net.onrc.onos.ofcontroller.flowmanager.FlowManager;
 import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
 import net.onrc.onos.ofcontroller.topology.TopologyManager;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
@@ -121,9 +121,7 @@
         CounterStore cs = new CounterStore();
         fmc.addService(ICounterStoreService.class, cs);
         
-        PktInProcessingTime ppt = new PktInProcessingTime();
-        fmc.addService(IPktInProcessingTimeService.class, ppt);
-        
+   
         tp = new MockThreadPoolService();
         fmc.addService(IThreadPoolService.class, tp);
         
@@ -133,18 +131,20 @@
         fmc.addService(ITopologyNetService.class, new TopologyManager() );
         StandaloneRegistry sr = new StandaloneRegistry();
         fmc.addService(IControllerRegistryService.class, sr );
+        LinkDiscoveryManager linkDiscovery = new LinkDiscoveryManager();
+        fmc.addService(ILinkDiscoveryService.class, linkDiscovery);
 
         
-        ppt.init(fmc);
         restApi.init(fmc);
         cm.init(fmc);
         tp.init(fmc);
         sr.init(fmc);
-        ppt.startUp(fmc);
+        linkDiscovery.init(fmc);
         restApi.startUp(fmc);
         cm.startUp(fmc);
         tp.startUp(fmc);
         sr.startUp(fmc);
+        linkDiscovery.startUp(fmc);
     }
 
     public Controller getController() {
@@ -399,7 +399,7 @@
         //Channel channel2 = createMock(Channel.class);
         //expect(newsw.getChannel()).andReturn(channel2);
         //expect(channel2.getRemoteAddress()).andReturn(null);
-        //expect(newsw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>());
+        expect(newsw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>());
         expect(newsw.getCapabilities()).andReturn(0).anyTimes();
         expect(newsw.getBuffers()).andReturn(0).anyTimes();
         expect(newsw.getTables()).andReturn((byte)0).anyTimes();
@@ -452,6 +452,10 @@
         }
         DummySwitchListener switchListener = new DummySwitchListener();
         IOFSwitch sw = createMock(IOFSwitch.class);
+        expect(sw.getId()).andReturn(1L).anyTimes();
+        expect(sw.getEnabledPorts()).andReturn(null);
+        expect(sw.getChannel()).andReturn(null).anyTimes();
+        replay(sw);
         ControllerRunThread t = new ControllerRunThread();
         t.start();
         
@@ -1137,6 +1141,7 @@
     @Test 
     public void testHandlePortStatus() throws Exception {
         IOFSwitch sw = createMock(IOFSwitch.class);
+        expect(sw.getId()).andReturn(1L).anyTimes();
         OFPhysicalPort port = new OFPhysicalPort();
         port.setName("myPortName1");
         port.setPortNumber((short)42);
diff --git a/src/test/java/net/floodlightcontroller/core/module/FloodlightTestModuleLoader.java b/src/test/java/net/floodlightcontroller/core/module/FloodlightTestModuleLoader.java
index d938abe..a4fba5d 100644
--- a/src/test/java/net/floodlightcontroller/core/module/FloodlightTestModuleLoader.java
+++ b/src/test/java/net/floodlightcontroller/core/module/FloodlightTestModuleLoader.java
@@ -9,7 +9,6 @@
 import net.floodlightcontroller.counter.NullCounterStore;
 import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
 import net.floodlightcontroller.devicemanager.test.MockDeviceManager;
-import net.floodlightcontroller.perfmon.NullPktInProcessingTime;
 import net.floodlightcontroller.topology.TopologyManager;
 
 import org.slf4j.Logger;
@@ -31,8 +30,7 @@
 			MockThreadPoolService.class;
 	public static final Class<? extends IFloodlightModule> DEFAULT_ENTITY_CLASSIFIER =
 			DefaultEntityClassifier.class;
-	public static final Class<? extends IFloodlightModule> DEFAULT_PERFMON =
-			NullPktInProcessingTime.class;
+	
 	
 	protected static final Collection<Class<? extends IFloodlightModule>> DEFAULT_MODULE_LIST;
 	
@@ -44,7 +42,7 @@
 		DEFAULT_MODULE_LIST.add(DEFAULT_COUNTER_STORE);
 		DEFAULT_MODULE_LIST.add(DEFAULT_THREADPOOL);
 		DEFAULT_MODULE_LIST.add(DEFAULT_ENTITY_CLASSIFIER);
-		DEFAULT_MODULE_LIST.add(DEFAULT_PERFMON);
+
 	}
 	
 	protected IFloodlightModuleContext fmc;
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index 3fccd0f..b37efe3 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -57,8 +57,6 @@
 import net.floodlightcontroller.devicemanager.test.MockEntityClassifier;
 import net.floodlightcontroller.devicemanager.test.MockEntityClassifierMac;
 import net.floodlightcontroller.devicemanager.test.MockFlexEntityClassifier;
-import net.floodlightcontroller.flowcache.FlowReconcileManager;
-import net.floodlightcontroller.flowcache.IFlowReconcileService;
 import net.floodlightcontroller.packet.ARP;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPacket;
@@ -95,8 +93,6 @@
     private byte[] testARPReplyPacket_3_Serialized;
     MockFloodlightProvider mockFloodlightProvider;
     DeviceManagerImpl deviceManager;
-    //MemoryStorageSource storageSource;
-    FlowReconcileManager flowReconcileMgr;
 
     private IOFSwitch makeSwitchMock(long id) {
         IOFSwitch mockSwitch = createMock(IOFSwitch.class);
@@ -121,25 +117,25 @@
         fmc.addService(IThreadPoolService.class, tp);
         mockFloodlightProvider = getMockFloodlightProvider();
         deviceManager = new DeviceManagerImpl();
-        flowReconcileMgr = new FlowReconcileManager();
+       
         DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier();
         fmc.addService(IDeviceService.class, deviceManager);
         //storageSource = new MemoryStorageSource();
         //fmc.addService(IStorageSourceService.class, storageSource);
         fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider);
         fmc.addService(IRestApiService.class, restApi);
-        fmc.addService(IFlowReconcileService.class, flowReconcileMgr);
+ 
         fmc.addService(IEntityClassifierService.class, entityClassifier);
         fmc.addService(ITopologyService.class, topology);
         tp.init(fmc);
         restApi.init(fmc);
         //storageSource.init(fmc);
         deviceManager.init(fmc);
-        flowReconcileMgr.init(fmc);
+
         entityClassifier.init(fmc);
         //storageSource.startUp(fmc);
         deviceManager.startUp(fmc);
-        flowReconcileMgr.startUp(fmc);
+
         tp.startUp(fmc);
         entityClassifier.startUp(fmc);
 
diff --git a/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java b/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java
deleted file mode 100644
index 0427828..0000000
--- a/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java
+++ /dev/null
@@ -1,500 +0,0 @@
-package net.floodlightcontroller.flowcache;
-
-import static org.easymock.EasyMock.*;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.ListIterator;
-
-import net.floodlightcontroller.core.IListener.Command;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
-import net.floodlightcontroller.core.test.MockThreadPoolService;
-import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.counter.SimpleCounter;
-import net.floodlightcontroller.counter.CounterValue.CounterType;
-import net.floodlightcontroller.flowcache.IFlowReconcileListener;
-import net.floodlightcontroller.flowcache.OFMatchReconcile;
-import net.floodlightcontroller.test.FloodlightTestCase;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.junit.Before;
-import org.junit.Test;
-import org.openflow.protocol.OFStatisticsRequest;
-import org.openflow.protocol.OFType;
-
-public class FlowReconcileMgrTest extends FloodlightTestCase {
-
-    protected MockFloodlightProvider mockFloodlightProvider;
-    protected FlowReconcileManager flowReconcileMgr;
-    protected MockThreadPoolService threadPool;
-    protected ICounterStoreService counterStore;
-    protected FloodlightModuleContext fmc;
-    
-    OFStatisticsRequest ofStatsRequest;
-
-    protected int NUM_FLOWS_PER_THREAD = 100;
-    protected int NUM_THREADS = 100;
-    
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        fmc = new FloodlightModuleContext();
-        flowReconcileMgr = new FlowReconcileManager();
-        threadPool = new MockThreadPoolService();
-        counterStore = createMock(ICounterStoreService.class);
-        
-        fmc.addService(ICounterStoreService.class, counterStore);
-        fmc.addService(IThreadPoolService.class, threadPool);
-        
-        threadPool.init(fmc);
-        flowReconcileMgr.init(fmc);
-
-        threadPool.startUp(fmc);
-        flowReconcileMgr.startUp(fmc);
-    }
-
-    /** Verify pipeline listener registration and ordering
-     * 
-     * @throws Exception
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testFlowReconcilePipeLine() throws Exception {
-        flowReconcileMgr.flowReconcileEnabled = true;
-    
-        IFlowReconcileListener r1 =
-            EasyMock.createNiceMock(IFlowReconcileListener.class);
-        IFlowReconcileListener r2 =
-            EasyMock.createNiceMock(IFlowReconcileListener.class);
-        IFlowReconcileListener r3 =
-            EasyMock.createNiceMock(IFlowReconcileListener.class);
-        
-        expect(r1.getName()).andReturn("r1").anyTimes();
-        expect(r2.getName()).andReturn("r2").anyTimes();
-        expect(r3.getName()).andReturn("r3").anyTimes();
-        
-        // Set the listeners' order: r1 -> r2 -> r3
-        expect(r1.isCallbackOrderingPrereq((OFType)anyObject(),
-            (String)anyObject())).andReturn(false).anyTimes();
-        expect(r1.isCallbackOrderingPostreq((OFType)anyObject(),
-            (String)anyObject())).andReturn(false).anyTimes();
-        expect(r2.isCallbackOrderingPrereq((OFType)anyObject(),
-            eq("r1"))).andReturn(true).anyTimes();
-        expect(r2.isCallbackOrderingPrereq((OFType)anyObject(),
-            eq("r3"))).andReturn(false).anyTimes();
-        expect(r2.isCallbackOrderingPostreq((OFType)anyObject(),
-            eq("r1"))).andReturn(false).anyTimes();
-        expect(r2.isCallbackOrderingPostreq((OFType)anyObject(),
-            eq("r3"))).andReturn(true).anyTimes();
-        expect(r3.isCallbackOrderingPrereq((OFType)anyObject(),
-            eq("r1"))).andReturn(false).anyTimes();
-        expect(r3.isCallbackOrderingPrereq((OFType)anyObject(),
-            eq("r2"))).andReturn(true).anyTimes();
-        expect(r3.isCallbackOrderingPostreq((OFType)anyObject(),
-            (String)anyObject())).andReturn(false).anyTimes();
-        
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject())).
-                  andThrow(new RuntimeException("This is NOT an error! " +
-                            "We are testing exception catching."));
-        
-        SimpleCounter cnt = (SimpleCounter)SimpleCounter.createCounter(
-                            new Date(),
-                            CounterType.LONG);
-        cnt.increment();
-        expect(counterStore.getCounter(
-                flowReconcileMgr.controllerPktInCounterName))
-                .andReturn(cnt)
-                .anyTimes();
-        
-        replay(r1, r2, r3, counterStore);
-        flowReconcileMgr.clearFlowReconcileListeners();
-        flowReconcileMgr.addFlowReconcileListener(r1);
-        flowReconcileMgr.addFlowReconcileListener(r2);
-        flowReconcileMgr.addFlowReconcileListener(r3);
-        
-        int pre_flowReconcileThreadRunCount =
-                flowReconcileMgr.flowReconcileThreadRunCount;
-        Date startTime = new Date();
-        OFMatchReconcile ofmRcIn = new OFMatchReconcile();
-        try {
-            flowReconcileMgr.reconcileFlow(ofmRcIn);
-            flowReconcileMgr.doReconcile();
-        } catch (RuntimeException e) {
-            assertEquals(e.getMessage()
-                .startsWith("This is NOT an error!"), true);
-        }
-        
-        verify(r1, r2, r3);
-
-        // verify STOP works
-        reset(r1, r2, r3);
-        
-        // restart reconcileThread since it exited due to previous runtime
-        // exception.
-        flowReconcileMgr.startUp(fmc);
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.STOP).times(1);
-        expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                fail("Unexpected call");
-                return Command.STOP;
-            }
-        }).anyTimes();
-        
-        pre_flowReconcileThreadRunCount =
-            flowReconcileMgr.flowReconcileThreadRunCount;
-        startTime = new Date();
-        replay(r1, r2, r3);
-        flowReconcileMgr.reconcileFlow(ofmRcIn);
-        while (flowReconcileMgr.flowReconcileThreadRunCount <=
-                pre_flowReconcileThreadRunCount) {
-            Thread.sleep(10);
-            Date currTime = new Date();
-            assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
-        }
-        verify(r1, r2, r3);
-        
-        // verify CONTINUE works
-        reset(r1, r2, r3);
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.CONTINUE).times(1);
-        expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.STOP).times(1);
-        expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                fail("Unexpected call");
-                return Command.STOP;
-            }
-        }).anyTimes();
-        
-        pre_flowReconcileThreadRunCount =
-            flowReconcileMgr.flowReconcileThreadRunCount;
-        startTime = new Date();
-        
-        replay(r1, r2, r3);
-        flowReconcileMgr.reconcileFlow(ofmRcIn);
-        while (flowReconcileMgr.flowReconcileThreadRunCount <=
-                pre_flowReconcileThreadRunCount) {
-            Thread.sleep(10);
-            Date currTime = new Date();
-            assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
-        }
-        verify(r1, r2, r3);
-        
-        // verify CONTINUE works
-        reset(r1, r2, r3);
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.CONTINUE).times(1);
-        expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.CONTINUE).times(1);
-        expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.STOP).times(1);
-        
-        pre_flowReconcileThreadRunCount =
-            flowReconcileMgr.flowReconcileThreadRunCount;
-        startTime = new Date();
-        
-        replay(r1, r2, r3);
-        flowReconcileMgr.reconcileFlow(ofmRcIn);
-        while (flowReconcileMgr.flowReconcileThreadRunCount <=
-                pre_flowReconcileThreadRunCount) {
-            Thread.sleep(10);
-            Date currTime = new Date();
-            assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
-        }
-        verify(r1, r2, r3);
-        
-        // Verify removeFlowReconcileListener
-        flowReconcileMgr.removeFlowReconcileListener(r1);
-        reset(r1, r2, r3);
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                fail("Unexpected call to a listener that is " +
-                        "removed from the chain.");
-                return Command.STOP;
-            }
-        }).anyTimes();
-        expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.CONTINUE).times(1);
-        expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.STOP).times(1);
-        
-        pre_flowReconcileThreadRunCount =
-            flowReconcileMgr.flowReconcileThreadRunCount;
-        startTime = new Date();
-        replay(r1, r2, r3);
-        flowReconcileMgr.reconcileFlow(ofmRcIn);
-        while (flowReconcileMgr.flowReconcileThreadRunCount <=
-                pre_flowReconcileThreadRunCount) {
-            Thread.sleep(10);
-            Date currTime = new Date();
-            assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
-        }
-        verify(r1, r2, r3);
-    }
-    
-    @Test
-    public void testGetPktInRate() {
-        internalTestGetPktInRate(CounterType.LONG);
-        internalTestGetPktInRate(CounterType.DOUBLE);
-    }
-    
-    protected void internalTestGetPktInRate(CounterType type) {
-        Date currentTime = new Date();
-        SimpleCounter newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                                currentTime, type);
-        newCnt.increment(currentTime, 1);
-    
-        // Set the lastCounter time in the future of the current time
-        Date lastCounterTime = new Date(currentTime.getTime() + 1000);
-        flowReconcileMgr.lastPacketInCounter =
-                (SimpleCounter)SimpleCounter.createCounter(
-                    lastCounterTime, type);
-        flowReconcileMgr.lastPacketInCounter.increment(lastCounterTime, 1);
-    
-        assertEquals(FlowReconcileManager.MAX_SYSTEM_LOAD_PER_SECOND,
-                flowReconcileMgr.getPktInRate(newCnt, new Date()));
-    
-        // Verify the rate == 0 time difference is zero.
-        lastCounterTime = new Date(currentTime.getTime() - 1000);
-        flowReconcileMgr.lastPacketInCounter.increment(lastCounterTime, 1);
-        assertEquals(0, flowReconcileMgr.getPktInRate(newCnt, lastCounterTime));
-    
-        /** verify the computation is correct.
-         *  new = 2000, old = 1000, Tdiff = 1 second.
-         *  rate should be 1000/second
-         */
-        newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                currentTime, type);
-        newCnt.increment(currentTime, 2000);
-    
-        lastCounterTime = new Date(currentTime.getTime() - 1000);
-        flowReconcileMgr.lastPacketInCounter =
-                (SimpleCounter)SimpleCounter.createCounter(
-                    lastCounterTime, type);
-        flowReconcileMgr.lastPacketInCounter.increment(lastCounterTime, 1000);
-        assertEquals(1000, flowReconcileMgr.getPktInRate(newCnt, currentTime));
-    
-        /** verify the computation is correct.
-         *  new = 2,000,000, old = 1,000,000, Tdiff = 2 second.
-         *  rate should be 1000/second
-         */
-        newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                currentTime, type);
-        newCnt.increment(currentTime, 2000000);
-    
-        lastCounterTime = new Date(currentTime.getTime() - 2000);
-        flowReconcileMgr.lastPacketInCounter =
-                (SimpleCounter)SimpleCounter.createCounter(
-                    lastCounterTime, type);
-        flowReconcileMgr.lastPacketInCounter.increment(lastCounterTime,
-                1000000);
-        assertEquals(500000, flowReconcileMgr.getPktInRate(newCnt,
-                    currentTime));
-    }
-    
-    @Test
-    public void testGetCurrentCapacity() throws Exception {
-        // Disable the reconcile thread.
-        flowReconcileMgr.flowReconcileEnabled = false;
-    
-        int minFlows = FlowReconcileManager.MIN_FLOW_RECONCILE_PER_SECOND *
-                FlowReconcileManager.FLOW_RECONCILE_DELAY_MILLISEC / 1000;
-    
-        /** Verify the initial state, when packetIn counter has not
-         *  been created.
-         */
-        expect(counterStore.getCounter(
-                flowReconcileMgr.controllerPktInCounterName))
-        .andReturn(null)
-        .times(1);
-    
-        replay(counterStore);
-        assertEquals(minFlows, flowReconcileMgr.getCurrentCapacity());
-        verify(counterStore);
-    
-        /** Verify the initial state, when lastPacketInCounter is null */
-        reset(counterStore);
-        Date currentTime = new Date();
-        SimpleCounter newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                        currentTime, CounterType.LONG);
-    
-        expect(counterStore.getCounter(
-            flowReconcileMgr.controllerPktInCounterName))
-        .andReturn(newCnt)
-        .times(1);
-        long initPktInCount = 10000;
-        newCnt.increment(currentTime, initPktInCount);
-    
-        replay(counterStore);
-        assertEquals(minFlows, flowReconcileMgr.getCurrentCapacity());
-        verify(counterStore);
-    
-        /** Now the lastPacketInCounter has been set.
-         *  lastCounter = 100,000 and newCounter = 300,000, t = 1 second
-         *  packetInRate = 200,000/sec.
-         *  capacity should be 500k - 200k = 300k
-         */
-        reset(counterStore);
-        newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                    currentTime, CounterType.LONG);
-        currentTime = new Date(currentTime.getTime() + 200);
-        long nextPktInCount = 30000;
-        newCnt.increment(currentTime, nextPktInCount);
-    
-        expect(counterStore.getCounter(
-                flowReconcileMgr.controllerPktInCounterName))
-        .andReturn(newCnt)
-        .times(1);
-    
-        replay(counterStore);
-        // Wait for 1 second so that enough elapsed time to compute capacity.
-        Thread.sleep(1000);
-        int capacity = flowReconcileMgr.getCurrentCapacity();
-        verify(counterStore);
-        long expectedCap = (FlowReconcileManager.MAX_SYSTEM_LOAD_PER_SECOND -
-                (nextPktInCount - initPktInCount)) *
-                FlowReconcileManager.FLOW_RECONCILE_DELAY_MILLISEC / 1000;
-        assertEquals(expectedCap, capacity);
-    }
-    
-    private class FlowReconcileWorker implements Runnable {
-    @Override
-        public void run() {
-            OFMatchReconcile ofmRc = new OFMatchReconcile();
-            // push large number of flows to be reconciled.
-            for (int i = 0; i < NUM_FLOWS_PER_THREAD; i++) {
-                flowReconcileMgr.reconcileFlow(ofmRc);
-            }
-        }
-    }
-    
-    /** Verify the flows are sent to the reconcile pipeline in order.
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testQueueFlowsOrder() {
-        flowReconcileMgr.flowReconcileEnabled = false;
-        
-        IFlowReconcileListener r1 =
-            EasyMock.createNiceMock(IFlowReconcileListener.class);
-        
-        expect(r1.getName()).andReturn("r1").anyTimes();
-        
-        // Set the listeners' order: r1 -> r2 -> r3
-        expect(r1.isCallbackOrderingPrereq((OFType)anyObject(),
-            (String)anyObject())).andReturn(false).anyTimes();
-        expect(r1.isCallbackOrderingPostreq((OFType)anyObject(),
-            (String)anyObject())).andReturn(false).anyTimes();
-        
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andAnswer(new IAnswer<Command>() {
-            @Override
-            public Command answer() throws Throwable {
-                ArrayList<OFMatchReconcile> ofmList =
-                    (ArrayList<OFMatchReconcile>)EasyMock.
-                        getCurrentArguments()[0];
-                ListIterator<OFMatchReconcile> lit = ofmList.listIterator();
-                int index = 0;
-                while (lit.hasNext()) {
-                    OFMatchReconcile ofm = lit.next();
-                    assertEquals(index++, ofm.cookie);
-                }
-                return Command.STOP;
-            }
-        }).times(1);
-        
-        SimpleCounter cnt = (SimpleCounter)SimpleCounter.createCounter(
-                            new Date(),
-                            CounterType.LONG);
-        cnt.increment();
-        expect(counterStore.getCounter(
-                flowReconcileMgr.controllerPktInCounterName))
-                .andReturn(cnt)
-                .anyTimes();
-        
-        replay(r1, counterStore);
-        flowReconcileMgr.clearFlowReconcileListeners();
-        flowReconcileMgr.addFlowReconcileListener(r1);
-        
-        OFMatchReconcile ofmRcIn = new OFMatchReconcile();
-        int index = 0;
-        for (index = 0; index < 10; index++) {
-            ofmRcIn.cookie = index;
-            flowReconcileMgr.reconcileFlow(ofmRcIn);
-        }
-        flowReconcileMgr.flowReconcileEnabled = true;
-        flowReconcileMgr.doReconcile();
-        
-        verify(r1);
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testQueueFlowsByManyThreads() {
-        // Disable the reconcile thread so that the queue won't be emptied.
-        flowQueueTest(false);
-    
-        // Enable the reconcile thread. The queue should be empty.
-        Date currentTime = new Date();
-        SimpleCounter newCnt = (SimpleCounter)SimpleCounter.createCounter(
-                    currentTime, CounterType.LONG);
-    
-        expect(counterStore.getCounter(
-                    flowReconcileMgr.controllerPktInCounterName))
-        .andReturn(newCnt)
-        .anyTimes();
-        long initPktInCount = 10000;
-        newCnt.increment(currentTime, initPktInCount);
-    
-        IFlowReconcileListener r1 =
-                EasyMock.createNiceMock(IFlowReconcileListener.class);
-        
-        expect(r1.getName()).andReturn("r1").anyTimes();
-        
-        // Set the listeners' order: r1 -> r2 -> r3
-        expect(r1.isCallbackOrderingPrereq((OFType)anyObject(),
-                (String)anyObject())).andReturn(false).anyTimes();
-        expect(r1.isCallbackOrderingPostreq((OFType)anyObject(),
-                (String)anyObject())).andReturn(false).anyTimes();
-        
-        expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
-        .andReturn(Command.CONTINUE).anyTimes();
-        
-        flowReconcileMgr.clearFlowReconcileListeners();
-        replay(r1, counterStore);
-        flowQueueTest(true);
-        verify(r1, counterStore);
-    }
-    
-    protected void flowQueueTest(boolean enableReconcileThread) {
-        flowReconcileMgr.flowReconcileEnabled = enableReconcileThread;
-    
-        // Simulate flow
-        for (int i = 0; i < NUM_THREADS; i++) {
-            Runnable worker = this.new FlowReconcileWorker();
-            Thread t = new Thread(worker);
-            t.start();
-        }
-    
-        Date startTime = new Date();
-        int totalFlows = NUM_THREADS * NUM_FLOWS_PER_THREAD;
-        if (enableReconcileThread) {
-            totalFlows = 0;
-        }
-        while (flowReconcileMgr.flowQueue.size() != totalFlows) {
-            Date currTime = new Date();
-            assertTrue((currTime.getTime() - startTime.getTime()) < 2000);
-        }
-    
-        // Make sure all flows are in the queue.
-        assertEquals(totalFlows, flowReconcileMgr.flowQueue.size());
-    }
-}
diff --git a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
index 7a37589..3e262af 100644
--- a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
+++ b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java
@@ -50,8 +50,6 @@
 import net.floodlightcontroller.topology.ITopologyListener;
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.topology.NodePortTuple;
-import net.floodlightcontroller.flowcache.FlowReconcileManager;
-import net.floodlightcontroller.flowcache.IFlowReconcileService;
 import net.floodlightcontroller.forwarding.Forwarding;
 
 import org.easymock.Capture;
@@ -77,7 +75,6 @@
     protected MockDeviceManager deviceManager;
     protected IRoutingService routingEngine;
     protected Forwarding forwarding;
-    protected FlowReconcileManager flowReconcileMgr;
     protected ITopologyService topology;
     protected MockThreadPoolService threadPool;
     protected IOFSwitch sw1, sw2;
@@ -121,7 +118,6 @@
         forwarding = new Forwarding();
         threadPool = new MockThreadPoolService();
         deviceManager = new MockDeviceManager();
-        flowReconcileMgr = new FlowReconcileManager();
         routingEngine = createMock(IRoutingService.class);
         topology = createMock(ITopologyService.class);
         DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier();
@@ -135,7 +131,6 @@
         fmc.addService(IRoutingService.class, routingEngine);
         fmc.addService(ICounterStoreService.class, new CounterStore());
         fmc.addService(IDeviceService.class, deviceManager);
-        fmc.addService(IFlowReconcileService.class, flowReconcileMgr);
         fmc.addService(IEntityClassifierService.class, entityClassifier);
 
         topology.addListener(anyObject(ITopologyListener.class));
@@ -144,12 +139,10 @@
         threadPool.init(fmc);
         forwarding.init(fmc);
         deviceManager.init(fmc);
-        flowReconcileMgr.init(fmc);
         entityClassifier.init(fmc);
         threadPool.startUp(fmc);
         deviceManager.startUp(fmc);
         forwarding.startUp(fmc);
-        flowReconcileMgr.startUp(fmc);
         entityClassifier.startUp(fmc);
         verify(topology);
         
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
index 06d8522..f1c2c71 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
@@ -78,6 +78,38 @@
 		flowEntry.setFlowEntryId(flowEntryId);
 		assertEquals(flowEntry.getFlowEntryId(), flowEntryId);
 	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get Idle Timeout.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set Idle Timeout.
+	 * 2. Should get Idle Timeout.
+	 */
+	@Test
+	public void testSetGetIdleTimeout() {
+		Integer idleTimeout = 5;
+		flowEntry.setIdleTimeout(idleTimeout);
+		assertEquals(flowEntry.getIdleTimeout(), idleTimeout);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get Hard Timeout.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set Hard Timeout.
+	 * 2. Should get Hard Timeout.
+	 */
+	@Test
+	public void testSetGetHardTimeout() {
+		Integer hardTimeout = 5;
+		flowEntry.setHardTimeout(hardTimeout);
+		assertEquals(flowEntry.getHardTimeout(), hardTimeout);
+	}
 	
 	/**
 	 * Desc:
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java
index 9a1e34a..39e4955 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java
@@ -158,6 +158,42 @@
 
 	/**
 	 * Desc:
+	 *  Test method for get and set Idle Timeout method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the Idle Timeout.
+	 * 2. Should get the Idle Timeout.
+	 */
+	@Test
+	public void testSetGetIdleTimeout() {
+		String flowId = "xx";
+		Integer idleTimeout = 5;
+		flowPath.setFlowId(flowId);
+		flowPath.setIdleTimeout(idleTimeout);
+		assertEquals(flowPath.getIdleTimeout(), idleTimeout);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for get and set Hard Timeout method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the Hard Timeout.
+	 * 2. Should get the Hard Timeout.
+	 */
+	@Test
+	public void testSetGetHardTimeout() {
+		String flowId = "xx";
+		Integer hardTimeout = 5;
+		flowPath.setFlowId(flowId);
+		flowPath.setHardTimeout(hardTimeout);
+		assertEquals(flowPath.getHardTimeout(), hardTimeout);
+	}
+
+	/**
+	 * Desc:
 	 *  Test method for get and set SourceSwitch method.
 	 * Condition:
 	 *  N/A
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
index 4aea22a..8034d44 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
@@ -37,6 +37,7 @@
  */
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({LinkStorageImpl.class, GraphDBConnection.class, GraphDBOperation.class})
+@SuppressWarnings("serial")
 public class LinkStorageImplTest {
 	protected final static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);
 
@@ -519,7 +520,6 @@
 	 * 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);
 		
@@ -672,7 +672,6 @@
 	 * @param dpid DPID of the switch
 	 * @return List of port number
 	 */
-	@SuppressWarnings("serial")
 	private List<Short> getPorts(long dpid) {
 		List<Short> ports;
 		
@@ -699,7 +698,6 @@
 	 * 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"));
@@ -726,12 +724,6 @@
 		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
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
index d7724ae..8da306f 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
@@ -326,6 +326,7 @@
 	 * tests in net.onrc.onos.ofcontroller.core.*
 	 */
 	public static class TestDeviceObject implements IDeviceObject {
+		@SuppressWarnings("unused")
 		private String state,type,mac,ipaddr;
 		private List<IPortObject> ports;
 		private List<ISwitchObject> switches;
@@ -456,6 +457,8 @@
 		private String flowPathType;
 		private String flowPathUserState;
 		private Long flowPathFlags;
+		private Integer idleTimeout;
+		private Integer hardTimeout;
 		private String dataPathSummary;
 		private Short srcPort,dstPort;
 		private String matchSrcMac,matchDstMac;
@@ -474,6 +477,8 @@
 		private String flowPathTypeToUpdate;
 		private String flowPathUserStateToUpdate;
 		private Long flowPathFlagsToUpdate;
+		private Integer idleTimeoutToUpdate;
+		private Integer hardTimeoutToUpdate;
 		private String dataPathSummaryToUpdate;
 		private Short srcPortToUpdate,dstPortToUpdate;
 		private String matchSrcMacToUpdate,matchDstMacToUpdate;
@@ -514,6 +519,8 @@
 			if(flowPathTypeToUpdate != null) { flowPathType = flowPathTypeToUpdate; }
 			if(flowPathUserStateToUpdate != null) { flowPathUserState = flowPathUserStateToUpdate; }
 			if(flowPathFlagsToUpdate != null) { flowPathFlags = flowPathFlagsToUpdate; }
+			if(idleTimeoutToUpdate != null) { idleTimeout = idleTimeoutToUpdate; }
+			if(hardTimeoutToUpdate != null) { hardTimeout = hardTimeoutToUpdate; }
 			if(srcSwToUpdate != null) { srcSw = srcSwToUpdate; }
 			if(dstSwToUpdate != null) { dstSw = dstSwToUpdate; }
 			if(dataPathSummaryToUpdate != null) { dataPathSummary = dataPathSummaryToUpdate; }
@@ -545,6 +552,8 @@
 			flowPathTypeToUpdate = null;
 			flowPathUserStateToUpdate = null;
 			flowPathFlagsToUpdate = null;
+			idleTimeoutToUpdate = null;
+			hardTimeoutToUpdate = null;
 			srcSwToUpdate = dstSwToUpdate = dataPathSummaryToUpdate = null;
 			srcPortToUpdate = dstPortToUpdate = null;
 			matchSrcMacToUpdate = matchDstMacToUpdate = null;
@@ -565,6 +574,8 @@
 		public void setFlowPathTypeForTest(String flowPathType) { this.flowPathType = flowPathType; }
 		public void setFlowPathUserStateForTest(String flowPathUserState) { this.flowPathUserState = flowPathUserState; }
 		public void setFlowPathFlagsForTest(Long flowPathFlags) { this.flowPathFlags = flowPathFlags; }
+		public void setIdleTimeoutForTest(Integer idleTimeout) { this.idleTimeout = idleTimeout; }
+		public void setHardTimeoutForTest(Integer hardTimeout) { this.hardTimeout = hardTimeout; }
 		public void setSrcSwForTest(String srcSw) { this.srcSw = srcSw; }
 		public void setDstSwForTest(String dstSw) { this.dstSw = dstSw; }
 		public void setDataPathSummaryForTest(String dataPathSummary) { this.dataPathSummary = dataPathSummary; }
@@ -634,6 +645,18 @@
 		public void setFlowPathFlags(Long flowPathFlags) { flowPathFlagsToUpdate = flowPathFlags; }
 
 		@Override
+		public Integer getIdleTimeout() { return idleTimeout; }
+
+		@Override
+		public void setIdleTimeout(Integer idleTimeout) { idleTimeoutToUpdate = idleTimeout; }
+
+		@Override
+		public Integer getHardTimeout() { return hardTimeout; }
+
+		@Override
+		public void setHardTimeout(Integer hardTimeout) { hardTimeoutToUpdate = hardTimeout; }
+
+		@Override
 		public String getSrcSwitch() { return srcSw; }
 
 		@Override
@@ -768,6 +791,8 @@
 
 	public static class TestFlowEntry implements IFlowEntry {
 		private String state,type,entryId,dpid,userState,switchState,errorStateType,errorStateCode;
+		private Integer idleTimeout;
+		private Integer hardTimeout;
 		private Short matchInPort;
 		private String matchSrcMac,matchDstMac;
 		private Short matchEtherFrameType;
@@ -785,6 +810,8 @@
 	
 		private String stateToUpdate,typeToUpdate,entryIdToUpdate,dpidToUpdate,
 			userStateToUpdate,switchStateToUpdate,errorStateTypeToUpdate,errorStateCodeToUpdate;
+		private Integer idleTimeoutToUpdate;
+		private Integer hardTimeoutToUpdate;
 		private Short matchInPortToUpdate;
 		private String matchSrcMacToUpdate,matchDstMacToUpdate;
 		private Short matchEtherFrameTypeToUpdate;
@@ -810,6 +837,8 @@
 			if(stateToUpdate != null) { state = stateToUpdate; }
 			if(typeToUpdate != null) { type = typeToUpdate; }
 			if(entryIdToUpdate != null) { entryId = entryIdToUpdate; }
+			if(idleTimeoutToUpdate != null) { idleTimeout = idleTimeoutToUpdate; }
+			if(hardTimeoutToUpdate != null) { hardTimeout = hardTimeoutToUpdate; }
 			if(dpidToUpdate != null) { dpid = dpidToUpdate; }
 			if(userStateToUpdate != null) { userState = userStateToUpdate; }
 			if(switchStateToUpdate != null) { switchState = switchStateToUpdate; }
@@ -844,6 +873,7 @@
 		
 		public void clearUncommitedData() {
 			stateToUpdate = typeToUpdate = entryIdToUpdate = dpidToUpdate = null;
+			idleTimeoutToUpdate = hardTimeoutToUpdate = null;
 			userStateToUpdate = switchStateToUpdate = errorStateTypeToUpdate = errorStateCodeToUpdate = null;
 			matchInPortToUpdate = null;
 			matchSrcMacToUpdate = matchDstMacToUpdate = null;
@@ -864,6 +894,8 @@
 		public void setStateForTest(String state) { this.state = state; }
 		public void setTypeForTest(String type) { this.type = type; }
 		public void setEntryIdForTest(String entryId) { this.entryId = entryId; }
+		public void setIdleTimeoutForTest(Integer idleTimeout) { this.idleTimeout = idleTimeout; }
+		public void setHardTimeoutForTest(Integer hardTimeout) { this.hardTimeout = hardTimeout; }
 		public void setDpidForTest(String dpid) { this.dpid = dpid; }
 		public void setUserStateForTest(String userState) { this.userState = userState; }
 		public void setSwitchStateForTest(String switchState) { this.switchState = switchState; }
@@ -911,6 +943,18 @@
 	
 		@Override
 		public void setFlowEntryId(String flowEntryId) { entryIdToUpdate = flowEntryId; }
+
+		@Override
+		public Integer getIdleTimeout() { return idleTimeout; }
+	
+		@Override
+		public void setIdleTimeout(Integer idleTimeout) { idleTimeoutToUpdate = idleTimeout; }
+
+		@Override
+		public Integer getHardTimeout() { return hardTimeout; }
+	
+		@Override
+		public void setHardTimeout(Integer hardTimeout) { hardTimeoutToUpdate = hardTimeout; }
 	
 		@Override
 		public String getSwitchDpid() { return dpid; }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java
index c7c74a5..9964ec3 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java
@@ -2,6 +2,8 @@
 
 import static org.junit.Assert.*;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.List;
 
@@ -485,9 +487,10 @@
 			IDeviceObject dev1 = ope.searchDevice(macAddr);
 			assertEquals(macAddr, dev1.getMACAddress());
 
+			int ip_int = getPackedIPv4Address(ip);
 			//XXX not updated to new interface
-		    //IDeviceObject dev = deviceImpl.getDeviceByIP(ip);
-			IDeviceObject dev = null;
+		    IDeviceObject dev = deviceImpl.getDeviceByIP(ip_int);
+			//IDeviceObject dev = null;
 			
 		    assertNotNull(dev);
 		    
@@ -656,4 +659,14 @@
 		}
 	}
 
+	int getPackedIPv4Address(String ip) throws UnknownHostException {
+		byte[] bytes = InetAddress.getByName(ip).getAddress();
+
+		int val = 0;
+		  for (int i = 0; i < bytes.length; i++) {
+		    val <<= 8;
+		    val |= bytes[i] & 0xff;
+		  }
+		  return val;
+	}
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
index 7fd0f67..b43ce1c 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
@@ -26,7 +26,6 @@
 import net.onrc.onos.ofcontroller.util.*;
 
 import org.easymock.EasyMock;
-import org.easymock.IAnswer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -124,6 +123,7 @@
 		return flowPath;
 	}
 	
+	/*
 	private ArrayList<FlowPath> createTestFlowPaths() {
 		FlowPath flowPath1 = createTestFlowPath(1, "foo caller id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 1, 2, 2); 
 		FlowPath flowPath2 = createTestFlowPath(2, "caller id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 1, 2, 2); 
@@ -136,13 +136,14 @@
 		
 		return flowPaths;
 	}
+	*/
 	
 
 	// IFlowService methods
 
 
 	/**
-	 * Test method for {@link FlowManager#addFlow(FlowPath, FlowId, String)}.
+	 * Test method for {@link FlowManager#addFlow(FlowPath)}.
 	 * @throws Exception 
 	 */
 	@Test
@@ -163,15 +164,15 @@
 		replayAll();
 
 		fm.init(context);
-		Boolean result = fm.addFlow(flowPath, flowId);
+		FlowId result = fm.addFlow(flowPath);
 
 		// verify the test
 		verifyAll();
-		assertFalse(result);
+		assertNotNull(result);
 	}
 
 	/**
-	 * Test method for {@link FlowManager#addFlow(FlowPath, FlowId)}.
+	 * Test method for {@link FlowManager#addFlow(FlowPath)}.
 	 * @throws Exception 
 	 */
 	@Test
@@ -233,55 +234,54 @@
 		replayAll();
 		
 		fm.init(context);
-		Boolean result = fm.addFlow(flowPath, new FlowId(0x100));
+		FlowId result = fm.addFlow(flowPath);
 
 		// verify the test
 		verifyAll();
-		assertTrue(result);
+		assertNotNull(result);
 	}
-	
+
 	/**
-	 * Test method for {@link FlowManager#deleteAllFlows()}.
-	 * @throws Exception 
+	 * Test method for {@link FlowManager#deleteFlow(FlowId)}.
+	 * @throws Exception
 	 */
 	@Test
-	public final void testDeleteAllFlowsSuccessNormally() throws Exception {
+	public final void testDeleteFlowSuccessNormally() throws Exception {
 		// create mock objects
-		IFlowPath flowPath1 = createNiceMock(IFlowPath.class);
-		IFlowPath flowPath2 = createNiceMock(IFlowPath.class);
+		IFlowPath flowPath = createIFlowPathMock(123, "id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 2, 3, 4);
+		IFlowEntry flowEntry1 = createMock(IFlowEntry.class);
+		IFlowEntry flowEntry2 = createMock(IFlowEntry.class);
+		IFlowEntry flowEntry3 = createMock(IFlowEntry.class);
 		
 		// instantiate required objects
-		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
-		flowPaths.add(flowPath1);
-		flowPaths.add(flowPath2);
 		FlowManager fm = new FlowManager();
-		
+		FlowId flowId = new FlowId(123);
+		ArrayList<IFlowEntry> flowEntries = new ArrayList<IFlowEntry>();
+		flowEntries.add(flowEntry1);
+		flowEntries.add(flowEntry2);
+		flowEntries.add(flowEntry3);
+
 		// setup expectations
 		expectInitWithContext();
-		expect(op.getAllFlowPaths()).andReturn(flowPaths);
-
-		expect(flowPath1.getFlowId()).andReturn("1").anyTimes();
-		expect(op.searchFlowPath(cmpEq(new FlowId(1)))).andReturn(flowPath1);
-		expect(flowPath1.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>());
-		op.removeFlowPath(flowPath1);
-		
-		expect(flowPath2.getFlowId()).andReturn("2").anyTimes();
-		expect(op.searchFlowPath(cmpEq(new FlowId(2)))).andReturn(flowPath2);
-		expect(flowPath2.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>());
-		op.removeFlowPath(flowPath2);
-
+		expect(op.searchFlowPath(cmpEq(flowId))).andReturn(flowPath);
+		expect(flowPath.getFlowEntries()).andReturn(flowEntries);
+		flowPath.removeFlowEntry(flowEntry1);
+		flowPath.removeFlowEntry(flowEntry2);
+		flowPath.removeFlowEntry(flowEntry3);
+		op.removeFlowEntry(flowEntry1);
+		op.removeFlowEntry(flowEntry2);
+		op.removeFlowEntry(flowEntry3);
+		op.removeFlowPath(flowPath);
 		op.commit();
-		expectLastCall().anyTimes();
 
 		// start the test
 		replayAll();
 		
 		fm.init(context);
-		Boolean result = fm.deleteAllFlows();
+		fm.deleteFlow(flowId);
 
 		// verify the test
 		verifyAll();
-		assertTrue(result);
 	}
 	
 	/**
@@ -316,16 +316,16 @@
 	}
 	
 	/**
-	 * Test method for {@link FlowManager#clearAllFlows()}.
+	 * Test method for {@link FlowManager#deleteAllFlows()}.
 	 * @throws Exception 
 	 */
 	@Test
-	public final void testClearAllFlowsSuccessNormally() throws Exception {
+	public final void testDeleteAllFlowsSuccessNormally() throws Exception {
 		// create mock objects
 		IFlowPath flowPath1 = createNiceMock(IFlowPath.class);
 		IFlowPath flowPath2 = createNiceMock(IFlowPath.class);
 		IFlowPath flowPath3 = createNiceMock(IFlowPath.class);
-		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, "clearFlow");
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, "deleteFlow");
 		
 		// instantiate required objects
 		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
@@ -340,16 +340,16 @@
 		expect(flowPath1.getFlowId()).andReturn(new FlowId(1).toString());
 		expect(flowPath2.getFlowId()).andReturn(null);
 		expect(flowPath3.getFlowId()).andReturn(new FlowId(3).toString());
-		expect(fm.clearFlow(cmpEq(new FlowId(1)))).andReturn(true);
-		expect(fm.clearFlow(cmpEq(new FlowId(3)))).andReturn(true);
+		expect(fm.deleteFlow(cmpEq(new FlowId(1)))).andReturn(true);
+		expect(fm.deleteFlow(cmpEq(new FlowId(3)))).andReturn(true);
 		
 		// start the test
 		replayAll();
 
 		fm.init(context);
-		Boolean result = fm.clearAllFlows();
+		Boolean result = fm.deleteAllFlows();
 		
-		//verify the test
+		// verify the test
 		verifyAll();
 		assertTrue(result);
 	}
@@ -389,110 +389,40 @@
 	}
 	
 	/**
-	 * Test method for {@link FlowManager#getAllFlows(CallerId, DataPathEndpoints)}.
-	 * @throws Exception 
-	 */ 
-	@Test
-	public final void testGetAllFlowsWithCallerIdAndDataPathEndpointsSuccessNormally() throws Exception {
-		final String getAllFlows = "getAllFlows";
-		// create mock objects
-		FlowManager fm = createPartialMock(FlowManager.class, getAllFlows,
-				new Class<?>[]{}, new Object[]{});
-
-		// instantiate required objects
-		DataPathEndpoints dataPathEndpoints = new DataPathEndpoints(
-				new SwitchPort(new Dpid(1), new Port((short)1)),
-				new SwitchPort(new Dpid(2), new Port((short)2)));
-
-		ArrayList<FlowPath> obtainedAllFlows = createTestFlowPaths();
-			
-		//setup expectations
-		expectInitWithContext();
-		expectPrivate(fm, getAllFlows).andReturn(obtainedAllFlows);
-		
-		//start the test
-		replayAll();
-		
-		fm.init(context);
-		ArrayList<FlowPath> flows = fm.getAllFlows(new CallerId("caller id"), dataPathEndpoints);
-
-		// verify the test
-		verifyAll();
-		assertEquals(1, flows.size());
-		assertEquals(obtainedAllFlows.get(1), flows.get(0));
-	}
-	
-	/**
-	 * Test method for {@link FlowManager#getAllFlows(DataPathEndpoints)}.
-	 * @throws Exception 
-	 */
-	@Test
-	public final void testGetAllFlowsWithDataPathEndpointsSuccessNormally() throws Exception {
-		final String getAllFlows = "getAllFlows";
-		// create mock objects
-		FlowManager fm = createPartialMock(FlowManager.class, getAllFlows,
-				new Class<?>[]{}, new Object[]{});
-
-		// instantiate required objects
-		DataPathEndpoints dataPathEndpoints = new DataPathEndpoints(
-				new SwitchPort(new Dpid(1), new Port((short)1)),
-				new SwitchPort(new Dpid(2), new Port((short)2)));
-
-		ArrayList<FlowPath> obtainedAllFlows = createTestFlowPaths();
-			
-		//setup expectations
-		expectInitWithContext();
-		expectPrivate(fm, getAllFlows).andReturn(obtainedAllFlows);
-		
-		//start the test
-		replayAll();
-		
-		fm.init(context);
-		ArrayList<FlowPath> flows = fm.getAllFlows(dataPathEndpoints);
-
-		// verify the test
-		verifyAll();
-		assertEquals(2, flows.size());
-		assertEquals(obtainedAllFlows.get(0), flows.get(0));
-		assertEquals(obtainedAllFlows.get(1), flows.get(1));
-		// TODO: ignore the order of flows in the list
-	}
-	
-	/**
 	 * Test method for {@link FlowManager#getAllFlowsSummary(FlowId, int)}.
 	 * @throws Exception 
 	 */
 	@Test
 	public final void testGetAllFlowsSummarySuccessNormally() throws Exception {
-		final String getAllFlowsWithoutFlowEntries = "getAllFlowsWithoutFlowEntries";
+		final String getAllFlowsWithDataPathSummary = "getAllFlowsWithDataPathSummary";
 		// create mock objects
-		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, getAllFlowsWithoutFlowEntries);
-		IFlowPath flowPath1 = createIFlowPathMock(1, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 2, 3, 4);
-		IFlowPath flowPath2 = createIFlowPathMock(5, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 2, 3, 4, 5);
-		IFlowPath flowPath3 = createIFlowPathMock(10, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 3, 4, 5, 6);
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, getAllFlowsWithDataPathSummary);
+		FlowPath flowPath1 = createTestFlowPath(1, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 2, 3, 4);
+		FlowPath flowPath2 = createTestFlowPath(5, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 2, 3, 4, 5);
+		FlowPath flowPath3 = createTestFlowPath(10, "", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 3, 4, 5, 6);
 
 		// instantiate required objects
-		ArrayList<IFlowPath> flows = new ArrayList<IFlowPath>();
+		ArrayList<FlowPath> flows = new ArrayList<FlowPath>();
 		flows.add(flowPath3);
 		flows.add(flowPath1);
 		flows.add(flowPath2);
 		
 		// setup expectations
 		expectInitWithContext();
-		expectPrivate(fm, getAllFlowsWithoutFlowEntries).andReturn(flows);
+		expectPrivate(fm, getAllFlowsWithDataPathSummary).andReturn(flows);
 
 		// start the test
 		replayAll();
 		
 		fm.init(context);
-		ArrayList<IFlowPath> returnedFlows = fm.getAllFlowsSummary(null, 0);
+		ArrayList<FlowPath> returnedFlows = fm.getAllFlowsSummary(null, 0);
 		
 		// verify the test
 		verifyAll();
 		assertEquals(3, returnedFlows.size());
-		assertEquals(1, new FlowId(returnedFlows.get(0).getFlowId()).value());
-		assertEquals(5, new FlowId(returnedFlows.get(1).getFlowId()).value());
-		assertEquals(10, new FlowId(returnedFlows.get(2).getFlowId()).value());
+		assertEquals(1, new FlowId(returnedFlows.get(0).flowId().value()).value());
+		assertEquals(5, new FlowId(returnedFlows.get(1).flowId().value()).value());
+		assertEquals(10, new FlowId(returnedFlows.get(2).flowId().value()).value());
 	}
 
 	/**
@@ -534,72 +464,6 @@
 		// TODO: more asserts
 		// TODO: ignore seq. of the list
 	}
-	
-	/**
-	 * Test method for {@link FlowManager#addAndMaintainShortestPathFlow(FlowPath)}.
-	 * @throws Exception 
-	 */
-	@Test
-	public final void testAddAndMaintainShortestPathFlowSuccessNormally() throws Exception {
-		final String addFlow = "addFlow";
-
-		// create mock objects
-		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlow);
-
-		// instantiate required objects
-		DataPath dataPath = new DataPath();
-		dataPath.setSrcPort(new SwitchPort(new Dpid(1), new Port((short)3)));
-		dataPath.setDstPort(new SwitchPort(new Dpid(2), new Port((short)4)));
-		FlowEntryMatch match = new FlowEntryMatch();
-		FlowPath paramFlow = new FlowPath();
-		paramFlow.setFlowId(new FlowId(100));
-		paramFlow.setInstallerId(new CallerId("installer id"));
-		paramFlow.setFlowPathType(FlowPathType.valueOf("FP_TYPE_SHORTEST_PATH"));
-		paramFlow.setFlowPathUserState(FlowPathUserState.valueOf("FP_USER_ADD"));
-		paramFlow.setFlowPathFlags(new FlowPathFlags(0));
-		paramFlow.setDataPath(dataPath);
-		paramFlow.setFlowEntryMatch(match);
-		
-		// setup expectations
-		expectInitWithContext();
-		expectPrivate(fm, addFlow,
-				EasyMock.anyObject(FlowPath.class),
-				EasyMock.anyObject(FlowId.class),
-				EasyMock.anyObject(String.class)
-				).andAnswer(new IAnswer<Object>() {
-					public Object answer() throws Exception {
-						FlowPath flowPath = (FlowPath)EasyMock.getCurrentArguments()[0];
-						assertEquals(flowPath.flowId().value(), 100);
-						assertEquals(flowPath.installerId().toString(), "installer id");
-						assertEquals(flowPath.flowPathType().toString(), "PF_TYPE_SHORTEST_PATH");
-						assertEquals(flowPath.flowPathUserState().toString(), "PF_USER_STATE");
-						assertEquals(flowPath.flowPathFlags().flags(), 0);
-						assertEquals(flowPath.dataPath().srcPort().toString(),
-								new SwitchPort(new Dpid(1), new Port((short)3)).toString());
-
-						String dataPathSummary = (String)EasyMock.getCurrentArguments()[2];
-						assertEquals(dataPathSummary, "X");
-						
-						return true;
-					}
-				});
-		
-		// start the test
-		replayAll();
-
-		fm.init(context);
-		FlowPath resultFlow = fm.addAndMaintainShortestPathFlow(paramFlow);
-				
-		// verify the test
-		verifyAll();
-		assertEquals(paramFlow.flowId().value(), resultFlow.flowId().value());
-		assertEquals(paramFlow.installerId().toString(), resultFlow.installerId().toString());
-		assertEquals(paramFlow.flowPathType().toString(), resultFlow.flowPathType().toString());
-		assertEquals(paramFlow.flowPathUserState().toString(), resultFlow.flowPathUserState().toString());
-		assertEquals(paramFlow.flowPathFlags().flags(), resultFlow.flowPathFlags().flags());
-		assertEquals(paramFlow.dataPath().toString(), resultFlow.dataPath().toString());
-		assertEquals(paramFlow.flowEntryMatch().toString(), resultFlow.flowEntryMatch().toString());
-	}
 		
 	// INetMapStorage methods
 	
@@ -786,85 +650,6 @@
 	
 	// other methods
 	
-	
-	/**
-	 * Test method for {@link FlowManager#clearFlow(FlowId)}.
-	 * @throws Exception
-	 */
-	@Test
-	public final void testClearFlowSuccessNormally() throws Exception {
-		// create mock objects
-		IFlowPath flowPath = createIFlowPathMock(123, "id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 2, 3, 4);
-		IFlowEntry flowEntry1 = createMock(IFlowEntry.class);
-		IFlowEntry flowEntry2 = createMock(IFlowEntry.class);
-		IFlowEntry flowEntry3 = createMock(IFlowEntry.class);
-		
-		// instantiate required objects
-		FlowManager fm = new FlowManager();
-		FlowId flowId = new FlowId(123);
-		ArrayList<IFlowEntry> flowEntries = new ArrayList<IFlowEntry>();
-		flowEntries.add(flowEntry1);
-		flowEntries.add(flowEntry2);
-		flowEntries.add(flowEntry3);
-
-		// setup expectations
-		expectInitWithContext();
-		expect(op.searchFlowPath(cmpEq(flowId))).andReturn(flowPath);
-		expect(flowPath.getFlowEntries()).andReturn(flowEntries);
-		flowPath.removeFlowEntry(flowEntry1);
-		flowPath.removeFlowEntry(flowEntry2);
-		flowPath.removeFlowEntry(flowEntry3);
-		op.removeFlowEntry(flowEntry1);
-		op.removeFlowEntry(flowEntry2);
-		op.removeFlowEntry(flowEntry3);
-		op.removeFlowPath(flowPath);
-		op.commit();
-
-		// start the test
-		replayAll();
-		
-		fm.init(context);
-		fm.clearFlow(flowId);
-
-		// verify the test
-		verifyAll();
-	}
-	
-	/**
-	 * Test method for {@link FlowManager#getAllFlowsWithoutFlowEntries()}.
-	 * @throws Exception 
-	 */
-	@Test
-	public final void testGetAllFlowsWithoutFlowEntriesSuccessNormally() throws Exception {
-		// create mock objects
-		IFlowPath iFlowPath1 = createIFlowPathMock(1, "caller id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 1, 1, 2, 2); 
-		IFlowPath iFlowPath2 = createIFlowPathMock(2, "caller id", "FP_TYPE_SHORTEST_PATH", "FP_USER_ADD", 0, 2, 5, 3, 5);
-		
-		// instantiate required objects
-		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
-		flowPaths.add(iFlowPath1);
-		flowPaths.add(iFlowPath2);
-		FlowManager fm = new FlowManager();
-		
-		// setup expectations
-		expectInitWithContext();
-		op.commit();
-		expect(op.getAllFlowPaths()).andReturn(flowPaths);
-		
-		// start the test
-		replayAll();
-		
-		fm.init(context);
-		ArrayList<IFlowPath> result = fm.getAllFlowsWithoutFlowEntries();
-		
-		// verify the test
-		verifyAll();
-		assertEquals(iFlowPath1, result.get(0));
-		assertEquals(iFlowPath2, result.get(1));
-		
-		// TODO: does this method just return the replica of the flow paths?
-	}
-	
 	/**
 	 * Test method for {@link FlowManager#reconcileFlow(IFlowPath, DataPath)}.
 	 * @throws Exception
@@ -926,7 +711,7 @@
 		fm.init(context);
 		// Use reflection to test the private method
 		// Boolean result = fm.reconcileFlow(iFlowPath1, dataPath);
-		Class fmClass = FlowManager.class;
+		Class<?> fmClass = FlowManager.class;
 		Method method = fmClass.getDeclaredMethod(
 			"reconcileFlow",
 			new Class[] { IFlowPath.class, DataPath.class });
@@ -988,7 +773,7 @@
 		fm.init(context);
 		// Use reflection to test the private method
 		// Boolean result = fm.installFlowEntry(iofSwitch, iFlowPath, iFlowEntry);
-		Class fmClass = FlowManager.class;
+		Class<?> fmClass = FlowManager.class;
 		Method method = fmClass.getDeclaredMethod(
 			"installFlowEntry",
 			new Class[] { IOFSwitch.class, IFlowPath.class, IFlowEntry.class });
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java
new file mode 100644
index 0000000..4779b75
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java
@@ -0,0 +1,544 @@
+package net.onrc.onos.ofcontroller.flowprogrammer;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.floodlightcontroller.util.OFMessageDamper;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
+import net.onrc.onos.ofcontroller.util.FlowEntryErrorState;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
+import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.Port;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.Test;
+import org.openflow.protocol.OFBarrierRequest;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.factory.BasicFactory;
+
+public class FlowPusherTest {
+	private FlowPusher pusher;
+	private FloodlightContext context;
+	private FloodlightModuleContext modContext;
+	private BasicFactory factory;
+	private OFMessageDamper damper;
+	private IFloodlightProviderService flProviderService;
+	private IThreadPoolService threadPoolService;
+	private IFlowService flowService;
+
+	/**
+	 * Test single OFMessage is correctly sent to single switch via MessageDamper.
+	 */
+	@Test
+	public void testAddMessage() {
+		beginInitMock();
+		
+		OFMessage msg = EasyMock.createMock(OFMessage.class);
+		EasyMock.expect(msg.getXid()).andReturn(1).anyTimes();
+		EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+		EasyMock.replay(msg);
+		
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		sw.flush();
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(sw);
+		
+		try {
+			EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.eq(msg), EasyMock.eq(context)))
+				.andReturn(true).once();
+		} catch (IOException e1) {
+			fail("Failed in OFMessageDamper#write()");
+		}
+		
+		endInitMock();
+		initPusher(1);
+		
+		boolean add_result = pusher.add(sw, msg);
+		assertTrue(add_result);
+		
+		try {
+			// wait until message is processed.
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			fail("Failed in Thread.sleep()");
+		}
+		
+		EasyMock.verify(msg);
+		EasyMock.verify(sw);
+		
+		pusher.stop();
+	}
+	
+	/**
+	 * Test bunch of OFMessages are correctly sent to single switch via MessageDamper.
+	 */
+	@Test
+	public void testMassiveAddMessage() {
+		final int NUM_MSG = 10000;
+		
+		beginInitMock();
+
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		sw.flush();
+		EasyMock.expectLastCall().atLeastOnce();
+		EasyMock.replay(sw);
+		
+		List<OFMessage> messages = new ArrayList<OFMessage>();
+		
+		for (int i = 0; i < NUM_MSG; ++i) {
+			OFMessage msg = EasyMock.createMock(OFMessage.class);
+			EasyMock.expect(msg.getXid()).andReturn(i).anyTimes();
+			EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+			EasyMock.replay(msg);
+			messages.add(msg);
+			
+			try {
+				EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.eq(msg), EasyMock.eq(context)))
+					.andReturn(true).once();
+			} catch (IOException e1) {
+				fail("Failed in OFMessageDamper#write()");
+			}
+		}
+		
+		endInitMock();
+		initPusher(1);
+		
+		for (OFMessage msg : messages) {
+			boolean add_result = pusher.add(sw, msg);
+			assertTrue(add_result);
+		}
+		
+		try {
+			// wait until message is processed.
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			fail("Failed in Thread.sleep()");
+		}
+		
+		for (OFMessage msg : messages) {
+			EasyMock.verify(msg);
+		}
+		EasyMock.verify(sw);
+		
+		pusher.stop();
+	}
+	
+	/**
+	 * Test bunch of OFMessages are correctly sent to multiple switches with single threads.
+	 */
+	@Test
+	public void testMultiSwitchAddMessage() {
+		final int NUM_SWITCH = 10;
+		final int NUM_MSG = 100;	// messages per thread
+		
+		beginInitMock();
+
+		Map<IOFSwitch, List<OFMessage>> sw_map = new HashMap<IOFSwitch, List<OFMessage>>();
+		for (int i = 0; i < NUM_SWITCH; ++i) {
+			IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+			EasyMock.expect(sw.getId()).andReturn((long)i).anyTimes();
+			sw.flush();
+			EasyMock.expectLastCall().atLeastOnce();
+			EasyMock.replay(sw);
+			
+			List<OFMessage> messages = new ArrayList<OFMessage>();
+			
+			for (int j = 0; j < NUM_MSG; ++j) {
+				OFMessage msg = EasyMock.createMock(OFMessage.class);
+				EasyMock.expect(msg.getXid()).andReturn(j).anyTimes();
+				EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+				EasyMock.replay(msg);
+				messages.add(msg);
+				
+				try {
+					EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.eq(msg), EasyMock.eq(context)))
+						.andReturn(true).once();
+				} catch (IOException e1) {
+					fail("Failed in OFMessageDamper#write()");
+				}
+			}
+			sw_map.put(sw, messages);
+		}
+		
+		endInitMock();
+		initPusher(1);
+		
+		for (IOFSwitch sw : sw_map.keySet()) {
+			for (OFMessage msg : sw_map.get(sw)) {
+				boolean add_result = pusher.add(sw, msg);
+				assertTrue(add_result);
+			}
+		}
+		
+		try {
+			// wait until message is processed.
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			fail("Failed in Thread.sleep()");
+		}
+		
+		for (IOFSwitch sw : sw_map.keySet()) {
+			for (OFMessage msg : sw_map.get(sw)) {
+				EasyMock.verify(msg);
+			}
+			
+			EasyMock.verify(sw);
+		}
+		
+		pusher.stop();
+	}
+	
+	/**
+	 * Test bunch of OFMessages are correctly sent to multiple switches using multiple threads.
+	 */
+	@Test
+	public void testMultiThreadedAddMessage() {
+		final int NUM_THREAD = 10;
+		final int NUM_MSG = 100;	// messages per thread
+		
+		beginInitMock();
+
+		Map<IOFSwitch, List<OFMessage>> sw_map = new HashMap<IOFSwitch, List<OFMessage>>();
+		for (int i = 0; i < NUM_THREAD; ++i) {
+			IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+			EasyMock.expect(sw.getId()).andReturn((long)i).anyTimes();
+			sw.flush();
+			EasyMock.expectLastCall().atLeastOnce();
+			EasyMock.replay(sw);
+			
+			List<OFMessage> messages = new ArrayList<OFMessage>();
+			
+			for (int j = 0; j < NUM_MSG; ++j) {
+				OFMessage msg = EasyMock.createMock(OFMessage.class);
+				EasyMock.expect(msg.getXid()).andReturn(j).anyTimes();
+				EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+				EasyMock.replay(msg);
+				messages.add(msg);
+				
+				try {
+					EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.eq(msg), EasyMock.eq(context)))
+						.andReturn(true).once();
+				} catch (IOException e1) {
+					fail("Failed in OFMessageDamper#write()");
+				}
+			}
+			sw_map.put(sw, messages);
+		}
+		
+		endInitMock();
+		initPusher(NUM_THREAD);
+		
+		for (IOFSwitch sw : sw_map.keySet()) {
+			for (OFMessage msg : sw_map.get(sw)) {
+				boolean add_result = pusher.add(sw, msg);
+				assertTrue(add_result);
+			}
+		}
+		
+		try {
+			// wait until message is processed.
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			fail("Failed in Thread.sleep()");
+		}
+		
+		for (IOFSwitch sw : sw_map.keySet()) {
+			for (OFMessage msg : sw_map.get(sw)) {
+				EasyMock.verify(msg);
+			}
+			
+			EasyMock.verify(sw);
+		}
+		
+		pusher.stop();
+	}
+	
+	private long barrierTime = 0;
+	/**
+	 * Test rate limitation of messages works correctly.
+	 */
+	@Test
+	public void testRateLimitedAddMessage() {
+		final long LIMIT_RATE = 100; // [bytes/ms]
+		final int NUM_MSG = 1000;
+		
+		// Accuracy of FlowPusher's rate calculation can't be measured by unit test
+		// because switch doesn't return BARRIER_REPLY.
+		// In unit test we use approximate way to measure rate. This value is 
+		// acceptable margin of measured rate.
+		final double ACCEPTABLE_RATE = LIMIT_RATE * 1.2;
+		
+		beginInitMock();
+
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		sw.flush();
+		EasyMock.expectLastCall().atLeastOnce();
+		prepareBarrier(sw);
+		EasyMock.replay(sw);
+		
+		List<OFMessage> messages = new ArrayList<OFMessage>();
+		
+		for (int i = 0; i < NUM_MSG; ++i) {
+			OFMessage msg = EasyMock.createMock(OFMessage.class);
+			EasyMock.expect(msg.getXid()).andReturn(1).anyTimes();
+			EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+			EasyMock.expect(msg.getLengthU()).andReturn(100).anyTimes();
+			EasyMock.replay(msg);
+			messages.add(msg);
+			
+			try {
+				EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.eq(msg), EasyMock.eq(context)))
+					.andReturn(true).once();
+			} catch (IOException e) {
+				fail("Failed in OFMessageDamper#write()");
+			}
+		}
+		
+		try {
+			EasyMock.expect(damper.write(EasyMock.eq(sw), (OFMessage)EasyMock.anyObject(), EasyMock.eq(context)))
+				.andAnswer(new IAnswer<Boolean>() {
+					@Override
+					public Boolean answer() throws Throwable {
+						OFMessage msg = (OFMessage)EasyMock.getCurrentArguments()[1];
+						if (msg.getType() == OFType.BARRIER_REQUEST) {
+							barrierTime = System.currentTimeMillis();
+						}
+						return true;
+					}
+				}).once();
+		} catch (IOException e1) {
+			fail("Failed in OFMessageDamper#write()");
+		}
+
+		endInitMock();
+		initPusher(1);
+		
+		pusher.createQueue(sw);
+		pusher.setRate(sw, LIMIT_RATE);
+		
+		long beginTime = System.currentTimeMillis();
+		for (OFMessage msg : messages) {
+			boolean add_result = pusher.add(sw, msg);
+			assertTrue(add_result);
+		}
+		
+		pusher.barrierAsync(sw);
+
+		try {
+			do {
+				Thread.sleep(1000);
+			} while (barrierTime == 0);
+		} catch (InterruptedException e) {
+			fail("Failed to sleep");
+		}
+		
+		double measured_rate = NUM_MSG * 100 /  (barrierTime - beginTime);
+		assertTrue(measured_rate < ACCEPTABLE_RATE);
+		
+		for (OFMessage msg : messages) {
+			EasyMock.verify(msg);
+		}
+		EasyMock.verify(sw);
+		
+		pusher.stop();
+	}
+
+	/**
+	 * Test barrier message is correctly sent to a switch.
+	 */
+	@Test
+	public void testBarrierMessage() {
+		beginInitMock();
+		
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		sw.flush();
+		EasyMock.expectLastCall().atLeastOnce();
+		prepareBarrier(sw);
+		EasyMock.replay(sw);
+
+		try {
+			EasyMock.expect(damper.write(EasyMock.eq(sw), (OFMessage)EasyMock.anyObject(), EasyMock.eq(context)))
+				.andReturn(true).once();
+		} catch (IOException e1) {
+			fail("Failed in OFMessageDamper#write()");
+		}
+
+		endInitMock();
+		initPusher(1);
+
+		OFBarrierReplyFuture future = pusher.barrierAsync(sw);
+		
+		assertNotNull(future);
+		pusher.stop();
+	}
+	
+	/**
+	 * Test FlowObject is correctly converted to message and is sent to a switch.
+	 */
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testAddFlow() {
+		// Code below are copied from FlowManagerTest
+		
+		// instantiate required objects
+		FlowEntry flowEntry1 = new FlowEntry();
+		flowEntry1.setDpid(new Dpid(1));
+		flowEntry1.setFlowId(new FlowId(1));
+		flowEntry1.setInPort(new Port((short) 1));
+		flowEntry1.setOutPort(new Port((short) 11));
+		flowEntry1.setFlowEntryId(new FlowEntryId(1));
+		flowEntry1.setFlowEntryMatch(new FlowEntryMatch());
+		flowEntry1.setFlowEntryActions(new FlowEntryActions());
+		flowEntry1.setFlowEntryErrorState(new FlowEntryErrorState());
+		flowEntry1.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
+		
+		beginInitMock();
+		
+		OFFlowMod msg = EasyMock.createMock(OFFlowMod.class);
+		EasyMock.expect(msg.setIdleTimeout(EasyMock.anyShort())).andReturn(msg);
+		EasyMock.expect(msg.setHardTimeout(EasyMock.anyShort())).andReturn(msg);
+		EasyMock.expect(msg.setPriority(EasyMock.anyShort())).andReturn(msg);
+		EasyMock.expect(msg.setBufferId(EasyMock.anyInt())).andReturn(msg);
+		EasyMock.expect(msg.setCookie(EasyMock.anyLong())).andReturn(msg);
+		EasyMock.expect(msg.setCommand(EasyMock.anyShort())).andReturn(msg);
+		EasyMock.expect(msg.setMatch(EasyMock.anyObject(OFMatch.class))).andReturn(msg);
+		EasyMock.expect(msg.setActions((List<OFAction>)EasyMock.anyObject())).andReturn(msg);
+		EasyMock.expect(msg.setLengthU(EasyMock.anyShort())).andReturn(msg);
+		EasyMock.expect(msg.setOutPort(EasyMock.anyShort())).andReturn(msg).atLeastOnce();
+		EasyMock.expect(msg.getXid()).andReturn(1).anyTimes();
+		EasyMock.expect(msg.getType()).andReturn(OFType.FLOW_MOD).anyTimes();
+		EasyMock.expect(msg.getLength()).andReturn((short)100).anyTimes();
+		EasyMock.replay(msg);
+		
+		EasyMock.expect(factory.getMessage(EasyMock.eq(OFType.FLOW_MOD))).andReturn(msg);
+		
+		ScheduledExecutorService executor = EasyMock.createMock(ScheduledExecutorService.class);
+		EasyMock.expect(executor.schedule((Runnable)EasyMock.anyObject(), EasyMock.anyLong(),
+				(TimeUnit)EasyMock.anyObject())).andReturn(null).once();
+		EasyMock.replay(executor);
+		EasyMock.expect(threadPoolService.getScheduledExecutor()).andReturn(executor);
+
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		EasyMock.expect(sw.getStringId()).andReturn("1").anyTimes();
+		sw.flush();
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(sw);
+		
+		try {
+			EasyMock.expect(damper.write(EasyMock.eq(sw), EasyMock.anyObject(OFMessage.class), EasyMock.eq(context)))
+				.andAnswer(new IAnswer<Boolean>() {
+					@Override
+					public Boolean answer() throws Throwable {
+						OFMessage msg = (OFMessage)EasyMock.getCurrentArguments()[1];
+						assertEquals(msg.getType(), OFType.FLOW_MOD);
+						return true;
+					}
+				}).once();
+		} catch (IOException e1) {
+			fail("Failed in OFMessageDamper#write()");
+		}
+		
+		endInitMock();
+		initPusher(1);
+
+		pusher.pushFlowEntry(sw, flowEntry1);
+		
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+			fail("Failed to sleep");
+		}
+		
+		EasyMock.verify(sw);
+		
+		pusher.stop();
+	}
+	
+	@SuppressWarnings("unchecked")
+	private void beginInitMock() {
+		context = EasyMock.createMock(FloodlightContext.class);
+		modContext = EasyMock.createMock(FloodlightModuleContext.class);
+		factory = EasyMock.createMock(BasicFactory.class);
+		damper = EasyMock.createMock(OFMessageDamper.class);
+		flProviderService = EasyMock.createMock(IFloodlightProviderService.class);
+		threadPoolService = EasyMock.createMock(IThreadPoolService.class);
+		flowService = EasyMock.createMock(IFlowService.class);
+		
+		flowService.flowEntriesPushedToSwitch(EasyMock.anyObject(Collection.class));
+		EasyMock.expectLastCall().anyTimes();
+		
+		EasyMock.expect(modContext.getServiceImpl(EasyMock.eq(IThreadPoolService.class)))
+			.andReturn(threadPoolService).once();
+		EasyMock.expect(modContext.getServiceImpl(EasyMock.eq(IFloodlightProviderService.class)))
+			.andReturn(flProviderService).once();
+		EasyMock.expect(modContext.getServiceImpl(EasyMock.eq(IFlowService.class)))
+			.andReturn(flowService).once();
+		flProviderService.addOFMessageListener(EasyMock.eq(OFType.BARRIER_REPLY),
+				(FlowPusher) EasyMock.anyObject());
+		EasyMock.expectLastCall().once();
+	}
+	
+	private void endInitMock() {
+		EasyMock.replay(flowService);
+		EasyMock.replay(threadPoolService);
+		EasyMock.replay(flProviderService);
+		EasyMock.replay(damper);
+		EasyMock.replay(factory);
+		EasyMock.replay(modContext);
+		EasyMock.replay(context);
+	}
+	
+	private void initPusher(int num_thread) {
+		pusher = new FlowPusher(num_thread);
+		pusher.init(context, modContext, factory, damper);
+		pusher.start();
+	}
+	
+	private void prepareBarrier(IOFSwitch sw) {
+		OFBarrierRequest req = EasyMock.createMock(OFBarrierRequest.class);
+		req.setXid(EasyMock.anyInt());
+		EasyMock.expectLastCall().once();
+		EasyMock.expect(req.getXid()).andReturn(1).anyTimes();
+		EasyMock.expect(req.getType()).andReturn(OFType.BARRIER_REQUEST).anyTimes();
+		EasyMock.expect(req.getLength()).andReturn((short)100).anyTimes();
+		EasyMock.replay(req);
+		EasyMock.expect(factory.getMessage(EasyMock.eq(OFType.BARRIER_REQUEST))).andReturn(req);
+		
+		ScheduledExecutorService executor = EasyMock.createMock(ScheduledExecutorService.class);
+		EasyMock.expect(executor.schedule((Runnable)EasyMock.anyObject(), EasyMock.anyLong(),
+				(TimeUnit)EasyMock.anyObject())).andReturn(null).once();
+		EasyMock.replay(executor);
+		EasyMock.expect(threadPoolService.getScheduledExecutor()).andReturn(executor);
+
+		EasyMock.expect(sw.getNextTransactionId()).andReturn(1);
+	}
+	
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java
new file mode 100644
index 0000000..68b4f1f
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizerTest.java
@@ -0,0 +1,313 @@
+package net.onrc.onos.ofcontroller.flowprogrammer;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.flowmanager.FlowDatabaseOperation;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowSyncService.SyncResult;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFStatisticsRequest;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.statistics.OFFlowStatisticsReply;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FlowSynchronizer.class, GraphDBOperation.class, FlowDatabaseOperation.class})
+public class FlowSynchronizerTest {
+	private FlowPusher pusher;
+	private FlowSynchronizer sync;
+	private List<Long> idAdded;
+	private List<Long> idRemoved;
+
+	@Before
+	public void setUp() throws Exception {
+		idAdded = new ArrayList<Long>();
+		idRemoved = new ArrayList<Long>();
+		
+		pusher = EasyMock.createMock(FlowPusher.class);
+		pusher.add(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(OFMessage.class));
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+				@Override
+				public Object answer() throws Throwable {
+					OFMessage msg = (OFMessage)EasyMock.getCurrentArguments()[1];
+					if (msg.getType().equals(OFType.FLOW_MOD)) {
+						OFFlowMod fm = (OFFlowMod)msg;
+						if (fm.getCommand() == OFFlowMod.OFPFC_DELETE_STRICT) {
+							idRemoved.add(fm.getCookie());
+						}
+					}
+					return null;
+				}
+			}).anyTimes();
+		pusher.pushFlowEntry(EasyMock.anyObject(IOFSwitch.class), EasyMock.anyObject(FlowEntry.class));
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+			@Override
+			public Object answer() throws Throwable {
+				FlowEntry flow = (FlowEntry)EasyMock.getCurrentArguments()[1];
+				idAdded.add(flow.flowEntryId().value());
+				return null;
+			}
+		}).anyTimes();
+		EasyMock.replay(pusher);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	/**
+	 * Test that synchronization doesn't affect anything in case either DB and
+	 * flow table has the same entries.
+	 */
+	@Test
+	public void testStable() {
+		// Create mock of flow table : flow 1
+		IOFSwitch sw = createMockSwitch(new long[] {1});
+		
+		// Create mock of flow entries : flow 1
+		initMockGraph(new long[] {1});
+		
+		// synchronize
+		doSynchronization(sw);
+		
+		// check if flow is not changed
+		assertEquals(0, idAdded.size());
+		assertEquals(0, idRemoved.size());
+	}
+
+	/**
+	 * Test that an flow is added in case DB has an extra FlowEntry.
+	 */
+	@Test
+	public void testSingleAdd() {
+		// Create mock of flow table : null
+		IOFSwitch sw = createMockSwitch(new long[] {});
+		
+		// Create mock of flow entries : flow 1
+		initMockGraph(new long[] {1});
+		
+		// synchronize
+		doSynchronization(sw);
+		
+		// check if single flow is installed
+		assertEquals(1, idAdded.size());
+		assertTrue(idAdded.contains((long)1));
+		assertEquals(0, idRemoved.size());
+	}
+
+	/**
+	 * Test that an flow is deleted in case switch has an extra FlowEntry.
+	 */
+	@Test
+	public void testSingleDelete() {
+		// Create mock of flow table : flow 1
+		IOFSwitch sw = createMockSwitch(new long[] {1});
+		
+		// Create mock of flow entries : null
+		initMockGraph(new long[] {});
+		
+		// synchronize
+		doSynchronization(sw);
+		
+		// check if single flow is deleted
+		assertEquals(0, idAdded.size());
+		assertEquals(1, idRemoved.size());
+		assertTrue(idRemoved.contains((long)1));
+	}
+	
+	/**
+	 * Test that appropriate flows are added and other appropriate flows are deleted
+	 * in case flows in DB are overlapping flows in switch.
+	 */
+	@Test
+	public void testMixed() {
+		// Create mock of flow table : flow 1,2,3
+		IOFSwitch sw = createMockSwitch(new long[] {1,2,3});
+		
+		// Create mock of flow entries : flow 2,3,4,5
+		initMockGraph(new long[] {2,3,4,5});
+		
+		// synchronize
+		doSynchronization(sw);
+		
+		// check if two flows {4,5} is installed and one flow {1} is deleted
+		assertEquals(2, idAdded.size());
+		assertTrue(idAdded.contains((long)4));
+		assertTrue(idAdded.contains((long)5));
+		assertEquals(1, idRemoved.size());
+		assertTrue(idRemoved.contains((long)1));
+	}
+	
+
+	@Test
+	public void testMassive() {
+		// Create mock of flow table : flow 0-1999
+		long [] swIdList = new long [2000];
+		for (long i = 0; i < 2000; ++i) {
+			swIdList[(int)i] = i;
+		}
+		IOFSwitch sw = createMockSwitch(swIdList);
+		
+		// Create mock of flow entries : flow 1500-3499
+		long [] dbIdList = new long [2000];
+		for (long i = 0; i < 2000; ++i) {
+			dbIdList[(int)i] = 1500 + i;
+		}
+		initMockGraph(dbIdList);
+
+		// synchronize
+		doSynchronization(sw);
+		
+		// check if 1500 flows {2000-3499} is installed and 1500 flows {0,...,1499} is deleted
+		assertEquals(1500, idAdded.size());
+		for (long i = 2000; i < 3500; ++i) {
+			assertTrue(idAdded.contains(i));
+		}
+		assertEquals(1500, idRemoved.size());
+		for (long i = 0; i < 1500; ++i) {
+			assertTrue(idRemoved.contains(i));
+		}
+	}
+
+	/**
+	 * Create mock IOFSwitch with flow table which has arbitrary flows.
+	 * @param cookieList List of FlowEntry IDs switch has.
+	 * @return Mock object.
+	 */
+	private IOFSwitch createMockSwitch(long[] cookieList) {
+		IOFSwitch sw = EasyMock.createMock(IOFSwitch.class);
+		EasyMock.expect(sw.getId()).andReturn((long)1).anyTimes();
+		
+		List<OFStatistics> stats = new ArrayList<OFStatistics>();
+		for (long cookie : cookieList) {
+			stats.add(createReply(cookie));
+		}
+		
+		@SuppressWarnings("unchecked")
+		Future<List<OFStatistics>> future = EasyMock.createMock(Future.class);
+		try {
+			EasyMock.expect(future.get()).andReturn(stats).once();
+		} catch (InterruptedException e1) {
+			fail("Failed in Future#get()");
+		} catch (ExecutionException e1) {
+			fail("Failed in Future#get()");
+		}
+		EasyMock.replay(future);
+		
+		try {
+			EasyMock.expect(sw.getStatistics(EasyMock.anyObject(OFStatisticsRequest.class)))
+				.andReturn(future).once();
+		} catch (IOException e) {
+			fail("Failed in IOFSwitch#getStatistics()");
+		}
+		
+		EasyMock.replay(sw);
+		return sw;
+	}
+	
+	/**
+	 * Create single OFFlowStatisticsReply object which is actually obtained from switch.
+	 * @param cookie Cookie value, which indicates ID of FlowEntry installed to switch.
+	 * @return Created object.
+	 */
+	private OFFlowStatisticsReply createReply(long cookie) {
+		OFFlowStatisticsReply stat = new OFFlowStatisticsReply();
+		OFMatch match = new OFMatch();
+		
+		stat.setCookie(cookie);
+		stat.setMatch(match);
+		stat.setPriority((short)1);
+
+		return stat;
+	}
+	
+	/**
+	 * Create mock GraphDBOperation and FlowDatabaseOperation to mock DB.
+	 * @param idList List of FlowEntry IDs stored in DB.
+	 */
+	private void initMockGraph(long[] idList) {
+		List<IFlowEntry> flowEntryList = new ArrayList<IFlowEntry>();
+		
+		for (long id : idList) {
+			IFlowEntry entry = EasyMock.createMock(IFlowEntry.class);
+			EasyMock.expect(entry.getFlowEntryId()).andReturn(String.valueOf(id)).anyTimes();
+			EasyMock.replay(entry);
+			flowEntryList.add(entry);
+		}
+		
+		ISwitchObject swObj = EasyMock.createMock(ISwitchObject.class);
+		EasyMock.expect(swObj.getFlowEntries()).andReturn(flowEntryList).once();
+		EasyMock.replay(swObj);
+		
+		GraphDBOperation mockOp = PowerMock.createMock(GraphDBOperation.class);
+		EasyMock.expect(mockOp.searchSwitch(EasyMock.anyObject(String.class))).andReturn(swObj).once();
+		
+		PowerMock.mockStatic(FlowDatabaseOperation.class);
+		for (IFlowEntry entry : flowEntryList) {
+			EasyMock.expect(FlowDatabaseOperation.extractFlowEntry(EasyMock.eq(entry)))
+				.andAnswer(new IAnswer<FlowEntry>() {
+					@Override
+					public FlowEntry answer() throws Throwable {
+						IFlowEntry iflow = (IFlowEntry)EasyMock.getCurrentArguments()[0];
+						long flowEntryId = Long.valueOf(iflow.getFlowEntryId());
+						
+						FlowEntry flow = EasyMock.createMock(FlowEntry.class);
+						EasyMock.expect(flow.flowEntryId()).andReturn(new FlowEntryId(flowEntryId)).anyTimes();
+						EasyMock.replay(flow);
+						return flow;
+					}
+					
+				}).anyTimes();
+			EasyMock.expect(mockOp.searchFlowEntry(EasyMock.eq(new FlowEntryId(entry.getFlowEntryId()))))
+				.andReturn(entry);
+		}
+		PowerMock.replay(FlowDatabaseOperation.class);
+		EasyMock.replay(mockOp);
+		
+		try {
+			PowerMock.expectNew(GraphDBOperation.class, "").andReturn(mockOp);
+		} catch (Exception e) {
+			fail("Failed to create GraphDBOperation");
+		}
+		PowerMock.replay(GraphDBOperation.class);
+	}
+	
+	/**
+	 * Instantiate FlowSynchronizer and sync flows.
+	 * @param sw Target IOFSwitch object
+	 */
+	private void doSynchronization(IOFSwitch sw) {
+		sync = new FlowSynchronizer();
+		sync.init(pusher);
+		Future<SyncResult> future = sync.synchronize(sw);
+		try {
+			future.get();
+		} catch (Exception e) {
+			fail("Failed to Future#get()");
+		}
+	}
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
index 09d0a00..e054e05 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/topology/TopologyManagerTest.java
@@ -2,7 +2,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import java.util.Map;
 
 import org.easymock.EasyMock;
 
diff --git a/src/test/java/net/onrc/onos/ofcontroller/util/FlowEntryTest.java b/src/test/java/net/onrc/onos/ofcontroller/util/FlowEntryTest.java
index fc17178..696f9e5 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/util/FlowEntryTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/util/FlowEntryTest.java
@@ -13,6 +13,8 @@
 	
 	FlowId flowId = new FlowId(0x1234);
 	FlowEntryId flowEntryId = new FlowEntryId(0x5678);
+	int idleTimeout = 5;
+	int hardTimeout = 10;
 	FlowEntryMatch match;
 	FlowEntryActions actions;
 	
@@ -50,6 +52,9 @@
 
 		flowEntryId = new FlowEntryId("0x5678");
 		entry.setFlowEntryId(flowEntryId);
+
+		entry.setIdleTimeout(5);
+		entry.setHardTimeout(10);
 		
 		dpid = new Dpid("CA:FE");
 		entry.setDpid( dpid );
@@ -188,6 +193,16 @@
 	}
 
 	@Test
+	public void testIdleTimeout(){
+		assertEquals("idleTimeout", idleTimeout, entry.idleTimeout() );
+	}
+
+	@Test
+	public void testHardTimeout(){
+		assertEquals("hardTimeout", hardTimeout, entry.hardTimeout() );
+	}
+
+	@Test
 	public void testFlowEntryMatch(){
 		assertEquals("flowEntryMatch", match, entry.flowEntryMatch() );
 	}
@@ -237,8 +252,8 @@
 	@Test
 	public void testToString(){
 		FlowEntry def = new FlowEntry();
-		assertEquals("toString", def.toString(), "[ flowEntryActions=[] flowEntryUserState=FE_USER_UNKNOWN flowEntrySwitchState=FE_SWITCH_UNKNOWN]" );
-		assertEquals("toString", entry.toString(), "[flowEntryId=0x5678 flowId=0x1234 flowEntryMatch=[inPort=1 srcMac=01:02:03:04:05:06 dstMac=06:05:04:03:02:01 ethernetFrameType=2 vlanId=3 vlanPriority=4 srcIPv4Net=127.0.0.1/32 dstIPv4Net=127.0.0.2/32 ipProto=5 ipToS=6 srcTcpUdpPort=7 dstTcpUdpPort=8] flowEntryActions=[[type=ACTION_OUTPUT action=[port=9 maxLen=0]];[type=ACTION_OUTPUT action=[port=-3 maxLen=0]];[type=ACTION_SET_VLAN_VID action=[vlanId=3]];[type=ACTION_SET_VLAN_PCP action=[vlanPriority=4]];[type=ACTION_STRIP_VLAN action=[stripVlan=true]];[type=ACTION_SET_DL_SRC action=[addr=01:02:03:04:05:06]];[type=ACTION_SET_DL_DST action=[addr=06:05:04:03:02:01]];[type=ACTION_SET_NW_SRC action=[addr=127.0.0.3]];[type=ACTION_SET_NW_DST action=[addr=127.0.0.4]];[type=ACTION_SET_NW_TOS action=[ipToS=6]];[type=ACTION_SET_TP_SRC action=[port=7]];[type=ACTION_SET_TP_DST action=[port=8]];[type=ACTION_ENQUEUE action=[port=10 queueId=11]];] dpid=00:00:00:00:00:00:ca:fe inPort=1 outPort=9 flowEntryUserState=FE_USER_ADD flowEntrySwitchState=FE_SWITCH_UPDATED flowEntryErrorState=[type=12 code=13]]" );
+		assertEquals("toString", def.toString(), "[ idleTimeout=0 hardTimeout=0 flowEntryActions=[] flowEntryUserState=FE_USER_UNKNOWN flowEntrySwitchState=FE_SWITCH_UNKNOWN]" );
+		assertEquals("toString", entry.toString(), "[flowEntryId=0x5678 flowId=0x1234 idleTimeout=5 hardTimeout=10 flowEntryMatch=[inPort=1 srcMac=01:02:03:04:05:06 dstMac=06:05:04:03:02:01 ethernetFrameType=2 vlanId=3 vlanPriority=4 srcIPv4Net=127.0.0.1/32 dstIPv4Net=127.0.0.2/32 ipProto=5 ipToS=6 srcTcpUdpPort=7 dstTcpUdpPort=8] flowEntryActions=[[type=ACTION_OUTPUT action=[port=9 maxLen=0]];[type=ACTION_OUTPUT action=[port=-3 maxLen=0]];[type=ACTION_SET_VLAN_VID action=[vlanId=3]];[type=ACTION_SET_VLAN_PCP action=[vlanPriority=4]];[type=ACTION_STRIP_VLAN action=[stripVlan=true]];[type=ACTION_SET_DL_SRC action=[addr=01:02:03:04:05:06]];[type=ACTION_SET_DL_DST action=[addr=06:05:04:03:02:01]];[type=ACTION_SET_NW_SRC action=[addr=127.0.0.3]];[type=ACTION_SET_NW_DST action=[addr=127.0.0.4]];[type=ACTION_SET_NW_TOS action=[ipToS=6]];[type=ACTION_SET_TP_SRC action=[port=7]];[type=ACTION_SET_TP_DST action=[port=8]];[type=ACTION_ENQUEUE action=[port=10 queueId=11]];] dpid=00:00:00:00:00:00:ca:fe inPort=1 outPort=9 flowEntryUserState=FE_USER_ADD flowEntrySwitchState=FE_SWITCH_UPDATED flowEntryErrorState=[type=12 code=13]]" );
 	}
 
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/util/FlowPathTest.java b/src/test/java/net/onrc/onos/ofcontroller/util/FlowPathTest.java
index bd42ac8..76ccf9f 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/util/FlowPathTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/util/FlowPathTest.java
@@ -19,6 +19,8 @@
 		iFlowPath.setFlowPathTypeForTest("FP_TYPE_SHORTEST_PATH");
 		iFlowPath.setFlowPathUserStateForTest("FP_USER_ADD");
 		iFlowPath.setFlowPathFlagsForTest(0L);
+		iFlowPath.setIdleTimeoutForTest(5);
+		iFlowPath.setHardTimeoutForTest(10);
 		iFlowPath.setSrcSwForTest("CA:FE");
 		iFlowPath.setSrcPortForTest((short)1);
 		iFlowPath.setDstSwForTest("BA:BE");
@@ -44,6 +46,8 @@
 		assertTrue ( flowPath.flowPathUserState() == FlowPathUserState.FP_USER_UNKNOWN);
 		assertFalse( flowPath.flowPathFlags().isDiscardFirstHopEntry() );
 		assertFalse( flowPath.flowPathFlags().isKeepOnlyFirstHopEntry() );
+		assertTrue (flowPath.idleTimeout() == 0);
+		assertTrue (flowPath.hardTimeout() == 0);
 		assertTrue( flowPath.flowEntryActions().isEmpty() );
 	}
 
@@ -55,6 +59,8 @@
 		iFlowPath.setFlowPathTypeForTest("FP_TYPE_SHORTEST_PATH");
 		iFlowPath.setFlowPathUserStateForTest("FP_USER_ADD");
 		iFlowPath.setFlowPathFlagsForTest(0L);
+		iFlowPath.setIdleTimeoutForTest(5);
+		iFlowPath.setHardTimeoutForTest(10);
 		iFlowPath.setSrcSwForTest("CA:FE");
 		iFlowPath.setSrcPortForTest((short)1);
 		iFlowPath.setDstSwForTest("BA:BE");
@@ -100,6 +106,8 @@
 		assertEquals(flowPath.flowPathType(), FlowPathType.FP_TYPE_SHORTEST_PATH);
 		assertEquals(flowPath.flowPathUserState(), FlowPathUserState.FP_USER_ADD);
 		assertEquals(flowPath.flowPathFlags().flags(), 0);
+		assertEquals(flowPath.idleTimeout(), 5);
+		assertEquals(flowPath.hardTimeout(), 10);
 		assertEquals(flowPath.dataPath().srcPort().dpid().value(), 0xCAFE);
 		assertEquals(flowPath.dataPath().srcPort().port().value(), 1);
 		assertEquals(flowPath.dataPath().dstPort().dpid().value(), 0xBABE);
@@ -123,6 +131,8 @@
 		
 		assertEquals(0x14, flowPath.dataPath().flowEntries().get(0).flowEntryId().value() );
 		assertEquals(0xBEEF, flowPath.dataPath().flowEntries().get(0).dpid().value() );
+		assertEquals(0, flowPath.dataPath().flowEntries().get(0).idleTimeout() );
+		assertEquals(0, flowPath.dataPath().flowEntries().get(0).hardTimeout() );
 		assertEquals(15, flowPath.dataPath().flowEntries().get(0).flowEntryMatch().inPort().value() );
 		assertEquals("11:22:33:44:55:66", flowPath.dataPath().flowEntries().get(0).flowEntryMatch().srcMac().toString());
 		assertEquals("66:55:44:33:22:11", flowPath.dataPath().flowEntries().get(0).flowEntryMatch().dstMac().toString());
@@ -179,6 +189,22 @@
 	}
 
 	@Test
+	public void testSetIdleTimeout(){
+		FlowPath flowPath = new FlowPath();
+		int idleTimeout = 15;
+		flowPath.setIdleTimeout( idleTimeout );
+		assertTrue( flowPath.idleTimeout() == 15 );
+	}
+
+	@Test
+	public void testSetHardTimeout(){
+		FlowPath flowPath = new FlowPath();
+		int hardTimeout = 20;
+		flowPath.setHardTimeout( hardTimeout );
+		assertTrue( flowPath.hardTimeout() == 20 );
+	}
+
+	@Test
 	public void testSetDataPath(){
 		FlowPath flowPath = new FlowPath();
 		DataPath dataPath = new DataPath();
@@ -189,7 +215,7 @@
 	@Test
 	public void testToString(){
 
-		assertEquals("[flowId=0x1234 installerId=installerId flowPathType=FP_TYPE_SHORTEST_PATH flowPathUserState=FP_USER_ADD flowPathFlags=[flags=] dataPath=[src=00:00:00:00:00:00:ca:fe/1 flowEntry=[flowEntryId=0x14 flowEntryMatch=[] flowEntryActions=[[type=ACTION_OUTPUT action=[port=23 maxLen=24]];[type=ACTION_OUTPUT action=[port=25 maxLen=26]];] dpid=00:00:00:00:00:00:be:ef flowEntryUserState=FE_USER_MODIFY flowEntrySwitchState=FE_SWITCH_UPDATE_IN_PROGRESS] dst=00:00:00:00:00:00:ba:be/2] flowEntryMatch=[] flowEntryActions=[[type=ACTION_OUTPUT action=[port=10 maxLen=11]];[type=ACTION_OUTPUT action=[port=12 maxLen=13]];]]", flowPath.toString());
+		assertEquals("[flowId=0x1234 installerId=installerId flowPathType=FP_TYPE_SHORTEST_PATH flowPathUserState=FP_USER_ADD flowPathFlags=[flags=] idleTimeout=5 hardTimeout=10 dataPath=[src=00:00:00:00:00:00:ca:fe/1 flowEntry=[flowEntryId=0x14 idleTimeout=0 hardTimeout=0 flowEntryMatch=[] flowEntryActions=[[type=ACTION_OUTPUT action=[port=23 maxLen=24]];[type=ACTION_OUTPUT action=[port=25 maxLen=26]];] dpid=00:00:00:00:00:00:be:ef flowEntryUserState=FE_USER_MODIFY flowEntrySwitchState=FE_SWITCH_UPDATE_IN_PROGRESS] dst=00:00:00:00:00:00:ba:be/2] flowEntryMatch=[] flowEntryActions=[[type=ACTION_OUTPUT action=[port=10 maxLen=11]];[type=ACTION_OUTPUT action=[port=12 maxLen=13]];]]", flowPath.toString());
 	}
 
 	@Test