first proposal of integration plugin - library
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / ConnectionConductorImplTest.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core;
10
11 import java.math.BigInteger;
12 import java.util.Stack;
13 import java.util.concurrent.ScheduledThreadPoolExecutor;
14 import java.util.concurrent.TimeUnit;
15
16 import org.junit.After;
17 import org.junit.Assert;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
21 import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
22 import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * @author mirehak
35  */
36 public class ConnectionConductorImplTest {
37
38     private static final Logger LOG = LoggerFactory
39             .getLogger(ConnectionConductorImplTest.class);
40
41     protected ConnectionAdapterStackImpl adapter;
42     private ConnectionConductorImpl connectionConductor;
43     private Stack<SwitchTestEvent> eventPlan;
44
45     private Thread libSimulation;
46     private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
47             8);
48
49     /**
50      * @throws java.lang.Exception
51      */
52     @Before
53     public void setUp() throws Exception {
54         adapter = new ConnectionAdapterStackImpl();
55         connectionConductor = new ConnectionConductorImpl(adapter);
56         connectionConductor.init();
57         eventPlan = new Stack<>();
58         adapter.setEventPlan(eventPlan);
59         adapter.setProceedTimeout(5000L);
60         adapter.checkListeners();
61     }
62
63     /**
64      * @throws java.lang.Exception
65      */
66     @After
67     public void tearDown() throws Exception {
68         if (libSimulation != null) {
69             libSimulation.join();
70         }
71         for (Exception problem : adapter.getOccuredExceptions()) {
72             LOG.error("during simulation on adapter side: "
73                     + problem.getMessage());
74         }
75         Assert.assertEquals(0, adapter.getOccuredExceptions().size());
76         adapter = null;
77         if (LOG.isDebugEnabled()) {
78             if (eventPlan.size() > 0) {
79                 LOG.debug("eventPlan size: " + eventPlan.size());
80                 for (SwitchTestEvent event : eventPlan) {
81                     LOG.debug(" # EVENT:: " + event.toString());
82                 }
83             }
84         }
85         Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
86         eventPlan = null;
87     }
88
89     /**
90      * Test method for
91      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
92      * .
93      * @throws Exception
94      */
95     @Test
96     public void testOnEchoRequestMessage() throws Exception {
97         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
98                 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
99         eventPlan.add(0,
100                 EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
101         executeNow();
102     }
103
104     /**
105      * Test of handshake, covering version negotiation and features .
106      * @throws Exception
107      */
108     @Test
109     public void testHandshake1() throws Exception {
110         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
111                 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
112         eventPlan.add(0,
113                 EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
114         eventPlan.add(0,
115                 EventFactory.createDefaultWaitForRpcEvent(42, "getFeatures"));
116         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
117         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
118         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
119         getFeaturesOutputBuilder.setBuffers(4L);
120         getFeaturesOutputBuilder.setReserved(0L);
121         getFeaturesOutputBuilder.setTables((short) 2);
122         getFeaturesOutputBuilder.setCapabilities(84L);
123
124         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(42,
125                 EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
126
127         execute(true);
128         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
129                 connectionConductor.getConductorState());
130         Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
131                 .shortValue());
132     }
133
134     /**
135      * Test of handshake, covering version negotiation and features .
136      * @throws Exception
137      */
138     @Test
139     public void testHandshake2() throws Exception {
140         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
141                 (short) 0x05, new HelloMessageBuilder()));
142         eventPlan.add(0,
143                 EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
144         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
145                 (short) 0x03, new HelloMessageBuilder()));
146         eventPlan.add(0,
147                 EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
148         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
149                 (short) 0x01, new HelloMessageBuilder()));
150         eventPlan.add(0,
151                 EventFactory.createDefaultWaitForRpcEvent(42, "helloReply"));
152         eventPlan.add(0,
153                 EventFactory.createDefaultWaitForRpcEvent(42, "getFeatures"));
154         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
155         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
156         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
157         getFeaturesOutputBuilder.setBuffers(4L);
158         getFeaturesOutputBuilder.setReserved(0L);
159         getFeaturesOutputBuilder.setTables((short) 2);
160         getFeaturesOutputBuilder.setCapabilities(84L);
161
162         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(42,
163                 EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
164
165         executeNow();
166         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
167                 connectionConductor.getConductorState());
168         Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
169                 .shortValue());
170     }
171
172     /**
173      * Test of handshake, covering version negotiation and features .
174      * @throws Exception
175      */
176     @Test
177     public void testHandshake3() throws Exception {
178         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
179                 (short) 0x00, new HelloMessageBuilder()));
180
181         executeNow();
182         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.HANDSHAKING,
183                 connectionConductor.getConductorState());
184         Assert.assertNull(connectionConductor.getVersion());
185     }
186
187     /**
188      * Test method for
189      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
190      * .
191      * @throws InterruptedException
192      */
193     @Test
194     public void testOnExperimenterMessage1() throws InterruptedException {
195         eventPlan.add(0,
196                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
197         ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
198         builder1.setExperimenter(84L).setExpType(4L);
199         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
200                 EventFactory.DEFAULT_VERSION, builder1));
201         executeLater();
202
203         Runnable sendExperimenterCmd = new Runnable() {
204
205             @Override
206             public void run() {
207                 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
208                 builder2.setExperimenter(84L).setExpType(4L);
209                 EventFactory.setupHeader(42L, builder2);
210                 adapter.experimenter(builder2.build());
211             }
212         };
213         pool.schedule(sendExperimenterCmd,
214                 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
215     }
216
217     /**
218      * Test method for
219      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
220      * .
221      * @throws InterruptedException
222      */
223     @Test
224     public void testOnExperimenterMessage2() throws InterruptedException {
225         eventPlan.add(0,
226                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
227         ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
228         builder1.setType(ErrorType.BADREQUEST).setCode(3)
229                 .setData(new byte[] { 1, 2, 3 });
230
231         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
232                 EventFactory.DEFAULT_VERSION, builder1));
233
234         executeLater();
235
236         Runnable sendExperimenterCmd = new Runnable() {
237
238             @Override
239             public void run() {
240                 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
241                 builder2.setExperimenter(84L).setExpType(4L);
242                 EventFactory.setupHeader(42L, builder2);
243                 adapter.experimenter(builder2.build());
244             }
245         };
246         pool.schedule(sendExperimenterCmd,
247                 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
248     }
249
250     /**
251      * Test method for
252      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
253      * .
254      */
255     @Test
256     public void testOnFlowRemovedMessage() {
257         // fail("Not yet implemented");
258         // TODO:: add test
259     }
260
261     /**
262      * Test method for
263      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
264      * .
265      */
266     @Test
267     public void testOnMultipartReplyMessage() {
268         // fail("Not yet implemented");
269         // TODO:: add test
270     }
271
272     /**
273      * Test method for
274      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestMessage)}
275      * .
276      */
277     @Test
278     public void testOnMultipartRequestMessage() {
279         // fail("Not yet implemented");
280         // TODO:: add test
281     }
282
283     /**
284      * Test method for
285      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
286      * .
287      */
288     @Test
289     public void testOnPacketInMessage() {
290         // fail("Not yet implemented");
291         // TODO:: add test
292     }
293
294     /**
295      * Test method for
296      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
297      * .
298      */
299     @Test
300     public void testOnPortStatusMessage() {
301         // fail("Not yet implemented");
302         // TODO:: add test
303     }
304
305     /**
306      * Test method for
307      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#proposeVersion(short)}
308      * .
309      */
310     @Test
311     public void testProposeVersion() {
312         short[] remoteVer = new short[] { 0x05, 0x04, 0x03, 0x02, 0x01, 0x8f,
313                 0xff };
314         short[] expectedProposal = new short[] { 0x04, 0x04, 0x01, 0x01, 0x01,
315                 0x04, 0x04 };
316
317         for (int i = 0; i < remoteVer.length; i++) {
318             short actualProposal = connectionConductor
319                     .proposeVersion(remoteVer[i]);
320             Assert.assertEquals(
321                     String.format("proposing for version: %04x", remoteVer[i]),
322                     expectedProposal[i], actualProposal);
323         }
324
325         try {
326             connectionConductor.proposeVersion((short) 0);
327             Assert.fail("there should be no proposition for this version");
328         } catch (Exception e) {
329             // expected
330         }
331     }
332
333     /**
334      * @throws InterruptedException
335      */
336     private void executeLater() throws InterruptedException {
337         execute(false);
338     }
339
340     /**
341      * @throws InterruptedException
342      */
343     private void executeNow() throws InterruptedException {
344         execute(true);
345     }
346
347     /**
348      * @throws InterruptedException
349      */
350     private void execute(boolean join) throws InterruptedException {
351         libSimulation = new Thread(adapter, "junit-adapter");
352         libSimulation.start();
353         if (join) {
354             libSimulation.join();
355         }
356     }
357
358 }