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