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