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 org.junit.Assert;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 import org.mockito.Mock;
19 import org.mockito.Mockito;
20 import org.mockito.runners.MockitoJUnitRunner;
21 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.openflowplugin.api.OFConstants;
27 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
28 import org.opendaylight.openflowplugin.api.openflow.connection.ThrottledConnectionsHolder;
29 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
30 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
31 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
32 import org.opendaylight.openflowplugin.api.openflow.device.exception.DeviceDataException;
33 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.FlowRemovedMask;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PacketInMask;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PortStatusMask;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
50 import org.opendaylight.yangtools.yang.common.RpcError;
51 import org.opendaylight.yangtools.yang.common.RpcResult;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 @RunWith(MockitoJUnitRunner.class)
56 public class DeviceContextImplTest {
57 private static final Logger LOG = LoggerFactory
58 .getLogger(DeviceContextImplTest.class);
61 DeviceContextImpl deviceContext;
62 TransactionChainManager txChainManager;
64 RequestContext<GetAsyncReply> requestContext;
66 RequestContext<MultipartReply> requestContextMultiReply;
69 ConnectionContext connectionContext;
71 DeviceState deviceState;
73 DataBroker dataBroker;
77 ReadOnlyTransaction rTx;
79 BindingTransactionChain txChainFactory;
81 HashedWheelTimer timer;
83 MessageIntelligenceAgency messageIntelligenceAgency;
85 ThrottledConnectionsHolder throttledConnectionsHolder;
89 Mockito.when(dataBroker.createTransactionChain(Mockito.any(TransactionChainManager.class))).thenReturn(txChainFactory);
90 txChainManager = new TransactionChainManager(dataBroker, timer, 5L, 5L);
91 final SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
92 final SettableFuture<RpcResult<MultipartReply>> settableFutureMultiReply = SettableFuture.create();
93 Mockito.when(requestContext.getFuture()).thenReturn(settableFuture);
94 Mockito.when(requestContextMultiReply.getFuture()).thenReturn(settableFutureMultiReply);
95 Mockito.when(txChainFactory.newWriteOnlyTransaction()).thenReturn(wTx);
96 Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
98 deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
99 xid = deviceContext.getNextXid();
100 xidMulti = deviceContext.getNextXid();
103 @Test(expected = NullPointerException.class)
104 public void testDeviceContextImplConstructorNullConnectionContext() {
105 new DeviceContextImpl(null, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
108 @Test(expected = NullPointerException.class)
109 public void testDeviceContextImplConstructorNullDataBroker() {
110 new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency,throttledConnectionsHolder);
113 @Test(expected = NullPointerException.class)
114 public void testDeviceContextImplConstructorNullDeviceState() {
115 new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
118 @Test(expected = NullPointerException.class)
119 public void testDeviceContextImplConstructorNullTimer() {
120 new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency,throttledConnectionsHolder);
124 public void testGetDeviceState() {
125 final DeviceState deviceSt = deviceContext.getDeviceState();
126 Assert.assertNotNull(deviceSt);
127 Assert.assertEquals(deviceState, deviceSt);
131 public void testGetReadTransaction() {
132 final ReadTransaction readTx = deviceContext.getReadTransaction();
133 Assert.assertNotNull(readTx);
134 Assert.assertEquals(rTx, readTx);
137 private static GetAsyncOutput createAsyncOutput(final Xid xid) {
138 final GetAsyncOutputBuilder asyncOutputBuilder = new GetAsyncOutputBuilder();
139 asyncOutputBuilder.setFlowRemovedMask(Collections.<FlowRemovedMask>emptyList());
140 asyncOutputBuilder.setPacketInMask(Collections.<PacketInMask>emptyList());
141 asyncOutputBuilder.setPortStatusMask(Collections.<PortStatusMask>emptyList());
142 asyncOutputBuilder.setVersion(OFConstants.OFP_VERSION_1_3);
143 asyncOutputBuilder.setXid(xid.getValue());
144 return asyncOutputBuilder.build();
148 public void testProcessReply() {
149 final GetAsyncOutput asyncOutput = createAsyncOutput(xid);
150 LOG.info("Hooking RequestContext");
151 deviceContext.hookRequestCtx(xid, requestContext);
152 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
154 Assert.assertFalse(requestContext.getFuture().isDone());
155 LOG.info("Sending reply from device");
156 deviceContext.processReply(asyncOutput);
157 Assert.assertTrue(requestContext.getFuture().isDone());
159 LOG.info("Checking RequestContext.future");
161 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
162 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
163 final GetAsyncOutput getAsyncOutput = (GetAsyncOutput) rpcResult.getResult();
164 assertEquals(asyncOutput.getVersion(), getAsyncOutput.getVersion());
165 } catch (InterruptedException | ExecutionException | TimeoutException e) {
166 LOG.error("Test failed when checking RequestContext.future", e);
169 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
172 private static Error createError(final Xid xid) {
173 final ErrorMessageBuilder errorMessageBuilder = new ErrorMessageBuilder();
174 errorMessageBuilder.setCode(42);
175 errorMessageBuilder.setCodeString("42");
176 errorMessageBuilder.setXid(xid.getValue());
177 return errorMessageBuilder.build();
181 public void testProcessReplyError() {
182 LOG.info("Hooking RequestContext");
183 deviceContext.hookRequestCtx(xid, requestContext);
184 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
186 Assert.assertFalse(requestContext.getFuture().isDone());
187 LOG.info("Sending error reply from device");
188 final Error error = createError(xid);
189 deviceContext.processReply(error);
190 Assert.assertTrue(requestContext.getFuture().isDone());
192 LOG.info("Checking RequestContext.future");
194 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
195 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
196 Assert.assertFalse(rpcResult.isSuccessful());
197 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
198 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
199 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
200 Assert.assertEquals(error, cause.getError());
201 } catch (InterruptedException | ExecutionException | TimeoutException e) {
202 LOG.error("Test failed when checking RequestContext.future", e);
205 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
209 public void testProcessReplyList() {
210 LOG.info("Hooking RequestContext");
211 deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
212 Assert.assertEquals(requestContextMultiReply, deviceContext.lookupRequest(xidMulti));
214 Assert.assertFalse(requestContextMultiReply.getFuture().isDone());
215 LOG.info("Sending reply from device");
216 deviceContext.processReply(xidMulti, createMultipartReplyList(xidMulti));
217 Assert.assertTrue(requestContextMultiReply.getFuture().isDone());
219 LOG.info("Checking RequestContext.future");
221 final Object object = requestContextMultiReply.getFuture().get(1L, TimeUnit.SECONDS);
222 final RpcResult<List<OfHeader>> rpcResult = (RpcResult<List<OfHeader>>) object;
223 final List<OfHeader> multipartReplies = rpcResult.getResult();
224 final List<MultipartReply> expectedMpReplies = createMultipartReplyList(xidMulti);
225 assertEquals(expectedMpReplies, multipartReplies);
226 } catch (InterruptedException | ExecutionException | TimeoutException e) {
227 LOG.error("Test failed when checking RequestContext.future", e);
230 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
233 private static List<MultipartReply> createMultipartReplyList(final Xid xid) {
234 final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc("hw-test-value").build();
235 final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
236 .setMultipartReplyDesc(descValue).build();
237 final List<MultipartReply> multipartReplies = new ArrayList<>();
238 multipartReplies.add(new MultipartReplyMessageBuilder()
239 .setMultipartReplyBody(replyBody)
240 .setXid(xid.getValue())
241 .setFlags(new MultipartRequestFlags(false))
243 multipartReplies.add(new MultipartReplyMessageBuilder()
244 .setMultipartReplyBody(replyBody)
245 .setXid(xid.getValue())
246 .setFlags(new MultipartRequestFlags(true))
248 return multipartReplies;
252 public void testProcessException() {
253 LOG.info("Hooking RequestContext");
254 deviceContext.hookRequestCtx(xid, requestContext);
255 Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
257 Assert.assertFalse(requestContext.getFuture().isDone());
259 LOG.info("Sending reply from device");
260 deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
261 Assert.assertTrue(requestContext.getFuture().isDone());
263 LOG.info("Checking RequestContext.future");
265 final Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
266 final RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
267 Assert.assertFalse(rpcResult.isSuccessful());
268 final List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
269 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
270 final DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
271 Assert.assertTrue(cause.getCause() instanceof NullPointerException);
272 } catch (InterruptedException | ExecutionException | TimeoutException e) {
273 LOG.error("Test failed when checking RequestContext.future", e);
276 Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);