Merge "Failed to cancel service reconciliation, When controller become slave."
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / services / sal / SalFlowsBatchServiceImplTest.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 java.util.List;
13 import java.util.concurrent.Future;
14 import org.junit.After;
15 import org.junit.Assert;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.junit.runner.RunWith;
19 import org.mockito.ArgumentCaptor;
20 import org.mockito.ArgumentMatchers;
21 import org.mockito.Captor;
22 import org.mockito.InOrder;
23 import org.mockito.Mock;
24 import org.mockito.Mockito;
25 import org.mockito.junit.MockitoJUnitRunner;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchOutput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlows;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlowsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.OriginalBatchedFlowBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.UpdatedBatchedFlowBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlows;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlowsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlows;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlowsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.opendaylight.yangtools.yang.common.RpcError;
64 import org.opendaylight.yangtools.yang.common.RpcResult;
65 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69 /**
70  * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl}.
71  */
72 @RunWith(MockitoJUnitRunner.class)
73 public class SalFlowsBatchServiceImplTest {
74
75     private static final Logger LOG = LoggerFactory.getLogger(SalFlowsBatchServiceImplTest.class);
76
77     public static final NodeId NODE_ID = new NodeId("ut-dummy-node");
78     public static final NodeKey NODE_KEY = new NodeKey(NODE_ID);
79     public static final NodeRef NODE_REF =
80             new NodeRef(InstanceIdentifier.create(Nodes.class).child(Node.class, NODE_KEY));
81
82     @Mock
83     private SalFlowService salFlowService;
84     @Mock
85     private FlowCapableTransactionService transactionService;
86     @Captor
87     private ArgumentCaptor<RemoveFlowInput> removeFlowInputCpt;
88     @Captor
89     private ArgumentCaptor<UpdateFlowInput> updateFlowInputCpt;
90     @Captor
91     private ArgumentCaptor<AddFlowInput> addFlowInputCpt;
92
93     private SalFlowsBatchServiceImpl salFlowsBatchService;
94     public static final String FLOW_ID_VALUE_1 = "ut-dummy-flow1";
95     public static final String FLOW_ID_VALUE_2 = "ut-dummy-flow2";
96
97     @Before
98     public void setUp() {
99         salFlowsBatchService = new SalFlowsBatchServiceImpl(salFlowService, transactionService);
100
101         Mockito.when(transactionService.sendBarrier(ArgumentMatchers.any()))
102                 .thenReturn(RpcResultBuilder.<SendBarrierOutput>success().buildFuture());
103     }
104
105     @After
106     public void tearDown() {
107         Mockito.verifyNoMoreInteractions(salFlowService, transactionService);
108     }
109
110     @Test
111     public void testRemoveFlowsBatch_success() throws Exception {
112         Mockito.when(salFlowService.removeFlow(ArgumentMatchers.any()))
113                 .thenReturn(RpcResultBuilder.success(new RemoveFlowOutputBuilder().build())
114                         .buildFuture());
115
116         final String flow1IdValue = "ut-dummy-flow1";
117         final String flow2IdValue = "ut-dummy-flow2";
118         final BatchRemoveFlows batchFlow1 = createEmptyBatchRemoveFlow(flow1IdValue, 42);
119         final BatchRemoveFlows batchFlow2 = createEmptyBatchRemoveFlow(flow2IdValue, 43);
120
121         final RemoveFlowsBatchInput input = new RemoveFlowsBatchInputBuilder()
122                 .setNode(NODE_REF)
123                 .setBarrierAfter(true)
124                 .setBatchRemoveFlows(Lists.newArrayList(batchFlow1, batchFlow2))
125                 .build();
126
127         final Future<RpcResult<RemoveFlowsBatchOutput>> resultFuture = salFlowsBatchService.removeFlowsBatch(input);
128
129         Assert.assertTrue(resultFuture.isDone());
130         final RpcResult<RemoveFlowsBatchOutput> rpcResult = resultFuture.get();
131         Assert.assertTrue(rpcResult.isSuccessful());
132         final RemoveFlowsBatchOutput result = rpcResult.getResult();
133         Assert.assertEquals(0, result.getBatchFailedFlowsOutput().size());
134
135         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
136
137         inOrder.verify(salFlowService, Mockito.times(2)).removeFlow(removeFlowInputCpt.capture());
138         final List<RemoveFlowInput> allValues = removeFlowInputCpt.getAllValues();
139         Assert.assertEquals(2, allValues.size());
140         Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
141         Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
142
143         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
144     }
145
146     @Test
147     public void testRemoveFlowsBatch_failed() throws Exception {
148         Mockito.when(salFlowService.removeFlow(ArgumentMatchers.any()))
149                 .thenReturn(RpcResultBuilder.<RemoveFlowOutput>failed()
150                         .withError(RpcError.ErrorType.APPLICATION, "flow-remove-fail-1")
151                         .buildFuture());
152
153         final BatchRemoveFlows batchFlow1 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_1, 42);
154         final BatchRemoveFlows batchFlow2 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_2, 43);
155
156         final RemoveFlowsBatchInput input = new RemoveFlowsBatchInputBuilder()
157                 .setNode(NODE_REF)
158                 .setBarrierAfter(true)
159                 .setBatchRemoveFlows(Lists.newArrayList(batchFlow1, batchFlow2))
160                 .build();
161
162         final Future<RpcResult<RemoveFlowsBatchOutput>> resultFuture = salFlowsBatchService.removeFlowsBatch(input);
163
164         Assert.assertTrue(resultFuture.isDone());
165         final RpcResult<RemoveFlowsBatchOutput> rpcResult = resultFuture.get();
166         Assert.assertFalse(rpcResult.isSuccessful());
167         final RemoveFlowsBatchOutput result = rpcResult.getResult();
168         Assert.assertEquals(2, result.getBatchFailedFlowsOutput().size());
169         Assert.assertEquals(FLOW_ID_VALUE_1, result.getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
170         Assert.assertEquals(FLOW_ID_VALUE_2, result.getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
171
172         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
173
174         inOrder.verify(salFlowService, Mockito.times(2)).removeFlow(removeFlowInputCpt.capture());
175         final List<RemoveFlowInput> allValues = removeFlowInputCpt.getAllValues();
176         Assert.assertEquals(2, allValues.size());
177         Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
178         Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
179
180         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
181     }
182
183     private static BatchAddFlows createEmptyBatchAddFlow(final String flowIdValue, final int priority) {
184         return new BatchAddFlowsBuilder()
185                 .setFlowId(new FlowId(flowIdValue))
186                 .setPriority(priority)
187                 .setMatch(new MatchBuilder().build())
188                 .setTableId((short) 0)
189                 .build();
190     }
191
192     private static BatchRemoveFlows createEmptyBatchRemoveFlow(final String flowIdValue, final int priority) {
193         return new BatchRemoveFlowsBuilder()
194                 .setFlowId(new FlowId(flowIdValue))
195                 .setPriority(priority)
196                 .setMatch(new MatchBuilder().build())
197                 .setTableId((short) 0)
198                 .build();
199     }
200
201     private static BatchUpdateFlows createEmptyBatchUpdateFlow(final String flowIdValue, final int priority) {
202         final BatchAddFlows emptyOriginalFlow = createEmptyBatchAddFlow(flowIdValue, priority);
203         final BatchAddFlows emptyUpdatedFlow = createEmptyBatchAddFlow(flowIdValue, priority + 1);
204         return new BatchUpdateFlowsBuilder()
205                 .setFlowId(new FlowId(flowIdValue))
206                 .setOriginalBatchedFlow(new OriginalBatchedFlowBuilder(emptyOriginalFlow).build())
207                 .setUpdatedBatchedFlow(new UpdatedBatchedFlowBuilder(emptyUpdatedFlow).build())
208                 .build();
209     }
210
211     @Test
212     public void testAddFlowsBatch_success() throws Exception {
213         Mockito.when(salFlowService.addFlow(ArgumentMatchers.any()))
214                 .thenReturn(RpcResultBuilder.success(new AddFlowOutputBuilder().build()).buildFuture());
215
216         final AddFlowsBatchInput input = new AddFlowsBatchInputBuilder()
217                 .setNode(NODE_REF)
218                 .setBarrierAfter(true)
219                 .setBatchAddFlows(Lists.newArrayList(
220                         createEmptyBatchAddFlow("ut-dummy-flow1", 42),
221                         createEmptyBatchAddFlow("ut-dummy-flow2", 43)))
222                 .build();
223
224         final Future<RpcResult<AddFlowsBatchOutput>> resultFuture = salFlowsBatchService.addFlowsBatch(input);
225
226         Assert.assertTrue(resultFuture.isDone());
227         Assert.assertTrue(resultFuture.get().isSuccessful());
228
229         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
230
231         inOrder.verify(salFlowService, Mockito.times(2)).addFlow(addFlowInputCpt.capture());
232         final List<AddFlowInput> allValues = addFlowInputCpt.getAllValues();
233         Assert.assertEquals(2, allValues.size());
234         Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
235         Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
236
237         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
238     }
239
240     @Test
241     public void testAddFlowsBatch_failed() throws Exception {
242         Mockito.when(salFlowService.addFlow(ArgumentMatchers.any()))
243                 .thenReturn(RpcResultBuilder
244                         .<AddFlowOutput>failed().withError(RpcError.ErrorType.APPLICATION, "ut-groupAddError")
245                         .buildFuture());
246
247         final AddFlowsBatchInput input = new AddFlowsBatchInputBuilder()
248                 .setNode(NODE_REF)
249                 .setBarrierAfter(true)
250                 .setBatchAddFlows(Lists.newArrayList(
251                         createEmptyBatchAddFlow(FLOW_ID_VALUE_1, 42),
252                         createEmptyBatchAddFlow(FLOW_ID_VALUE_2, 43)))
253                 .build();
254
255         final Future<RpcResult<AddFlowsBatchOutput>> resultFuture = salFlowsBatchService.addFlowsBatch(input);
256
257         Assert.assertTrue(resultFuture.isDone());
258         Assert.assertFalse(resultFuture.get().isSuccessful());
259         Assert.assertEquals(2, resultFuture.get().getResult().getBatchFailedFlowsOutput().size());
260         Assert.assertEquals(FLOW_ID_VALUE_1,
261                 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
262         Assert.assertEquals(FLOW_ID_VALUE_2,
263                 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
264         Assert.assertEquals(2, resultFuture.get().getErrors().size());
265
266         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
267
268         inOrder.verify(salFlowService, Mockito.times(2)).addFlow(addFlowInputCpt.capture());
269         final List<AddFlowInput> allValues = addFlowInputCpt.getAllValues();
270         Assert.assertEquals(2, allValues.size());
271         Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
272         Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
273
274         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
275     }
276
277     @Test
278     public void testUpdateFlowsBatch_success() throws Exception {
279         Mockito.when(salFlowService.updateFlow(ArgumentMatchers.any()))
280                 .thenReturn(RpcResultBuilder.success(new UpdateFlowOutputBuilder().build()).buildFuture());
281
282         final UpdateFlowsBatchInput input = new UpdateFlowsBatchInputBuilder()
283                 .setNode(NODE_REF)
284                 .setBarrierAfter(true)
285                 .setBatchUpdateFlows(Lists.newArrayList(
286                         createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
287                         createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
288                 .build();
289
290         final Future<RpcResult<UpdateFlowsBatchOutput>> resultFuture = salFlowsBatchService.updateFlowsBatch(input);
291
292         Assert.assertTrue(resultFuture.isDone());
293         Assert.assertTrue(resultFuture.get().isSuccessful());
294
295         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
296
297         inOrder.verify(salFlowService, Mockito.times(2)).updateFlow(updateFlowInputCpt.capture());
298         final List<UpdateFlowInput> allValues = updateFlowInputCpt.getAllValues();
299         Assert.assertEquals(2, allValues.size());
300         Assert.assertEquals(42, allValues.get(0).getOriginalFlow().getPriority().longValue());
301         Assert.assertEquals(43, allValues.get(0).getUpdatedFlow().getPriority().longValue());
302         Assert.assertEquals(44, allValues.get(1).getOriginalFlow().getPriority().longValue());
303         Assert.assertEquals(45, allValues.get(1).getUpdatedFlow().getPriority().longValue());
304
305         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
306     }
307
308     @Test
309     public void testUpdateFlowsBatch_failure() throws Exception {
310         Mockito.when(salFlowService.updateFlow(ArgumentMatchers.any()))
311                 .thenReturn(RpcResultBuilder.<UpdateFlowOutput>failed()
312                         .withError(RpcError.ErrorType.APPLICATION, "ut-flowUpdateError")
313                         .buildFuture());
314
315         final UpdateFlowsBatchInput input = new UpdateFlowsBatchInputBuilder()
316                 .setNode(NODE_REF)
317                 .setBarrierAfter(true)
318                 .setBatchUpdateFlows(Lists.newArrayList(
319                         createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
320                         createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
321                 .build();
322
323         final Future<RpcResult<UpdateFlowsBatchOutput>> resultFuture = salFlowsBatchService.updateFlowsBatch(input);
324
325         Assert.assertTrue(resultFuture.isDone());
326         Assert.assertFalse(resultFuture.get().isSuccessful());
327         Assert.assertFalse(resultFuture.get().isSuccessful());
328         Assert.assertEquals(2, resultFuture.get().getResult().getBatchFailedFlowsOutput().size());
329         Assert.assertEquals(FLOW_ID_VALUE_1,
330                 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
331         Assert.assertEquals(FLOW_ID_VALUE_2,
332                 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
333         Assert.assertEquals(2, resultFuture.get().getErrors().size());
334
335         final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
336         inOrder.verify(salFlowService, Mockito.times(2)).updateFlow(updateFlowInputCpt.capture());
337         final List<UpdateFlowInput> allValues = updateFlowInputCpt.getAllValues();
338         Assert.assertEquals(2, allValues.size());
339         Assert.assertEquals(42, allValues.get(0).getOriginalFlow().getPriority().longValue());
340         Assert.assertEquals(43, allValues.get(0).getUpdatedFlow().getPriority().longValue());
341         Assert.assertEquals(44, allValues.get(1).getOriginalFlow().getPriority().longValue());
342         Assert.assertEquals(45, allValues.get(1).getUpdatedFlow().getPriority().longValue());
343
344         inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.any());
345     }
346 }