2bd9bbf590291ad0d1f790a41ff13217ae15a1b6
[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 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;
56
57 @RunWith(MockitoJUnitRunner.class)
58 public class DeviceContextImplTest {
59     private static final Logger LOG = LoggerFactory
60             .getLogger(DeviceContextImplTest.class);
61     Xid xid;
62     Xid xidMulti;
63     DeviceContextImpl deviceContext;
64     TransactionChainManager txChainManager;
65     @Mock
66     RequestContext<GetAsyncReply> requestContext;
67     @Mock
68     RequestContext<MultipartReply> requestContextMultiReply;
69
70     @Mock
71     ConnectionContext connectionContext;
72     @Mock
73     DeviceState deviceState;
74     @Mock
75     DataBroker dataBroker;
76     @Mock
77     WriteTransaction wTx;
78     @Mock
79     ReadOnlyTransaction rTx;
80     @Mock
81     BindingTransactionChain txChainFactory;
82     @Mock
83     HashedWheelTimer timer;
84     @Mock
85     MessageIntelligenceAgency messageIntelligenceAgency;
86     @Mock
87     ThrottledNotificationsOfferer throttledConnectionsHolder;
88     @Mock
89     OutboundQueueProvider outboundQueueProvider;
90
91     private AtomicLong atomicLong = new AtomicLong(0);
92     @Before
93     public void setUp() {
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);
104
105         xid = new Xid(atomicLong.incrementAndGet());
106         xidMulti = new Xid(atomicLong.incrementAndGet());
107     }
108
109     @Test(expected = NullPointerException.class)
110     public void testDeviceContextImplConstructorNullConnectionContext() {
111         new DeviceContextImpl(null, deviceState, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
112     }
113
114     @Test(expected = NullPointerException.class)
115     public void testDeviceContextImplConstructorNullDataBroker() {
116         new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency,throttledConnectionsHolder);
117     }
118
119     @Test(expected = NullPointerException.class)
120     public void testDeviceContextImplConstructorNullDeviceState() {
121         new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency,throttledConnectionsHolder);
122     }
123
124     @Test(expected = NullPointerException.class)
125     public void testDeviceContextImplConstructorNullTimer() {
126         new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency,throttledConnectionsHolder);
127     }
128
129     @Test
130     public void testGetDeviceState() {
131         final DeviceState deviceSt = deviceContext.getDeviceState();
132         Assert.assertNotNull(deviceSt);
133         Assert.assertEquals(deviceState, deviceSt);
134     }
135
136     @Test
137     public void testGetReadTransaction() {
138         final ReadTransaction readTx = deviceContext.getReadTransaction();
139         Assert.assertNotNull(readTx);
140         Assert.assertEquals(rTx, readTx);
141     }
142
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();
151     }
152
153     @Test
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));
159
160         Assert.assertFalse(requestContext.getFuture().isDone());
161         LOG.info("Sending reply from device");
162         deviceContext.processReply(asyncOutput);
163         Assert.assertTrue(requestContext.getFuture().isDone());
164
165         LOG.info("Checking RequestContext.future");
166         try {
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);
173             fail("fail");
174         }
175         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
176     }
177
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();
184     }
185
186     @Test
187     public void testProcessReplyError() {
188         LOG.info("Hooking RequestContext");
189         deviceContext.hookRequestCtx(xid, requestContext);
190         Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
191
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());
197
198         LOG.info("Checking RequestContext.future");
199         try {
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);
209             fail("fail");
210         }
211         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
212     }
213
214     @Test
215     public void testProcessReplyList() {
216         LOG.info("Hooking RequestContext");
217         deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
218         Assert.assertEquals(requestContextMultiReply, deviceContext.lookupRequest(xidMulti));
219
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());
224
225         LOG.info("Checking RequestContext.future");
226         try {
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);
234             fail("fail");
235         }
236         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
237     }
238
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))
248                 .build());
249         multipartReplies.add(new MultipartReplyMessageBuilder()
250                 .setMultipartReplyBody(replyBody)
251                 .setXid(xid.getValue())
252                 .setFlags(new MultipartRequestFlags(true))
253                 .build());
254         return multipartReplies;
255     }
256
257     @Test
258     public void testProcessException() {
259         LOG.info("Hooking RequestContext");
260         deviceContext.hookRequestCtx(xid, requestContext);
261         Assert.assertEquals(requestContext, deviceContext.lookupRequest(xid));
262
263         Assert.assertFalse(requestContext.getFuture().isDone());
264
265         LOG.info("Sending reply from device");
266         deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
267         Assert.assertTrue(requestContext.getFuture().isDone());
268
269         LOG.info("Checking RequestContext.future");
270         try {
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);
280             fail("fail");
281         }
282         Assert.assertTrue(deviceContext.getNumberOfOutstandingRequests() == 0);
283     }
284
285 }