1 package org.opendaylight.openflowplugin.impl.device;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.fail;
5 import com.google.common.util.concurrent.SettableFuture;
6 import io.netty.util.HashedWheelTimer;
7 import java.util.ArrayList;
8 import java.util.Collections;
10 import java.util.concurrent.ExecutionException;
11 import java.util.concurrent.TimeUnit;
12 import java.util.concurrent.TimeoutException;
13 import org.junit.Assert;
14 import org.junit.Before;
15 import org.junit.Test;
16 import org.junit.runner.RunWith;
17 import org.mockito.Mock;
18 import org.mockito.Mockito;
19 import org.mockito.runners.MockitoJUnitRunner;
20 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.openflowplugin.api.OFConstants;
26 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
27 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
28 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
29 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
30 import org.opendaylight.openflowplugin.api.openflow.device.exception.DeviceDataException;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.FlowRemovedMask;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PacketInMask;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PortStatusMask;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
47 import org.opendaylight.yangtools.yang.common.RpcError;
48 import org.opendaylight.yangtools.yang.common.RpcResult;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 @RunWith(MockitoJUnitRunner.class)
53 public class DeviceContextImplTest {
54 private static final Logger LOG = LoggerFactory
55 .getLogger(DeviceContextImplTest.class);
58 DeviceContextImpl deviceContext;
59 TransactionChainManager txChainManager;
61 RequestContext<GetAsyncReply> requestContext;
63 RequestContext<MultipartReply> requestContextMultiReply;
66 ConnectionContext connectionContext;
68 DeviceState deviceState;
70 DataBroker dataBroker;
74 ReadOnlyTransaction rTx;
76 BindingTransactionChain txChainFactory;
78 HashedWheelTimer timer;
82 Mockito.when(dataBroker.createTransactionChain(Mockito.any(TransactionChainManager.class))).thenReturn(txChainFactory);
83 txChainManager = new TransactionChainManager(dataBroker, timer, 5L);
84 final SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
85 final SettableFuture<RpcResult<MultipartReply>> settableFutureMultiReply = SettableFuture.create();
86 Mockito.when(requestContext.getFuture()).thenReturn(settableFuture);
87 Mockito.when(requestContextMultiReply.getFuture()).thenReturn(settableFutureMultiReply);
88 Mockito.when(txChainFactory.newWriteOnlyTransaction()).thenReturn(wTx);
89 Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
91 deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer);
92 xid = deviceContext.getNextXid();
93 xidMulti = deviceContext.getNextXid();
96 @Test(expected = NullPointerException.class)
97 public void testDeviceContextImplConstructorNullConnectionContext() {
98 new DeviceContextImpl(null, deviceState, dataBroker, timer);
101 @Test(expected = NullPointerException.class)
102 public void testDeviceContextImplConstructorNullDataBroker() {
103 new DeviceContextImpl(connectionContext, deviceState, null, timer);
106 @Test(expected = NullPointerException.class)
107 public void testDeviceContextImplConstructorNullDeviceState() {
108 new DeviceContextImpl(connectionContext, null, dataBroker, timer);
111 @Test(expected = NullPointerException.class)
112 public void testDeviceContextImplConstructorNullTimer() {
113 new DeviceContextImpl(null, deviceState, dataBroker, null);
117 public void testGetDeviceState() {
118 final DeviceState deviceSt = deviceContext.getDeviceState();
119 Assert.assertNotNull(deviceSt);
120 Assert.assertEquals(deviceState, deviceSt);
124 public void testGetReadTransaction() {
125 final ReadTransaction readTx = deviceContext.getReadTransaction();
126 Assert.assertNotNull(readTx);
127 Assert.assertEquals(rTx, readTx);
130 private static GetAsyncOutput createAsyncOutput(final Xid xid) {
131 final GetAsyncOutputBuilder asyncOutputBuilder = new GetAsyncOutputBuilder();
132 asyncOutputBuilder.setFlowRemovedMask(Collections.<FlowRemovedMask> emptyList());
133 asyncOutputBuilder.setPacketInMask(Collections.<PacketInMask> emptyList());
134 asyncOutputBuilder.setPortStatusMask(Collections.<PortStatusMask> emptyList());
135 asyncOutputBuilder.setVersion(OFConstants.OFP_VERSION_1_3);
136 asyncOutputBuilder.setXid(xid.getValue());
137 return asyncOutputBuilder.build();
141 public void testProcessReply() {
142 final GetAsyncOutput asyncOutput = createAsyncOutput(xid);
143 LOG.info("Hooking RequestContext");
144 deviceContext.hookRequestCtx(xid, requestContext);
145 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
147 Assert.assertFalse(requestContext.getFuture().isDone());
148 LOG.info("Sending reply from device");
149 deviceContext.processReply(asyncOutput);
150 Assert.assertTrue(requestContext.getFuture().isDone());
152 LOG.info("Checking RequestContext.future");
154 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
155 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
156 final GetAsyncOutput getAsyncOutput = (GetAsyncOutput) rpcResult.getResult();
157 assertEquals(asyncOutput.getVersion(), getAsyncOutput.getVersion());
158 } catch (InterruptedException | ExecutionException | TimeoutException e) {
159 LOG.error("Test failed when checking RequestContext.future", e);
162 Assert.assertTrue(deviceContext.getRequests().isEmpty());
165 private static Error createError(final Xid xid) {
166 final ErrorMessageBuilder errorMessageBuilder = new ErrorMessageBuilder();
167 errorMessageBuilder.setCode(42);
168 errorMessageBuilder.setCodeString("42");
169 errorMessageBuilder.setXid(xid.getValue());
170 return errorMessageBuilder.build();
174 public void testProcessReplyError() {
175 LOG.info("Hooking RequestContext");
176 deviceContext.hookRequestCtx(xid, requestContext);
177 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
179 Assert.assertFalse(requestContext.getFuture().isDone());
180 LOG.info("Sending error reply from device");
181 final Error error = createError(xid);
182 deviceContext.processReply(error);
183 Assert.assertTrue(requestContext.getFuture().isDone());
185 LOG.info("Checking RequestContext.future");
187 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
188 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
189 Assert.assertFalse(rpcResult.isSuccessful());
190 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
191 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
192 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
193 Assert.assertEquals(error, cause.getError());
194 } catch (InterruptedException | ExecutionException | TimeoutException e) {
195 LOG.error("Test failed when checking RequestContext.future", e);
198 Assert.assertTrue(deviceContext.getRequests().isEmpty());
202 public void testProcessReplyList() {
203 LOG.info("Hooking RequestContext");
204 deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
205 Assert.assertEquals(requestContextMultiReply, deviceContext.getRequests().get(xidMulti.getValue()));
207 Assert.assertFalse(requestContextMultiReply.getFuture().isDone());
208 LOG.info("Sending reply from device");
209 deviceContext.processReply(xidMulti, createMultipartReplyList(xidMulti));
210 Assert.assertTrue(requestContextMultiReply.getFuture().isDone());
212 LOG.info("Checking RequestContext.future");
214 final Object object = requestContextMultiReply.getFuture().get(1L, TimeUnit.SECONDS);
215 final RpcResult<List<OfHeader>> rpcResult = (RpcResult<List<OfHeader>>) object;
216 final List<OfHeader> multipartReplies = rpcResult.getResult();
217 final List<MultipartReply> expectedMpReplies = createMultipartReplyList(xidMulti);
218 assertEquals(expectedMpReplies, multipartReplies);
219 } catch (InterruptedException | ExecutionException | TimeoutException e) {
220 LOG.error("Test failed when checking RequestContext.future", e);
223 Assert.assertTrue(deviceContext.getRequests().isEmpty());
226 private static List<MultipartReply> createMultipartReplyList(final Xid xid) {
227 final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc("hw-test-value").build();
228 final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
229 .setMultipartReplyDesc(descValue).build();
230 final List<MultipartReply> multipartReplies = new ArrayList<>();
231 multipartReplies.add(new MultipartReplyMessageBuilder()
232 .setMultipartReplyBody(replyBody)
233 .setXid(xid.getValue())
234 .setFlags(new MultipartRequestFlags(false))
236 multipartReplies.add(new MultipartReplyMessageBuilder()
237 .setMultipartReplyBody(replyBody)
238 .setXid(xid.getValue())
239 .setFlags(new MultipartRequestFlags(true))
241 return multipartReplies;
245 public void testProcessException() {
246 LOG.info("Hooking RequestContext");
247 deviceContext.hookRequestCtx(xid, requestContext);
248 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
250 Assert.assertFalse(requestContext.getFuture().isDone());
252 LOG.info("Sending reply from device");
253 deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
254 Assert.assertTrue(requestContext.getFuture().isDone());
256 LOG.info("Checking RequestContext.future");
258 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
259 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
260 Assert.assertFalse(rpcResult.isSuccessful());
261 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
262 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
263 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
264 Assert.assertTrue(cause.getCause() instanceof NullPointerException);
265 } catch (InterruptedException | ExecutionException | TimeoutException e) {
266 LOG.error("Test failed when checking RequestContext.future", e);
269 Assert.assertTrue(deviceContext.getRequests().isEmpty());