Merge remote-tracking branch 'liblldp/master'
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / util / FlatBatchUtilTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.openflowplugin.impl.util;
10
11 import com.google.common.collect.Lists;
12 import java.util.ArrayList;
13 import java.util.EnumSet;
14 import java.util.List;
15 import org.junit.Assert;
16 import org.junit.Test;
17 import org.opendaylight.openflowplugin.impl.services.batch.BatchPlanStep;
18 import org.opendaylight.openflowplugin.impl.services.batch.BatchStepType;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.Batch;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.BatchChoice;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCaseBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCaseBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.flow._case.FlatBatchAddFlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.group._case.FlatBatchAddGroupBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.add.meter._case.FlatBatchAddMeterBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.flow._case.FlatBatchRemoveFlowBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.group._case.FlatBatchRemoveGroupBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.remove.meter._case.FlatBatchRemoveMeterBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.flow._case.FlatBatchUpdateFlowBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.group._case.FlatBatchUpdateGroupBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.flat.batch.update.meter._case.FlatBatchUpdateMeterBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailureBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.batch.failure.batch.item.id.choice.FlatBatchFailureFlowIdCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
46 import org.opendaylight.yangtools.yang.common.RpcError;
47 import org.opendaylight.yangtools.yang.common.RpcResult;
48 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * Test for {@link FlatBatchUtil}.
54  */
55 public class FlatBatchUtilTest {
56
57     private static final Logger LOG = LoggerFactory.getLogger(FlatBatchUtilTest.class);
58
59     @Test
60     public void testMarkBarriersWhereNeeded_noBarrier() throws Exception {
61         final List<Batch> batches = Lists.newArrayList(
62                 //general part - no flush required
63                 createBatch(BatchStepType.GROUP_REMOVE),
64                 createBatch(BatchStepType.METER_REMOVE),
65                 createBatch(BatchStepType.FLOW_ADD),
66                 createBatch(BatchStepType.FLOW_REMOVE, 2),
67                 createBatch(BatchStepType.FLOW_ADD),
68                 createBatch(BatchStepType.FLOW_UPDATE),
69                 createBatch(BatchStepType.GROUP_ADD),
70                 createBatch(BatchStepType.GROUP_UPDATE),
71                 createBatch(BatchStepType.METER_ADD),
72                 createBatch(BatchStepType.METER_UPDATE)
73         );
74
75         final List<BatchPlanStep> batchPlan = FlatBatchUtil.assembleBatchPlan(batches);
76         FlatBatchUtil.markBarriersWhereNeeded(batchPlan);
77
78         Assert.assertEquals(10, batchPlan.size());
79         for (int i = 0; i < batchPlan.size(); i++) {
80             final BatchPlanStep planStep = batchPlan.get(i);
81             final boolean barrierBefore = planStep.isBarrierAfter();
82             LOG.debug("checking barrier mark @ {} {} -> {}",
83                     i, planStep.getStepType(), barrierBefore);
84
85             Assert.assertFalse(barrierBefore);
86         }
87     }
88
89     @Test
90     public void testMarkBarriersWhereNeeded_allBarriers() throws Exception {
91         // need to flush G+/F+
92         checkBarriersBetween(BatchStepType.GROUP_ADD, BatchStepType.FLOW_ADD);
93         // need to flush G+/F*
94         checkBarriersBetween(BatchStepType.GROUP_ADD, BatchStepType.FLOW_UPDATE);
95         // need to flush F-/G-
96         checkBarriersBetween(BatchStepType.FLOW_REMOVE, BatchStepType.GROUP_REMOVE);
97         // need to flush F*/G-
98         checkBarriersBetween(BatchStepType.FLOW_UPDATE, BatchStepType.GROUP_REMOVE);
99
100         // need to flush G+/G+
101         checkBarriersBetween(BatchStepType.GROUP_ADD, BatchStepType.GROUP_ADD);
102         // need to flush G-/G-
103         checkBarriersBetween(BatchStepType.GROUP_REMOVE, BatchStepType.GROUP_REMOVE);
104         // need to flush G*/G+
105         checkBarriersBetween(BatchStepType.GROUP_UPDATE, BatchStepType.GROUP_ADD);
106         // need to flush G*/G-
107         checkBarriersBetween(BatchStepType.GROUP_UPDATE, BatchStepType.GROUP_REMOVE);
108
109         // need to flush M+/F+
110         checkBarriersBetween(BatchStepType.METER_ADD, BatchStepType.FLOW_ADD);
111         // need to flush M+/F*
112         checkBarriersBetween(BatchStepType.METER_ADD, BatchStepType.FLOW_UPDATE);
113         // need to flush F-/M-
114         checkBarriersBetween(BatchStepType.FLOW_REMOVE, BatchStepType.METER_REMOVE);
115         // need to flush F*/M-
116         checkBarriersBetween(BatchStepType.FLOW_UPDATE, BatchStepType.METER_REMOVE);
117     }
118
119     private void checkBarriersBetween(final BatchStepType typeOfFirst, final BatchStepType typeOfSecond) {
120         final List<Batch> batches = Lists.newArrayList(createBatch(typeOfFirst), createBatch(typeOfSecond));
121         final List<BatchPlanStep> batchPlan = FlatBatchUtil.assembleBatchPlan(batches);
122         FlatBatchUtil.markBarriersWhereNeeded(batchPlan);
123         LOG.debug("checking barrier between {} / {}", typeOfFirst, typeOfSecond);
124         Assert.assertEquals(2, batchPlan.size());
125         Assert.assertTrue("barrier expected between "
126                 + typeOfFirst + " / "
127                 + typeOfSecond, batchPlan.get(0).isBarrierAfter());
128         Assert.assertFalse(batchPlan.get(1).isBarrierAfter());
129     }
130
131     @Test
132     public void testMarkBarriersWhereNeeded_single() throws Exception {
133         final List<Batch> batches = Lists.newArrayList(
134                 //general part - no flush required
135                 createBatch(BatchStepType.GROUP_REMOVE)
136         );
137
138         final List<BatchPlanStep> batchPlan = FlatBatchUtil.assembleBatchPlan(batches);
139         FlatBatchUtil.markBarriersWhereNeeded(batchPlan);
140
141         Assert.assertEquals(1, batchPlan.size());
142         Assert.assertFalse(batchPlan.get(0).isBarrierAfter());
143     }
144
145     @Test
146     public void testDecideBarrier() throws Exception {
147         Assert.assertTrue(FlatBatchUtil.decideBarrier(EnumSet.of(BatchStepType.GROUP_ADD), BatchStepType.FLOW_ADD));
148         Assert.assertTrue(FlatBatchUtil.decideBarrier(EnumSet.of(BatchStepType.GROUP_ADD), BatchStepType.FLOW_UPDATE));
149
150         Assert.assertTrue(FlatBatchUtil
151                 .decideBarrier(EnumSet.of(BatchStepType.FLOW_REMOVE), BatchStepType.GROUP_REMOVE));
152         Assert.assertTrue(FlatBatchUtil
153                 .decideBarrier(EnumSet.of(BatchStepType.FLOW_UPDATE), BatchStepType.GROUP_REMOVE));
154
155         Assert.assertTrue(FlatBatchUtil.decideBarrier(EnumSet.of(BatchStepType.METER_ADD), BatchStepType.FLOW_ADD));
156         Assert.assertTrue(FlatBatchUtil.decideBarrier(EnumSet.of(BatchStepType.METER_ADD), BatchStepType.FLOW_UPDATE));
157
158         Assert.assertTrue(FlatBatchUtil
159                 .decideBarrier(EnumSet.of(BatchStepType.FLOW_REMOVE), BatchStepType.METER_REMOVE));
160         Assert.assertTrue(FlatBatchUtil
161                 .decideBarrier(EnumSet.of(BatchStepType.FLOW_UPDATE), BatchStepType.METER_REMOVE));
162     }
163
164     @Test
165     public void testAssembleBatchPlan() throws Exception {
166         final List<Batch> batches = Lists.newArrayList(
167                 createBatch(BatchStepType.GROUP_ADD),
168                 createBatch(BatchStepType.GROUP_REMOVE, 2),
169                 createBatch(BatchStepType.GROUP_REMOVE),
170                 createBatch(BatchStepType.GROUP_ADD),
171                 createBatch(BatchStepType.GROUP_UPDATE, 3)
172         );
173
174         final List<BatchPlanStep> batchPlanSteps = FlatBatchUtil.assembleBatchPlan(batches);
175         Assert.assertEquals(5, batchPlanSteps.size());
176
177         int index = 0;
178         checkSegment(batchPlanSteps.get(index++), BatchStepType.GROUP_ADD, 1);
179         checkSegment(batchPlanSteps.get(index++), BatchStepType.GROUP_REMOVE, 2);
180         checkSegment(batchPlanSteps.get(index++), BatchStepType.GROUP_REMOVE, 1);
181         checkSegment(batchPlanSteps.get(index++), BatchStepType.GROUP_ADD, 1);
182         checkSegment(batchPlanSteps.get(index++), BatchStepType.GROUP_UPDATE, 3);
183     }
184
185     private void checkSegment(final BatchPlanStep planStep, final BatchStepType stepType, final int expected) {
186         Assert.assertEquals(stepType, planStep.getStepType());
187         Assert.assertEquals(expected, planStep.getTaskBag().size());
188     }
189
190     @Test
191     public void testDetectBatchStepType() throws Exception {
192         for (BatchStepType stepType : BatchStepType.values()) {
193             LOG.debug("checking detection of: {}", stepType);
194             final Batch batch = createBatch(stepType);
195             final BatchStepType actualType = FlatBatchUtil.detectBatchStepType(batch.getBatchChoice());
196             Assert.assertEquals(stepType, actualType);
197         }
198     }
199
200     private Batch createBatch(BatchStepType type) {
201         return createBatch(type, 1);
202     }
203
204     private Batch createBatch(BatchStepType type, final int size) {
205         final BatchChoice batchCase;
206         switch (type) {
207             case FLOW_ADD:
208                 batchCase = new FlatBatchAddFlowCaseBuilder()
209                         .setFlatBatchAddFlow(repeatIntoList(new FlatBatchAddFlowBuilder().build(), size))
210                         .build();
211                 break;
212             case FLOW_REMOVE:
213                 batchCase = new FlatBatchRemoveFlowCaseBuilder()
214                         .setFlatBatchRemoveFlow(repeatIntoList(new FlatBatchRemoveFlowBuilder().build(), size))
215                         .build();
216                 break;
217             case FLOW_UPDATE:
218                 batchCase = new FlatBatchUpdateFlowCaseBuilder()
219                         .setFlatBatchUpdateFlow(repeatIntoList(new FlatBatchUpdateFlowBuilder().build(), size))
220                         .build();
221                 break;
222             case GROUP_ADD:
223                 batchCase = new FlatBatchAddGroupCaseBuilder()
224                         .setFlatBatchAddGroup(repeatIntoList(new FlatBatchAddGroupBuilder().build(), size))
225                         .build();
226                 break;
227             case GROUP_REMOVE:
228                 batchCase = new FlatBatchRemoveGroupCaseBuilder()
229                         .setFlatBatchRemoveGroup(repeatIntoList(new FlatBatchRemoveGroupBuilder().build(), size))
230                         .build();
231                 break;
232             case GROUP_UPDATE:
233                 batchCase = new FlatBatchUpdateGroupCaseBuilder()
234                         .setFlatBatchUpdateGroup(repeatIntoList(new FlatBatchUpdateGroupBuilder().build(), size))
235                         .build();
236                 break;
237             case METER_ADD:
238                 batchCase = new FlatBatchAddMeterCaseBuilder()
239                         .setFlatBatchAddMeter(repeatIntoList(new FlatBatchAddMeterBuilder().build(), size))
240                         .build();
241                 break;
242             case METER_REMOVE:
243                 batchCase = new FlatBatchRemoveMeterCaseBuilder()
244                         .setFlatBatchRemoveMeter(repeatIntoList(new FlatBatchRemoveMeterBuilder().build(), size))
245                         .build();
246                 break;
247             case METER_UPDATE:
248                 batchCase = new FlatBatchUpdateMeterCaseBuilder()
249                         .setFlatBatchUpdateMeter(repeatIntoList(new FlatBatchUpdateMeterBuilder().build(), size))
250                         .build();
251                 break;
252             default:
253                 LOG.warn("unsupported batch type: {}", type);
254                 throw new IllegalArgumentException("unsupported batch type: " + type);
255         }
256
257         return new BatchBuilder()
258                 .setBatchChoice(batchCase)
259                 .build();
260     }
261
262     private <T> List<T> repeatIntoList(final T element, final int size) {
263         final List<T> list = new ArrayList<>();
264         for (int i = 0; i < size; i++) {
265             list.add(element);
266         }
267         return list;
268     }
269
270     @Test
271     public void testMergeJobsResultsFutures() throws Exception {
272         final BatchFailure batchFailure = new BatchFailureBuilder()
273                 .setBatchOrder(9)
274                 .setBatchItemIdChoice(new FlatBatchFailureFlowIdCaseBuilder()
275                         .setFlowId(new FlowId("11"))
276                         .build())
277                 .build();
278
279         final ProcessFlatBatchOutput output
280                 = new ProcessFlatBatchOutputBuilder().setBatchFailure(Lists.newArrayList(batchFailure)).build();
281
282         final RpcResult<ProcessFlatBatchOutput> rpcResultFailed = RpcResultBuilder.<ProcessFlatBatchOutput>failed()
283                 .withError(RpcError.ErrorType.APPLICATION, "ut-rpcError")
284                 .withResult(output).build();
285         final RpcResult<ProcessFlatBatchOutput> rpcResultSuccess = RpcResultBuilder.<ProcessFlatBatchOutput>success()
286                 .withResult(new ProcessFlatBatchOutputBuilder().setBatchFailure(new ArrayList<>())).build();
287
288         final RpcResult<ProcessFlatBatchOutput> rpcResult1
289                 = FlatBatchUtil.mergeRpcResults().apply(Lists.newArrayList(rpcResultFailed, rpcResultSuccess));
290         Assert.assertEquals(1, rpcResult1.getErrors().size());
291         Assert.assertFalse(rpcResult1.isSuccessful());
292
293         final RpcResult<ProcessFlatBatchOutput> rpcResult2
294                 = FlatBatchUtil.mergeRpcResults().apply(Lists.newArrayList(rpcResultFailed, rpcResultFailed));
295         Assert.assertEquals(2, rpcResult2.getErrors().size());
296         Assert.assertFalse(rpcResult2.isSuccessful());
297
298         final RpcResult<ProcessFlatBatchOutput> rpcResult3
299                 = FlatBatchUtil.mergeRpcResults().apply(Lists.newArrayList(rpcResultSuccess, rpcResultSuccess));
300         Assert.assertEquals(0, rpcResult3.getErrors().size());
301         Assert.assertTrue(rpcResult3.isSuccessful());
302     }
303 }