connection adapter is set to autoread = false when notofications are not handled
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / device / DeviceContextImplTest.java
1 package org.opendaylight.openflowplugin.impl.device;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.fail;
5
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;
54
55 @RunWith(MockitoJUnitRunner.class)
56 public class DeviceContextImplTest {
57     private static final Logger LOG = LoggerFactory
58             .getLogger(DeviceContextImplTest.class);
59     Xid xid;
60     Xid xidMulti;
61     DeviceContextImpl deviceContext;
62     TransactionChainManager txChainManager;
63     @Mock
64     RequestContext<GetAsyncReply> requestContext;
65     @Mock
66     RequestContext<MultipartReply> requestContextMultiReply;
67
68     @Mock
69     ConnectionContext connectionContext;
70     @Mock
71     DeviceState deviceState;
72     @Mock
73     DataBroker dataBroker;
74     @Mock
75     WriteTransaction wTx;
76     @Mock
77     ReadOnlyTransaction rTx;
78     @Mock
79     BindingTransactionChain txChainFactory;
80     @Mock
81     HashedWheelTimer timer;
82     @Mock
83     MessageIntelligenceAgency messageIntelligenceAgency;
84     @Mock
85     ThrottledConnectionsHolder throttledConnectionsHolder;
86
87     @Before
88     public void setUp() {
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);
97
98         deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
99         xid = deviceContext.getNextXid();
100         xidMulti = deviceContext.getNextXid();
101     }
102
103     @Test(expected = NullPointerException.class)
104     public void testDeviceContextImplConstructorNullConnectionContext() {
105         new DeviceContextImpl(null, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
106     }
107
108     @Test(expected = NullPointerException.class)
109     public void testDeviceContextImplConstructorNullDataBroker() {
110         new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency,throttledConnectionsHolder);
111     }
112
113     @Test(expected = NullPointerException.class)
114     public void testDeviceContextImplConstructorNullDeviceState() {
115         new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
116     }
117
118     @Test(expected = NullPointerException.class)
119     public void testDeviceContextImplConstructorNullTimer() {
120         new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency,throttledConnectionsHolder);
121     }
122
123     @Test
124     public void testGetDeviceState() {
125         final DeviceState deviceSt = deviceContext.getDeviceState();
126         Assert.assertNotNull(deviceSt);
127         Assert.assertEquals(deviceState, deviceSt);
128     }
129
130     @Test
131     public void testGetReadTransaction() {
132         final ReadTransaction readTx = deviceContext.getReadTransaction();
133         Assert.assertNotNull(readTx);
134         Assert.assertEquals(rTx, readTx);
135     }
136
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();
145     }
146
147     @Test
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));
153
154         Assert.assertFalse(requestContext.getFuture().isDone());
155         LOG.info("Sending reply from device");
156         deviceContext.processReply(asyncOutput);
157         Assert.assertTrue(requestContext.getFuture().isDone());
158
159         LOG.info("Checking RequestContext.future");
160         try {
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);
167             fail("fail");
168         }
169         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
170     }
171
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();
178     }
179
180     @Test
181     public void testProcessReplyError() {
182         LOG.info("Hooking RequestContext");
183         deviceContext.hookRequestCtx(xid, requestContext);
184         Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
185
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());
191
192         LOG.info("Checking RequestContext.future");
193         try {
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);
203             fail("fail");
204         }
205         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
206     }
207
208     @Test
209     public void testProcessReplyList() {
210         LOG.info("Hooking RequestContext");
211         deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
212         Assert.assertEquals(requestContextMultiReply, deviceContext.lookupRequest(xidMulti));
213
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());
218
219         LOG.info("Checking RequestContext.future");
220         try {
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);
228             fail("fail");
229         }
230         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
231     }
232
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))
242                 .build());
243         multipartReplies.add(new MultipartReplyMessageBuilder()
244                 .setMultipartReplyBody(replyBody)
245                 .setXid(xid.getValue())
246                 .setFlags(new MultipartRequestFlags(true))
247                 .build());
248         return multipartReplies;
249     }
250
251     @Test
252     public void testProcessException() {
253         LOG.info("Hooking RequestContext");
254         deviceContext.hookRequestCtx(xid, requestContext);
255         Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
256
257         Assert.assertFalse(requestContext.getFuture().isDone());
258
259         LOG.info("Sending reply from device");
260         deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
261         Assert.assertTrue(requestContext.getFuture().isDone());
262
263         LOG.info("Checking RequestContext.future");
264         try {
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);
274             fail("fail");
275         }
276         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
277     }
278
279 }