Add multipart reply deserializers unit tests 55/50955/24
authormiroslav.macko <miroslav.macko@pantheon.tech>
Tue, 24 Jan 2017 15:00:29 +0000 (16:00 +0100)
committerTomas Slusny <tomas.slusny@pantheon.tech>
Wed, 15 Feb 2017 15:13:41 +0000 (16:13 +0100)
Add unit tests

See also: bug 7140

Change-Id: Ice9189919efca286c06ea1cced0265dd7e43429d
Signed-off-by: miroslav.macko <miroslav.macko@pantheon.tech>
22 files changed:
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowStatsDeserializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterConfigDeserializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterFeaturesDeserializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyTableFeaturesDeserializer.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/TableFeaturesMatchFieldDeserializer.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/AbstractMultipartDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyDescDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowAggregateStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowTableStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupDescDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupFeaturesDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMessageDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterConfigDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterFeaturesDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortDescDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyQueueStatsDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyTableFeaturesDeserializerTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/TableFeaturesMatchFieldDeserializerTest.java [new file with mode: 0644]

index 63ff4fcfc8cc7457270f93054a1ca5800f1e297e..2a3495fee28e3fb57f3e74e03a7f4c49473d4206 100644 (file)
@@ -76,14 +76,14 @@ public class MultipartReplyFlowStatsDeserializer implements OFDeserializer<Multi
             itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
 
             itemBuilder
-                .setCookie(new FlowCookie(BigInteger.valueOf(message.readLong())))
-                .setCookieMask(new FlowCookie(BigInteger.valueOf(message.readLong())))
-                .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
-                .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())));
+                .setCookie(new FlowCookie(BigInteger.valueOf(itemMessage.readLong())))
+                .setCookieMask(new FlowCookie(BigInteger.valueOf(itemMessage.readLong())))
+                .setPacketCount(new Counter64(BigInteger.valueOf(itemMessage.readLong())))
+                .setByteCount(new Counter64(BigInteger.valueOf(itemMessage.readLong())));
 
 
             final OFDeserializer<Match> matchDeserializer = registry.getDeserializer(MATCH_KEY);
-            itemBuilder.setMatch(new MatchBuilder(matchDeserializer.deserialize(message)).build());
+            itemBuilder.setMatch(new MatchBuilder(matchDeserializer.deserialize(itemMessage)).build());
 
             final int length = itemMessage.readableBytes();
 
index 7cc511be8dce8d1a29e33f637d8cc48f67d923d5..d541c1da833f595419226c4f5b2a87b49303fc8c 100644 (file)
@@ -106,6 +106,7 @@ public class MultipartReplyMeterConfigDeserializer implements OFDeserializer<Mul
                         break;
 
                 }
+                subItems.add(subItemBuilder.build());
             }
 
             items.add(itemBuilder
index e85345375a845f4ea45c6c0ee39ac2085a0b3190..14d50d860ea6f2841cb5088b7c28a6cbc64925c9 100644 (file)
@@ -40,8 +40,8 @@ public class MultipartReplyMeterFeaturesDeserializer implements OFDeserializer<M
     private static List<Class<? extends MeterBand>> readMeterBands(ByteBuf message) {
         final List<Class<? extends MeterBand>> bandTypes = new ArrayList<>();
         final long typesMask = message.readUnsignedInt();
-        final boolean mbtDROP = (typesMask & (1 << 1)) != 0;
-        final boolean mbtDSCPREMARK = (typesMask & (1 << 2)) != 0;
+        final boolean mbtDROP = (typesMask & (1 << 0)) != 0;
+        final boolean mbtDSCPREMARK = (typesMask & (1 << 1)) != 0;
 
         if (mbtDROP) bandTypes.add(MeterBandDrop.class);
         if (mbtDSCPREMARK) bandTypes.add(MeterBandDscpRemark.class);
index 5236f211665e330a95f27320709c0b31ac8561af..3d7af701cc890105ef41801a88c8c2aed784526c 100644 (file)
@@ -216,6 +216,7 @@ public class MultipartReplyTableFeaturesDeserializer implements OFDeserializer<M
                 case OFPTFPTAPPLYSETFIELDMISS:
                     propBuilder.setTableFeaturePropType(new ApplySetfieldMissBuilder()
                             .setApplySetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.apply.setfield.miss.ApplySetfieldMissBuilder()
+                                .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
                                 .build())
                             .build());
                     break;
@@ -259,6 +260,7 @@ public class MultipartReplyTableFeaturesDeserializer implements OFDeserializer<M
             MATCH_FIELD_DESERIALIZER
                 .deserialize(message)
                 .ifPresent(matchField -> matchFields.add(matchField));
+            message.getUnsignedByte(message.readerIndex());
         }
 
         return matchFields;
index c79ac4f11cf3f1159cff2a2355d8012b66257ce3..f60ed59f3b4858e2e1bf895a7621f7d7453f4b7d 100644 (file)
@@ -229,34 +229,19 @@ public class TableFeaturesMatchFieldDeserializer {
                     OxmMatchConstants.NXM_NX_TCP_FLAG), TcpFlags.class)
         .build();
 
-    /**
-     * Processes match entry header and returns if it have mask, or not
-     * @param in input buffer
-     * @return SetFieldMatchBuilder with hasMask properly set
-     */
-    protected static SetFieldMatchBuilder processHeader(ByteBuf in) {
-        in.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES); // skip oxm_class
-        boolean hasMask = (in.readUnsignedByte() & 1) != 0;
-        in.skipBytes(EncodeConstants.SIZE_OF_BYTE_IN_BYTES); // skip match entry length
-
-        return new SetFieldMatchBuilder()
-            .setHasMask(hasMask);
-    }
-
     /**
      * Deserialize match field if deserializer supports it, otherwise returns empty optional
      * @param message input buffer
      * @return set field match
      */
     public Optional<SetFieldMatch> deserialize(ByteBuf message) {
-        int oxmClass = message.getUnsignedShort(message.readerIndex());
-        int oxmField = message.getUnsignedByte(message.readerIndex()
-                + EncodeConstants.SIZE_OF_SHORT_IN_BYTES) >>> 1;
+        int oxmClass = message.readUnsignedShort();
+        int oxmFieldAndMask = message.readUnsignedByte();
+        int oxmField = oxmFieldAndMask >>> 1;
         Long expId = null;
 
         if (oxmClass == EncodeConstants.EXPERIMENTER_VALUE) {
-            expId = message.getUnsignedInt(message.readerIndex() + EncodeConstants.SIZE_OF_SHORT_IN_BYTES
-                    + 2 * EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
+            expId = message.getUnsignedInt(message.readerIndex());
         }
 
         final MatchEntryDeserializerKey key =
@@ -266,7 +251,8 @@ public class TableFeaturesMatchFieldDeserializer {
 
         return Optional
             .ofNullable(CODE_TO_FIELD.get(key))
-            .map(clazz -> processHeader(message)
+            .map(clazz -> new SetFieldMatchBuilder()
+                    .setHasMask((oxmFieldAndMask & 1) != 0)
                     .setKey(new SetFieldMatchKey(clazz))
                     .setMatchType(clazz)
                     .build());
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/AbstractMultipartDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/AbstractMultipartDeserializerTest.java
new file mode 100644 (file)
index 0000000..6ae1220
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.AbstractDeserializerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
+
+public abstract class AbstractMultipartDeserializerTest  extends AbstractDeserializerTest {
+
+    private OFDeserializer<MultipartReplyBody> deserializer;
+
+    @Override
+    protected void init() {
+        deserializer = getRegistry().getDeserializer(
+                new MessageCodeKey(EncodeConstants.OF13_VERSION_ID, getType(), MultipartReplyBody.class));
+    }
+
+    protected MultipartReplyBody deserializeMultipart(ByteBuf message) {
+        return deserializer.deserialize(message);
+    }
+
+    protected abstract int getType();
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyDescDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyDescDeserializerTest.java
new file mode 100644 (file)
index 0000000..1caef2f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.multipart.reply.multipart.reply.body.MultipartReplyDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyDescDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final int DESC_STR_LEN = 256;
+    private static final int SERIAL_NUM_LEN = 32;
+    private static final String MANUFACTURER = "Company";
+    private static final String HARDWARE = "HW";
+    private static final String SOFTWARE = "SW";
+    private static final String SERIAL_NUMBER = "12345678";
+    private static final String DESCRIPTION = "Description";
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeBytes(MANUFACTURER.getBytes());
+        buffer.writeZero(DESC_STR_LEN - MANUFACTURER.length());
+        buffer.writeBytes(HARDWARE.getBytes());
+        buffer.writeZero(DESC_STR_LEN - HARDWARE.length());
+        buffer.writeBytes(SOFTWARE.getBytes());
+        buffer.writeZero(DESC_STR_LEN - SOFTWARE.length());
+        buffer.writeBytes(SERIAL_NUMBER.getBytes());
+        buffer.writeZero(SERIAL_NUM_LEN - SERIAL_NUMBER.length());
+        buffer.writeBytes(DESCRIPTION.getBytes());
+        buffer.writeZero(DESC_STR_LEN - DESCRIPTION.length());
+
+        final MultipartReplyDesc reply = (MultipartReplyDesc) deserializeMultipart(buffer);
+        assertEquals(MANUFACTURER, reply.getManufacturer().trim());
+        assertEquals(HARDWARE, reply.getHardware().trim());
+        assertEquals(SOFTWARE, reply.getSoftware().trim());
+        assertEquals(SERIAL_NUMBER, reply.getSerialNumber().trim());
+        assertEquals(DESCRIPTION, reply.getDescription().trim());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPDESC.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowAggregateStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowAggregateStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..fce52a4
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowAggregateStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyFlowAggregateStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final long PACKET_COUNT = 6l;
+    private static final long BYTE_COUNT = 256l;
+    private static final int FLOW_COUNT = 3;
+    private static final byte PADDING_IN_MULTIPART_REPLY_HEADER = 4;
+
+    @Test
+    public void testDeserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeLong(PACKET_COUNT);
+        buffer.writeLong(BYTE_COUNT);
+        buffer.writeInt(FLOW_COUNT);
+        buffer.writeZero(PADDING_IN_MULTIPART_REPLY_HEADER);
+
+        final MultipartReplyFlowAggregateStats reply = (MultipartReplyFlowAggregateStats) deserializeMultipart(buffer);
+        assertEquals(PACKET_COUNT, reply.getPacketCount().getValue().longValue());
+        assertEquals(BYTE_COUNT, reply.getByteCount().getValue().longValue());
+        assertEquals(FLOW_COUNT, reply.getFlowCount().getValue().intValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPAGGREGATE.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..7f5b2c8
--- /dev/null
@@ -0,0 +1,171 @@
+/**
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.ActionConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyFlowStatsDeserializerTest extends AbstractMultipartDeserializerTest{
+
+    private static final byte PADDING_IN_FLOW_STATS_HEADER_01 = 1;
+    private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 4;
+
+    private static  final short ITEM_LENGTH = 104;
+    private static  final byte TABLE_ID = 1;
+    private static  final int SECOND = 1;
+    private static  final int NANOSECOND = 2;
+    private static  final short PRIORITY = 2;
+    private static  final short IDLE_TIMEOUT = 3;
+    private static  final short HARD_TIMEOUT = 4;
+    private static final boolean SEND_FLOWREM = true;
+    private static final boolean RESET_COUNTS = false;
+    private static final boolean NO_PKTCOUNTS = true;
+    private static final boolean NO_BYTCOUNTS = true;
+    private static final boolean CHECK_OVERLAP = false;
+    private static final FlowModFlags FLAGS = new FlowModFlags(
+            CHECK_OVERLAP, NO_BYTCOUNTS, NO_PKTCOUNTS, RESET_COUNTS, SEND_FLOWREM);
+    private static  final long COOKIE = 2;
+    private static  final long COOKIE_MASK = 3;
+    private static  final long PACKET_COUNT = 4;
+    private static  final long BYTE_COUNT = 5;
+
+    private static final int OXM_MATCH_TYPE_CODE = 1;
+    private static final int MPLS_LABEL = 135;
+
+    @Test
+    public void testDeserialize() throws Exception {
+
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeByte(TABLE_ID);
+        buffer.writeZero(PADDING_IN_FLOW_STATS_HEADER_01);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+        buffer.writeShort(PRIORITY);
+        buffer.writeShort(IDLE_TIMEOUT);
+        buffer.writeShort(HARD_TIMEOUT);
+        buffer.writeShort(ByteBufUtils.fillBitMask(0,
+                FLAGS.isSENDFLOWREM(),
+                FLAGS.isCHECKOVERLAP(),
+                FLAGS.isRESETCOUNTS(),
+                FLAGS.isNOPKTCOUNTS(),
+                FLAGS.isNOBYTCOUNTS()));
+        buffer.writeZero(PADDING_IN_FLOW_STATS_HEADER_02);
+        buffer.writeLong(COOKIE);
+        buffer.writeLong(COOKIE_MASK);
+        buffer.writeLong(PACKET_COUNT);
+        buffer.writeLong(BYTE_COUNT);
+
+        // Match header
+        int matchStartIndex = buffer.writerIndex();
+        buffer.writeShort(OXM_MATCH_TYPE_CODE);
+        int matchLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+
+        // MplsLabel match
+        buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+        buffer.writeByte(OxmMatchConstants.MPLS_LABEL << 1);
+        buffer.writeByte(EncodeConstants.SIZE_OF_INT_IN_BYTES);
+        buffer.writeInt(MPLS_LABEL);
+
+        // Match footer
+        int matchLength = buffer.writerIndex() - matchStartIndex;
+        buffer.setShort(matchLengthIndex, matchLength);
+        int paddingRemainder = matchLength % EncodeConstants.PADDING;
+        if (paddingRemainder != 0) {
+            buffer.writeZero(EncodeConstants.PADDING - paddingRemainder);
+        }
+
+        // Instruction POP PBB header
+        int instructionStartIndex = buffer.writerIndex();
+        buffer.writeShort(InstructionConstants.APPLY_ACTIONS_TYPE);
+        int instructionLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+        buffer.writeZero(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
+
+        // POP PBB action
+        buffer.writeShort(ActionConstants.POP_PBB_CODE);
+        buffer.writeShort(ActionConstants.GENERAL_ACTION_LENGTH);
+        buffer.writeZero(ActionConstants.PADDING_IN_ACTION_HEADER);
+
+        // Count total length of instruction
+        buffer.setShort(instructionLengthIndex, buffer.writerIndex() - instructionStartIndex);
+
+        // Instruction POP Vlan header
+        instructionStartIndex = buffer.writerIndex();
+        buffer.writeShort(InstructionConstants.WRITE_ACTIONS_TYPE);
+        instructionLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+        buffer.writeZero(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
+
+        // POP Vlan action
+        buffer.writeShort(ActionConstants.POP_VLAN_CODE);
+        buffer.writeShort(ActionConstants.GENERAL_ACTION_LENGTH);
+        buffer.writeZero(ActionConstants.PADDING_IN_ACTION_HEADER);
+
+        // Count total length of instruction
+        buffer.setShort(instructionLengthIndex, buffer.writerIndex() - instructionStartIndex);
+
+        final MultipartReplyFlowStats reply = (MultipartReplyFlowStats) deserializeMultipart(buffer);
+        final FlowAndStatisticsMapList flowAndStatisticsMapList = reply.getFlowAndStatisticsMapList().get(0);
+        assertEquals(TABLE_ID, flowAndStatisticsMapList.getTableId().shortValue());
+        assertEquals(SECOND, flowAndStatisticsMapList.getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, flowAndStatisticsMapList.getDuration().getNanosecond().getValue().intValue());
+        assertEquals(PRIORITY, flowAndStatisticsMapList.getPriority().intValue());
+        assertEquals(IDLE_TIMEOUT, flowAndStatisticsMapList.getIdleTimeout().intValue());
+        assertEquals(HARD_TIMEOUT, flowAndStatisticsMapList.getHardTimeout().intValue());
+        assertTrue(flowAndStatisticsMapList.getFlags().equals(FLAGS));
+        assertEquals(COOKIE, flowAndStatisticsMapList.getCookie().getValue().longValue());
+        assertEquals(COOKIE_MASK, flowAndStatisticsMapList.getCookieMask().getValue().longValue());
+        assertEquals(BYTE_COUNT, flowAndStatisticsMapList.getByteCount().getValue().longValue());
+        assertEquals(PACKET_COUNT, flowAndStatisticsMapList.getPacketCount().getValue().longValue());
+
+        assertEquals(2, flowAndStatisticsMapList.getInstructions().getInstruction().size());
+
+        final Instruction instruction = flowAndStatisticsMapList.getInstructions().getInstruction().get(0).getInstruction();
+        assertEquals(ApplyActionsCase.class, instruction.getImplementedInterface());
+
+        final ApplyActionsCase applyActions = ApplyActionsCase.class.cast(instruction);
+        assertEquals(1, applyActions.getApplyActions().getAction().size());
+        assertEquals(PopPbbActionCase.class, applyActions.getApplyActions().getAction().get(0)
+                .getAction().getImplementedInterface());
+
+        final Instruction instruction1 = flowAndStatisticsMapList.getInstructions().getInstruction().get(1).getInstruction();
+        assertEquals(WriteActionsCase.class, instruction1.getImplementedInterface());
+
+        final WriteActionsCase writeActions = WriteActionsCase.class.cast(instruction1);
+        assertEquals(1, writeActions.getWriteActions().getAction().size());
+        assertEquals(PopVlanActionCase.class, writeActions.getWriteActions().getAction().get(0)
+                .getAction().getImplementedInterface());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPFLOW.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowTableStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyFlowTableStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..83dde69
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.multipart.reply.multipart.reply.body.MultipartReplyFlowTableStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyFlowTableStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final byte TABLE_ID = 2;
+    private static final long PACKETS_LOOKEDUP = 1l;
+    private static final long PACKETS_MATCHED = 2l;
+    private static final int ACTIVE_FLOWS = 3;
+    private static final byte PADDING_IN_TABLE_HEADER = 3;
+
+    @Test
+    public void testDeserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeByte(TABLE_ID);
+        buffer.writeZero(PADDING_IN_TABLE_HEADER);
+        buffer.writeInt(ACTIVE_FLOWS);
+        buffer.writeLong(PACKETS_LOOKEDUP);
+        buffer.writeLong(PACKETS_MATCHED);
+
+        final MultipartReplyFlowTableStats reply = (MultipartReplyFlowTableStats) deserializeMultipart(buffer);
+        assertEquals(TABLE_ID, reply.getFlowTableAndStatisticsMap().get(0).getTableId().getValue().byteValue());
+        assertEquals(ACTIVE_FLOWS, reply.getFlowTableAndStatisticsMap().get(0).getActiveFlows().getValue().intValue());
+        assertEquals(PACKETS_LOOKEDUP, reply.getFlowTableAndStatisticsMap().get(0).getPacketsLookedUp().getValue().longValue());
+        assertEquals(PACKETS_MATCHED, reply.getFlowTableAndStatisticsMap().get(0).getPacketsMatched().getValue().longValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPTABLE.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupDescDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupDescDeserializerTest.java
new file mode 100644 (file)
index 0000000..f3b86dd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.impl.util.ActionConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyGroupDescDeserializerTest extends AbstractMultipartDeserializerTest{
+    private static final byte PADDING_IN_GROUP_DESC_HEADER = 1;
+    private static final byte PADDING_IN_BUCKETS_HEADER = 4;
+    private static final short ITEM_LENGTH = 32;
+    private static final int GROUP_TYPE = GroupTypes.GroupSelect.getIntValue();
+    private static final int GROUP_ID = 1;
+    private static final short BUCKET_LENGTH = 24;
+    private static final short WEIGHT = 2;
+    private static final int WATCH_PORT = 3;
+    private static final int WATCH_GROUP = 4;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeByte(GROUP_TYPE);
+        buffer.writeZero(PADDING_IN_GROUP_DESC_HEADER);
+        buffer.writeInt(GROUP_ID);
+        buffer.writeShort(BUCKET_LENGTH);
+        buffer.writeShort(WEIGHT);
+        buffer.writeInt(WATCH_PORT);
+        buffer.writeInt(WATCH_GROUP);
+        buffer.writeZero(PADDING_IN_BUCKETS_HEADER);
+
+        // POP PBB action
+        buffer.writeShort(ActionConstants.POP_PBB_CODE);
+        buffer.writeShort(ActionConstants.GENERAL_ACTION_LENGTH);
+        buffer.writeZero(ActionConstants.PADDING_IN_ACTION_HEADER);
+
+        final MultipartReplyGroupDesc reply = (MultipartReplyGroupDesc) deserializeMultipart(buffer);
+
+        assertEquals(GROUP_ID, reply.getGroupDescStats().get(0).getGroupId().getValue().intValue());
+        assertEquals(WEIGHT, reply.getGroupDescStats().get(0).getBuckets().getBucket().get(0).getWeight().intValue());
+        assertEquals(WATCH_PORT, reply.getGroupDescStats().get(0).getBuckets().getBucket().get(0).getWatchPort().intValue());
+        assertEquals(WATCH_GROUP, reply.getGroupDescStats().get(0).getBuckets().getBucket().get(0).getWatchGroup().intValue());
+        assertEquals(GROUP_TYPE, reply.getGroupDescStats().get(0).getGroupType().getIntValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPGROUPDESC.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupFeaturesDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupFeaturesDeserializerTest.java
new file mode 100644 (file)
index 0000000..e7fbb80
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupCapabilities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupIndirect;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupSelect;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyGroupFeaturesDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final List<Long> MAX_GROUPS_LIST = Arrays.asList(1l, 2l, 3l, 4l);
+    private static final List<Long> ACTIONS_LIST = Arrays.asList(5l, 6l, 7l, 8l);
+
+    private static final List<GroupTypes> GROUP_TYPES_SUPPORTED = Arrays.asList(
+            GroupTypes.GroupAll,
+            GroupTypes.GroupSelect,
+            GroupTypes.GroupIndirect);
+
+    private static final List<GroupCapabilities> GROUP_CAPABILITIES_SUPPORTED = Arrays.asList(
+            GroupCapabilities.Chaining,
+            GroupCapabilities.ChainingChecks);
+
+    @Test
+    public void testDeserialize() throws Exception {
+
+        int bitMaskGroups = ByteBufUtils.fillBitMask(0,
+                GROUP_TYPES_SUPPORTED.contains(GroupTypes.GroupAll),
+                GROUP_TYPES_SUPPORTED.contains(GroupTypes.GroupSelect),
+                GROUP_TYPES_SUPPORTED.contains(GroupTypes.GroupIndirect),
+                GROUP_TYPES_SUPPORTED.contains(GroupTypes.GroupFf));
+
+        int bitMaskCapabilities = ByteBufUtils.fillBitMask(0,
+                GROUP_CAPABILITIES_SUPPORTED.contains(GroupCapabilities.SelectWeight),
+                GROUP_CAPABILITIES_SUPPORTED.contains(GroupCapabilities.SelectLiveness),
+                GROUP_CAPABILITIES_SUPPORTED.contains(GroupCapabilities.Chaining),
+                GROUP_CAPABILITIES_SUPPORTED.contains(GroupCapabilities.ChainingChecks));
+
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+
+        buffer.writeInt(bitMaskGroups);
+        buffer.writeInt(bitMaskCapabilities);
+
+        for (Long group: MAX_GROUPS_LIST) {
+            buffer.writeInt(group.intValue());
+        }
+
+        for (Long action: ACTIONS_LIST) {
+            buffer.writeInt(action.intValue());
+        }
+
+        final MultipartReplyGroupFeatures reply = (MultipartReplyGroupFeatures) deserializeMultipart(buffer);
+        assertTrue(reply.getActions().containsAll(ACTIONS_LIST));
+        assertTrue(reply.getMaxGroups().containsAll(MAX_GROUPS_LIST));
+
+        assertEquals(GROUP_TYPES_SUPPORTED.size(), reply.getGroupTypesSupported().size());
+        assertEquals(GroupAll.class, reply.getGroupTypesSupported().get(0));
+        assertEquals(GroupSelect.class, reply.getGroupTypesSupported().get(1));
+        assertEquals(GroupIndirect.class, reply.getGroupTypesSupported().get(2));
+
+        assertEquals(GROUP_CAPABILITIES_SUPPORTED.size(), reply.getGroupCapabilitiesSupported().size());
+        assertEquals(Chaining.class, reply.getGroupCapabilitiesSupported().get(0));
+        assertEquals(ChainingChecks.class, reply.getGroupCapabilitiesSupported().get(1));
+
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPGROUPFEATURES.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyGroupStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..367abcc
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyGroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyGroupStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final byte PADDING_IN_GROUP_HEADER_01 = 2;
+    private static final byte PADDING_IN_GROUP_HEADER_02 = 4;
+
+    private static final short ITEM_LENGTH = 56;
+    private static final int GROUP_ID = 3;
+    private static final int REF_COUNT = 4;
+    private static final int SECOND = 5;
+    private static final int NANOSECOND = 6;
+    private static final long PACKET_COUNT = 1l;
+    private static final long BYTE_COUNT = 2l;
+
+    @Test
+    public void testDeserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeZero(PADDING_IN_GROUP_HEADER_01);
+        buffer.writeInt(GROUP_ID);
+        buffer.writeInt(REF_COUNT);
+        buffer.writeZero(PADDING_IN_GROUP_HEADER_02);
+        buffer.writeLong(PACKET_COUNT);
+        buffer.writeLong(BYTE_COUNT);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+        buffer.writeLong(PACKET_COUNT);
+        buffer.writeLong(BYTE_COUNT);
+
+        final MultipartReplyGroupStats reply = (MultipartReplyGroupStats) deserializeMultipart(buffer);
+        assertEquals(GROUP_ID, reply.getGroupStats().get(0).getGroupId().getValue().intValue());
+        assertEquals(REF_COUNT, reply.getGroupStats().get(0).getRefCount().getValue().intValue());
+        assertEquals(PACKET_COUNT, reply.getGroupStats().get(0).getPacketCount().getValue().longValue());
+        assertEquals(BYTE_COUNT, reply.getGroupStats().get(0).getByteCount().getValue().longValue());
+        assertEquals(SECOND, reply.getGroupStats().get(0).getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, reply.getGroupStats().get(0).getDuration().getNanosecond().getValue().intValue());
+        assertEquals(PACKET_COUNT, reply.getGroupStats().get(0).getPacketCount().getValue().longValue());
+        assertEquals(BYTE_COUNT, reply.getGroupStats().get(0).getByteCount().getValue().longValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPGROUP.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMessageDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMessageDeserializerTest.java
new file mode 100644 (file)
index 0000000..15ac117
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.ActionConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.AbstractDeserializerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopPbbActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.MultipartReply;
+
+public class MultipartReplyMessageDeserializerTest extends AbstractDeserializerTest {
+    private static final byte PADDING_IN_MULTIPART_REPLY_HEADER = 4;
+    private static final byte PADDING_IN_FLOW_STATS_HEADER_01 = 1;
+    private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 4;
+
+    private static final int XID = 42;
+    private static final short TYPE = 19;
+    private static final short MULTIPART_TYPE = 1;
+    private static final short REQ_MORE = 1;
+    private static final short ITEM_LENGTH = 88;
+
+    private static  final byte TABLE_ID = 1;
+    private static  final int SECOND = 1;
+    private static  final int NANOSECOND = 2;
+    private static  final short PRIORITY = 2;
+    private static  final short IDLE_TIMEOUT = 3;
+    private static  final short HARD_TIMEOUT = 4;
+    private static final boolean SEND_FLOWREM = true;
+    private static final boolean RESET_COUNTS = false;
+    private static final boolean NO_PKTCOUNTS = true;
+    private static final boolean NO_BYTCOUNTS = true;
+    private static final boolean CHECK_OVERLAP = false;
+    private static final FlowModFlags FLAGS = new FlowModFlags(
+            CHECK_OVERLAP, NO_BYTCOUNTS, NO_PKTCOUNTS, RESET_COUNTS, SEND_FLOWREM);
+    private static  final long COOKIE = 2;
+    private static  final long COOKIE_MASK = 3;
+    private static  final long PACKET_COUNT = 4;
+    private static  final long BYTE_COUNT = 5;
+
+    private static final int OXM_MATCH_TYPE_CODE = 1;
+    private static final int MPLS_LABEL = 135;
+
+    @Override
+    protected void init() {
+    }
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeByte(TYPE);
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+        buffer.writeInt(XID);
+        buffer.writeShort(MULTIPART_TYPE);
+        buffer.writeShort(REQ_MORE);
+        buffer.writeZero(PADDING_IN_MULTIPART_REPLY_HEADER);
+
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeByte(TABLE_ID);
+        buffer.writeZero(PADDING_IN_FLOW_STATS_HEADER_01);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+        buffer.writeShort(PRIORITY);
+        buffer.writeShort(IDLE_TIMEOUT);
+        buffer.writeShort(HARD_TIMEOUT);
+        buffer.writeShort(ByteBufUtils.fillBitMask(0,
+                FLAGS.isSENDFLOWREM(),
+                FLAGS.isCHECKOVERLAP(),
+                FLAGS.isRESETCOUNTS(),
+                FLAGS.isNOPKTCOUNTS(),
+                FLAGS.isNOBYTCOUNTS()));
+        buffer.writeZero(PADDING_IN_FLOW_STATS_HEADER_02);
+        buffer.writeLong(COOKIE);
+        buffer.writeLong(COOKIE_MASK);
+        buffer.writeLong(PACKET_COUNT);
+        buffer.writeLong(BYTE_COUNT);
+
+        // Match header
+        int matchStartIndex = buffer.writerIndex();
+        buffer.writeShort(OXM_MATCH_TYPE_CODE);
+        int matchLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+
+        // MplsLabel match
+        buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+        buffer.writeByte(OxmMatchConstants.MPLS_LABEL << 1);
+        buffer.writeByte(EncodeConstants.SIZE_OF_INT_IN_BYTES);
+        buffer.writeInt(MPLS_LABEL);
+
+        // Match footer
+        int matchLength = buffer.writerIndex() - matchStartIndex;
+        buffer.setShort(matchLengthIndex, matchLength);
+        int paddingRemainder = matchLength % EncodeConstants.PADDING;
+        if (paddingRemainder != 0) {
+            buffer.writeZero(EncodeConstants.PADDING - paddingRemainder);
+        }
+
+        // Instruction POP PBB header
+        int instructionStartIndex = buffer.writerIndex();
+        buffer.writeShort(InstructionConstants.APPLY_ACTIONS_TYPE);
+        int instructionLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+        buffer.writeZero(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
+
+        // POP PBB action
+        buffer.writeShort(ActionConstants.POP_PBB_CODE);
+        buffer.writeShort(ActionConstants.GENERAL_ACTION_LENGTH);
+        buffer.writeZero(ActionConstants.PADDING_IN_ACTION_HEADER);
+
+        // Count total length of instruction
+        buffer.setShort(instructionLengthIndex, buffer.writerIndex() - instructionStartIndex);
+
+        // Deserialize and check everything
+        final MultipartReply message = (MultipartReply) getFactory()
+                .deserialize(buffer, EncodeConstants.OF13_VERSION_ID);
+
+        final MultipartReplyFlowStats reply = (MultipartReplyFlowStats) message.getMultipartReplyBody();
+
+        assertEquals(XID, message.getXid().intValue());
+        final FlowAndStatisticsMapList flowAndStatisticsMapList = reply.getFlowAndStatisticsMapList().get(0);
+        assertEquals(TABLE_ID, flowAndStatisticsMapList.getTableId().shortValue());
+        assertEquals(SECOND, flowAndStatisticsMapList.getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, flowAndStatisticsMapList.getDuration().getNanosecond().getValue().intValue());
+        assertEquals(PRIORITY, flowAndStatisticsMapList.getPriority().intValue());
+        assertEquals(IDLE_TIMEOUT, flowAndStatisticsMapList.getIdleTimeout().intValue());
+        assertEquals(HARD_TIMEOUT, flowAndStatisticsMapList.getHardTimeout().intValue());
+        assertTrue(flowAndStatisticsMapList.getFlags().equals(FLAGS));
+        assertEquals(COOKIE, flowAndStatisticsMapList.getCookie().getValue().longValue());
+        assertEquals(COOKIE_MASK, flowAndStatisticsMapList.getCookieMask().getValue().longValue());
+        assertEquals(BYTE_COUNT, flowAndStatisticsMapList.getByteCount().getValue().longValue());
+        assertEquals(PACKET_COUNT, flowAndStatisticsMapList.getPacketCount().getValue().longValue());
+
+        assertEquals(1, flowAndStatisticsMapList.getInstructions().getInstruction().size());
+
+        final Instruction instruction = flowAndStatisticsMapList.getInstructions().getInstruction().get(0).getInstruction();
+        assertEquals(ApplyActionsCase.class, instruction.getImplementedInterface());
+
+        final ApplyActionsCase applyActions = ApplyActionsCase.class.cast(instruction);
+        assertEquals(1, applyActions.getApplyActions().getAction().size());
+        assertEquals(PopPbbActionCase.class, applyActions.getApplyActions().getAction().get(0)
+                .getAction().getImplementedInterface());
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterConfigDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterConfigDeserializerTest.java
new file mode 100644 (file)
index 0000000..ab7d255
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyMeterConfigDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final byte PADDING_IN_METER_BAND_DROP_HEADER = 4;
+    private static final byte PADDING_IN_METER_BAND_DSCP_HEADER = 3;
+    private static final int OFPMBTDROP = 1;
+    private static final int OFPMBTDSCP = 2;
+    private static final short ITEM_LENGTH = 16;
+    private static final boolean MF_KBPS = true;
+    private static final boolean MF_PKTPS = false;
+    private static final boolean MF_BURST = true;
+    private static final boolean MF_STATS = true;
+    private static final MeterFlags FLAGS = new MeterFlags(MF_KBPS, MF_PKTPS, MF_BURST, MF_STATS);
+    private static final int METER_ID = 1;
+    private static final short SUB_ITEM = 8;
+    private static final int DROP_RATE = 2;
+    private static final int DROP_BURST_SIZE = 3;
+    private static final int DSCP_REMARK_RATE = 3;
+    private static final int DSCP_REMARK_BURST_SIZE = 3;
+    private static final byte PREC_LEVEL = 3;
+
+    @Test
+    public void deserializeDrop() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        writeCommonAtributes(buffer);
+        buffer.writeShort(OFPMBTDROP);
+        buffer.writeShort(SUB_ITEM);
+        buffer.writeInt(DROP_RATE);
+        buffer.writeInt(DROP_BURST_SIZE);
+        buffer.writeZero(PADDING_IN_METER_BAND_DROP_HEADER);
+
+        final MultipartReplyMeterConfig reply = (MultipartReplyMeterConfig) deserializeMultipart(buffer);
+
+        assertEquals(METER_ID, reply.getMeterConfigStats().get(0).getMeterId().getValue().intValue());
+        assertEquals(FLAGS, reply.getMeterConfigStats().get(0).getFlags());
+        final Drop drop = (Drop) reply.getMeterConfigStats().get(0)
+                .getMeterBandHeaders().getMeterBandHeader().get(0).getBandType();
+        assertEquals(DROP_RATE, drop.getDropRate().intValue());
+        assertEquals(DROP_BURST_SIZE, drop.getDropBurstSize().intValue());
+    }
+
+    @Test
+    public void deserializeDscp() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        writeCommonAtributes(buffer);
+        buffer.writeShort(OFPMBTDSCP);
+        buffer.writeShort(SUB_ITEM);
+        buffer.writeInt(DSCP_REMARK_RATE);
+        buffer.writeInt(DSCP_REMARK_BURST_SIZE);
+        buffer.writeByte(PREC_LEVEL);
+        buffer.writeZero(PADDING_IN_METER_BAND_DSCP_HEADER);
+
+        final MultipartReplyMeterConfig reply = (MultipartReplyMeterConfig) deserializeMultipart(buffer);
+
+        final DscpRemark dscpRemark = (DscpRemark) reply.getMeterConfigStats().get(0)
+                .getMeterBandHeaders().getMeterBandHeader().get(0).getBandType();
+        assertEquals(DSCP_REMARK_RATE, dscpRemark.getDscpRemarkRate().intValue());
+        assertEquals(DSCP_REMARK_BURST_SIZE, dscpRemark.getDscpRemarkBurstSize().intValue());
+        assertEquals(PREC_LEVEL, dscpRemark.getPrecLevel().byteValue());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPMETERCONFIG.getIntValue();
+    }
+
+    private void writeCommonAtributes(ByteBuf buffer) {
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeShort(ByteBufUtils.fillBitMask(0,
+                FLAGS.isMeterKbps(),
+                FLAGS.isMeterPktps(),
+                FLAGS.isMeterBurst(),
+                FLAGS.isMeterStats()));
+        buffer.writeInt(METER_ID);
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterFeaturesDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterFeaturesDeserializerTest.java
new file mode 100644 (file)
index 0000000..5a97ca3
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBurst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterKbps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterPktps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyMeterFeaturesDeserializerTest extends AbstractMultipartDeserializerTest{
+    private static final int MAX_METER = 3;
+    private static final List BANDS_SUPPORTED = Arrays.asList(MeterBandDrop.class);
+    private static final List CAPABILITIES_SUPPORTED = Arrays.asList(MeterKbps.class, MeterBurst.class);
+    private static final byte MAX_BANDS = 56;
+    private static final byte MAX_COLOR = 48;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeInt(MAX_METER);
+
+        int bitMaskBands = ByteBufUtils.fillBitMask(0,
+                BANDS_SUPPORTED.contains(MeterBandDrop.class),
+                BANDS_SUPPORTED.contains(MeterBandDscpRemark.class));
+        buffer.writeInt(bitMaskBands);
+
+        int bitMaskCapabilities = ByteBufUtils.fillBitMask(0,
+                CAPABILITIES_SUPPORTED.contains(MeterKbps.class),
+                CAPABILITIES_SUPPORTED.contains(MeterPktps.class),
+                CAPABILITIES_SUPPORTED.contains(MeterBurst.class),
+                CAPABILITIES_SUPPORTED.contains(MeterStats.class));
+        buffer.writeInt(bitMaskCapabilities);
+
+        buffer.writeByte(MAX_BANDS);
+        buffer.writeByte(MAX_COLOR);
+
+        final MultipartReplyMeterFeatures reply = (MultipartReplyMeterFeatures) deserializeMultipart(buffer);
+
+        assertEquals(MAX_METER, reply.getMaxMeter().getValue().intValue());
+        assertTrue(reply.getMeterBandSupported().containsAll(BANDS_SUPPORTED));
+        assertTrue(reply.getMeterCapabilitiesSupported().containsAll(CAPABILITIES_SUPPORTED));
+        assertEquals(MAX_BANDS, reply.getMaxBands().byteValue());
+        assertEquals(MAX_COLOR, reply.getMaxColor().byteValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPMETERFEATURES.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyMeterStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..c3e0f38
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyMeterStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final byte PADDING_IN_METER_STATS_HEADER = 6;
+    private static final int METER_ID = 1;
+    private static final short ITEM_LENGTH = 50;
+    private static final int FLOW_COUNT = 2;
+    private static final long PACKET_IN_COUNT = 3l;
+    private static final long BYTE_IN_COUNT = 4l;
+    private static final int SECOND = 5;
+    private static final int NANOSECOND = 6;
+    private static final long PACKET_BAND_COUNT = 7l;
+    private static final long BYTE_BAND_COUNT = 8l;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeInt(METER_ID);
+        buffer.writeShort(ITEM_LENGTH);
+        buffer.writeZero(PADDING_IN_METER_STATS_HEADER);
+        buffer.writeInt(FLOW_COUNT);
+        buffer.writeLong(PACKET_IN_COUNT);
+        buffer.writeLong(BYTE_IN_COUNT);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+        buffer.writeLong(PACKET_BAND_COUNT);
+        buffer.writeLong(BYTE_BAND_COUNT);
+
+        final MultipartReplyMeterStats reply = (MultipartReplyMeterStats) deserializeMultipart(buffer);
+
+        final MeterStats meterStats = reply.getMeterStats().get(0);
+
+        assertEquals(METER_ID, meterStats.getMeterId().getValue().intValue());
+        assertEquals(FLOW_COUNT, meterStats.getFlowCount().getValue().intValue());
+        assertEquals(PACKET_IN_COUNT, meterStats.getPacketInCount().getValue().longValue());
+        assertEquals(BYTE_IN_COUNT, meterStats.getByteInCount().getValue().intValue());
+        assertEquals(SECOND, meterStats.getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, meterStats.getDuration().getNanosecond().getValue().intValue());
+        assertEquals(PACKET_BAND_COUNT, meterStats.getMeterBandStats().getBandStat().get(0)
+                .getPacketBandCount().getValue().longValue());
+        assertEquals(BYTE_BAND_COUNT, meterStats.getMeterBandStats().getBandStat().get(0)
+                .getByteBandCount().getValue().longValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPMETER.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortDescDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortDescDeserializerTest.java
new file mode 100644 (file)
index 0000000..d01be07
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.multipart.reply.multipart.reply.body.MultipartReplyPortDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+
+public class MultipartReplyPortDescDeserializerTest extends AbstractMultipartDeserializerTest{
+    private static final byte PADDING_IN_PORT_DESC_HEADER_01 = 4;
+    private static final byte PADDING_IN_PORT_DESC_HEADER_02 = 2;
+
+    private static final int PORT_NUMBER = 1;
+    private static final byte[] MAC_ADDRESS = new byte[] {1,2,3,4,5,6};
+
+    private static final boolean PC_PORT_DOWN = true;
+    private static final boolean PC_N0_RECV = true;
+    private static final boolean PC_N0_FWD = false;
+    private static final boolean PC_N0_PACKET_IN = true;
+    private static final PortConfig PORT_CONFIG = new PortConfig(PC_N0_FWD, PC_N0_PACKET_IN, PC_N0_RECV, PC_PORT_DOWN);
+
+    private static final boolean PS_LINK_DOWN = true;
+    private static final boolean PS_BLOCKED = true;
+    private static final boolean PS_LIVE = false;
+
+    private static final boolean PF10MBHD = true;
+    private static final boolean PF10MBFD = true;
+    private static final boolean PF100MBHD = true;
+    private static final boolean PF100MBFD = true;
+    private static final boolean PF1GBHD = true;
+    private static final boolean PF1GBFD = true;
+    private static final boolean PF10GBFD = true;
+    private static final boolean PF40GBFD = true;
+    private static final boolean PF100GBFD = true;
+    private static final boolean PF1TBFD = false;
+    private static final boolean PFOTHER = false;
+    private static final boolean PFCOPPER = false;
+    private static final boolean PFFIBER = false;
+    private static final boolean PFAUTONEG = false;
+    private static final boolean PFPAUSE = false;
+    private static final boolean PFPAUSEASYM = false;
+    private static  final PortFeatures CURRENT_FEATURE = new PortFeatures(PFAUTONEG, PFCOPPER, PFFIBER, PF40GBFD,
+                                                        PF100GBFD, PF100MBFD, PF100MBHD, PF1GBFD, PF1GBHD, PF1TBFD,
+                                                        PFOTHER, PFPAUSE, PFPAUSEASYM, PF10GBFD, PF10MBFD, PF10MBHD);
+    private static final int ADVERTISED_FEATURE = 6;
+    private static final int SUPPORTED_FEATURE = 7;
+    private static final int PEER_FEATURES = 8;
+    private static final int CURRENT_SPEED = 9;
+    private static final int MAXIMUM_SPEED = 10;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeInt(PORT_NUMBER);
+        buffer.writeZero(PADDING_IN_PORT_DESC_HEADER_01);
+        buffer.writeBytes(MAC_ADDRESS);
+        buffer.writeZero(PADDING_IN_PORT_DESC_HEADER_02);
+        buffer.writeZero(EncodeConstants.MAX_PORT_NAME_LENGTH);
+
+        Map<Integer, Boolean> portMap = new HashMap<>();
+        portMap.put(new Integer(0), PORT_CONFIG.isPORTDOWN());
+        portMap.put(new Integer(2), PORT_CONFIG.isNORECV());
+        portMap.put(new Integer(5), PORT_CONFIG.isNOFWD());
+        portMap.put(new Integer(6), PORT_CONFIG.isNOPACKETIN());
+
+        buffer.writeInt(ByteBufUtils.fillBitMaskFromMap(portMap));
+        buffer.writeInt(ByteBufUtils.fillBitMask(0, PS_BLOCKED, PS_LINK_DOWN, PS_LIVE));
+        buffer.writeInt(ByteBufUtils.fillBitMask(0,
+                CURRENT_FEATURE.isTenMbHd(),
+                CURRENT_FEATURE.isTenMbFd(),
+                CURRENT_FEATURE.isHundredMbHd(),
+                CURRENT_FEATURE.isHundredMbFd(),
+                CURRENT_FEATURE.isOneGbHd(),
+                CURRENT_FEATURE.isOneGbFd(),
+                CURRENT_FEATURE.isTenGbFd(),
+                CURRENT_FEATURE.isFortyGbFd(),
+                CURRENT_FEATURE.isHundredGbFd(),
+                CURRENT_FEATURE.isOneTbFd(),
+                CURRENT_FEATURE.isOther(),
+                CURRENT_FEATURE.isFiber(),
+                CURRENT_FEATURE.isAutoeng(),
+                CURRENT_FEATURE.isCopper(),
+                CURRENT_FEATURE.isPause(),
+                CURRENT_FEATURE.isPauseAsym()));
+        buffer.writeInt(ADVERTISED_FEATURE);
+        buffer.writeInt(SUPPORTED_FEATURE);
+        buffer.writeInt(PEER_FEATURES);
+        buffer.writeInt(CURRENT_SPEED);
+        buffer.writeInt(MAXIMUM_SPEED);
+
+        final MultipartReplyPortDesc reply = (MultipartReplyPortDesc) deserializeMultipart(buffer);
+        assertEquals(PORT_NUMBER, reply.getPorts().get(0).getPortNumber().getUint32().intValue());
+        assertEquals("01:02:03:04:05:06", reply.getPorts().get(0).getHardwareAddress().getValue());
+        assertEquals(PORT_CONFIG, reply.getPorts().get(0).getConfiguration());
+        assertEquals(PS_BLOCKED, reply.getPorts().get(0).getState().isBlocked());
+        assertEquals(PS_LINK_DOWN, reply.getPorts().get(0).getState().isLinkDown());
+        assertEquals(PS_LIVE, reply.getPorts().get(0).getState().isLive());
+        assertEquals(CURRENT_FEATURE, reply.getPorts().get(0).getCurrentFeature());
+        assertEquals(CURRENT_SPEED, reply.getPorts().get(0).getCurrentSpeed().intValue());
+        assertEquals(MAXIMUM_SPEED, reply.getPorts().get(0).getMaximumSpeed().intValue());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPPORTDESC.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyPortStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..6733b94
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.multipart.reply.multipart.reply.body.MultipartReplyPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+
+public class MultipartReplyPortStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final byte PADDING_IN_PORT_STATS_HEADER = 4;
+    private static final int PORT = 1;
+    private static final long PACKETS_RECEIVED = 2l;
+    private static final long PACKETS_TRANSMITTED = 3l;
+    private static final long BYTES_RECEIVED = 4l;
+    private static final long BYTES_TRANSMITTED = 5l;
+    private static final long RECEIVE_DROPS = 6l;
+    private static final long TRANSMIT_DROPS = 7l;
+    private static final long RECEIVE_ERRORS = 8l;
+    private static final long TRANSMIT_ERRORS = 9l;
+    private static final long RECEIVE_FRAME_ERROR = 10l;
+    private static final long RECEIVE_OVER_RUN_ERROR = 11l;
+    private static final long RECEIVE_CRC_ERROR = 12l;
+    private static final long COLLIESION_COUNT = 13l;
+    private static final int SECOND = 14;
+    private static final int NANOSECOND = 15;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeInt(PORT);
+        buffer.writeZero(PADDING_IN_PORT_STATS_HEADER);
+        buffer.writeLong(PACKETS_RECEIVED);
+        buffer.writeLong(PACKETS_TRANSMITTED);
+        buffer.writeLong(BYTES_RECEIVED);
+        buffer.writeLong(BYTES_TRANSMITTED);
+        buffer.writeLong(RECEIVE_DROPS);
+        buffer.writeLong(TRANSMIT_DROPS);
+        buffer.writeLong(RECEIVE_ERRORS);
+        buffer.writeLong(TRANSMIT_ERRORS);
+        buffer.writeLong(RECEIVE_FRAME_ERROR);
+        buffer.writeLong(RECEIVE_OVER_RUN_ERROR);
+        buffer.writeLong(RECEIVE_CRC_ERROR);
+        buffer.writeLong(COLLIESION_COUNT);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+
+        final MultipartReplyPortStats reply = (MultipartReplyPortStats) deserializeMultipart(buffer);
+
+        final NodeConnectorStatisticsAndPortNumberMap portStats = reply.getNodeConnectorStatisticsAndPortNumberMap().get(0);
+        assertEquals(PACKETS_RECEIVED, portStats.getPackets().getReceived().longValue());
+        assertEquals(PACKETS_TRANSMITTED, portStats.getPackets().getTransmitted().longValue());
+        assertEquals(BYTES_RECEIVED, portStats.getBytes().getReceived().longValue());
+        assertEquals(BYTES_TRANSMITTED, portStats.getBytes().getTransmitted().longValue());
+        assertEquals(RECEIVE_DROPS, portStats.getReceiveDrops().longValue());
+        assertEquals(TRANSMIT_DROPS, portStats.getTransmitDrops().longValue());
+        assertEquals(RECEIVE_ERRORS, portStats.getReceiveErrors().longValue());
+        assertEquals(TRANSMIT_ERRORS, portStats.getTransmitErrors().longValue());
+        assertEquals(RECEIVE_FRAME_ERROR, portStats.getReceiveFrameError().longValue());
+        assertEquals(RECEIVE_OVER_RUN_ERROR, portStats.getReceiveOverRunError().longValue());
+        assertEquals(RECEIVE_CRC_ERROR, portStats.getReceiveCrcError().longValue());
+        assertEquals(COLLIESION_COUNT, portStats.getCollisionCount().longValue());
+        assertEquals(SECOND, portStats.getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, portStats.getDuration().getNanosecond().getValue().intValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPPORTSTATS.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyQueueStatsDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyQueueStatsDeserializerTest.java
new file mode 100644 (file)
index 0000000..fbedf4c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.multipart.reply.multipart.reply.body.MultipartReplyQueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.queue.id.and.statistics.map.QueueIdAndStatisticsMap;
+
+public class MultipartReplyQueueStatsDeserializerTest extends AbstractMultipartDeserializerTest {
+    private static final int PORT = 1;
+    private static final int QUEUE_ID = 1;
+    private static final long TRANSMITTED_BYTES = 5l;
+    private static final long TRANSMITTED_PACKETS = 3l;
+    private static final long TRANSMISSON_ERRORS = 9l;
+    private static final int SECOND = 14;
+    private static final int NANOSECOND = 15;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+        buffer.writeInt(PORT);
+        buffer.writeInt(QUEUE_ID);
+        buffer.writeLong(TRANSMITTED_BYTES);
+        buffer.writeLong(TRANSMITTED_PACKETS);
+        buffer.writeLong(TRANSMISSON_ERRORS);
+        buffer.writeInt(SECOND);
+        buffer.writeInt(NANOSECOND);
+
+        final MultipartReplyQueueStats reply = (MultipartReplyQueueStats) deserializeMultipart(buffer);
+
+        final QueueIdAndStatisticsMap queueStats = reply.getQueueIdAndStatisticsMap().get(0);
+
+        assertEquals(QUEUE_ID, queueStats.getQueueId().getValue().intValue());
+        assertEquals(TRANSMITTED_BYTES, queueStats.getTransmittedBytes().getValue().longValue());
+        assertEquals(TRANSMITTED_PACKETS, queueStats.getTransmittedPackets().getValue().longValue());
+        assertEquals(TRANSMISSON_ERRORS, queueStats.getTransmissionErrors().getValue().longValue());
+        assertEquals(SECOND, queueStats.getDuration().getSecond().getValue().intValue());
+        assertEquals(NANOSECOND, queueStats.getDuration().getNanosecond().getValue().intValue());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPQUEUE.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyTableFeaturesDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/MultipartReplyTableFeaturesDeserializerTest.java
new file mode 100644 (file)
index 0000000..58b37e9
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsMiss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfield;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldMiss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsMiss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableMiss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.Wildcards;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsMiss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfield;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldMiss;
+
+public class MultipartReplyTableFeaturesDeserializerTest extends AbstractMultipartDeserializerTest {
+
+    private static final byte PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES = 5;
+    private static final byte MAX_TABLE_NAME_LENGTH = 32;
+
+    private static final byte TABLE_ID = 1;
+    private static final long METADATA_MATCH = 2;
+    private static final long METADATA_WRITE = 3;
+    private static final int  TABLE_CONFIG= 3;
+    private static final int  MAX_ENTRIES= 3;
+
+    private static final int OFPTFPT_INSTRUCTIONS = 0;
+    private static final int OFPTFPT_INSTRUCTIONS_MISS = 1;
+    private static final int OFPTFPT_NEXT_TABLES = 2;
+    private static final int OFPTFPT_NEXT_TABLES_MISS = 3;
+    private static final int OFPTFPT_WRITE_ACTIONS = 4;
+    private static final int OFPTFPT_WRITE_ACTIONS_MISS = 5;
+    private static final int OFPTFPT_APPLY_ACTIONS = 6;
+    private static final int OFPTFPT_APPLY_ACTIONS_MISS = 7;
+    private static final int OFPTFPT_MATCH = 8;
+    private static final int OFPTFPT_WILDCARDS = 10;
+    private static final int OFPTFPT_WRITE_SETFIELD = 12;
+    private static final int OFPTFPT_WRITE_SETFIELD_MISS = 13;
+    private static final int OFPTFPT_APPLY_SETFIELD = 14;
+    private static final int OFPTFPT_APPLY_SETFIELD_MISS = 15;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+
+        writeValues(buffer, OFPTFPT_INSTRUCTIONS);
+        MultipartReplyTableFeatures reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(TABLE_ID, reply.getTableFeatures().get(0).getTableId().byteValue());
+        assertEquals(METADATA_MATCH, reply.getTableFeatures().get(0).getMetadataMatch().longValue());
+        assertEquals(METADATA_WRITE, reply.getTableFeatures().get(0).getMetadataWrite().longValue());
+        assertEquals(MAX_ENTRIES, reply.getTableFeatures().get(0).getMaxEntries().longValue());
+        assertEquals(MAX_ENTRIES, reply.getTableFeatures().get(0).getMaxEntries().longValue());
+        assertEquals(Instructions.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_INSTRUCTIONS_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(InstructionsMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_NEXT_TABLES);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(NextTable.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_NEXT_TABLES_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(NextTableMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_WRITE_ACTIONS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(WriteActions.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_WRITE_ACTIONS_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(WriteActionsMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_APPLY_ACTIONS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(ApplyActions.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_APPLY_ACTIONS_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(ApplyActionsMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_MATCH);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(Match.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_WILDCARDS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(Wildcards.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_WRITE_SETFIELD);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(WriteSetfield.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_WRITE_SETFIELD_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(WriteSetfieldMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_APPLY_SETFIELD);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(ApplySetfield.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+
+        writeValues(buffer, OFPTFPT_APPLY_SETFIELD_MISS);
+        reply = (MultipartReplyTableFeatures) deserializeMultipart(buffer);
+
+        assertEquals(ApplySetfieldMiss.class, reply.getTableFeatures().get(0).getTableProperties()
+                .getTableFeatureProperties().get(0).getTableFeaturePropType().getImplementedInterface());
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    private void writeValues(ByteBuf buffer, int propertyType) {
+        TableFeaturesPropType propType = TableFeaturesPropType.forValue(propertyType);
+
+        buffer.clear();
+        int replyIndex = buffer.readerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+        buffer.writeByte(TABLE_ID);
+        buffer.writeZero(PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES);
+        buffer.writeZero(MAX_TABLE_NAME_LENGTH);
+        buffer.writeLong(METADATA_MATCH);
+        buffer.writeLong(METADATA_WRITE);
+        buffer.writeInt(TABLE_CONFIG);
+        buffer.writeInt(MAX_ENTRIES);
+
+        int propIndex = buffer.writerIndex();
+        buffer.writeShort(propertyType);
+
+        int propLengthIndex = buffer.writerIndex();
+        buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+
+        switch (propType) {
+            case OFPTFPTINSTRUCTIONS:
+            case OFPTFPTINSTRUCTIONSMISS:
+                int instructionStartIndex = buffer.writerIndex();
+                buffer.writeShort(InstructionConstants.APPLY_ACTIONS_TYPE);
+                int instructionLengthIndex = buffer.writerIndex();
+                buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+                buffer.setShort(instructionLengthIndex, buffer.writerIndex() - instructionStartIndex);
+                break;
+            case OFPTFPTNEXTTABLES:
+            case OFPTFPTNEXTTABLESMISS:
+                buffer.writeByte(1);
+                buffer.writeByte(2);
+                break;
+            case OFPTFPTWRITEACTIONS:
+            case OFPTFPTWRITEACTIONSMISS:
+                buffer.writeShort(InstructionConstants.WRITE_ACTIONS_TYPE);
+                buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+                break;
+            case OFPTFPTAPPLYACTIONS:
+            case OFPTFPTAPPLYACTIONSMISS:
+                buffer.writeShort(InstructionConstants.APPLY_ACTIONS_TYPE);
+                buffer.writeShort(EncodeConstants.EMPTY_LENGTH);
+                break;
+            case OFPTFPTMATCH:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ARP_OP << 1);
+                break;
+            case OFPTFPTWILDCARDS:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ARP_SHA << 1);
+                break;
+            case OFPTFPTWRITESETFIELD:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ARP_SPA << 1);
+                break;
+            case OFPTFPTWRITESETFIELDMISS:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ARP_THA << 1);
+                break;
+            case OFPTFPTAPPLYSETFIELD:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ARP_TPA << 1);
+                break;
+            case OFPTFPTAPPLYSETFIELDMISS:
+                buffer.writeShort(OxmMatchConstants.OPENFLOW_BASIC_CLASS);
+                buffer.writeByte(OxmMatchConstants.ETH_TYPE << 1);
+                break;
+            default:
+                break;
+        }
+
+        int propLength = buffer.writerIndex() - propIndex;
+        buffer.setShort(propLengthIndex, buffer.writerIndex() - propIndex);
+
+        int paddingRemainder = propLength % EncodeConstants.PADDING;
+        int result = 0;
+        if (paddingRemainder != 0) {
+            result = EncodeConstants.PADDING - paddingRemainder;
+        }
+        buffer.writeZero(result);
+
+        buffer.setShort(replyIndex, buffer.writerIndex() - replyIndex);
+    }
+
+    @Override
+    protected int getType() {
+        return MultipartType.OFPMPTABLEFEATURES.getIntValue();
+    }
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/TableFeaturesMatchFieldDeserializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/deserialization/multipart/TableFeaturesMatchFieldDeserializerTest.java
new file mode 100644 (file)
index 0000000..7211391
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.protocol.deserialization.multipart;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import java.util.Optional;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpSha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpSpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpTha;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpTpa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv4Code;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv4Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv6Code;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Icmpv6Type;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.InPhyPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.InPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpDscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpEcn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpProto;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Exthdr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Flabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdSll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6NdTll;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv6Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Metadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsBos;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsLabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsTc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.PbbIsid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.SctpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.SctpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TunnelId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.VlanPcp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.VlanVid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatch;
+
+public class TableFeaturesMatchFieldDeserializerTest {
+    private TableFeaturesMatchFieldDeserializer deserializer = new TableFeaturesMatchFieldDeserializer();
+    private Optional<SetFieldMatch> fieldMatch;
+
+    @Test
+    public void deserialize() throws Exception {
+        ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ARP_OP);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(ArpOp.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ARP_SHA);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(ArpSha.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ARP_SPA);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(ArpSpa.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ARP_THA);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(ArpTha.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ARP_TPA);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(ArpTpa.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ETH_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(EthDst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ETH_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(EthSrc.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ICMPV4_CODE);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Icmpv4Code.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ICMPV4_TYPE);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Icmpv4Type.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ICMPV6_CODE);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Icmpv6Code.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.ICMPV6_TYPE);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Icmpv6Type.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IN_PHY_PORT);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(InPhyPort.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IN_PORT);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(InPort.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IP_DSCP);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(IpDscp.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IP_ECN);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(IpEcn.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IP_PROTO);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(IpProto.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV4_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv4Src.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV4_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv4Dst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6Src.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6Dst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_EXTHDR);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6Exthdr.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_FLABEL);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6Flabel.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_ND_SLL);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6NdSll.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_ND_TLL);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6NdTll.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.IPV6_ND_TARGET);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Ipv6NdTarget.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.METADATA);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(Metadata.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.MPLS_BOS);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(MplsBos.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.MPLS_LABEL);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(MplsLabel.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.MPLS_TC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(MplsTc.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.PBB_ISID);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(PbbIsid.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.SCTP_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(SctpSrc.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.SCTP_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(SctpDst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.TCP_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(TcpSrc.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.TCP_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(TcpDst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.TUNNEL_ID);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(TunnelId.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.UDP_SRC);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(UdpSrc.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.UDP_DST);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(UdpDst.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.VLAN_PCP);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(VlanPcp.class, fieldMatch.get().getKey().getMatchType());
+
+        addValues(buffer, OxmMatchConstants.OPENFLOW_BASIC_CLASS, OxmMatchConstants.VLAN_VID);
+        fieldMatch = deserializer.deserialize(buffer);
+        assertEquals(VlanVid.class, fieldMatch.get().getKey().getMatchType());
+
+        assertEquals(0, buffer.readableBytes());
+    }
+
+    private void addValues(ByteBuf buffer, int oxmClass, int oxmField) {
+        buffer.clear();
+        buffer.writeShort(oxmClass);
+        buffer.writeByte(oxmField << 1);
+    }
+}
\ No newline at end of file