1 package org.opendaylight.openflowplugin.impl.device;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.fail;
6 import com.google.common.util.concurrent.SettableFuture;
7 import io.netty.util.HashedWheelTimer;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.List;
11 import java.util.concurrent.ExecutionException;
12 import java.util.concurrent.TimeUnit;
13 import java.util.concurrent.TimeoutException;
14 import java.util.concurrent.atomic.AtomicLong;
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.Mock;
20 import org.mockito.Mockito;
21 import org.mockito.runners.MockitoJUnitRunner;
22 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.openflowplugin.api.OFConstants;
28 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
29 import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
30 import org.opendaylight.openflowplugin.api.openflow.connection.ThrottledNotificationsOfferer;
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.Xid;
34 import org.opendaylight.openflowplugin.api.openflow.device.exception.DeviceDataException;
35 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.FlowRemovedMask;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PacketInMask;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PortStatusMask;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
52 import org.opendaylight.yangtools.yang.common.RpcError;
53 import org.opendaylight.yangtools.yang.common.RpcResult;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 @RunWith(MockitoJUnitRunner.class)
58 public class DeviceContextImplTest {
59 private static final Logger LOG = LoggerFactory
60 .getLogger(DeviceContextImplTest.class);
63 DeviceContextImpl deviceContext;
64 TransactionChainManager txChainManager;
66 RequestContext<GetAsyncReply> requestContext;
68 RequestContext<MultipartReply> requestContextMultiReply;
71 ConnectionContext connectionContext;
73 DeviceState deviceState;
75 DataBroker dataBroker;
79 ReadOnlyTransaction rTx;
81 BindingTransactionChain txChainFactory;
83 HashedWheelTimer timer;
85 MessageIntelligenceAgency messageIntelligenceAgency;
87 ThrottledNotificationsOfferer throttledConnectionsHolder;
89 OutboundQueueProvider outboundQueueProvider;
91 private AtomicLong atomicLong = new AtomicLong(0);
94 Mockito.when(dataBroker.createTransactionChain(Mockito.any(TransactionChainManager.class))).thenReturn(txChainFactory);
95 txChainManager = new TransactionChainManager(dataBroker, timer, 5L, 5L);
96 final SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
97 final SettableFuture<RpcResult<MultipartReply>> settableFutureMultiReply = SettableFuture.create();
98 Mockito.when(requestContext.getFuture()).thenReturn(settableFuture);
99 Mockito.when(requestContextMultiReply.getFuture()).thenReturn(settableFutureMultiReply);
100 Mockito.when(txChainFactory.newWriteOnlyTransaction()).thenReturn(wTx);
101 Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
102 Mockito.when(connectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider);
103 deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
105 xid = new Xid(atomicLong.incrementAndGet());
106 xidMulti = new Xid(atomicLong.incrementAndGet());
109 @Test(expected = NullPointerException.class)
110 public void testDeviceContextImplConstructorNullConnectionContext() {
111 new DeviceContextImpl(null, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
114 @Test(expected = NullPointerException.class)
115 public void testDeviceContextImplConstructorNullDataBroker() {
116 new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency,throttledConnectionsHolder);
119 @Test(expected = NullPointerException.class)
120 public void testDeviceContextImplConstructorNullDeviceState() {
121 new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
124 @Test(expected = NullPointerException.class)
125 public void testDeviceContextImplConstructorNullTimer() {
126 new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency,throttledConnectionsHolder);
130 public void testGetDeviceState() {
131 final DeviceState deviceSt = deviceContext.getDeviceState();
132 Assert.assertNotNull(deviceSt);
133 Assert.assertEquals(deviceState, deviceSt);
137 public void testGetReadTransaction() {
138 final ReadTransaction readTx = deviceContext.getReadTransaction();
139 Assert.assertNotNull(readTx);
140 Assert.assertEquals(rTx, readTx);
143 private static GetAsyncOutput createAsyncOutput(final Xid xid) {
144 final GetAsyncOutputBuilder asyncOutputBuilder = new GetAsyncOutputBuilder();
145 asyncOutputBuilder.setFlowRemovedMask(Collections.<FlowRemovedMask>emptyList());
146 asyncOutputBuilder.setPacketInMask(Collections.<PacketInMask>emptyList());
147 asyncOutputBuilder.setPortStatusMask(Collections.<PortStatusMask>emptyList());
148 asyncOutputBuilder.setVersion(OFConstants.OFP_VERSION_1_3);
149 asyncOutputBuilder.setXid(xid.getValue());
150 return asyncOutputBuilder.build();
154 public void testProcessReply() {
155 final GetAsyncOutput asyncOutput = createAsyncOutput(xid);
156 LOG.info("Hooking RequestContext");
157 deviceContext.hookRequestCtx(xid, requestContext);
158 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
160 Assert.assertFalse(requestContext.getFuture().isDone());
161 LOG.info("Sending reply from device");
162 deviceContext.processReply(asyncOutput);
163 Assert.assertTrue(requestContext.getFuture().isDone());
165 LOG.info("Checking RequestContext.future");
167 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
168 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
169 final GetAsyncOutput getAsyncOutput = (GetAsyncOutput) rpcResult.getResult();
170 assertEquals(asyncOutput.getVersion(), getAsyncOutput.getVersion());
171 } catch (InterruptedException | ExecutionException | TimeoutException e) {
172 LOG.error("Test failed when checking RequestContext.future", e);
175 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
178 private static Error createError(final Xid xid) {
179 final ErrorMessageBuilder errorMessageBuilder = new ErrorMessageBuilder();
180 errorMessageBuilder.setCode(42);
181 errorMessageBuilder.setCodeString("42");
182 errorMessageBuilder.setXid(xid.getValue());
183 return errorMessageBuilder.build();
187 public void testProcessReplyError() {
188 LOG.info("Hooking RequestContext");
189 deviceContext.hookRequestCtx(xid, requestContext);
190 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
192 Assert.assertFalse(requestContext.getFuture().isDone());
193 LOG.info("Sending error reply from device");
194 final Error error = createError(xid);
195 deviceContext.processReply(error);
196 Assert.assertTrue(requestContext.getFuture().isDone());
198 LOG.info("Checking RequestContext.future");
200 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
201 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
202 Assert.assertFalse(rpcResult.isSuccessful());
203 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
204 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
205 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
206 Assert.assertEquals(error, cause.getError());
207 } catch (InterruptedException | ExecutionException | TimeoutException e) {
208 LOG.error("Test failed when checking RequestContext.future", e);
211 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
215 public void testProcessReplyList() {
216 LOG.info("Hooking RequestContext");
217 deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
218 Assert.assertEquals(requestContextMultiReply, deviceContext.lookupRequest(xidMulti));
220 Assert.assertFalse(requestContextMultiReply.getFuture().isDone());
221 LOG.info("Sending reply from device");
222 deviceContext.processReply(xidMulti, createMultipartReplyList(xidMulti));
223 Assert.assertTrue(requestContextMultiReply.getFuture().isDone());
225 LOG.info("Checking RequestContext.future");
227 final Object object = requestContextMultiReply.getFuture().get(1L, TimeUnit.SECONDS);
228 final RpcResult<List<OfHeader>> rpcResult = (RpcResult<List<OfHeader>>) object;
229 final List<OfHeader> multipartReplies = rpcResult.getResult();
230 final List<MultipartReply> expectedMpReplies = createMultipartReplyList(xidMulti);
231 assertEquals(expectedMpReplies, multipartReplies);
232 } catch (InterruptedException | ExecutionException | TimeoutException e) {
233 LOG.error("Test failed when checking RequestContext.future", e);
236 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
239 private static List<MultipartReply> createMultipartReplyList(final Xid xid) {
240 final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc("hw-test-value").build();
241 final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
242 .setMultipartReplyDesc(descValue).build();
243 final List<MultipartReply> multipartReplies = new ArrayList<>();
244 multipartReplies.add(new MultipartReplyMessageBuilder()
245 .setMultipartReplyBody(replyBody)
246 .setXid(xid.getValue())
247 .setFlags(new MultipartRequestFlags(false))
249 multipartReplies.add(new MultipartReplyMessageBuilder()
250 .setMultipartReplyBody(replyBody)
251 .setXid(xid.getValue())
252 .setFlags(new MultipartRequestFlags(true))
254 return multipartReplies;
258 public void testProcessException() {
259 LOG.info("Hooking RequestContext");
260 deviceContext.hookRequestCtx(xid, requestContext);
261 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
263 Assert.assertFalse(requestContext.getFuture().isDone());
265 LOG.info("Sending reply from device");
266 deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
267 Assert.assertTrue(requestContext.getFuture().isDone());
269 LOG.info("Checking RequestContext.future");
271 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
272 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
273 Assert.assertFalse(rpcResult.isSuccessful());
274 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
275 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
276 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
277 Assert.assertTrue(cause.getCause() instanceof NullPointerException);
278 } catch (InterruptedException | ExecutionException | TimeoutException e) {
279 LOG.error("Test failed when checking RequestContext.future", e);
282 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);