Remove unused routedRpcRegistration
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / services / sal / ProcessFlatBatchImplTest.java
1 /*
2  * Copyright (c) 2017 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.openflowplugin.impl.services.sal;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.Mockito.inOrder;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.verifyNoMoreInteractions;
19 import static org.mockito.Mockito.when;
20
21 import com.google.common.collect.Lists;
22 import com.google.common.util.concurrent.AsyncFunction;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import java.util.Iterator;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.Captor;
34 import org.mockito.Mock;
35 import org.mockito.junit.MockitoJUnitRunner;
36 import org.opendaylight.openflowplugin.impl.services.batch.BatchPlanStep;
37 import org.opendaylight.openflowplugin.impl.services.batch.BatchStepJob;
38 import org.opendaylight.openflowplugin.impl.services.batch.BatchStepType;
39 import org.opendaylight.openflowplugin.impl.util.FlatBatchUtil;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.failure.ids.aug.FlatBatchFailureFlowIdCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.failure.ids.aug.FlatBatchFailureFlowIdCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.FlatBatchAddFlowCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.FlatBatchRemoveFlowCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.FlatBatchUpdateFlowCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.flat.batch.add.flow._case.FlatBatchAddFlow;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.flat.batch.add.flow._case.FlatBatchAddFlowBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.flat.batch.add.flow._case.FlatBatchAddFlowKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.flat.batch.remove.flow._case.FlatBatchRemoveFlowBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.flow.crud._case.aug.flat.batch.update.flow._case.FlatBatchUpdateFlowBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.FlatBatchAddGroupCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.FlatBatchRemoveGroupCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.FlatBatchUpdateGroupCaseBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.flat.batch.add.group._case.FlatBatchAddGroupBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.flat.batch.remove.group._case.FlatBatchRemoveGroupBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.group.crud._case.aug.flat.batch.update.group._case.FlatBatchUpdateGroupBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.FlatBatchAddMeterCaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.FlatBatchRemoveMeterCaseBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.FlatBatchUpdateMeterCaseBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.flat.batch.add.meter._case.FlatBatchAddMeterBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.flat.batch.remove.meter._case.FlatBatchRemoveMeterBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.flat.batch.meter.crud._case.aug.flat.batch.update.meter._case.FlatBatchUpdateMeterBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.Batch;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailure;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.output.BatchFailureBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatch;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchOutputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatch;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchOutput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchOutputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatch;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchOutputBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.output.list.grouping.BatchFailedFlowsOutputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatch;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.AddGroupsBatchOutputBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatch;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.RemoveGroupsBatchOutputBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatch;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.UpdateGroupsBatchOutputBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.input.update.grouping.OriginalBatchedGroupBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.groups.service.rev160315.batch.group.input.update.grouping.UpdatedBatchedGroupBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatch;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.AddMetersBatchOutputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatch;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.RemoveMetersBatchOutputBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatch;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.UpdateMetersBatchOutputBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.input.update.grouping.OriginalBatchedMeterBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.meters.service.rev160316.batch.meter.input.update.grouping.UpdatedBatchedMeterBuilder;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
107 import org.opendaylight.yangtools.yang.common.ErrorType;
108 import org.opendaylight.yangtools.yang.common.RpcResult;
109 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
110 import org.opendaylight.yangtools.yang.common.Uint16;
111 import org.opendaylight.yangtools.yang.common.Uint32;
112
113 /**
114  * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlatBatchServiceImpl}.
115  */
116 @RunWith(MockitoJUnitRunner.class)
117 public class ProcessFlatBatchImplTest {
118     private static final NodeId NODE_ID = new NodeId("ut-node-id");
119     private static final InstanceIdentifier<Node> NODE_II = InstanceIdentifier.create(Nodes.class)
120             .child(Node.class, new NodeKey(NODE_ID));
121     private static final NodeRef NODE_REF = new NodeRef(NODE_II);
122
123     @Mock
124     private AddFlowsBatch addFlowsBatch;
125     @Mock
126     private RemoveFlowsBatch removeFlowsBatch;
127     @Mock
128     private UpdateFlowsBatch updateFlowsBatch;
129     @Mock
130     private AddGroupsBatch addGroupsBatch;
131     @Mock
132     private RemoveGroupsBatch removeGroupsBatch;
133     @Mock
134     private UpdateGroupsBatch updateGroupsBatch;
135     @Mock
136     private AddMetersBatch addMetersBatch;
137     @Mock
138     private RemoveMetersBatch removeMetersBatch;
139     @Mock
140     private UpdateMetersBatch updateMetersBatch;
141     @Captor
142     private ArgumentCaptor<AddFlowsBatchInput> addFlowsBatchInputCpt;
143
144     private ProcessFlatBatchImpl processFlatBatch;
145
146     @Before
147     public void setUp() {
148         processFlatBatch = new ProcessFlatBatchImpl(addFlowsBatch, removeFlowsBatch, updateFlowsBatch, addGroupsBatch,
149             removeGroupsBatch, updateGroupsBatch, addMetersBatch, removeMetersBatch, updateMetersBatch);
150     }
151
152     @After
153     public void tearDown() {
154         verifyNoMoreInteractions(addFlowsBatch, removeFlowsBatch, updateFlowsBatch, addGroupsBatch,
155             removeGroupsBatch, updateGroupsBatch, addMetersBatch, removeMetersBatch, updateMetersBatch);
156     }
157
158     @Test
159     public void testProcessFlatBatch_allSuccessFinished() throws Exception {
160         when(addFlowsBatch.invoke(any()))
161                 .thenReturn(RpcResultBuilder.success(new AddFlowsBatchOutputBuilder().build()).buildFuture());
162         when(removeFlowsBatch.invoke(any()))
163                 .thenReturn(RpcResultBuilder.success(new RemoveFlowsBatchOutputBuilder().build()).buildFuture());
164         when(updateFlowsBatch.invoke(any()))
165                 .thenReturn(RpcResultBuilder.success(new UpdateFlowsBatchOutputBuilder().build()).buildFuture());
166
167         when(addGroupsBatch.invoke(any()))
168                 .thenReturn(RpcResultBuilder.success(new AddGroupsBatchOutputBuilder().build()).buildFuture());
169         when(removeGroupsBatch.invoke(any()))
170                 .thenReturn(RpcResultBuilder.success(new RemoveGroupsBatchOutputBuilder().build()).buildFuture());
171         when(updateGroupsBatch.invoke(any()))
172                 .thenReturn(RpcResultBuilder.success(new UpdateGroupsBatchOutputBuilder().build()).buildFuture());
173
174         when(addMetersBatch.invoke(any()))
175                 .thenReturn(RpcResultBuilder.success(new AddMetersBatchOutputBuilder().build()).buildFuture());
176         when(removeMetersBatch.invoke(any()))
177                 .thenReturn(RpcResultBuilder.success(new RemoveMetersBatchOutputBuilder().build()).buildFuture());
178         when(updateMetersBatch.invoke(any()))
179                 .thenReturn(RpcResultBuilder.success(new UpdateMetersBatchOutputBuilder().build()).buildFuture());
180
181
182         ProcessFlatBatchInput batchInput = new ProcessFlatBatchInputBuilder()
183                 .setNode(NODE_REF)
184                 .setBatch(BindingMap.ordered(
185                         createFlowAddBatch(0, "f1"),
186                         createFlowRemoveBatch(1, "f2"),
187                         createFlowUpdateBatch(2, "f3"),
188
189                         createGroupAddBatch(3, 1L),
190                         createGroupRemoveBatch(4, 2L),
191                         createGroupUpdateBatch(5, 3L),
192
193                         createMeterAddBatch(6, 1L),
194                         createMeterRemoveBatch(7, 2L),
195                         createMeterUpdateBatch(8, 3L)
196                 ))
197                 .setExitOnFirstError(true)
198                 .build();
199
200         final var rpcResultFuture = processFlatBatch.invoke(batchInput);
201         assertTrue(rpcResultFuture.isDone());
202         final var rpcResult = rpcResultFuture.get();
203         assertTrue(rpcResult.isSuccessful());
204         assertTrue(rpcResult.getErrors().isEmpty());
205         assertTrue(rpcResult.getResult().nonnullBatchFailure().isEmpty());
206
207         final var inOrder = inOrder(addFlowsBatch, removeFlowsBatch, updateFlowsBatch, addGroupsBatch,
208             removeGroupsBatch, updateGroupsBatch, addMetersBatch, removeMetersBatch, updateMetersBatch);
209         inOrder.verify(addFlowsBatch).invoke(any());
210         inOrder.verify(removeFlowsBatch).invoke(any());
211         inOrder.verify(updateFlowsBatch).invoke(any());
212
213         inOrder.verify(addGroupsBatch).invoke(any());
214         inOrder.verify(removeGroupsBatch).invoke(any());
215         inOrder.verify(updateGroupsBatch).invoke(any());
216
217         inOrder.verify(addMetersBatch).invoke(any());
218         inOrder.verify(removeMetersBatch).invoke(any());
219         inOrder.verify(updateMetersBatch).invoke(any());
220     }
221
222     @Test
223     public void testProcessFlatBatch_firstFailedInterrupted() throws Exception {
224         prepareFirstFailingMockService();
225
226         int idx = 0;
227         ProcessFlatBatchInput batchInput = new ProcessFlatBatchInputBuilder()
228                 .setNode(NODE_REF)
229                 .setBatch(BindingMap.ordered(
230                         createFlowAddBatch(idx++, "f1", 2),
231                         createFlowRemoveBatch(idx++, "f2"),
232                         createFlowUpdateBatch(idx++, "f3"),
233
234                         createGroupAddBatch(idx++, 1L),
235                         createGroupRemoveBatch(idx++, 2L),
236                         createGroupUpdateBatch(idx++, 3L),
237
238                         createMeterAddBatch(idx++, 1L),
239                         createMeterRemoveBatch(idx++, 2L),
240                         createMeterUpdateBatch(idx++, 3L)
241                 ))
242                 .setExitOnFirstError(true)
243                 .build();
244
245         final var rpcResultFuture = processFlatBatch.invoke(batchInput);
246         assertTrue(rpcResultFuture.isDone());
247         final var rpcResult = rpcResultFuture.get();
248         assertFalse(rpcResult.isSuccessful());
249         assertEquals(1, rpcResult.getErrors().size());
250         assertEquals(1, rpcResult.getResult().nonnullBatchFailure().size());
251         assertEquals(3, rpcResult.getResult().nonnullBatchFailure().values().iterator().next()
252                 .getBatchOrder().intValue());
253
254         final var inOrder = inOrder(addFlowsBatch, removeFlowsBatch, updateFlowsBatch, addGroupsBatch);
255         inOrder.verify(addFlowsBatch).invoke(any());
256         inOrder.verify(removeFlowsBatch).invoke(any());
257         inOrder.verify(updateFlowsBatch).invoke(any());
258         inOrder.verify(addGroupsBatch).invoke(any());
259     }
260
261     @Test
262     public void testProcessFlatBatch_firstFailedContinue() throws Exception {
263         prepareFirstFailingMockService();
264
265         int idx = 0;
266         ProcessFlatBatchInput batchInput = new ProcessFlatBatchInputBuilder()
267                 .setNode(NODE_REF)
268                 .setBatch(BindingMap.ordered(
269                         createFlowAddBatch(idx++, "f1", 2),
270                         createFlowRemoveBatch(idx++, "f2"),
271                         createFlowUpdateBatch(idx++, "f3"),
272
273                         createGroupAddBatch(idx++, 1L),
274                         createGroupRemoveBatch(idx++, 2L),
275                         createGroupUpdateBatch(idx++, 3L),
276
277                         createMeterAddBatch(idx++, 1L),
278                         createMeterRemoveBatch(idx++, 2L),
279                         createMeterUpdateBatch(idx++, 3L)
280                 ))
281                 .setExitOnFirstError(false)
282                 .build();
283
284         final var rpcResultFuture = processFlatBatch.invoke(batchInput);
285         assertTrue(rpcResultFuture.isDone());
286         final RpcResult<ProcessFlatBatchOutput> rpcResult = rpcResultFuture.get();
287         assertFalse(rpcResult.isSuccessful());
288         assertEquals(1, rpcResult.getErrors().size());
289         assertEquals(1, rpcResult.getResult().nonnullBatchFailure().size());
290         assertEquals(3, rpcResult.getResult().nonnullBatchFailure().values().iterator().next()
291                 .getBatchOrder().intValue());
292
293         final var inOrder = inOrder(addFlowsBatch, removeFlowsBatch, updateFlowsBatch, addGroupsBatch,
294             removeGroupsBatch, updateGroupsBatch, addMetersBatch, removeMetersBatch, updateMetersBatch);
295         inOrder.verify(addFlowsBatch).invoke(any());
296         inOrder.verify(removeFlowsBatch).invoke(any());
297         inOrder.verify(updateFlowsBatch).invoke(any());
298
299         inOrder.verify(addGroupsBatch).invoke(any());
300         inOrder.verify(removeGroupsBatch).invoke(any());
301         inOrder.verify(updateGroupsBatch).invoke(any());
302
303         inOrder.verify(addMetersBatch).invoke(any());
304         inOrder.verify(removeMetersBatch).invoke(any());
305         inOrder.verify(updateMetersBatch).invoke(any());
306     }
307
308     private void prepareFirstFailingMockService() {
309         when(addFlowsBatch.invoke(any()))
310                 .thenReturn(RpcResultBuilder.success(new AddFlowsBatchOutputBuilder().build()).buildFuture());
311         when(removeFlowsBatch.invoke(any()))
312                 .thenReturn(RpcResultBuilder.<RemoveFlowsBatchOutput>failed()
313                         .withResult(new RemoveFlowsBatchOutputBuilder()
314                                 .setBatchFailedFlowsOutput(BindingMap.ordered(
315                                         new BatchFailedFlowsOutputBuilder()
316                                                 .setBatchOrder(Uint16.ONE)
317                                                 .setFlowId(new FlowId("123"))
318                                                 .build()))
319                                 .build())
320                         .withError(ErrorType.APPLICATION, "ut-firstFlowAddError")
321                         .buildFuture());
322         when(updateFlowsBatch.invoke(any()))
323                 .thenReturn(RpcResultBuilder.success(new UpdateFlowsBatchOutputBuilder().build()).buildFuture());
324
325         when(addGroupsBatch.invoke(any()))
326                 .thenReturn(RpcResultBuilder.success(new AddGroupsBatchOutputBuilder().build()).buildFuture());
327         when(removeGroupsBatch.invoke(any()))
328                 .thenReturn(RpcResultBuilder.success(new RemoveGroupsBatchOutputBuilder().build()).buildFuture());
329         when(updateGroupsBatch.invoke(any()))
330                 .thenReturn(RpcResultBuilder.success(new UpdateGroupsBatchOutputBuilder().build()).buildFuture());
331
332         when(addMetersBatch.invoke(any()))
333                 .thenReturn(RpcResultBuilder.success(new AddMetersBatchOutputBuilder().build()).buildFuture());
334         when(removeMetersBatch.invoke(any()))
335                 .thenReturn(RpcResultBuilder.success(new RemoveMetersBatchOutputBuilder().build()).buildFuture());
336         when(updateMetersBatch.invoke(any()))
337                 .thenReturn(RpcResultBuilder.success(new UpdateMetersBatchOutputBuilder().build()).buildFuture());
338     }
339
340     private static Batch createFlowAddBatch(final int batchOrder, final String flowIdValue) {
341         return createFlowAddBatch(batchOrder, flowIdValue, 1);
342     }
343
344     private static Batch createFlowAddBatch(final int batchOrder, final String flowIdValue, final int amount) {
345         return new BatchBuilder()
346                 .setBatchOrder(Uint16.valueOf(batchOrder))
347                 .setBatchChoice(new FlatBatchAddFlowCaseBuilder()
348                         .setFlatBatchAddFlow(repeatFlatBatchAddFlowInList(flowIdValue, amount))
349                         .build())
350                 .build();
351     }
352
353     private static Map<FlatBatchAddFlowKey, FlatBatchAddFlow> repeatFlatBatchAddFlowInList(final String flowIdValue,
354             final int amount) {
355         final Map<FlatBatchAddFlowKey, FlatBatchAddFlow> map = new LinkedHashMap<>();
356         for (int i = 0; i < amount; i++) {
357             final FlatBatchAddFlowKey key = new FlatBatchAddFlowKey(Uint16.valueOf(i));
358             map.put(key, new FlatBatchAddFlowBuilder().withKey(key).setFlowId(new FlowId(flowIdValue + i)).build());
359         }
360         return map;
361     }
362
363     private static Batch createFlowRemoveBatch(final int batchOrder, final String flowIdValue) {
364         return new BatchBuilder()
365                 .setBatchOrder(Uint16.valueOf(batchOrder))
366                 .setBatchChoice(new FlatBatchRemoveFlowCaseBuilder()
367                         .setFlatBatchRemoveFlow(BindingMap.of(new FlatBatchRemoveFlowBuilder()
368                                 .setFlowId(new FlowId(flowIdValue))
369                                 .setBatchOrder(Uint16.valueOf(batchOrder))
370                                 .build()))
371                         .build())
372                 .build();
373     }
374
375     private static Batch createFlowUpdateBatch(final int batchOrder, final String flowIdValue) {
376         final Uint16 uint = Uint16.valueOf(batchOrder);
377         return new BatchBuilder()
378                 .setBatchOrder(uint)
379                 .withKey(new BatchKey(uint))
380                 .setBatchChoice(new FlatBatchUpdateFlowCaseBuilder()
381                         .setFlatBatchUpdateFlow(BindingMap.of(new FlatBatchUpdateFlowBuilder()
382                                 .setFlowId(new FlowId(flowIdValue))
383                                 .setBatchOrder(Uint16.valueOf(batchOrder))
384                                 .build()))
385                         .build())
386                 .build();
387     }
388
389     private static Batch createGroupAddBatch(final int batchOrder, final long groupIdValue) {
390         return new BatchBuilder()
391                 .setBatchOrder(Uint16.valueOf(batchOrder))
392                 .setBatchChoice(new FlatBatchAddGroupCaseBuilder()
393                         .setFlatBatchAddGroup(BindingMap.of(new FlatBatchAddGroupBuilder()
394                                 .setGroupId(new GroupId(Uint32.valueOf(groupIdValue)))
395                                 .setBatchOrder(Uint16.valueOf(batchOrder))
396                                 .build()))
397                         .build())
398                 .build();
399     }
400
401     private static Batch createGroupRemoveBatch(final int batchOrder, final long groupIdValue) {
402         return new BatchBuilder()
403                 .setBatchOrder(Uint16.valueOf(batchOrder))
404                 .setBatchChoice(new FlatBatchRemoveGroupCaseBuilder()
405                         .setFlatBatchRemoveGroup(BindingMap.of(new FlatBatchRemoveGroupBuilder()
406                                 .setGroupId(new GroupId(Uint32.valueOf(groupIdValue)))
407                                 .setBatchOrder(Uint16.valueOf(batchOrder))
408                                 .build()))
409                         .build())
410                 .build();
411     }
412
413     private static Batch createGroupUpdateBatch(final int batchOrder, final long groupIdValue) {
414         return new BatchBuilder()
415                 .setBatchOrder(Uint16.valueOf(batchOrder))
416                 .setBatchChoice(new FlatBatchUpdateGroupCaseBuilder()
417                         .setFlatBatchUpdateGroup(BindingMap.of(new FlatBatchUpdateGroupBuilder()
418                                 .setOriginalBatchedGroup(new OriginalBatchedGroupBuilder()
419                                         .setGroupId(new GroupId(Uint32.valueOf(groupIdValue)))
420                                         .build())
421                                 .setUpdatedBatchedGroup(new UpdatedBatchedGroupBuilder()
422                                         .setGroupId(new GroupId(Uint32.valueOf(groupIdValue)))
423                                         .build())
424                                 .setBatchOrder(Uint16.valueOf(batchOrder))
425                                 .build()))
426                         .build())
427                 .build();
428     }
429
430     private static Batch createMeterAddBatch(final int batchOrder, final long groupIdValue) {
431         return new BatchBuilder()
432                 .setBatchOrder(Uint16.valueOf(batchOrder))
433                 .setBatchChoice(new FlatBatchAddMeterCaseBuilder()
434                         .setFlatBatchAddMeter(BindingMap.of(new FlatBatchAddMeterBuilder()
435                                 .setMeterId(new MeterId(Uint32.valueOf(groupIdValue)))
436                                 .setBatchOrder(Uint16.valueOf(batchOrder))
437                                 .build()))
438                         .build())
439                 .build();
440     }
441
442     private static Batch createMeterRemoveBatch(final int batchOrder, final long groupIdValue) {
443         return new BatchBuilder()
444                 .setBatchOrder(Uint16.valueOf(batchOrder))
445                 .setBatchChoice(new FlatBatchRemoveMeterCaseBuilder()
446                         .setFlatBatchRemoveMeter(BindingMap.of(new FlatBatchRemoveMeterBuilder()
447                                 .setMeterId(new MeterId(Uint32.valueOf(groupIdValue)))
448                                 .setBatchOrder(Uint16.valueOf(batchOrder))
449                                 .build()))
450                         .build())
451                 .build();
452     }
453
454     private static Batch createMeterUpdateBatch(final int batchOrder, final long groupIdValue) {
455         return new BatchBuilder()
456                 .setBatchOrder(Uint16.valueOf(batchOrder))
457                 .setBatchChoice(new FlatBatchUpdateMeterCaseBuilder()
458                         .setFlatBatchUpdateMeter(BindingMap.of(new FlatBatchUpdateMeterBuilder()
459                                 .setOriginalBatchedMeter(new OriginalBatchedMeterBuilder()
460                                         .setMeterId(new MeterId(Uint32.valueOf(groupIdValue)))
461                                         .build())
462                                 .setUpdatedBatchedMeter(new UpdatedBatchedMeterBuilder()
463                                         .setMeterId(new MeterId(Uint32.valueOf(groupIdValue)))
464                                         .build())
465                                 .setBatchOrder(Uint16.valueOf(batchOrder))
466                                 .build()))
467                         .build())
468                 .build();
469     }
470
471     @Test
472     public void testExecuteBatchPlan() throws Exception {
473         BatchStepJob batchStepJob1 = mock(BatchStepJob.class);
474         BatchStepJob batchStepJob2 = mock(BatchStepJob.class);
475         AsyncFunction<RpcResult<ProcessFlatBatchOutput>, RpcResult<ProcessFlatBatchOutput>> function1 =
476                 mock(AsyncFunction.class);
477         AsyncFunction<RpcResult<ProcessFlatBatchOutput>, RpcResult<ProcessFlatBatchOutput>> function2 =
478                 mock(AsyncFunction.class);
479         when(batchStepJob1.getStepFunction()).thenReturn(function1);
480         when(batchStepJob2.getStepFunction()).thenReturn(function2);
481         BatchPlanStep batchPlanStep1 = new BatchPlanStep(BatchStepType.GROUP_ADD);
482         batchPlanStep1.setBarrierAfter(true);
483         BatchPlanStep batchPlanStep2 = new BatchPlanStep(BatchStepType.FLOW_ADD);
484         batchPlanStep1.setBarrierAfter(false);
485         when(batchStepJob1.getPlanStep()).thenReturn(batchPlanStep1);
486         when(batchStepJob2.getPlanStep()).thenReturn(batchPlanStep2);
487
488         final ListenableFuture<RpcResult<ProcessFlatBatchOutput>> succeededChainOutput =
489                 FlatBatchUtil.createEmptyRpcBatchResultFuture(true);
490         final ListenableFuture<RpcResult<ProcessFlatBatchOutput>> failedChainOutput =
491                 RpcResultBuilder.<ProcessFlatBatchOutput>failed()
492                         .withError(ErrorType.APPLICATION, "ut-chainError")
493                         .withResult(createFlatBatchOutput(createFlowBatchFailure(Uint16.ZERO, "f1"),
494                                     createFlowBatchFailure(Uint16.ONE, "f2")))
495                         .buildFuture();
496
497         when(batchStepJob1.getStepFunction().apply(any())).thenReturn(succeededChainOutput);
498         when(batchStepJob2.getStepFunction().apply(any())).thenReturn(failedChainOutput);
499
500         final List<BatchStepJob> batchChainElements = Lists.newArrayList(batchStepJob1, batchStepJob2);
501         final var rpcResultFuture = processFlatBatch.executeBatchPlan(batchChainElements);
502
503         assertTrue(rpcResultFuture.isDone());
504         final var rpcResult = rpcResultFuture.get();
505         assertFalse(rpcResult.isSuccessful());
506         assertEquals(1, rpcResult.getErrors().size());
507         assertEquals(2, rpcResult.getResult().nonnullBatchFailure().size());
508         Iterator<BatchFailure> iterator = rpcResult.getResult().nonnullBatchFailure().values().iterator();
509         //Moving iterator two get second element
510         iterator.next();
511         assertEquals("f2",
512                 ((FlatBatchFailureFlowIdCase) iterator.next().getBatchItemIdChoice())
513                         .getFlowId().getValue());
514     }
515
516     private static BatchFailure createFlowBatchFailure(final Uint16 batchOrder, final String flowIdValue) {
517         return new BatchFailureBuilder()
518                 .setBatchOrder(batchOrder)
519                 .setBatchItemIdChoice(new FlatBatchFailureFlowIdCaseBuilder()
520                         .setFlowId(new FlowId(flowIdValue))
521                         .build())
522                 .build();
523     }
524
525     private static ProcessFlatBatchOutput createFlatBatchOutput(final BatchFailure... batchFailures) {
526         return new ProcessFlatBatchOutputBuilder()
527                 .setBatchFailure(BindingMap.ordered(batchFailures))
528                 .build();
529     }
530
531     @Test
532     public void testPrepareBatchPlan_success() throws Exception {
533         final FlatBatchAddFlow flatBatchAddFlow_1 = new FlatBatchAddFlowBuilder()
534                 .setFlowId(new FlowId("f1"))
535                 .setBatchOrder(Uint16.ONE)
536                 .build();
537         final FlatBatchAddFlow flatBatchAddFlow_2 = new FlatBatchAddFlowBuilder()
538                 .setFlowId(new FlowId("f2"))
539                 .setBatchOrder(Uint16.TWO)
540                 .build();
541         final BatchPlanStep batchPlanStep = new BatchPlanStep(BatchStepType.FLOW_ADD);
542         batchPlanStep.getTaskBag().addAll(Lists.newArrayList(flatBatchAddFlow_1, flatBatchAddFlow_2));
543         final List<BatchPlanStep> batchPlan = Lists.newArrayList(batchPlanStep);
544
545         final List<BatchStepJob> batchChain = processFlatBatch.prepareBatchChain(batchPlan, NODE_REF, true);
546
547         assertEquals(1, batchChain.size());
548
549         when(addFlowsBatch.invoke(any()))
550                 .thenReturn(RpcResultBuilder
551                         .success(new AddFlowsBatchOutputBuilder().build())
552                         .buildFuture());
553
554         final var rpcResultFuture = processFlatBatch.executeBatchPlan(batchChain);
555         assertTrue(rpcResultFuture.isDone());
556         final var rpcResult = rpcResultFuture.get();
557         assertTrue(rpcResult.isSuccessful());
558         assertEquals(0, rpcResult.getErrors().size());
559         assertEquals(0, rpcResult.getResult().nonnullBatchFailure().size());
560
561         verify(addFlowsBatch).invoke(any());
562     }
563
564     @Test
565     public void testPrepareBatchPlan_failure() throws Exception {
566         final FlatBatchAddFlow flatBatchAddFlow_1 = new FlatBatchAddFlowBuilder()
567                 .setFlowId(new FlowId("f1"))
568                 .setBatchOrder(Uint16.ONE)
569                 .build();
570         final FlatBatchAddFlow flatBatchAddFlow_2 = new FlatBatchAddFlowBuilder()
571                 .setFlowId(new FlowId("f2"))
572                 .setBatchOrder(Uint16.TWO)
573                 .build();
574         final BatchPlanStep batchPlanStep = new BatchPlanStep(BatchStepType.FLOW_ADD);
575         batchPlanStep.getTaskBag().addAll(Lists.newArrayList(flatBatchAddFlow_1, flatBatchAddFlow_2));
576
577         final List<BatchPlanStep> batchPlan = Lists.newArrayList(batchPlanStep, batchPlanStep);
578
579         final List<BatchStepJob> batchChain = processFlatBatch.prepareBatchChain(batchPlan, NODE_REF, true);
580
581         assertEquals(2, batchChain.size());
582
583         when(addFlowsBatch.invoke(any()))
584                 .thenReturn(RpcResultBuilder
585                         .<AddFlowsBatchOutput>failed()
586                         .withResult(new AddFlowsBatchOutputBuilder()
587                                 .setBatchFailedFlowsOutput(BindingMap.ordered(
588                                         new BatchFailedFlowsOutputBuilder()
589                                                 .setBatchOrder(Uint16.ZERO)
590                                                 .setFlowId(new FlowId("f1"))
591                                                 .build(),
592                                         new BatchFailedFlowsOutputBuilder()
593                                                 .setBatchOrder(Uint16.ONE)
594                                                 .setFlowId(new FlowId("f2"))
595                                                 .build()))
596                                 .build())
597                         .withError(ErrorType.APPLICATION, "ut-addFlowBatchError")
598                         .buildFuture());
599
600         final var rpcResultFuture = processFlatBatch.executeBatchPlan(batchChain);
601         assertTrue(rpcResultFuture.isDone());
602         final var rpcResult = rpcResultFuture.get();
603         assertFalse(rpcResult.isSuccessful());
604         assertEquals(2, rpcResult.getErrors().size());
605         assertEquals(4, rpcResult.getResult().getBatchFailure().size());
606
607         verify(addFlowsBatch, times(2)).invoke(addFlowsBatchInputCpt.capture());
608         assertEquals(2, addFlowsBatchInputCpt.getValue().nonnullBatchAddFlows().size());
609     }
610 }