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