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