2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.openflowplugin.impl.services.sal;
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;
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;
67 * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl}.
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";
79 private AddFlow addFlow;
81 private RemoveFlow removeFlow;
83 private UpdateFlow updateFlow;
85 private SendBarrier sendBarrier;
87 private ArgumentCaptor<RemoveFlowInput> removeFlowInputCpt;
89 private ArgumentCaptor<UpdateFlowInput> updateFlowInputCpt;
91 private ArgumentCaptor<AddFlowInput> addFlowInputCpt;
93 private AddFlowsBatchImpl addFlowsBatch;
94 private RemoveFlowsBatchImpl removeFlowsBatch;
95 private UpdateFlowsBatchImpl updateFlowsBatch;
99 addFlowsBatch = new AddFlowsBatchImpl(addFlow, sendBarrier);
100 removeFlowsBatch = new RemoveFlowsBatchImpl(removeFlow, sendBarrier);
101 updateFlowsBatch = new UpdateFlowsBatchImpl(updateFlow, sendBarrier);
103 when(sendBarrier.invoke(any())).thenReturn(RpcResultBuilder.<SendBarrierOutput>success().buildFuture());
107 public void tearDown() {
108 verifyNoMoreInteractions(addFlow, removeFlow, updateFlow, sendBarrier);
112 public void testRemoveFlowsBatch_success() throws Exception {
113 when(removeFlow.invoke(any()))
114 .thenReturn(RpcResultBuilder.success(new RemoveFlowOutputBuilder().build())
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);
122 final var input = new RemoveFlowsBatchInputBuilder()
124 .setBarrierAfter(true)
125 .setBatchRemoveFlows(BindingMap.ordered(batchFlow1, batchFlow2))
128 final var resultFuture = removeFlowsBatch.invoke(input);
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());
136 final var inOrder = inOrder(removeFlow, sendBarrier);
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());
144 inOrder.verify(sendBarrier).invoke(any());
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")
154 final var batchFlow1 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_1, 42);
155 final var batchFlow2 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_2, 43);
157 final var input = new RemoveFlowsBatchInputBuilder()
159 .setBarrierAfter(true)
160 .setBatchRemoveFlows(BindingMap.ordered(batchFlow1, batchFlow2))
163 final var resultFuture = removeFlowsBatch.invoke(input);
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());
174 final var inOrder = inOrder(removeFlow, sendBarrier);
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());
182 inOrder.verify(sendBarrier).invoke(any());
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)
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)
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())
214 public void testAddFlowsBatch_success() throws Exception {
215 when(addFlow.invoke(any()))
216 .thenReturn(RpcResultBuilder.success(new AddFlowOutputBuilder().build()).buildFuture());
218 final var input = new AddFlowsBatchInputBuilder()
220 .setBarrierAfter(true)
221 .setBatchAddFlows(BindingMap.ordered(
222 createEmptyBatchAddFlow("ut-dummy-flow1", 42),
223 createEmptyBatchAddFlow("ut-dummy-flow2", 43)))
226 final var resultFuture = addFlowsBatch.invoke(input);
228 assertTrue(resultFuture.isDone());
229 assertTrue(resultFuture.get().isSuccessful());
231 final var inOrder = inOrder(addFlow, sendBarrier);
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());
239 inOrder.verify(sendBarrier).invoke(any());
243 public void testAddFlowsBatch_failed() throws Exception {
244 when(addFlow.invoke(any()))
245 .thenReturn(RpcResultBuilder
246 .<AddFlowOutput>failed().withError(ErrorType.APPLICATION, "ut-groupAddError")
249 final var input = new AddFlowsBatchInputBuilder()
251 .setBarrierAfter(true)
252 .setBatchAddFlows(BindingMap.ordered(
253 createEmptyBatchAddFlow(FLOW_ID_VALUE_1, 42),
254 createEmptyBatchAddFlow(FLOW_ID_VALUE_2, 43)))
257 final var resultFuture = addFlowsBatch.invoke(input);
259 assertTrue(resultFuture.isDone());
261 final var result = resultFuture.get();
262 assertFalse(result.isSuccessful());
263 assertEquals(2, result.getResult().nonnullBatchFailedFlowsOutput().size());
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());
270 final var inOrder = inOrder(addFlow, sendBarrier);
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());
278 inOrder.verify(sendBarrier).invoke(any());
282 public void testUpdateFlowsBatch_success() throws Exception {
283 when(updateFlow.invoke(any()))
284 .thenReturn(RpcResultBuilder.success(new UpdateFlowOutputBuilder().build()).buildFuture());
286 final var input = new UpdateFlowsBatchInputBuilder()
288 .setBarrierAfter(true)
289 .setBatchUpdateFlows(BindingMap.ordered(
290 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
291 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
294 final var resultFuture = updateFlowsBatch.invoke(input);
296 assertTrue(resultFuture.isDone());
297 assertTrue(resultFuture.get().isSuccessful());
299 final var inOrder = inOrder(updateFlow, sendBarrier);
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());
309 inOrder.verify(sendBarrier).invoke(any());
313 public void testUpdateFlowsBatch_failure() throws Exception {
314 when(updateFlow.invoke(any()))
315 .thenReturn(RpcResultBuilder.<UpdateFlowOutput>failed()
316 .withError(ErrorType.APPLICATION, "ut-flowUpdateError")
319 final var input = new UpdateFlowsBatchInputBuilder()
321 .setBarrierAfter(true)
322 .setBatchUpdateFlows(BindingMap.ordered(
323 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
324 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
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());
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());
346 inOrder.verify(sendBarrier).invoke(any());