Changed methods in DeviceContext, created DeviceReplyProcessor interface
[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 java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.concurrent.ExecutionException;
10 import java.util.concurrent.TimeUnit;
11 import java.util.concurrent.TimeoutException;
12
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;
52
53 import com.google.common.util.concurrent.SettableFuture;
54
55 @RunWith(MockitoJUnitRunner.class)
56 public class DeviceContextImplTest {
57     private static final Logger LOG = LoggerFactory
58             .getLogger(DeviceContextImplTest.class);
59     XidGenerator xidGen;
60
61     Xid xid;
62     Xid xidMulti;
63     DeviceContextImpl deviceContext;
64     @Mock
65     RequestContext<GetAsyncReply> requestContext;
66     @Mock
67     RequestContext<MultipartReply> requestContextMultiReply;
68
69     @Mock
70     ConnectionContext connectionContext;
71     @Mock
72     DeviceState deviceState;
73     @Mock
74     DataBroker dataBroker;
75     @Mock
76     WriteTransaction wTx;
77     @Mock
78     ReadOnlyTransaction rTx;
79     @Mock
80     BindingTransactionChain txChainFactory;
81
82     @Before
83     public void setUp() {
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);
91
92         deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker);
93         xid = deviceContext.getNextXid();
94         xidMulti = deviceContext.getNextXid();
95         xidGen = new XidGenerator();
96     }
97
98     @Test(expected=NullPointerException.class)
99     public void testDeviceContextImplConstructorNullConnectionContext() {
100         new DeviceContextImpl(null, deviceState, dataBroker);
101     }
102
103     @Test(expected=NullPointerException.class)
104     public void testDeviceContextImplConstructorNullDataBroker() {
105         new DeviceContextImpl(connectionContext, deviceState, null);
106     }
107
108     @Test(expected=NullPointerException.class)
109     public void testDeviceContextImplConstructorNullDeviceState() {
110         new DeviceContextImpl(connectionContext, null, dataBroker);
111     }
112
113     @Test
114     public void testGetDeviceState() {
115         final DeviceState deviceSt = deviceContext.getDeviceState();
116         Assert.assertNotNull(deviceSt);
117         Assert.assertEquals(deviceState, deviceSt);
118     }
119
120     @Test
121     public void testGetReadTransaction() {
122         final ReadTransaction readTx = deviceContext.getReadTransaction();
123         Assert.assertNotNull(readTx);
124         Assert.assertEquals(rTx, readTx);
125     }
126
127     @Test
128     public void testGetWriteTransaction() {
129         final WriteTransaction writeTx = deviceContext.getWriteTransaction();
130         Assert.assertNotNull(writeTx);
131         Assert.assertEquals(wTx, writeTx);
132     }
133
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();
142     }
143
144     @Test
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()));
150
151         Assert.assertFalse(requestContext.getFuture().isDone());
152         LOG.info("Sending reply from device");
153         deviceContext.processReply(asyncOutput);
154         Assert.assertTrue(requestContext.getFuture().isDone());
155
156         LOG.info("Checking RequestContext.future");
157         try {
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);
164             fail("fail");
165         }
166         Assert.assertTrue(deviceContext.getRequests().isEmpty());
167     }
168
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();
175     }
176
177     @Test
178     public void testProcessReplyError() {
179         LOG.info("Hooking RequestContext");
180         deviceContext.hookRequestCtx(xid, requestContext);
181         Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
182
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());
188
189         LOG.info("Checking RequestContext.future");
190         try {
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);
200             fail("fail");
201         }
202         Assert.assertTrue(deviceContext.getRequests().isEmpty());
203     }
204
205     @Test
206     public void testProcessReplyList() {
207         LOG.info("Hooking RequestContext");
208         deviceContext.hookRequestCtx(xidMulti, requestContextMultiReply);
209         Assert.assertEquals(requestContextMultiReply, deviceContext.getRequests().get(xidMulti.getValue()));
210
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());
215
216         LOG.info("Checking RequestContext.future");
217         try {
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);
225             fail("fail");
226         }
227         Assert.assertTrue(deviceContext.getRequests().isEmpty());
228     }
229
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))
239                                     .build());
240         multipartReplies.add(new MultipartReplyMessageBuilder()
241                                     .setMultipartReplyBody(replyBody)
242                                     .setXid(xid.getValue())
243                                     .setFlags(new MultipartRequestFlags(true))
244                                     .build());
245         return multipartReplies;
246     }
247
248     @Test
249     public void testProcessException() {
250         LOG.info("Hooking RequestContext");
251         deviceContext.hookRequestCtx(xid, requestContext);
252         Assert.assertEquals(requestContext, deviceContext.getRequests().get(xid.getValue()));
253
254         Assert.assertFalse(requestContext.getFuture().isDone());
255
256         LOG.info("Sending reply from device");
257         deviceContext.processException(xid, new DeviceDataException("Some freakin' error", new NullPointerException()));
258         Assert.assertTrue(requestContext.getFuture().isDone());
259
260         LOG.info("Checking RequestContext.future");
261         try {
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);
271                 fail("fail");
272         }
273         Assert.assertTrue(deviceContext.getRequests().isEmpty());
274     }
275
276 }