Fix for bug #357- Set log levels on all log statements to appropriate level
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / ConnectionConductorImplTest.java
index 7f79b5ed99a503d098af4450c61f14463222f0f9..d06cbc0b5929d49403e9768734351a5213e43fae 100644 (file)
@@ -9,6 +9,11 @@
 package org.opendaylight.openflowplugin.openflow.md.core;
 
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Stack;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -17,47 +22,148 @@ import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.openflow.md.OFConstants;
 import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
 import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
 import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.queue.PopListener;
+import org.opendaylight.openflowplugin.openflow.md.queue.QueueKeeperLightImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeaturesBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * @author mirehak
- */
+@RunWith(MockitoJUnitRunner.class)
 public class ConnectionConductorImplTest {
 
-    private static final Logger LOG = LoggerFactory
+    protected static final Logger LOG = LoggerFactory
             .getLogger(ConnectionConductorImplTest.class);
 
+    /** in [ms] */
+    private final int maxProcessingTimeout = 500;
+
     protected ConnectionAdapterStackImpl adapter;
     private ConnectionConductorImpl connectionConductor;
+    private MDController controller;
     private Stack<SwitchTestEvent> eventPlan;
 
     private Thread libSimulation;
     private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
             8);
 
+    private QueueKeeperLightImpl queueKeeper;
+
+    private PopListener<DataObject> popListener;
+
+    private int experimenterMessageCounter;
+    private int packetinMessageCounter;
+    private int flowremovedMessageCounter;
+    private int portstatusAddMessageCounter;
+    private int portstatusDeleteMessageCounter;
+    private int portstatusModifyMessageCounter;
+    private int errorMessageCounter;
+
+    @Mock
+    private ErrorHandlerQueueImpl errorHandler;
+
+    private int expectedErrors = 0;
+
+    public void incrExperimenterMessageCounter() {
+        this.experimenterMessageCounter++;
+    }
+
+    public void incrPacketinMessageCounter() {
+        this.packetinMessageCounter++;
+    }
+
+    public void incrFlowremovedMessageCounter() {
+        this.flowremovedMessageCounter++;
+    }
+
+    public void incrPortstatusAddMessageCounter() {
+        this.portstatusAddMessageCounter++;
+    }
+
+    public void incrPortstatusDeleteMessageCounter() {
+        this.portstatusDeleteMessageCounter++;
+    }
+
+    public void incrPortstatusModifyMessageCounter() {
+        this.portstatusModifyMessageCounter++;
+    }
+
+    public void incrErrorMessageCounter() {
+        this.errorMessageCounter++;
+    }
+
+
     /**
      * @throws java.lang.Exception
      */
     @Before
     public void setUp() throws Exception {
         adapter = new ConnectionAdapterStackImpl();
+
+        popListener = new PopListenerCountingImpl<>();
+
+        queueKeeper = new QueueKeeperLightImpl();
+
         connectionConductor = new ConnectionConductorImpl(adapter);
+        connectionConductor.setQueueKeeper(queueKeeper);
         connectionConductor.init();
+        pool.execute(errorHandler);
+        connectionConductor.setErrorHandler(errorHandler);
+        controller = new MDController();
+        controller.init();
+        queueKeeper.setTranslatorMapping(controller.getMessageTranslators());
         eventPlan = new Stack<>();
         adapter.setEventPlan(eventPlan);
         adapter.setProceedTimeout(5000L);
         adapter.checkListeners();
+
+        controller.getMessageTranslators().putAll(assembleTranslatorMapping());
+        queueKeeper.setPopListenersMapping(assemblePopListenerMapping());
+        queueKeeper.init();
+    }
+
+    /**
+     * @return
+     */
+    private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> assemblePopListenerMapping() {
+        Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> mapping = new HashMap<>();
+        Collection<PopListener<DataObject>> popListenerBag = new ArrayList<>();
+        popListenerBag.add(popListener);
+        //TODO: add testing registered types
+        mapping.put(DataObject.class, popListenerBag);
+        return mapping;
     }
 
     /**
@@ -68,6 +174,9 @@ public class ConnectionConductorImplTest {
         if (libSimulation != null) {
             libSimulation.join();
         }
+        queueKeeper.shutdown();
+        connectionConductor.shutdownPool();
+
         for (Exception problem : adapter.getOccuredExceptions()) {
             LOG.error("during simulation on adapter side: "
                     + problem.getMessage());
@@ -84,6 +193,18 @@ public class ConnectionConductorImplTest {
         }
         Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
         eventPlan = null;
+        controller = null;
+        
+        // logging errors if occurred
+        ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
+        Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
+                errorCaptor.capture(), Matchers.any(SessionContext.class));
+        for (Throwable problem : errorCaptor.getAllValues()) {
+            LOG.warn(problem.getMessage(), problem);
+        }
+        
+        Mockito.verify(errorHandler, Mockito.times(expectedErrors )).handleException(
+                Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
     }
 
     /**
@@ -94,6 +215,8 @@ public class ConnectionConductorImplTest {
      */
     @Test
     public void testOnEchoRequestMessage() throws Exception {
+        simulateV13PostHandshakeState(connectionConductor);
+        
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
                 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
         eventPlan.add(0,
@@ -102,29 +225,54 @@ public class ConnectionConductorImplTest {
     }
 
     /**
-     * Test of handshake, covering version negotiation and features .
+     * Test of handshake, covering version negotiation and features.
+     * Switch delivers first helloMessage with default version.
      * @throws Exception
      */
     @Test
     public void testHandshake1() throws Exception {
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
                 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
-        eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
-        eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "getFeatures"));
-        GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
-        getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
-        getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
-        getFeaturesOutputBuilder.setBuffers(4L);
-        getFeaturesOutputBuilder.setReserved(0L);
-        getFeaturesOutputBuilder.setTables((short) 2);
-        getFeaturesOutputBuilder.setCapabilities(84L);
+        eventPlan.add(0, EventFactory.createDefaultWaitForAllEvent(
+                EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"),
+                EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures")));
+        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
+                EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
+        
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
+        executeNow();
 
-        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(42,
-                EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
+        Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
+                connectionConductor.getConductorState());
+        Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
+                .shortValue());
+    }
+    
+    /**
+     * Test of handshake, covering version negotiation and features.
+     * Controller sends first helloMessage with default version 
+     * @throws Exception
+     */
+    @Test
+    public void testHandshake1SwitchStarts() throws Exception {
+        eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
+        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
+                EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "getFeatures"));
+        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
+                EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
+        
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(3, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(4, "multipartRequestInput"));
+
+        executeNow();
 
-        execute(true);
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
                 connectionConductor.getConductorState());
         Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
@@ -132,56 +280,76 @@ public class ConnectionConductorImplTest {
     }
 
     /**
-     * Test of handshake, covering version negotiation and features .
+     * Test of handshake, covering version negotiation and features.
+     * Switch delivers first helloMessage with version 0x05 
+     * and negotiates following versions: 0x03, 0x01 
      * @throws Exception
      */
     @Test
     public void testHandshake2() throws Exception {
+        connectionConductor.setBitmapNegotiationEnable(false);
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
                 (short) 0x05, new HelloMessageBuilder()));
         eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
-        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
+                EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
+        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
                 (short) 0x03, new HelloMessageBuilder()));
         eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
-        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
+                EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
+        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
                 (short) 0x01, new HelloMessageBuilder()));
         eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
-        eventPlan.add(0,
-                EventFactory.createDefaultWaitForRpcEvent(42, "getFeatures"));
-        GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
-        getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
-        getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
-        getFeaturesOutputBuilder.setBuffers(4L);
-        getFeaturesOutputBuilder.setReserved(0L);
-        getFeaturesOutputBuilder.setTables((short) 2);
-        getFeaturesOutputBuilder.setCapabilities(84L);
+                EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
 
-        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(42,
-                EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
+        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
+                EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
+        
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
 
         executeNow();
+
         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
                 connectionConductor.getConductorState());
         Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
                 .shortValue());
     }
-
+    
     /**
-     * Test of handshake, covering version negotiation and features .
+     * Test of handshake, covering version negotiation and features.
+     * Controller sends first helloMessage with default version 
+     * and switch negotiates following versions: 0x05, 0x03, 0x01 
      * @throws Exception
      */
     @Test
-    public void testHandshake3() throws Exception {
+    public void testHandshake2SwitchStarts() throws Exception {
+        connectionConductor.setBitmapNegotiationEnable(false);
+        eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
+        eventPlan.add(0,
+                EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
-                (short) 0x00, new HelloMessageBuilder()));
+                (short) 0x05, new HelloMessageBuilder()));
+        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
+                (short) 0x03, new HelloMessageBuilder()));
+        eventPlan.add(0,
+                EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
+        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
+                (short) 0x01, new HelloMessageBuilder()));
+        eventPlan.add(0,
+                EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
+
+        eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
+                EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
+        
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(1, "multipartRequestInput"));
+        eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(2, "multipartRequestInput"));
 
         executeNow();
-        Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.HANDSHAKING,
+
+        Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
                 connectionConductor.getConductorState());
-        Assert.assertNull(connectionConductor.getVersion());
+        Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
+                .shortValue());
     }
 
     /**
@@ -192,12 +360,15 @@ public class ConnectionConductorImplTest {
      */
     @Test
     public void testOnExperimenterMessage1() throws InterruptedException {
+        simulateV13PostHandshakeState(connectionConductor);
+        
         eventPlan.add(0,
                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
         ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
         builder1.setExperimenter(84L).setExpType(4L);
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
                 EventFactory.DEFAULT_VERSION, builder1));
+
         executeLater();
 
         Runnable sendExperimenterCmd = new Runnable() {
@@ -222,10 +393,12 @@ public class ConnectionConductorImplTest {
      */
     @Test
     public void testOnExperimenterMessage2() throws InterruptedException {
+        simulateV13PostHandshakeState(connectionConductor);
+        
         eventPlan.add(0,
                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
         ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
-        builder1.setType(ErrorType.BADREQUEST).setCode(3)
+        builder1.setType(ErrorType.BADREQUEST.getIntValue()).setCode(3)
                 .setData(new byte[] { 1, 2, 3 });
 
         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
@@ -251,11 +424,31 @@ public class ConnectionConductorImplTest {
      * Test method for
      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
      * .
+     * @throws InterruptedException
      */
     @Test
-    public void testOnFlowRemovedMessage() {
-        // fail("Not yet implemented");
-        // TODO:: add test
+    public void testOnFlowRemovedMessage() throws InterruptedException {
+        IMDMessageTranslator<OfHeader, List<DataObject>> objFms = new FlowRemovedMessageService() ;
+        controller.addMessageTranslator(FlowRemovedMessage.class, 4, objFms);
+
+        simulateV13PostHandshakeState(connectionConductor);
+
+        // Now send Flow Removed messages
+        FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
+        builder1.setVersion((short) 4);
+        builder1.setXid(1L);
+        connectionConductor.onFlowRemovedMessage(builder1.build());
+        synchronized (popListener) {
+            LOG.debug("about to wait for popListener");
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(1, flowremovedMessageCounter);
+        builder1.setXid(2L);
+        connectionConductor.onFlowRemovedMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(2, flowremovedMessageCounter);
     }
 
     /**
@@ -269,65 +462,71 @@ public class ConnectionConductorImplTest {
         // TODO:: add test
     }
 
-    /**
-     * Test method for
-     * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestMessage)}
-     * .
-     */
-    @Test
-    public void testOnMultipartRequestMessage() {
-        // fail("Not yet implemented");
-        // TODO:: add test
-    }
-
     /**
      * Test method for
      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
      * .
+     * @throws InterruptedException
      */
     @Test
-    public void testOnPacketInMessage() {
-        // fail("Not yet implemented");
-        // TODO:: add test
+    public void testOnPacketInMessage() throws InterruptedException {
+        IMDMessageTranslator<OfHeader, List<DataObject>> objPms = new PacketInMessageService() ;
+        controller.addMessageTranslator(PacketInMessage.class, 4, objPms);
+
+        simulateV13PostHandshakeState(connectionConductor);
+
+        // Now send PacketIn
+        PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
+        builder1.setVersion((short) 4);
+        builder1.setBufferId((long)1);
+        connectionConductor.onPacketInMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(1, packetinMessageCounter);
+        builder1.setBufferId((long)2);
+        connectionConductor.onPacketInMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(2, packetinMessageCounter);
     }
 
     /**
      * Test method for
      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
      * .
+     * @throws InterruptedException
      */
     @Test
-    public void testOnPortStatusMessage() {
-        // fail("Not yet implemented");
-        // TODO:: add test
-    }
-
-    /**
-     * Test method for
-     * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#proposeVersion(short)}
-     * .
-     */
-    @Test
-    public void testProposeVersion() {
-        short[] remoteVer = new short[] { 0x05, 0x04, 0x03, 0x02, 0x01, 0x8f,
-                0xff };
-        short[] expectedProposal = new short[] { 0x04, 0x04, 0x01, 0x01, 0x01,
-                0x04, 0x04 };
-
-        for (int i = 0; i < remoteVer.length; i++) {
-            short actualProposal = connectionConductor
-                    .proposeVersion(remoteVer[i]);
-            Assert.assertEquals(
-                    String.format("proposing for version: %04x", remoteVer[i]),
-                    expectedProposal[i], actualProposal);
+    public void testOnPortStatusMessage() throws InterruptedException {
+        IMDMessageTranslator<OfHeader, List<DataObject>> objPSms = new PortStatusMessageService() ;
+        controller.addMessageTranslator(PortStatusMessage.class, 4, objPSms);
+
+        simulateV13PostHandshakeState(connectionConductor);
+
+        // Send Port Status messages
+        PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
+        builder1.setVersion((short) 4);
+        PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
+        builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
+        connectionConductor.onPortStatusMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
         }
-
-        try {
-            connectionConductor.proposeVersion((short) 0);
-            Assert.fail("there should be no proposition for this version");
-        } catch (Exception e) {
-            // expected
+        Assert.assertEquals(1, portstatusAddMessageCounter);
+        builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
+        connectionConductor.onPortStatusMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
         }
+        Assert.assertEquals(1, portstatusModifyMessageCounter);
+        builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
+        connectionConductor.onPortStatusMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(1, portstatusDeleteMessageCounter);
     }
 
     /**
@@ -342,6 +541,7 @@ public class ConnectionConductorImplTest {
      */
     private void executeNow() throws InterruptedException {
         execute(true);
+        connectionConductor.shutdownPool();
     }
 
     /**
@@ -355,4 +555,224 @@ public class ConnectionConductorImplTest {
         }
     }
 
+    private static GetFeaturesOutputBuilder getFeatureResponseMsg() {
+        GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
+        getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
+        getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
+        getFeaturesOutputBuilder.setBuffers(4L);
+        getFeaturesOutputBuilder.setReserved(0L);
+        getFeaturesOutputBuilder.setTables((short) 2);
+        getFeaturesOutputBuilder.setCapabilities(createCapabilities(84));
+
+        return getFeaturesOutputBuilder;
+    }
+
+    /**
+     * @return
+     */
+    private static Capabilities createCapabilities(long input) {
+        final Boolean FLOW_STATS = (input & (1 << 0)) != 0;
+        final Boolean TABLE_STATS = (input & (1 << 1)) != 0;
+        final Boolean PORT_STATS = (input & (1 << 2)) != 0;
+        final Boolean GROUP_STATS = (input & (1 << 3)) != 0;
+        final Boolean IP_REASM = (input & (1 << 5)) != 0;
+        final Boolean QUEUE_STATS = (input & (1 << 6)) != 0;
+        final Boolean PORT_BLOCKED = (input & (1 << 8)) != 0;
+        Capabilities capabilities = new Capabilities(FLOW_STATS, GROUP_STATS, IP_REASM,
+                PORT_BLOCKED, PORT_STATS, QUEUE_STATS, TABLE_STATS);
+        return capabilities;
+    }
+
+    public class ExperimenterMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+        @Override
+        public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
+            LOG.debug("Received a packet in Experimenter Service");
+            ConnectionConductorImplTest.this.incrExperimenterMessageCounter();
+            return null;
+        }
+    }
+
+    public class PacketInMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+        @Override
+        public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
+            LOG.debug("Received a packet in PacketIn Service");
+            ConnectionConductorImplTest.this.incrPacketinMessageCounter();
+            return null;
+        }
+    }
+
+    public class FlowRemovedMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+        @Override
+        public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
+            LOG.debug("Received a packet in FlowRemoved Service");
+            ConnectionConductorImplTest.this.incrFlowremovedMessageCounter();
+            return null;
+        }
+    }
+
+    public class PortStatusMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+        @Override
+        public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
+            LOG.debug("Received a packet in PortStatus Service");
+            if ( (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRADD))  ) {
+                ConnectionConductorImplTest.this.incrPortstatusAddMessageCounter();
+            } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRDELETE)){
+                ConnectionConductorImplTest.this.incrPortstatusDeleteMessageCounter();
+            } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRMODIFY)) {
+                ConnectionConductorImplTest.this.incrPortstatusModifyMessageCounter();
+            }
+            return null;
+        }
+    }
+
+    public class ErrorMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
+        @Override
+        public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
+            LOG.debug("Received a packet in Experimenter Service");
+            ConnectionConductorImplTest.this.incrErrorMessageCounter();
+            return null;
+        }
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
+     * .
+     * @throws InterruptedException
+     */
+    @Test
+    public void testOnExperimenterMessage() throws InterruptedException {
+        simulateV13PostHandshakeState(connectionConductor);
+        
+        ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
+        builder1.setVersion((short) 4);
+        builder1.setExperimenter(84L).setExpType(4L);
+        connectionConductor.onExperimenterMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(1, experimenterMessageCounter);
+
+        builder1.setExperimenter(85L).setExpType(4L);
+        connectionConductor.onExperimenterMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(2, experimenterMessageCounter);
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage)}
+     * .
+     * @throws InterruptedException
+     */
+    @Test
+    public void testOnErrorMessage() throws InterruptedException {
+        simulateV13PostHandshakeState(connectionConductor);
+        
+        ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
+        builder1.setVersion((short) 4);
+        builder1.setCode(100);
+        connectionConductor.onErrorMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(1, errorMessageCounter);
+        builder1.setCode(200);
+        connectionConductor.onErrorMessage(builder1.build());
+        synchronized (popListener) {
+            popListener.wait(maxProcessingTimeout);
+        }
+        Assert.assertEquals(2, errorMessageCounter);
+    }
+
+    /**
+     * @return listener mapping for:
+     * <ul>
+     * <li>experimenter</li>
+     * <li>error</li>
+     * </ul>
+     */
+    private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> assembleTranslatorMapping() {
+        Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping = new HashMap<>();
+        TranslatorKey tKey;
+
+        IMDMessageTranslator<OfHeader, List<DataObject>> objEms = new ExperimenterMessageService() ;
+        Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = new ArrayList<>();
+        existingValues.add(objEms);
+        tKey = new TranslatorKey(4, ExperimenterMessage.class.getName());
+        translatorMapping.put(tKey, existingValues);
+        IMDMessageTranslator<OfHeader, List<DataObject>> objErms = new ErrorMessageService() ;
+        existingValues.add(objErms);
+        tKey = new TranslatorKey(4, ErrorMessage.class.getName());
+        translatorMapping.put(tKey, existingValues);
+        return translatorMapping;
+    }
+
+    /**
+     * Test method for
+     * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#processPortStatusMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
+     * <br><br> 
+     * Tests for getting features from port status message by port version 
+     * <ul>
+     * <li>features are malformed - one of them is null</li>
+     * <li>mismatch between port version and port features</li>
+     * <li>mismatch between port version and port features</li>
+     * <li>non-existing port version</li>
+     * <li>port version OF 1.0</li>
+     * <li>port version OF 1.3</li>
+     * </ul>
+     * 
+     */
+    @Test
+    public void testProcessPortStatusMsg() {
+        simulateV13PostHandshakeState(connectionConductor);
+        
+               long portNumber = 90L;
+               long portNumberV10 = 91L;
+               PortStatusMessage msg;
+               
+               PortStatusMessageBuilder builder = new PortStatusMessageBuilder();              
+        PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
+        PortFeatures featuresMal = new PortFeatures(true,false,false,false,null,false,false,false,false,false,false,false,false,false,false,false);
+        PortFeaturesV10 featuresV10 = new PortFeaturesV10(true,false,false,false,false,false,false,false,false,false,false,false);
+        
+        //Malformed features           
+        builder.setVersion((short) 1).setPortNo(portNumber).setReason(PortReason.OFPPRADD).setCurrentFeatures(featuresMal);            
+        connectionConductor.processPortStatusMsg(builder.build());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
+               
+        //Version-features mismatch            
+        builder.setCurrentFeatures(features);          
+        connectionConductor.processPortStatusMsg(builder.build());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
+               
+        //Non existing version
+        builder.setVersion((short) 0);
+        connectionConductor.processPortStatusMsg(builder.build());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
+               
+               //Version OF 1.3
+               builder.setVersion((short) 4);
+               msg = builder.build();
+               connectionConductor.processPortStatusMsg(builder.build());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumber));
+               Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumber), msg);
+               
+               //Version OF 1.0                        
+               builder.setVersion((short) 1).setPortNo(portNumberV10).setCurrentFeatures(null).setCurrentFeaturesV10(featuresV10);
+               msg = builder.build();
+               connectionConductor.processPortStatusMsg(builder.build());
+               Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumberV10));
+               Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumberV10), msg);
+    }
+    
+    private void simulateV13PostHandshakeState(ConnectionConductorImpl conductor) {
+        GetFeaturesOutputBuilder featureOutput = getFeatureResponseMsg();
+        conductor.postHandshakeBasic(featureOutput.build(), OFConstants.OFP_VERSION_1_3);
+    }
 }