Merge "MultiMsgCollector moving package"
authormichal rehak <mirehak@cisco.com>
Tue, 31 Mar 2015 08:35:40 +0000 (08:35 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 31 Mar 2015 08:35:40 +0000 (08:35 +0000)
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/MultiMsgCollector.java [moved from openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/MultiMsgCollector.java with 95% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/MultiMsgCollectorImpl.java [moved from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/MultiMsgCollectorImpl.java with 73% similarity]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerImpl.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/MultiMsgCollectorImplTest.java [moved from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/MultiMsgCollectorImplTest.java with 56% similarity]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerImplTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/testutil/MsgGeneratorTestUtils.java [new file with mode: 0644]

index edc5c4658fdd6a2c9aae81e0097ed623be036f1e..4894f14590c87e7b170a52aa0e8c059c3b31abde 100644 (file)
@@ -18,7 +18,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
  * <p/>
  * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
  */
-public interface ConnectionContext {
+public interface ConnectionContext extends MultiMsgCollector {
 
     /**
      * distinguished connection states
@@ -68,12 +68,12 @@ public interface ConnectionContext {
      * @param connectionState
      */
     void setConnectionState(CONNECTION_STATE connectionState);
-    
+
     /**
      * @param featuresReply as received from device during handshake
      */
     void setFeatures(FeaturesReply featuresReply);
-    
+
     /**
      * @return featureReply as received from device during handshake
      */
similarity index 95%
rename from openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/MultiMsgCollector.java
rename to openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/MultiMsgCollector.java
index 22928deb0eb819b5b1158eadc6a6e55af9c0591c..caf19a4d74ef16a71594d5414ffb33b381f92c4d 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.api.openflow.device;
+package org.opendaylight.openflowplugin.api.openflow.connection;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Collection;
@@ -40,7 +40,7 @@ public interface MultiMsgCollector {
      * @param xid
      * @return
      */
-    ListenableFuture<Collection<MultipartReply>> registerMultipartMsg(@Nonnull long xid);
+    ListenableFuture<Collection<MultipartReply>> registerMultipartMsg(long xid);
 
     /**
      * Method adds a reply multipart message to the collection and if the message has marker
index 7cdd4fa0156251fb76b9c7c5b89cae00d5839419..a35671c6b477606400b844d89e2e53d27f26af3b 100644 (file)
@@ -7,25 +7,31 @@
  */
 package org.opendaylight.openflowplugin.impl.connection;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.MultiMsgCollector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 
 /**
  * 
  */
 public class ConnectionContextImpl implements ConnectionContext {
 
-    private ConnectionAdapter connectionAdapter;
+    private final ConnectionAdapter connectionAdapter;
     private CONNECTION_STATE connectionState;
     private FeaturesReply featuresReply;
+    private final MultiMsgCollector multipartCollector;
 
     /**
      * @param connectionAdapter
      */
-    public ConnectionContextImpl(ConnectionAdapter connectionAdapter) {
+    public ConnectionContextImpl(final ConnectionAdapter connectionAdapter) {
         this.connectionAdapter = connectionAdapter;
+        multipartCollector = new MultiMsgCollectorImpl();
     }
 
     @Override
@@ -45,7 +51,7 @@ public class ConnectionContextImpl implements ConnectionContext {
     }
 
     @Override
-    public void setConnectionState(CONNECTION_STATE connectionState) {
+    public void setConnectionState(final CONNECTION_STATE connectionState) {
         this.connectionState = connectionState;
     }
 
@@ -55,7 +61,18 @@ public class ConnectionContextImpl implements ConnectionContext {
     }
 
     @Override
-    public void setFeatures(FeaturesReply featuresReply) {
+    public void setFeatures(final FeaturesReply featuresReply) {
         this.featuresReply = featuresReply;
+
+    }
+
+    @Override
+    public ListenableFuture<Collection<MultipartReply>> registerMultipartMsg(final long xid) {
+        return multipartCollector.registerMultipartMsg(xid);
+    }
+
+    @Override
+    public void addMultipartMsg(final MultipartReply reply) {
+        multipartCollector.addMultipartMsg(reply);
     }
 }
similarity index 73%
rename from openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/MultiMsgCollectorImpl.java
rename to openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/MultiMsgCollectorImpl.java
index e59e3c2db7eb67ec4a3580aa27b88b7187cc7bd7..200b7cf69764a96986dbde12a94acb4c2f238068 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.device;
+package org.opendaylight.openflowplugin.impl.connection;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
@@ -20,7 +20,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import org.opendaylight.openflowplugin.api.openflow.device.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.connection.MultiMsgCollector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,17 +57,21 @@ class MultiMsgCollectorImpl implements MultiMsgCollector {
         return new RemovalListener<Long, MultiCollectorObject>() {
             @Override
             public void onRemoval(final RemovalNotification<Long, MultiCollectorObject> notification) {
-                notification.getValue().invalidateFutureByTimeout();
+                if ( ! notification.getValue().future.isDone()) {
+                    LOG.warn("Removing data with XID {} from cache", notification.getKey());
+                    notification.getValue().invalidateFutureByTimeout();
+                }
             }
         };
     }
 
     private CacheBuilder<Long, MultiCollectorObject> initCacheBuilder(final int timeout) {
         return CacheBuilder.newBuilder()
-                .expireAfterWrite(timeout, TimeUnit.SECONDS)
+                .expireAfterAccess(timeout, TimeUnit.SECONDS)
                 .removalListener(getRemovalListener())
                 .initialCapacity(200)
-                .maximumSize(500);
+                .maximumSize(500)
+                .concurrencyLevel(1);
     }
 
     @Override
@@ -79,6 +84,7 @@ class MultiMsgCollectorImpl implements MultiMsgCollector {
     @Override
     public void addMultipartMsg(final MultipartReply reply) {
         Preconditions.checkNotNull(reply);
+        LOG.trace("Try to add Multipart reply msg with XID {}", reply.getXid());
         final Long xid = reply.getXid();
         final MultiCollectorObject cachedRef = cache.getIfPresent(xid);
         if (cachedRef == null) {
@@ -96,6 +102,7 @@ class MultiMsgCollectorImpl implements MultiMsgCollector {
     private class MultiCollectorObject {
         private final SettableFuture<Collection<MultipartReply>> future;
         private final Collection<MultipartReply> replyCollection;
+        private MultipartType msgType;
 
         MultiCollectorObject (final SettableFuture<Collection<MultipartReply>> future) {
             this.future = future;
@@ -103,6 +110,8 @@ class MultiMsgCollectorImpl implements MultiMsgCollector {
         }
 
         void add(final MultipartReply reply) {
+            /* Rise possible exception if it possible */
+            msgTypeValidation(reply.getType());
             replyCollection.add(reply);
         }
 
@@ -114,5 +123,21 @@ class MultiMsgCollectorImpl implements MultiMsgCollector {
             final String msg = "MultiMsgCollector can not wait for last multipart any more";
             future.setException(new TimeoutException(msg));
         }
+
+        void invalidateFutureByInputType(final MultipartType type) {
+            final String msg = "MultiMsgCollector get incorrect multipart msg with type " + type
+                    + " but expected type is " + msgType;
+            future.setException(new IllegalArgumentException(msg));
+        }
+
+        private void msgTypeValidation(final MultipartType type) {
+            if (msgType == null) {
+                msgType = type;
+                return;
+            }
+            if ( ! msgType.equals(type)) {
+                invalidateFutureByInputType(type);
+            }
+        }
     }
 }
index bb95f5710f438c4586716a4a65942181cf4f2cfb..883b83108f295ca5bed9b93432d01a2fc5421f31 100644 (file)
@@ -1,12 +1,13 @@
 /**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- * 
+ *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 package org.opendaylight.openflowplugin.impl.connection.listener;
 
+import com.google.common.base.Objects;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
 import org.opendaylight.openflowplugin.openflow.md.core.HandshakeStepWrapper;
@@ -22,98 +23,98 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-
 /**
- * 
+ *
  */
 public class OpenflowProtocolListenerImpl implements OpenflowProtocolListener {
-    
+
     private static final Logger LOG = LoggerFactory.getLogger(OpenflowProtocolListenerImpl.class);
 
-    private ConnectionContext connectionContext;
-    private HandshakeContext handshakeContext;
+    private final ConnectionContext connectionContext;
+    private final HandshakeContext handshakeContext;
 
     /**
      * @param connectionContext
-     * @param handshakeContext 
+     * @param handshakeContext
      */
-    public OpenflowProtocolListenerImpl(ConnectionContext connectionContext,
-            HandshakeContext handshakeContext) {
+    public OpenflowProtocolListenerImpl(final ConnectionContext connectionContext,
+            final HandshakeContext handshakeContext) {
         this.connectionContext = connectionContext;
         this.handshakeContext = handshakeContext;
     }
 
     @Override
-    public void onEchoRequestMessage(EchoRequestMessage notification) {
+    public void onEchoRequestMessage(final EchoRequestMessage notification) {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void onErrorMessage(ErrorMessage notification) {
+    public void onErrorMessage(final ErrorMessage notification) {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void onExperimenterMessage(ExperimenterMessage notification) {
+    public void onExperimenterMessage(final ExperimenterMessage notification) {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void onFlowRemovedMessage(FlowRemovedMessage notification) {
+    public void onFlowRemovedMessage(final FlowRemovedMessage notification) {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void onHelloMessage(HelloMessage hello) {
+    public void onHelloMessage(final HelloMessage hello) {
         LOG.debug("processing HELLO.xid: {}", hello.getXid());
         if (connectionContext.getConnectionState() == null) {
             connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.HANDSHAKING);
         }
-        
+
         if (checkState(ConnectionContext.CONNECTION_STATE.HANDSHAKING)) {
-            HandshakeStepWrapper handshakeStepWrapper = new HandshakeStepWrapper(
+            final HandshakeStepWrapper handshakeStepWrapper = new HandshakeStepWrapper(
                     hello, handshakeContext.getHandshakeManager(), connectionContext.getConnectionAdapter());
             handshakeContext.getHandshakePool().submit(handshakeStepWrapper);
         } else {
             //TODO: consider disconnecting of bad behaving device
         }
-        
+
     }
 
     @Override
-    public void onMultipartReplyMessage(MultipartReplyMessage notification) {
-        // TODO Auto-generated method stub
-
+    public void onMultipartReplyMessage(final MultipartReplyMessage notification) {
+        LOG.trace("Multipart Reply with XID: {}", notification.getXid());
+        if (checkState(ConnectionContext.CONNECTION_STATE.WORKING)) {
+            connectionContext.addMultipartMsg(notification);
+        }
     }
 
     @Override
-    public void onPacketInMessage(PacketInMessage notification) {
+    public void onPacketInMessage(final PacketInMessage notification) {
         // TODO Auto-generated method stub
 
     }
 
     @Override
-    public void onPortStatusMessage(PortStatusMessage notification) {
+    public void onPortStatusMessage(final PortStatusMessage notification) {
         // TODO Auto-generated method stub
 
     }
-    
+
     /**
      * @param expectedState
      */
-    protected boolean checkState(ConnectionContext.CONNECTION_STATE expectedState) {
+    protected boolean checkState(final ConnectionContext.CONNECTION_STATE expectedState) {
         boolean verdict = true;
         if (! Objects.equal(connectionContext.getConnectionState(), expectedState)) {
             verdict = false;
-            LOG.info("Expected state: {}, actual state: {}", expectedState, 
+            LOG.info("Expected state: {}, actual state: {}", expectedState,
                     connectionContext.getConnectionState());
         }
-        
+
         return verdict;
     }
 
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java
new file mode 100644 (file)
index 0000000..8eb1153
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.connection;
+
+import static org.junit.Assert.fail;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.api.openflow.device.XidGenerator;
+import org.opendaylight.openflowplugin.impl.connection.testutil.MsgGeneratorTestUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+
+/**
+ * openflowplugin-impl
+ * org.opendaylight.openflowplugin.impl.connection
+ *
+ * test of {@link ConnectionContextImpl} - lightweight version, using basic ways (TDD)
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Mar 26, 2015
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ConnectionContextImplTest {
+
+    private static XidGenerator xidGenerator = new XidGenerator();
+    private ConnectionContextImpl conContext;
+
+    @Mock
+    private ConnectionAdapter conAdapter;
+
+    @Before
+    public void initialization() {
+        // place for mocking method's general behavior for ConnectorAdapter
+        conContext = new ConnectionContextImpl(conAdapter);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#ConnectionContextImpl(org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter)}.
+     */
+    @Test
+    @Ignore
+    public void testConnectionContextImpl(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getConnectionAdapter()}.
+     */
+    @Test
+    @Ignore
+    public void testGetConnectionAdapter(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getConnectionState()}.
+     */
+    @Test
+    @Ignore
+    public void testGetConnectionState(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getNodeId()}.
+     */
+    @Test
+    @Ignore
+    public void testGetNodeId(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#setConnectionState(org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext.CONNECTION_STATE)}.
+     */
+    @Test
+    @Ignore
+    public void testSetConnectionState(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getFeatures()}.
+     */
+    @Test
+    @Ignore
+    public void testGetFeatures(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#setFeatures(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply)}.
+     */
+    @Test
+    @Ignore
+    public void testSetFeatures(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#registerMultipartMsg(long)}.
+     */
+    @Test
+    public void testRegisterMultipartMsg(){
+        final long xid = xidGenerator.generate().getValue();
+        final ListenableFuture<Collection<MultipartReply>> futureObj = conContext.registerMultipartMsg(xid);
+        Assert.assertNotNull(futureObj);
+        Assert.assertTrue(futureObj instanceof SettableFuture);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#addMultipartMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply)}.
+     * @throws TimeoutException
+     * @throws ExecutionException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testAddMultipartMsg() throws InterruptedException, ExecutionException, TimeoutException{
+        final long xid = xidGenerator.generate().getValue();
+        final ListenableFuture<Collection<MultipartReply>> futureObj = conContext.registerMultipartMsg(xid);
+        Assert.assertNotNull(futureObj);
+        final MultipartReply muplipartReply = MsgGeneratorTestUtils.makeMultipartDescReply(xid, "test-value", false);
+        conContext.addMultipartMsg(muplipartReply);
+        final Collection<MultipartReply> response = futureObj.get(1L, TimeUnit.SECONDS);
+        Assert.assertNotNull(response);
+        Assert.assertFalse(response.isEmpty());
+        Assert.assertTrue(response.size() == 1);
+        Assert.assertTrue(response.contains(muplipartReply));
+    }
+}
similarity index 56%
rename from openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/MultiMsgCollectorImplTest.java
rename to openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/MultiMsgCollectorImplTest.java
index 0fe942214669186306ee523229b0f4e01ddc921a..9835c38459405bf58a49a11efe4a2ca7e9757c5c 100644 (file)
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.openflowplugin.impl.device;
+package org.opendaylight.openflowplugin.impl.connection;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -21,19 +21,18 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.openflowplugin.api.openflow.device.XidGenerator;
+import org.opendaylight.openflowplugin.impl.connection.testutil.MsgGeneratorTestUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
 
 /**
  * openflowplugin-api
  * org.opendaylight.openflowplugin.impl.openflow.device
  *
- * Test class for testing basic method functionality for {@link org.opendaylight.openflowplugin.api.openflow.device.MultiMsgCollector}
+ * Test class for testing basic method functionality for {@link org.opendaylight.openflowplugin.api.openflow.connection.MultiMsgCollector}
  *
  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
  * @author <a href="mailto:tkubas@cisco.com">Timotej Kubas</a>
@@ -42,43 +41,44 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
  */
 public class MultiMsgCollectorImplTest {
 
+    private static XidGenerator xidGenerator = new XidGenerator();
     private MultiMsgCollectorImpl collector;
 
     @Before
     public void initialization() {
-        collector = new MultiMsgCollectorImpl(1);
+        collector = new MultiMsgCollectorImpl(3);
     }
 
     /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.openflow.device.MultiMsgCollectorImpl#registerMultipartMsg(org.opendaylight.openflowplugin.api.openflow.device.Xid)}.
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.openflow.device.MultiMsgCollectorImpl#registerMultipartMsg(org.opendaylight.openflowplugin.api.openflow.device.Xid)}.
      * @throws ExecutionException
      * @throws InterruptedException
      * @throws TimeoutException
      */
     @Test
     public void testRegisterMultipartMsg() throws InterruptedException, ExecutionException, TimeoutException{
-        final long xid = 45L;
+        final long xid = xidGenerator.generate().getValue();
         final String hwTestValue = "test-value";
         final ListenableFuture<Collection<MultipartReply>> response = collector.registerMultipartMsg(xid);
-        collector.addMultipartMsg(makeMultipartDescReply(xid, hwTestValue, false));
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, false));
 
         validateDescReply(response, xid, Collections.singletonList(hwTestValue));
     }
 
     /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.openflow.device.MultiMsgCollectorImpl#addMultipartMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply)}.
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.openflow.device.MultiMsgCollectorImpl#addMultipartMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply)}.
      * @throws TimeoutException
      * @throws ExecutionException
      * @throws InterruptedException
      */
     @Test
     public void testAddMultipartMsg() throws InterruptedException, ExecutionException, TimeoutException{
-        final long xid = 22L;
+        final long xid = xidGenerator.generate().getValue();
         final String hwTestValue1 = "test-value1";
         final String hwTestValue2 = "test-value2";
         final ListenableFuture<Collection<MultipartReply>> response = collector.registerMultipartMsg(xid);
-        collector.addMultipartMsg(makeMultipartDescReply(xid, hwTestValue1, true));
-        collector.addMultipartMsg(makeMultipartDescReply(xid, hwTestValue2, false));
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue1, true));
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue2, false));
 
         validateDescReply(response, xid, Arrays.asList(hwTestValue1, hwTestValue2));
     }
@@ -88,28 +88,58 @@ public class MultiMsgCollectorImplTest {
      */
     @Test
     public void testAddMultipartMsgNotExpectedXid() {
-        final long xid = 23L;
+        final long xid = xidGenerator.generate().getValue();
         final String hwTestValue = "test-value";
-        collector.addMultipartMsg(makeMultipartDescReply(xid, hwTestValue, true));
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, hwTestValue, true));
     }
 
     /**
      * Test could return NullPointerException if the body of addMultipartMsg not
      * @throws InterruptedException
+     * @throws TimeoutException
      */
-    @Test(timeout=20000)
-    public void testCheckExistMultipartMsgInCacheAfterTimeout() throws InterruptedException, ExecutionException {
-        final long xid = 24L;
+    @Test
+    public void testCheckExistMultipartMsgInCacheAfterTimeout() throws InterruptedException, TimeoutException {
+        final long xid = xidGenerator.generate().getValue();
+        try {
+            final ListenableFuture<Collection<MultipartReply>> response = collector.registerMultipartMsg(xid);
+            assertNotNull(response);
+            collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, "hw-test-value", true));
+            Thread.sleep(4000);
+            collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, "hw-test-value2", false));
+            collector.registerMultipartMsg(5L);
+            response.get(1, TimeUnit.SECONDS);
+            fail("We expected timeout exception");
+        }
+        catch (final ExecutionException e) {
+            assertNotNull(e.getMessage());
+            assertNotNull(e.getMessage().contains(""+xid));
+            assertNotNull(e.getCause() instanceof TimeoutException);
+        }
+    }
+
+    /**
+     * Test returns ExcetionException because we set different MultipartType as is expected for second
+     * message. So Internal {@link MultiMsgCollectorImpl} validation has to rise IllgalStateException
+     * @throws InterruptedException
+     */
+    @Test
+    public void testCheckErrorForBadMultipartMsgType() throws InterruptedException {
+        final long xid = xidGenerator.generate().getValue();
         final ListenableFuture<Collection<MultipartReply>> response = collector.registerMultipartMsg(xid);
         assertNotNull(response);
-        Thread.sleep(2000);
-        collector.addMultipartMsg(makeMultipartDescReply(xid, "hw-text-value", false));
+        collector.addMultipartMsg(MsgGeneratorTestUtils.makeMultipartDescReply(xid, "hw-text-value", true));
+        final MultipartReply nextMultipart = new MultipartReplyMessageBuilder(MsgGeneratorTestUtils
+                .makeMultipartDescReply(xid, "hw-test-next", true)).setType(MultipartType.OFPMPEXPERIMENTER).build();
+        collector.addMultipartMsg(nextMultipart);
         try {
-            response.get(1L, TimeUnit.SECONDS);
-            fail("We expected timeout exception");
+            response.get();
+            fail("We expect Illgal argument exception in ExecutionException");
         }
-        catch (final TimeoutException e) {
-            // expected exception
+        catch (final ExecutionException e) {
+            assertNotNull(e.getMessage());
+            assertTrue(e.getMessage().contains("OFPMPEXPERIMENTER"));
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
         }
     }
 
@@ -130,12 +160,4 @@ public class MultiMsgCollectorImplTest {
             assertTrue(hwTestValues.contains(replayHwTestString));
         }
     }
-
-    private MultipartReply makeMultipartDescReply(final long xid, final String value, final boolean isLast) {
-        final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc(value).build();
-        final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
-                                                        .setMultipartReplyDesc(descValue).build();
-        return new MultipartReplyMessageBuilder().setMultipartReplyBody(replyBody)
-                .setXid(xid).setFlags(new MultipartRequestFlags(isLast)).build();
-    }
 }
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerImplTest.java
new file mode 100644 (file)
index 0000000..532e648
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.connection.listener;
+
+import static org.junit.Assert.fail;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
+import org.opendaylight.openflowplugin.api.openflow.device.XidGenerator;
+import org.opendaylight.openflowplugin.impl.connection.testutil.MsgGeneratorTestUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
+
+/**
+ * openflowplugin-impl
+ * org.opendaylight.openflowplugin.impl.connection.listener
+ *
+ * test of {@link OpenflowProtocolListenerImpl} - lightweight version, using basic ways (TDD)
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Mar 26, 2015
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class OpenflowProtocolListenerImplTest {
+
+    private static XidGenerator xidGenerator = new XidGenerator();
+
+    private OpenflowProtocolListenerImpl ofProtocolListener;
+
+    @Mock
+    private HandshakeContext handshakeContext;
+
+    @Mock
+    private ConnectionContext connectionContext;
+
+    @Before
+    public void initialize() {
+        // place for mocking method's general behavior for HandshakeContext and ConnectionContext
+        ofProtocolListener = new OpenflowProtocolListenerImpl(connectionContext, handshakeContext);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#OpenflowProtocolListenerImpl(org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext, org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext)}.
+     */
+    @Test
+    @Ignore
+    public void testOpenflowProtocolListenerImpl(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnEchoRequestMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onErrorMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnErrorMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnExperimenterMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnFlowRemovedMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onHelloMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnHelloMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}.
+     */
+    @Test
+    public void testOnMultipartReplyMessage(){
+        final long xid = xidGenerator.generate().getValue();
+        Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
+        final MultipartReply multipartReply = MsgGeneratorTestUtils.makeMultipartDescReply(xid, "test-val", false);
+        ofProtocolListener.onMultipartReplyMessage((MultipartReplyMessage) multipartReply);
+        Mockito.verify(connectionContext, Mockito.times(1)).addMultipartMsg(multipartReply);
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnPacketInMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}.
+     */
+    @Test
+    @Ignore
+    public void testOnPortStatusMessage(){
+    fail("Not yet implemented");
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.listener.OpenflowProtocolListenerImpl#checkState(org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext.CONNECTION_STATE)}.
+     */
+    @Test
+    @Ignore
+    public void testCheckState(){
+    fail("Not yet implemented");
+    }
+
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/testutil/MsgGeneratorTestUtils.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/testutil/MsgGeneratorTestUtils.java
new file mode 100644 (file)
index 0000000..0311509
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.connection.testutil;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
+
+/**
+ * openflowplugin-impl
+ * org.opendaylight.openflowplugin.impl.connection.testutil
+ *
+ *
+ *
+ * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
+ *
+ * Created: Mar 26, 2015
+ */
+public class MsgGeneratorTestUtils {
+
+    private MsgGeneratorTestUtils () {
+        throw new UnsupportedOperationException("Test Utility class");
+    }
+
+    public static MultipartReply makeMultipartDescReply(final long xid, final String value, final boolean hasNext) {
+        final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc(value).build();
+        final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
+                                                        .setMultipartReplyDesc(descValue).build();
+        return new MultipartReplyMessageBuilder().setMultipartReplyBody(replyBody)
+                .setXid(xid).setFlags(new MultipartRequestFlags(hasNext)).setType(MultipartType.OFPMPDESC).build();
+    }
+}