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