d7a19d203528a097c0ac2939c65607e4f962a8b4
[openflowjava.git] / openflow-protocol-impl / src / test / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / multipart / MultipartRequestTableFeaturesTest.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowjava.protocol.impl.serialization.factories.multipart;
9
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.UnpooledByteBufAllocator;
12
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.junit.Assert;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.mockito.Matchers;
22 import org.mockito.Mock;
23 import org.mockito.Mockito;
24 import org.mockito.runners.MockitoJUnitRunner;
25 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
26 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
27 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
28 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
29 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializerRegistryImpl;
30 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.MultipartRequestInputFactory;
31 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.MultipartRequestInputFactoryTest;
32 import org.opendaylight.openflowjava.protocol.impl.util.BufferHelper;
33 import org.opendaylight.openflowjava.util.ByteBufUtils;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ActionRelatedTableFeatureProperty;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ActionRelatedTableFeaturePropertyBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdTableFeatureProperty;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdTableFeaturePropertyBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.InstructionRelatedTableFeatureProperty;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.InstructionRelatedTableFeaturePropertyBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.NextTableRelatedTableFeatureProperty;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.NextTableRelatedTableFeaturePropertyBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.OxmRelatedTableFeatureProperty;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.OxmRelatedTableFeaturePropertyBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.table.features.properties.container.table.feature.properties.NextTableIds;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.table.features.properties.container.table.feature.properties.NextTableIdsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Output;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.ActionBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPhyPort;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPort;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpEcn;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpProto;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OpenflowBasicClass;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.multipart.request.table.features.TableFeatures;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.multipart.request.table.features.TableFeaturesBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeatureProperties;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeaturePropertiesBuilder;
77
78 /**
79  * @author michal.polkorab
80  *
81  */
82 @RunWith(MockitoJUnitRunner.class)
83 public class MultipartRequestTableFeaturesTest {
84
85     private static final byte PADDING_IN_MULTIPART_REQUEST_MESSAGE =
86             MultipartRequestInputFactoryTest.PADDING_IN_MULTIPART_REQUEST_MESSAGE;
87     private SerializerRegistry registry;
88     private OFSerializer<MultipartRequestInput> multipartFactory;
89
90     @Mock SerializerRegistry mockRegistry;
91     @Mock OFSerializer<TableFeatureProperties> serializer;
92
93     /**
94      * Initializes serializer registry and stores correct factory in field
95      */
96     @Before
97     public void startUp() {
98         Mockito.when(mockRegistry.getSerializer((MessageTypeKey<?>)Matchers.any()))
99         .thenReturn(serializer);
100         registry = new SerializerRegistryImpl();
101         registry.init();
102         multipartFactory = registry.getSerializer(
103                 new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, MultipartRequestInput.class));
104     }
105
106     /**
107      * @throws Exception
108      * Testing of {@link MultipartRequestInputFactory} for correct translation from POJO
109      */
110     @Test
111     public void testMultipartRequestTableFeaturesMessageFactory() throws Exception {
112         MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
113         BufferHelper.setupHeader(builder, EncodeConstants.OF13_VERSION_ID);
114         builder.setType(MultipartType.forValue(12));
115         builder.setFlags(new MultipartRequestFlags(true));
116         MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder();
117         MultipartRequestTableFeaturesBuilder featuresBuilder = new MultipartRequestTableFeaturesBuilder();
118         List<TableFeatures> tableFeaturesList = new ArrayList<>();
119         TableFeaturesBuilder tableFeaturesBuilder = new TableFeaturesBuilder();
120         tableFeaturesBuilder.setTableId((short) 8);
121         tableFeaturesBuilder.setName("AAAABBBBCCCCDDDDEEEEFFFFGGGG");
122         tableFeaturesBuilder.setMetadataMatch(new BigInteger(new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}));
123         tableFeaturesBuilder.setMetadataWrite(new BigInteger(new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}));
124         tableFeaturesBuilder.setConfig(new TableConfig(true));
125         tableFeaturesBuilder.setMaxEntries(65L);
126         List<TableFeatureProperties> properties = new ArrayList<>();
127         TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder();
128         propBuilder.setType(TableFeaturesPropType.OFPTFPTNEXTTABLES);
129         NextTableRelatedTableFeaturePropertyBuilder nextPropBuilder =
130                 new NextTableRelatedTableFeaturePropertyBuilder();
131         List<NextTableIds> nextIds = new ArrayList<>();
132         nextIds.add(new NextTableIdsBuilder().setTableId((short) 1).build());
133         nextIds.add(new NextTableIdsBuilder().setTableId((short) 2).build());
134         nextPropBuilder.setNextTableIds(nextIds);
135         propBuilder.addAugmentation(NextTableRelatedTableFeatureProperty.class, nextPropBuilder.build());
136         properties.add(propBuilder.build());
137         propBuilder = new TableFeaturePropertiesBuilder();
138         propBuilder.setType(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS);
139         nextPropBuilder = new NextTableRelatedTableFeaturePropertyBuilder();
140         nextIds = new ArrayList<>();
141         nextPropBuilder.setNextTableIds(nextIds);
142         propBuilder.addAugmentation(NextTableRelatedTableFeatureProperty.class, nextPropBuilder.build());
143         properties.add(propBuilder.build());
144         propBuilder = new TableFeaturePropertiesBuilder();
145         propBuilder.setType(TableFeaturesPropType.OFPTFPTINSTRUCTIONS);
146         InstructionRelatedTableFeaturePropertyBuilder insPropBuilder =
147                 new InstructionRelatedTableFeaturePropertyBuilder();
148         List<Instruction> insIds = new ArrayList<>();
149         InstructionBuilder insBuilder = new InstructionBuilder();
150         insBuilder.setType(WriteActions.class);
151         insIds.add(insBuilder.build());
152         insBuilder = new InstructionBuilder();
153         insBuilder.setType(GotoTable.class);
154         insIds.add(insBuilder.build());
155         insPropBuilder.setInstruction(insIds);
156         propBuilder.addAugmentation(InstructionRelatedTableFeatureProperty.class, insPropBuilder.build());
157         properties.add(propBuilder.build());
158         propBuilder = new TableFeaturePropertiesBuilder();
159         propBuilder.setType(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS);
160         insPropBuilder = new InstructionRelatedTableFeaturePropertyBuilder();
161         insIds = new ArrayList<>();
162         insBuilder = new InstructionBuilder();
163         insBuilder.setType(WriteMetadata.class);
164         insIds.add(insBuilder.build());
165         insBuilder = new InstructionBuilder();
166         insBuilder.setType(ApplyActions.class);
167         insIds.add(insBuilder.build());
168         insBuilder = new InstructionBuilder();
169         insBuilder.setType(Meter.class);
170         insIds.add(insBuilder.build());
171         insBuilder = new InstructionBuilder();
172         insBuilder.setType(ClearActions.class);
173         insIds.add(insBuilder.build());
174         insBuilder = new InstructionBuilder();
175         insBuilder.setType(GotoTable.class);
176         insIds.add(insBuilder.build());
177         insPropBuilder.setInstruction(insIds);
178         propBuilder.addAugmentation(InstructionRelatedTableFeatureProperty.class, insPropBuilder.build());
179         properties.add(propBuilder.build());
180         tableFeaturesBuilder.setTableFeatureProperties(properties);
181         tableFeaturesList.add(tableFeaturesBuilder.build());
182         tableFeaturesBuilder = new TableFeaturesBuilder();
183         tableFeaturesBuilder.setTableId((short) 8);
184         tableFeaturesBuilder.setName("AAAABBBBCCCCDDDDEEEEFFFFGGGG");
185         tableFeaturesBuilder.setMetadataMatch(new BigInteger(new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}));
186         tableFeaturesBuilder.setMetadataWrite(new BigInteger(new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}));
187         tableFeaturesBuilder.setConfig(new TableConfig(true));
188         tableFeaturesBuilder.setMaxEntries(67L);
189         properties = new ArrayList<>();
190         propBuilder = new TableFeaturePropertiesBuilder();
191         propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITEACTIONS);
192         ActionRelatedTableFeaturePropertyBuilder actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
193         List<Action> actions = new ArrayList<>();
194         ActionBuilder actionBuilder = new ActionBuilder();
195         actionBuilder.setType(Output.class);
196         actions.add(actionBuilder.build());
197         actBuilder.setAction(actions);
198         propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
199         properties.add(propBuilder.build());
200         propBuilder = new TableFeaturePropertiesBuilder();
201         propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS);
202         actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
203         actions = new ArrayList<>();
204         actBuilder.setAction(actions);
205         propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
206         properties.add(propBuilder.build());
207         propBuilder = new TableFeaturePropertiesBuilder();
208         propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYACTIONS);
209         actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
210         actions = new ArrayList<>();
211         actBuilder.setAction(actions);
212         propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
213         properties.add(propBuilder.build());
214         propBuilder = new TableFeaturePropertiesBuilder();
215         propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS);
216         actBuilder = new ActionRelatedTableFeaturePropertyBuilder();
217         actions = new ArrayList<>();
218         actBuilder.setAction(actions);
219         propBuilder.addAugmentation(ActionRelatedTableFeatureProperty.class, actBuilder.build());
220         properties.add(propBuilder.build());
221         propBuilder = new TableFeaturePropertiesBuilder();
222         propBuilder.setType(TableFeaturesPropType.OFPTFPTMATCH);
223         OxmRelatedTableFeaturePropertyBuilder oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
224         List<MatchEntry> entries = new ArrayList<>();
225         MatchEntryBuilder entriesBuilder = new MatchEntryBuilder();
226         entriesBuilder.setOxmClass(OpenflowBasicClass.class);
227         entriesBuilder.setOxmMatchField(InPhyPort.class);
228         entriesBuilder.setHasMask(false);
229         entries.add(entriesBuilder.build());
230         entriesBuilder = new MatchEntryBuilder();
231         entriesBuilder.setOxmClass(OpenflowBasicClass.class);
232         entriesBuilder.setOxmMatchField(InPort.class);
233         entriesBuilder.setHasMask(false);
234         entries.add(entriesBuilder.build());
235         oxmBuilder.setMatchEntry(entries);
236         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
237         properties.add(propBuilder.build());
238         propBuilder = new TableFeaturePropertiesBuilder();
239         propBuilder.setType(TableFeaturesPropType.OFPTFPTWILDCARDS);
240         oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
241         entries = new ArrayList<>();
242         oxmBuilder.setMatchEntry(entries);
243         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
244         properties.add(propBuilder.build());
245         propBuilder = new TableFeaturePropertiesBuilder();
246         propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITESETFIELD);
247         oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
248         entries = new ArrayList<>();
249         oxmBuilder.setMatchEntry(entries);
250         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
251         properties.add(propBuilder.build());
252         propBuilder = new TableFeaturePropertiesBuilder();
253         propBuilder.setType(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS);
254         oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
255         entries = new ArrayList<>();
256         oxmBuilder.setMatchEntry(entries);
257         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
258         properties.add(propBuilder.build());
259         propBuilder = new TableFeaturePropertiesBuilder();
260         propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD);
261         oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
262         entries = new ArrayList<>();
263         entriesBuilder = new MatchEntryBuilder();
264         entriesBuilder.setOxmClass(OpenflowBasicClass.class);
265         entriesBuilder.setOxmMatchField(IpProto.class);
266         entriesBuilder.setHasMask(false);
267         entries.add(entriesBuilder.build());
268         entriesBuilder = new MatchEntryBuilder();
269         entriesBuilder.setOxmClass(OpenflowBasicClass.class);
270         entriesBuilder.setOxmMatchField(IpEcn.class);
271         entriesBuilder.setHasMask(false);
272         entries.add(entriesBuilder.build());
273         oxmBuilder.setMatchEntry(entries);
274         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
275         properties.add(propBuilder.build());
276         propBuilder = new TableFeaturePropertiesBuilder();
277         propBuilder.setType(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS);
278         oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
279         entries = new ArrayList<>();
280         oxmBuilder.setMatchEntry(entries);
281         propBuilder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
282         properties.add(propBuilder.build());
283         tableFeaturesBuilder.setTableFeatureProperties(properties);
284         tableFeaturesList.add(tableFeaturesBuilder.build());
285         featuresBuilder.setTableFeatures(tableFeaturesList);
286         caseBuilder.setMultipartRequestTableFeatures(featuresBuilder.build());
287         builder.setMultipartRequestBody(caseBuilder.build());
288         MultipartRequestInput message = builder.build();
289
290         ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
291         multipartFactory.serialize(message, out);
292
293         BufferHelper.checkHeaderV13(out, (byte) 18, 296);
294         Assert.assertEquals("Wrong type", 12, out.readUnsignedShort());
295         Assert.assertEquals("Wrong flags", 1, out.readUnsignedShort());
296         out.skipBytes(PADDING_IN_MULTIPART_REQUEST_MESSAGE);
297         Assert.assertEquals("Wrong length", 120, out.readUnsignedShort());
298         Assert.assertEquals("Wrong registry-id", 8, out.readUnsignedByte());
299         out.skipBytes(5);
300         Assert.assertEquals("Wrong name", "AAAABBBBCCCCDDDDEEEEFFFFGGGG",
301                 ByteBufUtils.decodeNullTerminatedString(out, 32));
302         byte[] metadataMatch = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
303         out.readBytes(metadataMatch);
304         Assert.assertArrayEquals("Wrong metadata-match",
305                 new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}, metadataMatch);
306         byte[] metadataWrite = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
307         out.readBytes(metadataWrite);
308         Assert.assertArrayEquals("Wrong metadata-write",
309                 new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}, metadataWrite);
310         Assert.assertEquals("Wrong config", 8, out.readUnsignedInt());
311         Assert.assertEquals("Wrong max-entries", 65, out.readUnsignedInt());
312         Assert.assertEquals("Wrong property type", 2, out.readUnsignedShort());
313         Assert.assertEquals("Wrong property length", 6, out.readUnsignedShort());
314         Assert.assertEquals("Wrong next-registry-id", 1, out.readUnsignedByte());
315         Assert.assertEquals("Wrong next-registry-id", 2, out.readUnsignedByte());
316         out.skipBytes(2);
317         Assert.assertEquals("Wrong property type", 3, out.readUnsignedShort());
318         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
319         out.skipBytes(4);
320         Assert.assertEquals("Wrong property type", 0, out.readUnsignedShort());
321         Assert.assertEquals("Wrong property length", 12, out.readUnsignedShort());
322         Assert.assertEquals("Wrong instruction type", 3, out.readUnsignedShort());
323         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
324         Assert.assertEquals("Wrong instruction type", 1, out.readUnsignedShort());
325         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
326         out.skipBytes(4);
327         Assert.assertEquals("Wrong property type", 1, out.readUnsignedShort());
328         Assert.assertEquals("Wrong property length", 24, out.readUnsignedShort());
329         Assert.assertEquals("Wrong instruction type", 2, out.readUnsignedShort());
330         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
331         Assert.assertEquals("Wrong instruction type", 4, out.readUnsignedShort());
332         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
333         Assert.assertEquals("Wrong instruction type", 6, out.readUnsignedShort());
334         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
335         Assert.assertEquals("Wrong instruction type", 5, out.readUnsignedShort());
336         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
337         Assert.assertEquals("Wrong instruction type", 1, out.readUnsignedShort());
338         Assert.assertEquals("Wrong instruction length", 4, out.readUnsignedShort());
339         Assert.assertEquals("Wrong length", 160, out.readUnsignedShort());
340         Assert.assertEquals("Wrong registry-id", 8, out.readUnsignedByte());
341         out.skipBytes(5);
342         Assert.assertEquals("Wrong name", "AAAABBBBCCCCDDDDEEEEFFFFGGGG",
343                 ByteBufUtils.decodeNullTerminatedString(out, 32));
344         metadataMatch = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
345         out.readBytes(metadataMatch);
346         Assert.assertArrayEquals("Wrong metadata-match",
347                 new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}, metadataMatch);
348         metadataWrite = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
349         out.readBytes(metadataWrite);
350         Assert.assertArrayEquals("Wrong metadata-write",
351                 new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}, metadataWrite);
352         Assert.assertEquals("Wrong config", 8, out.readUnsignedInt());
353         Assert.assertEquals("Wrong max-entries", 67, out.readUnsignedInt());
354         Assert.assertEquals("Wrong property type", 4, out.readUnsignedShort());
355         Assert.assertEquals("Wrong property length", 8, out.readUnsignedShort());
356         Assert.assertEquals("Wrong action type", 0, out.readUnsignedShort());
357         Assert.assertEquals("Wrong action length", 4, out.readUnsignedShort());
358         Assert.assertEquals("Wrong property type", 5, out.readUnsignedShort());
359         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
360         out.skipBytes(4);
361         Assert.assertEquals("Wrong property type", 6, out.readUnsignedShort());
362         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
363         out.skipBytes(4);
364         Assert.assertEquals("Wrong property type", 7, out.readUnsignedShort());
365         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
366         out.skipBytes(4);
367         Assert.assertEquals("Wrong property type", 8, out.readUnsignedShort());
368         Assert.assertEquals("Wrong property length", 12, out.readUnsignedShort());
369         Assert.assertEquals("Wrong match class", 0x8000, out.readUnsignedShort());
370         Assert.assertEquals("Wrong match field&mask", 2, out.readUnsignedByte());
371         Assert.assertEquals("Wrong match length", 4, out.readUnsignedByte());
372         Assert.assertEquals("Wrong match class", 0x8000, out.readUnsignedShort());
373         Assert.assertEquals("Wrong match field&mask", 0, out.readUnsignedByte());
374         Assert.assertEquals("Wrong match length", 4, out.readUnsignedByte());
375         out.skipBytes(4);
376         Assert.assertEquals("Wrong property type", 10, out.readUnsignedShort());
377         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
378         out.skipBytes(4);
379         Assert.assertEquals("Wrong property type", 12, out.readUnsignedShort());
380         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
381         out.skipBytes(4);
382         Assert.assertEquals("Wrong property type", 13, out.readUnsignedShort());
383         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
384         out.skipBytes(4);
385         Assert.assertEquals("Wrong property type", 14, out.readUnsignedShort());
386         Assert.assertEquals("Wrong property length", 12, out.readUnsignedShort());
387         Assert.assertEquals("Wrong match class", 0x8000, out.readUnsignedShort());
388         Assert.assertEquals("Wrong match field&mask", 20, out.readUnsignedByte());
389         Assert.assertEquals("Wrong match length", 1, out.readUnsignedByte());
390         Assert.assertEquals("Wrong match class", 0x8000, out.readUnsignedShort());
391         Assert.assertEquals("Wrong match field&mask", 18, out.readUnsignedByte());
392         Assert.assertEquals("Wrong match length", 1, out.readUnsignedByte());
393         out.skipBytes(4);
394         Assert.assertEquals("Wrong property type", 15, out.readUnsignedShort());
395         Assert.assertEquals("Wrong property length", 4, out.readUnsignedShort());
396         out.skipBytes(4);
397         Assert.assertTrue("Unread data", out.readableBytes() == 0);
398     }
399
400     /**
401      * @throws Exception
402      * Testing of {@link MultipartRequestInputFactory} for correct translation from POJO
403      */
404     @Test
405     public void testMultipartRequestTableFeaturesExperimenter() throws Exception {
406         MultipartRequestInputFactory factory = new MultipartRequestInputFactory();
407         factory.injectSerializerRegistry(mockRegistry);
408         MultipartRequestInputBuilder builder = new MultipartRequestInputBuilder();
409         BufferHelper.setupHeader(builder, EncodeConstants.OF13_VERSION_ID);
410         builder.setType(MultipartType.forValue(12));
411         builder.setFlags(new MultipartRequestFlags(true));
412         MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder();
413         MultipartRequestTableFeaturesBuilder featuresBuilder = new MultipartRequestTableFeaturesBuilder();
414         List<TableFeatures> tableFeaturesList = new ArrayList<>();
415         TableFeaturesBuilder tableFeaturesBuilder = new TableFeaturesBuilder();
416         tableFeaturesBuilder.setTableId((short) 8);
417         tableFeaturesBuilder.setName("AAAABBBBCCCCDDDDEEEEFFFFGGGG");
418         tableFeaturesBuilder.setMetadataMatch(new BigInteger(new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}));
419         tableFeaturesBuilder.setMetadataWrite(new BigInteger(new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}));
420         tableFeaturesBuilder.setConfig(new TableConfig(true));
421         tableFeaturesBuilder.setMaxEntries(65L);
422         List<TableFeatureProperties> properties = new ArrayList<>();
423         TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder();
424         propBuilder.setType(TableFeaturesPropType.OFPTFPTEXPERIMENTER);
425         ExperimenterIdTableFeaturePropertyBuilder expBuilder = new ExperimenterIdTableFeaturePropertyBuilder();
426         expBuilder.setExperimenter(new ExperimenterId(42L));
427         propBuilder.addAugmentation(ExperimenterIdTableFeatureProperty.class, expBuilder.build());
428         properties.add(propBuilder.build());
429         propBuilder = new TableFeaturePropertiesBuilder();
430         propBuilder.setType(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS);
431         expBuilder = new ExperimenterIdTableFeaturePropertyBuilder();
432         expBuilder.setExperimenter(new ExperimenterId(43L));
433         propBuilder.addAugmentation(ExperimenterIdTableFeatureProperty.class, expBuilder.build());
434         properties.add(propBuilder.build());
435         tableFeaturesBuilder.setTableFeatureProperties(properties);
436         tableFeaturesList.add(tableFeaturesBuilder.build());
437         featuresBuilder.setTableFeatures(tableFeaturesList);
438         caseBuilder.setMultipartRequestTableFeatures(featuresBuilder.build());
439         builder.setMultipartRequestBody(caseBuilder.build());
440         MultipartRequestInput message = builder.build();
441
442         ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
443         factory.serialize(message, out);
444
445         BufferHelper.checkHeaderV13(out, (byte) 18, 80);
446         Assert.assertEquals("Wrong type", 12, out.readUnsignedShort());
447         Assert.assertEquals("Wrong flags", 1, out.readUnsignedShort());
448         out.skipBytes(PADDING_IN_MULTIPART_REQUEST_MESSAGE);
449         Assert.assertEquals("Wrong length", 64, out.readUnsignedShort());
450         Assert.assertEquals("Wrong registry-id", 8, out.readUnsignedByte());
451         out.skipBytes(5);
452         Assert.assertEquals("Wrong name", "AAAABBBBCCCCDDDDEEEEFFFFGGGG",
453                 ByteBufUtils.decodeNullTerminatedString(out, 32));
454         byte[] metadataMatch = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
455         out.readBytes(metadataMatch);
456         Assert.assertArrayEquals("Wrong metadata-match",
457                 new byte[] {0x00, 0x01, 0x02, 0x03, 0x01, 0x04, 0x08, 0x01}, metadataMatch);
458         byte[] metadataWrite = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
459         out.readBytes(metadataWrite);
460         Assert.assertArrayEquals("Wrong metadata-write",
461                 new byte[] {0x00, 0x07, 0x01, 0x05, 0x01, 0x00, 0x03, 0x01}, metadataWrite);
462         Assert.assertEquals("Wrong config", 8, out.readUnsignedInt());
463         Assert.assertEquals("Wrong max-entries", 65, out.readUnsignedInt());
464         Mockito.verify(serializer, Mockito.times(2)).serialize(Matchers.any(TableFeatureProperties.class),
465                 Matchers.any(ByteBuf.class));
466     }
467 }