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.assertFalse;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.when;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.util.concurrent.ExecutionException;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.Mock;
24 import org.mockito.junit.MockitoJUnitRunner;
25 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
26 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
27 import org.opendaylight.openflowplugin.api.OFConstants;
28 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
29 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
30 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
31 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
32 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
33 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
34 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
35 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
36 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
37 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
62 import org.opendaylight.yangtools.yang.binding.DataObject;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
67 import org.opendaylight.yangtools.yang.common.Uint16;
68 import org.opendaylight.yangtools.yang.common.Uint32;
69 import org.opendaylight.yangtools.yang.common.Uint64;
70 import org.opendaylight.yangtools.yang.common.Uint8;
72 @RunWith(MockitoJUnitRunner.StrictStubs.class)
73 public class SalFlowServiceImplTest {
74 private static final Uint64 DUMMY_DATAPATH_ID = Uint64.valueOf(444);
75 private static final String DUMMY_NODE_ID = "dummyNodeID";
76 private static final String DUMMY_FLOW_ID = "dummyFlowID";
77 private static final Uint8 DUMMY_TABLE_ID = Uint8.ZERO;
79 private static final KeyedInstanceIdentifier<Node, NodeKey> NODE_II =
80 InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(DUMMY_NODE_ID)));
82 private static final KeyedInstanceIdentifier<Table, TableKey> TABLE_II =
83 NODE_II.augmentation(FlowCapableNode.class).child(Table.class, new TableKey(DUMMY_TABLE_ID));
85 private final NodeRef noderef = new NodeRef(NODE_II);
88 private RequestContextStack mockedRequestContextStack;
90 private DeviceContext mockedDeviceContext;
92 private ConnectionContext mockedPrimConnectionContext;
94 private FeaturesReply mockedFeatures;
96 private ConnectionAdapter mockedConnectionAdapter;
98 private MessageSpy mockedMessagSpy;
100 private RequestContext<Object> requestContext;
102 private OutboundQueue outboundQueue;
107 private DeviceState mockedDeviceState;
109 private DeviceInfo mockedDeviceInfo;
111 private DeviceFlowRegistry deviceFlowRegistry;
113 private GetFeaturesOutput mockedFeaturesOutput;
116 public void initialization() {
118 when(mockedPrimConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueue);
120 when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimConnectionContext);
121 when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
122 when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
124 when(requestContext.getXid()).thenReturn(new Xid(Uint32.valueOf(84L)));
125 when(requestContext.getFuture()).thenReturn(RpcResultBuilder.success().buildFuture());
126 when(mockedRequestContextStack.createRequestContext()).thenReturn(requestContext);
128 when(mockedDeviceInfo.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
130 when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
133 private AddFlowImpl mockAddFlow(final Uint8 version) {
134 when(mockedFeatures.getVersion()).thenReturn(version);
135 when(mockedFeaturesOutput.getVersion()).thenReturn(version);
136 when(mockedDeviceInfo.getVersion()).thenReturn(version);
138 final var convertorManager = ConvertorManagerFactory.createDefaultManager();
139 return new AddFlowImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
142 private RemoveFlowImpl mockRemoveFlow(final Uint8 version) {
143 when(mockedFeatures.getVersion()).thenReturn(version);
144 when(mockedFeaturesOutput.getVersion()).thenReturn(version);
145 when(mockedDeviceInfo.getVersion()).thenReturn(version);
147 final var convertorManager = ConvertorManagerFactory.createDefaultManager();
148 return new RemoveFlowImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
151 private UpdateFlowImpl mockUpdateFlow(final Uint8 version) {
152 when(mockedFeatures.getVersion()).thenReturn(version);
153 when(mockedFeaturesOutput.getVersion()).thenReturn(version);
154 when(mockedDeviceInfo.getVersion()).thenReturn(version);
156 final var convertorManager = ConvertorManagerFactory.createDefaultManager();
157 return new UpdateFlowImpl(mockedRequestContextStack, mockedDeviceContext, convertorManager);
161 public void testAddFlow() throws Exception {
162 addFlow(OFConstants.OFP_VERSION_1_0);
163 addFlow(OFConstants.OFP_VERSION_1_3);
167 public void testAddFlowFailCallback() throws Exception {
168 addFlowFailCallback(OFConstants.OFP_VERSION_1_0);
172 public void testAddFlowFailCallback1() throws Exception {
173 addFlowFailCallback(OFConstants.OFP_VERSION_1_3);
176 private void addFlowFailCallback(final Uint8 version) throws InterruptedException, ExecutionException {
177 AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
179 .setTableId(Uint8.ONE)
183 doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
184 .when(requestContext).getFuture();
186 final var rpcResultFuture = mockAddFlow(version).invoke(mockedAddFlowInput);
188 assertNotNull(rpcResultFuture);
189 final var addFlowOutputRpcResult = rpcResultFuture.get();
190 assertNotNull(addFlowOutputRpcResult);
191 assertFalse(addFlowOutputRpcResult.isSuccessful());
195 public void testRemoveFlowFailCallback() throws Exception {
196 removeFlowFailCallback(OFConstants.OFP_VERSION_1_0);
200 public void testRemoveFlowFailCallback1() throws Exception {
201 removeFlowFailCallback(OFConstants.OFP_VERSION_1_3);
204 private void removeFlowFailCallback(final Uint8 version) throws InterruptedException, ExecutionException {
205 RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
206 .setTableId(Uint8.ONE)
211 doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
212 .when(requestContext).getFuture();
214 final var rpcResultFuture = mockRemoveFlow(version).invoke(mockedRemoveFlowInput);
216 assertNotNull(rpcResultFuture);
217 final var removeFlowOutputRpcResult = rpcResultFuture.get();
218 assertNotNull(removeFlowOutputRpcResult);
219 assertFalse(removeFlowOutputRpcResult.isSuccessful());
223 public void testAddFlowWithItemLifecycle() throws Exception {
224 addFlow(OFConstants.OFP_VERSION_1_0);
225 addFlow(OFConstants.OFP_VERSION_1_3);
228 private void addFlow(final Uint8 version) throws ExecutionException, InterruptedException {
229 AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
231 .setTableId(Uint8.ONE)
234 var addFlow = mockAddFlow(version);
236 verifyOutput(addFlow.invoke(mockedAddFlowInput));
240 public void testRemoveFlow() throws Exception {
241 removeFlow(OFConstants.OFP_VERSION_1_0);
242 removeFlow(OFConstants.OFP_VERSION_1_3);
246 public void testRemoveFlowWithItemLifecycle() throws Exception {
247 removeFlow(OFConstants.OFP_VERSION_1_0);
248 removeFlow(OFConstants.OFP_VERSION_1_3);
251 private void removeFlow(final Uint8 version) throws Exception {
252 RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
254 .setTableId(Uint8.ONE)
258 final var removeFlow = mockRemoveFlow(version);
259 verifyOutput(removeFlow.invoke(mockedRemoveFlowInput));
263 public void testUpdateFlow() throws Exception {
264 updateFlow(OFConstants.OFP_VERSION_1_0);
265 updateFlow(OFConstants.OFP_VERSION_1_3);
269 public void testUpdateFlowWithItemLifecycle() throws Exception {
270 updateFlow(OFConstants.OFP_VERSION_1_0);
271 updateFlow(OFConstants.OFP_VERSION_1_3);
274 private void updateFlow(final Uint8 version) throws Exception {
275 UpdateFlowInput mockedUpdateFlowInput = mock(UpdateFlowInput.class);
276 UpdateFlowInput mockedUpdateFlowInput1 = mock(UpdateFlowInput.class);
278 UpdatedFlow mockedUpdateFlow = new UpdatedFlowBuilder()
280 .setTableId(Uint8.ONE)
283 UpdatedFlow mockedUpdateFlow1 = new UpdatedFlowBuilder()
285 .setTableId(Uint8.ONE)
286 .setPriority(Uint16.ONE)
289 when(mockedUpdateFlowInput.getUpdatedFlow()).thenReturn(mockedUpdateFlow);
290 when(mockedUpdateFlowInput1.getUpdatedFlow()).thenReturn(mockedUpdateFlow1);
292 FlowRef mockedFlowRef = mock(FlowRef.class);
293 doReturn(TABLE_II.child(Flow.class,
294 new FlowKey(new FlowId(DUMMY_FLOW_ID)))).when(mockedFlowRef).getValue();
295 when(mockedUpdateFlowInput.getFlowRef()).thenReturn(mockedFlowRef);
296 when(mockedUpdateFlowInput1.getFlowRef()).thenReturn(mockedFlowRef);
298 OriginalFlow mockedOriginalFlow = new OriginalFlowBuilder()
300 .setTableId(Uint8.ONE)
303 OriginalFlow mockedOriginalFlow1 = new OriginalFlowBuilder()
305 .setTableId(Uint8.ONE)
306 .setPriority(Uint16.TWO)
309 when(mockedUpdateFlowInput.getOriginalFlow()).thenReturn(mockedOriginalFlow);
310 when(mockedUpdateFlowInput1.getOriginalFlow()).thenReturn(mockedOriginalFlow1);
312 final var updateFlow = mockUpdateFlow(version);
313 verifyOutput(updateFlow.invoke(mockedUpdateFlowInput));
314 verifyOutput(updateFlow.invoke(mockedUpdateFlowInput1));
317 private static <T extends DataObject> void verifyOutput(final ListenableFuture<RpcResult<T>> rpcResultFuture)
318 throws ExecutionException, InterruptedException {
319 assertNotNull(rpcResultFuture);
320 final var addFlowOutputRpcResult = rpcResultFuture.get();
321 assertNotNull(addFlowOutputRpcResult);
322 assertTrue(addFlowOutputRpcResult.isSuccessful());