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
9 package org.opendaylight.openflowplugin.impl.services.sal;
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.runners.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.SendBarrierInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.AddFlowsBatchOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchInputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.RemoveFlowsBatchOutput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchInputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.UpdateFlowsBatchOutput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlows;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.add.flows.batch.input.BatchAddFlowsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.OriginalBatchedFlowBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.batch.flow.input.update.grouping.UpdatedBatchedFlowBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlows;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.remove.flows.batch.input.BatchRemoveFlowsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlows;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flows.service.rev160314.update.flows.batch.input.BatchUpdateFlowsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.common.RpcError;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
71 * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.SalFlowsBatchServiceImpl}.
73 @RunWith(MockitoJUnitRunner.class)
74 public class SalFlowsBatchServiceImplTest {
76 private static final Logger LOG = LoggerFactory.getLogger(SalFlowsBatchServiceImplTest.class);
78 public static final NodeId NODE_ID = new NodeId("ut-dummy-node");
79 public static final NodeKey NODE_KEY = new NodeKey(NODE_ID);
80 public static final NodeRef NODE_REF =
81 new NodeRef(InstanceIdentifier.create(Nodes.class).child(Node.class, NODE_KEY));
84 private SalFlowService salFlowService;
86 private FlowCapableTransactionService transactionService;
88 private ArgumentCaptor<RemoveFlowInput> removeFlowInputCpt;
90 private ArgumentCaptor<UpdateFlowInput> updateFlowInputCpt;
92 private ArgumentCaptor<AddFlowInput> addFlowInputCpt;
94 private SalFlowsBatchServiceImpl salFlowsBatchService;
95 public static final String FLOW_ID_VALUE_1 = "ut-dummy-flow1";
96 public static final String FLOW_ID_VALUE_2 = "ut-dummy-flow2";
99 public void setUp() throws Exception {
100 salFlowsBatchService = new SalFlowsBatchServiceImpl(salFlowService, transactionService);
102 Mockito.when(transactionService.sendBarrier(ArgumentMatchers.<SendBarrierInput>any()))
103 .thenReturn(RpcResultBuilder.<SendBarrierOutput>success().buildFuture());
107 public void tearDown() throws Exception {
108 Mockito.verifyNoMoreInteractions(salFlowService, transactionService);
112 public void testRemoveFlowsBatch_success() throws Exception {
113 Mockito.when(salFlowService.removeFlow(ArgumentMatchers.<RemoveFlowInput>any()))
114 .thenReturn(RpcResultBuilder.success(new RemoveFlowOutputBuilder().build())
117 final String flow1IdValue = "ut-dummy-flow1";
118 final String flow2IdValue = "ut-dummy-flow2";
119 final BatchRemoveFlows batchFlow1 = createEmptyBatchRemoveFlow(flow1IdValue, 42);
120 final BatchRemoveFlows batchFlow2 = createEmptyBatchRemoveFlow(flow2IdValue, 43);
122 final RemoveFlowsBatchInput input = new RemoveFlowsBatchInputBuilder()
124 .setBarrierAfter(true)
125 .setBatchRemoveFlows(Lists.newArrayList(batchFlow1, batchFlow2))
128 final Future<RpcResult<RemoveFlowsBatchOutput>> resultFuture = salFlowsBatchService.removeFlowsBatch(input);
130 Assert.assertTrue(resultFuture.isDone());
131 final RpcResult<RemoveFlowsBatchOutput> rpcResult = resultFuture.get();
132 Assert.assertTrue(rpcResult.isSuccessful());
133 final RemoveFlowsBatchOutput result = rpcResult.getResult();
134 Assert.assertEquals(0, result.getBatchFailedFlowsOutput().size());
136 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
138 inOrder.verify(salFlowService, Mockito.times(2)).removeFlow(removeFlowInputCpt.capture());
139 final List<RemoveFlowInput> allValues = removeFlowInputCpt.getAllValues();
140 Assert.assertEquals(2, allValues.size());
141 Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
142 Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
144 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());
148 public void testRemoveFlowsBatch_failed() throws Exception {
149 Mockito.when(salFlowService.removeFlow(ArgumentMatchers.<RemoveFlowInput>any()))
150 .thenReturn(RpcResultBuilder.<RemoveFlowOutput>failed()
151 .withError(RpcError.ErrorType.APPLICATION, "flow-remove-fail-1")
154 final BatchRemoveFlows batchFlow1 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_1, 42);
155 final BatchRemoveFlows batchFlow2 = createEmptyBatchRemoveFlow(FLOW_ID_VALUE_2, 43);
157 final RemoveFlowsBatchInput input = new RemoveFlowsBatchInputBuilder()
159 .setBarrierAfter(true)
160 .setBatchRemoveFlows(Lists.newArrayList(batchFlow1, batchFlow2))
163 final Future<RpcResult<RemoveFlowsBatchOutput>> resultFuture = salFlowsBatchService.removeFlowsBatch(input);
165 Assert.assertTrue(resultFuture.isDone());
166 final RpcResult<RemoveFlowsBatchOutput> rpcResult = resultFuture.get();
167 Assert.assertFalse(rpcResult.isSuccessful());
168 final RemoveFlowsBatchOutput result = rpcResult.getResult();
169 Assert.assertEquals(2, result.getBatchFailedFlowsOutput().size());
170 Assert.assertEquals(FLOW_ID_VALUE_1, result.getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
171 Assert.assertEquals(FLOW_ID_VALUE_2, result.getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
173 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
175 inOrder.verify(salFlowService, Mockito.times(2)).removeFlow(removeFlowInputCpt.capture());
176 final List<RemoveFlowInput> allValues = removeFlowInputCpt.getAllValues();
177 Assert.assertEquals(2, allValues.size());
178 Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
179 Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
181 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());
184 private static BatchAddFlows createEmptyBatchAddFlow(final String flowIdValue, final int priority) {
185 return new BatchAddFlowsBuilder()
186 .setFlowId(new FlowId(flowIdValue))
187 .setPriority(priority)
188 .setMatch(new MatchBuilder().build())
189 .setTableId((short) 0)
193 private static BatchRemoveFlows createEmptyBatchRemoveFlow(final String flowIdValue, final int priority) {
194 return new BatchRemoveFlowsBuilder()
195 .setFlowId(new FlowId(flowIdValue))
196 .setPriority(priority)
197 .setMatch(new MatchBuilder().build())
198 .setTableId((short) 0)
202 private static BatchUpdateFlows createEmptyBatchUpdateFlow(final String flowIdValue, final int priority) {
203 final BatchAddFlows emptyOriginalFlow = createEmptyBatchAddFlow(flowIdValue, priority);
204 final BatchAddFlows emptyUpdatedFlow = createEmptyBatchAddFlow(flowIdValue, priority + 1);
205 return new BatchUpdateFlowsBuilder()
206 .setFlowId(new FlowId(flowIdValue))
207 .setOriginalBatchedFlow(new OriginalBatchedFlowBuilder(emptyOriginalFlow).build())
208 .setUpdatedBatchedFlow(new UpdatedBatchedFlowBuilder(emptyUpdatedFlow).build())
213 public void testAddFlowsBatch_success() throws Exception {
214 Mockito.when(salFlowService.addFlow(ArgumentMatchers.<AddFlowInput>any()))
215 .thenReturn(RpcResultBuilder.success(new AddFlowOutputBuilder().build()).buildFuture());
217 final AddFlowsBatchInput input = new AddFlowsBatchInputBuilder()
219 .setBarrierAfter(true)
220 .setBatchAddFlows(Lists.newArrayList(
221 createEmptyBatchAddFlow("ut-dummy-flow1", 42),
222 createEmptyBatchAddFlow("ut-dummy-flow2", 43)))
225 final Future<RpcResult<AddFlowsBatchOutput>> resultFuture = salFlowsBatchService.addFlowsBatch(input);
227 Assert.assertTrue(resultFuture.isDone());
228 Assert.assertTrue(resultFuture.get().isSuccessful());
230 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
232 inOrder.verify(salFlowService, Mockito.times(2)).addFlow(addFlowInputCpt.capture());
233 final List<AddFlowInput> allValues = addFlowInputCpt.getAllValues();
234 Assert.assertEquals(2, allValues.size());
235 Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
236 Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
238 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());
242 public void testAddFlowsBatch_failed() throws Exception {
243 Mockito.when(salFlowService.addFlow(ArgumentMatchers.<AddFlowInput>any()))
244 .thenReturn(RpcResultBuilder
245 .<AddFlowOutput>failed().withError(RpcError.ErrorType.APPLICATION, "ut-groupAddError")
248 final AddFlowsBatchInput input = new AddFlowsBatchInputBuilder()
250 .setBarrierAfter(true)
251 .setBatchAddFlows(Lists.newArrayList(
252 createEmptyBatchAddFlow(FLOW_ID_VALUE_1, 42),
253 createEmptyBatchAddFlow(FLOW_ID_VALUE_2, 43)))
256 final Future<RpcResult<AddFlowsBatchOutput>> resultFuture = salFlowsBatchService.addFlowsBatch(input);
258 Assert.assertTrue(resultFuture.isDone());
259 Assert.assertFalse(resultFuture.get().isSuccessful());
260 Assert.assertEquals(2, resultFuture.get().getResult().getBatchFailedFlowsOutput().size());
261 Assert.assertEquals(FLOW_ID_VALUE_1,
262 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
263 Assert.assertEquals(FLOW_ID_VALUE_2,
264 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
265 Assert.assertEquals(2, resultFuture.get().getErrors().size());
267 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
269 inOrder.verify(salFlowService, Mockito.times(2)).addFlow(addFlowInputCpt.capture());
270 final List<AddFlowInput> allValues = addFlowInputCpt.getAllValues();
271 Assert.assertEquals(2, allValues.size());
272 Assert.assertEquals(42, allValues.get(0).getPriority().longValue());
273 Assert.assertEquals(43, allValues.get(1).getPriority().longValue());
275 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());
279 public void testUpdateFlowsBatch_success() throws Exception {
280 Mockito.when(salFlowService.updateFlow(ArgumentMatchers.<UpdateFlowInput>any()))
281 .thenReturn(RpcResultBuilder.success(new UpdateFlowOutputBuilder().build()).buildFuture());
283 final UpdateFlowsBatchInput input = new UpdateFlowsBatchInputBuilder()
285 .setBarrierAfter(true)
286 .setBatchUpdateFlows(Lists.newArrayList(
287 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
288 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
291 final Future<RpcResult<UpdateFlowsBatchOutput>> resultFuture = salFlowsBatchService.updateFlowsBatch(input);
293 Assert.assertTrue(resultFuture.isDone());
294 Assert.assertTrue(resultFuture.get().isSuccessful());
296 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
298 inOrder.verify(salFlowService, Mockito.times(2)).updateFlow(updateFlowInputCpt.capture());
299 final List<UpdateFlowInput> allValues = updateFlowInputCpt.getAllValues();
300 Assert.assertEquals(2, allValues.size());
301 Assert.assertEquals(42, allValues.get(0).getOriginalFlow().getPriority().longValue());
302 Assert.assertEquals(43, allValues.get(0).getUpdatedFlow().getPriority().longValue());
303 Assert.assertEquals(44, allValues.get(1).getOriginalFlow().getPriority().longValue());
304 Assert.assertEquals(45, allValues.get(1).getUpdatedFlow().getPriority().longValue());
306 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());
310 public void testUpdateFlowsBatch_failure() throws Exception {
311 Mockito.when(salFlowService.updateFlow(ArgumentMatchers.<UpdateFlowInput>any()))
312 .thenReturn(RpcResultBuilder.<UpdateFlowOutput>failed()
313 .withError(RpcError.ErrorType.APPLICATION, "ut-flowUpdateError")
316 final UpdateFlowsBatchInput input = new UpdateFlowsBatchInputBuilder()
318 .setBarrierAfter(true)
319 .setBatchUpdateFlows(Lists.newArrayList(
320 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_1, 42),
321 createEmptyBatchUpdateFlow(FLOW_ID_VALUE_2, 44)))
324 final Future<RpcResult<UpdateFlowsBatchOutput>> resultFuture = salFlowsBatchService.updateFlowsBatch(input);
326 Assert.assertTrue(resultFuture.isDone());
327 Assert.assertFalse(resultFuture.get().isSuccessful());
328 Assert.assertFalse(resultFuture.get().isSuccessful());
329 Assert.assertEquals(2, resultFuture.get().getResult().getBatchFailedFlowsOutput().size());
330 Assert.assertEquals(FLOW_ID_VALUE_1,
331 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(0).getFlowId().getValue());
332 Assert.assertEquals(FLOW_ID_VALUE_2,
333 resultFuture.get().getResult().getBatchFailedFlowsOutput().get(1).getFlowId().getValue());
334 Assert.assertEquals(2, resultFuture.get().getErrors().size());
336 final InOrder inOrder = Mockito.inOrder(salFlowService, transactionService);
337 inOrder.verify(salFlowService, Mockito.times(2)).updateFlow(updateFlowInputCpt.capture());
338 final List<UpdateFlowInput> allValues = updateFlowInputCpt.getAllValues();
339 Assert.assertEquals(2, allValues.size());
340 Assert.assertEquals(42, allValues.get(0).getOriginalFlow().getPriority().longValue());
341 Assert.assertEquals(43, allValues.get(0).getUpdatedFlow().getPriority().longValue());
342 Assert.assertEquals(44, allValues.get(1).getOriginalFlow().getPriority().longValue());
343 Assert.assertEquals(45, allValues.get(1).getUpdatedFlow().getPriority().longValue());
345 inOrder.verify(transactionService).sendBarrier(ArgumentMatchers.<SendBarrierInput>any());