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