1 package org.opendaylight.openflowplugin.impl.device;
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.fail;
6 import java.util.ArrayList;
7 import java.util.Collections;
9 import java.util.concurrent.ExecutionException;
10 import java.util.concurrent.TimeUnit;
11 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.XidGenerator;
31 import org.opendaylight.openflowplugin.api.openflow.device.exception.DeviceDataException;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncOutputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncReply;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.FlowRemovedMask;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PacketInMask;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.async.body.grouping.PortStatusMask;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
48 import org.opendaylight.yangtools.yang.common.RpcError;
49 import org.opendaylight.yangtools.yang.common.RpcResult;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import com.google.common.util.concurrent.SettableFuture;
55 @RunWith(MockitoJUnitRunner.class)
56 public class DeviceContextImplTest {
57 private static final Logger LOG = LoggerFactory
58 .getLogger(DeviceContextImplTest.class);
63 DeviceContextImpl deviceContext;
65 RequestContext<GetAsyncReply> requestContext;
67 RequestContext<MultipartReply> requestContextMultiReply;
70 ConnectionContext connectionContext;
72 DeviceState deviceState;
74 DataBroker dataBroker;
78 ReadOnlyTransaction rTx;
80 BindingTransactionChain txChainFactory;
84 SettableFuture<RpcResult<GetAsyncReply>> settableFuture = SettableFuture.create();
85 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.createTransactionChain(Mockito.any(DeviceContextImpl.class))).thenReturn(txChainFactory);
90 Mockito.when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
92 deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker);
93 xid = deviceContext.getNextXid();
94 xidMulti = deviceContext.getNextXid();
95 xidGen = new XidGenerator();
98 @Test(expected=NullPointerException.class)
99 public void testDeviceContextImplConstructorNullConnectionContext() {
100 new DeviceContextImpl(null, deviceState, dataBroker);
103 @Test(expected=NullPointerException.class)
104 public void testDeviceContextImplConstructorNullDataBroker() {
105 new DeviceContextImpl(connectionContext, deviceState, null);
108 @Test(expected=NullPointerException.class)
109 public void testDeviceContextImplConstructorNullDeviceState() {
110 new DeviceContextImpl(connectionContext, null, dataBroker);
114 public void testGetDeviceState() {
115 final DeviceState deviceSt = deviceContext.getDeviceState();
116 Assert.assertNotNull(deviceSt);
117 Assert.assertEquals(deviceState, deviceSt);
121 public void testGetReadTransaction() {
122 final ReadTransaction readTx = deviceContext.getReadTransaction();
123 Assert.assertNotNull(readTx);
124 Assert.assertEquals(rTx, readTx);
128 public void testGetWriteTransaction() {
129 final WriteTransaction writeTx = deviceContext.getWriteTransaction();
130 Assert.assertNotNull(writeTx);
131 Assert.assertEquals(wTx, writeTx);
134 private static GetAsyncOutput createAsyncOutput(Xid xid) {
135 GetAsyncOutputBuilder asyncOutputBuilder = new GetAsyncOutputBuilder();
136 asyncOutputBuilder.setFlowRemovedMask(Collections.<FlowRemovedMask> emptyList());
137 asyncOutputBuilder.setPacketInMask(Collections.<PacketInMask> emptyList());
138 asyncOutputBuilder.setPortStatusMask(Collections.<PortStatusMask> emptyList());
139 asyncOutputBuilder.setVersion(OFConstants.OFP_VERSION_1_3);
140 asyncOutputBuilder.setXid(xid.getValue());
141 return asyncOutputBuilder.build();
145 public void testProcessReply() {
146 GetAsyncOutput asyncOutput = createAsyncOutput(xid);
147 LOG.info("Hooking RequestContext");
148 deviceContext.hookRequestCtx(xid, requestContext);
149 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
151 Assert.assertFalse(requestContext.getFuture().isDone());
152 LOG.info("Sending reply from device");
153 deviceContext.processReply(asyncOutput);
154 Assert.assertTrue(requestContext.getFuture().isDone());
156 LOG.info("Checking RequestContext.future");
158 Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
159 RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
160 GetAsyncOutput getAsyncOutput = (GetAsyncOutput) rpcResult.getResult();
161 assertEquals(asyncOutput.getVersion(), getAsyncOutput.getVersion());
162 } catch (InterruptedException | ExecutionException | TimeoutException e) {
163 LOG.error("Test failed when checking RequestContext.future", e);
166 Assert.assertTrue(deviceContext.getRequests().isEmpty());
169 private static Error createError(Xid xid) {
170 ErrorMessageBuilder errorMessageBuilder = new ErrorMessageBuilder();
171 errorMessageBuilder.setCode(42);
172 errorMessageBuilder.setCodeString("42");
173 errorMessageBuilder.setXid(xid.getValue());
174 return errorMessageBuilder.build();
178 public void testProcessReplyError() {
179 LOG.info("Hooking RequestContext");
180 deviceContext.hookRequestCtx(xid, requestContext);
181 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
183 Assert.assertFalse(requestContext.getFuture().isDone());
184 LOG.info("Sending error reply from device");
185 Error error = createError(xid);
186 deviceContext.processReply(error);
187 Assert.assertTrue(requestContext.getFuture().isDone());
189 LOG.info("Checking RequestContext.future");
191 Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
192 RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
193 Assert.assertFalse(rpcResult.isSuccessful());
194 List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
195 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
196 DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
197 Assert.assertEquals(error, cause.getError());
198 } catch (InterruptedException | ExecutionException | TimeoutException e) {
199 LOG.error("Test failed when checking RequestContext.future", e);
202 Assert.assertTrue(deviceContext.getRequests().isEmpty());
206 public void testProcessReplyList() {
207 LOG.info("Hooking RequestContext");
208 deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
209 Assert.assertEquals(requestContextMultiReply, deviceContext.getRequests().get(xidMulti.getValue()));
211 Assert.assertFalse(requestContextMultiReply.getFuture().isDone());
212 LOG.info("Sending reply from device");
213 deviceContext.processReply(xidMulti, createMultipartReplyList(xidMulti));
214 Assert.assertTrue(requestContextMultiReply.getFuture().isDone());
216 LOG.info("Checking RequestContext.future");
218 Object object = requestContextMultiReply.getFuture().get(1L, TimeUnit.SECONDS);
219 RpcResult<List<OfHeader>> rpcResult = (RpcResult<List<OfHeader>>) object;
220 List<OfHeader> multipartReplies = rpcResult.getResult();
221 List<OfHeader> expectedMpReplies = createMultipartReplyList(xidMulti);
222 assertEquals(expectedMpReplies, multipartReplies);
223 } catch (InterruptedException | ExecutionException | TimeoutException e) {
224 LOG.error("Test failed when checking RequestContext.future", e);
227 Assert.assertTrue(deviceContext.getRequests().isEmpty());
230 private static List<OfHeader> createMultipartReplyList(Xid xid) {
231 final MultipartReplyDesc descValue = new MultipartReplyDescBuilder().setHwDesc("hw-test-value").build();
232 final MultipartReplyDescCase replyBody = new MultipartReplyDescCaseBuilder()
233 .setMultipartReplyDesc(descValue).build();
234 List<OfHeader> multipartReplies = new ArrayList<OfHeader>();
235 multipartReplies.add(new MultipartReplyMessageBuilder()
236 .setMultipartReplyBody(replyBody)
237 .setXid(xid.getValue())
238 .setFlags(new MultipartRequestFlags(false))
240 multipartReplies.add(new MultipartReplyMessageBuilder()
241 .setMultipartReplyBody(replyBody)
242 .setXid(xid.getValue())
243 .setFlags(new MultipartRequestFlags(true))
245 return multipartReplies;
249 public void testProcessException() {
250 LOG.info("Hooking RequestContext");
251 deviceContext.hookRequestCtx(xid, requestContext);
252 Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
254 Assert.assertFalse(requestContext.getFuture().isDone());
256 LOG.info("Sending reply from device");
257 deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
258 Assert.assertTrue(requestContext.getFuture().isDone());
260 LOG.info("Checking RequestContext.future");
262 Object object = requestContext.getFuture().get(1L, TimeUnit.SECONDS);
263 RpcResult<OfHeader> rpcResult = (RpcResult<OfHeader>) object;
264 Assert.assertFalse(rpcResult.isSuccessful());
265 List<RpcError> errors = (List<RpcError>) rpcResult.getErrors();
266 Assert.assertTrue(errors.get(0).getCause() instanceof DeviceDataException);
267 DeviceDataException cause = (DeviceDataException) errors.get(0).getCause();
268 Assert.assertTrue(cause.getCause() instanceof NullPointerException);
269 } catch (InterruptedException | ExecutionException | TimeoutException e) {
270 LOG.error("Test failed when checking RequestContext.future", e);
273 Assert.assertTrue(deviceContext.getRequests().isEmpty());