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