sending hello upon connection established
[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.ArrayList;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Stack;
18 import java.util.concurrent.ScheduledThreadPoolExecutor;
19 import java.util.concurrent.TimeUnit;
20
21 import org.junit.After;
22 import org.junit.Assert;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
26 import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
27 import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
28 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
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.ExperimenterInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.google.common.collect.Lists;
53
54 /**
55  * @author mirehak
56  */
57 public class ConnectionConductorImplTest {
58
59     protected static final Logger LOG = LoggerFactory
60             .getLogger(ConnectionConductorImplTest.class);
61
62     protected ConnectionAdapterStackImpl adapter;
63     private ConnectionConductorImpl connectionConductor;
64     private MDController controller;
65     private Stack<SwitchTestEvent> eventPlan;
66
67     private Thread libSimulation;
68     private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
69             8);
70     protected int experimenterMessageCounter;
71     protected int packetinMessageCounter;
72     protected int flowremovedMessageCounter;
73     protected int portstatusAddMessageCounter;
74     protected int portstatusDeleteMessageCounter;
75     protected int portstatusModifyMessageCounter;
76
77     /**
78      * @throws java.lang.Exception
79      */
80     @Before
81     public void setUp() throws Exception {
82         adapter = new ConnectionAdapterStackImpl();
83         connectionConductor = new ConnectionConductorImpl(adapter);
84         connectionConductor.init();
85         controller = new MDController();
86         controller.init();
87         eventPlan = new Stack<>();
88         adapter.setEventPlan(eventPlan);
89         adapter.setProceedTimeout(5000L);
90         adapter.checkListeners();
91     }
92
93     /**
94      * @throws java.lang.Exception
95      */
96     @After
97     public void tearDown() throws Exception {
98         if (libSimulation != null) {
99             libSimulation.join();
100         }
101         for (Exception problem : adapter.getOccuredExceptions()) {
102             LOG.error("during simulation on adapter side: "
103                     + problem.getMessage());
104         }
105         Assert.assertEquals(0, adapter.getOccuredExceptions().size());
106         adapter = null;
107         if (LOG.isDebugEnabled()) {
108             if (eventPlan.size() > 0) {
109                 LOG.debug("eventPlan size: " + eventPlan.size());
110                 for (SwitchTestEvent event : eventPlan) {
111                     LOG.debug(" # EVENT:: " + event.toString());
112                 }
113             }
114         }
115         Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
116         eventPlan = null;
117         controller = null;
118     }
119
120     /**
121      * Test method for
122      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
123      * .
124      * @throws Exception
125      */
126     @Test
127     public void testOnEchoRequestMessage() throws Exception {
128         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
129                 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
130         eventPlan.add(0,
131                 EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
132         executeNow();
133     }
134
135     /**
136      * Test of handshake, covering version negotiation and features .
137      * @throws Exception
138      */
139     @Test
140     public void testHandshake1() throws Exception {
141         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
142                 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
143         eventPlan.add(0,
144                 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
145         eventPlan.add(0,
146                 EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
147         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
148         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
149         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
150         getFeaturesOutputBuilder.setBuffers(4L);
151         getFeaturesOutputBuilder.setReserved(0L);
152         getFeaturesOutputBuilder.setTables((short) 2);
153         getFeaturesOutputBuilder.setCapabilities(84L);
154
155         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
156                 EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
157
158         execute(true);
159         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
160                 connectionConductor.getConductorState());
161         Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
162                 .shortValue());
163     }
164
165     /**
166      * Test of handshake, covering version negotiation and features .
167      * @throws Exception
168      */
169     @Test
170     public void testHandshake2() throws Exception {
171         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
172                 (short) 0x05, new HelloMessageBuilder()));
173         eventPlan.add(0,
174                 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
175         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
176                 (short) 0x01, new HelloMessageBuilder()));
177         eventPlan.add(0,
178                 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
179         // Commented : connection will terminate if hello message is sent again
180         // with not supported version
181 //        eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
182 //                (short) 0x01, new HelloMessageBuilder()));
183 //        eventPlan.add(0,
184 //                EventFactory.createDefaultWaitForRpcEvent(45, "helloReply"));
185         eventPlan.add(0,
186                 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
187         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
188         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
189         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
190         getFeaturesOutputBuilder.setBuffers(4L);
191         getFeaturesOutputBuilder.setReserved(0L);
192         getFeaturesOutputBuilder.setTables((short) 2);
193         getFeaturesOutputBuilder.setCapabilities(84L);
194
195         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
196                 EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
197
198         executeNow();
199         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
200                 connectionConductor.getConductorState());
201         Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
202                 .shortValue());
203     }
204
205     /**
206      * Test of handshake, covering version negotiation and features .
207      * @throws Exception
208      */
209     @Test
210     public void testHandshake3() throws Exception {
211         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
212                 (short) 0x00, new HelloMessageBuilder()));
213
214         executeNow();
215         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.HANDSHAKING,
216                 connectionConductor.getConductorState());
217         Assert.assertNull(connectionConductor.getVersion());
218     }
219
220     /**
221      * Test method for
222      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
223      * .
224      * @throws InterruptedException
225      */
226     @Test
227     public void testOnExperimenterMessage1() throws InterruptedException {
228         eventPlan.add(0,
229                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
230         ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
231         builder1.setExperimenter(84L).setExpType(4L);
232         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
233                 EventFactory.DEFAULT_VERSION, builder1));
234         
235         connectionConductor.setListenerMapping(assembleListenerMapping());
236         
237         executeLater();
238
239         Runnable sendExperimenterCmd = new Runnable() {
240
241             @Override
242             public void run() {
243                 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
244                 builder2.setExperimenter(84L).setExpType(4L);
245                 EventFactory.setupHeader(42L, builder2);
246                 adapter.experimenter(builder2.build());
247             }
248         };
249         pool.schedule(sendExperimenterCmd,
250                 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
251     }
252
253     /**
254      * Test method for
255      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
256      * .
257      * @throws InterruptedException
258      */
259     @Test
260     public void testOnExperimenterMessage2() throws InterruptedException {
261         eventPlan.add(0,
262                 EventFactory.createDefaultWaitForRpcEvent(42, "experimenter"));
263         ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
264         builder1.setType(ErrorType.BADREQUEST).setCode(3)
265                 .setData(new byte[] { 1, 2, 3 });
266
267         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
268                 EventFactory.DEFAULT_VERSION, builder1));
269
270         executeLater();
271
272         Runnable sendExperimenterCmd = new Runnable() {
273
274             @Override
275             public void run() {
276                 ExperimenterInputBuilder builder2 = new ExperimenterInputBuilder();
277                 builder2.setExperimenter(84L).setExpType(4L);
278                 EventFactory.setupHeader(42L, builder2);
279                 adapter.experimenter(builder2.build());
280             }
281         };
282         pool.schedule(sendExperimenterCmd,
283                 ConnectionAdapterStackImpl.JOB_DELAY, TimeUnit.MILLISECONDS);
284     }
285
286     /**
287      * Test method for
288      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
289      * .
290      * @throws InterruptedException 
291      */
292     @Test
293     public void testOnFlowRemovedMessage() throws InterruptedException {
294         IMDMessageListener objFms = new FlowRemovedMessageService() ;
295         controller.addMessageListener(FlowRemovedMessage.class, objFms);
296         
297         // Complete HandShake
298         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
299         EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
300         eventPlan.add(0,
301         EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
302         eventPlan.add(0,EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
303         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
304         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
305         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
306         getFeaturesOutputBuilder.setBuffers(4L);
307         getFeaturesOutputBuilder.setReserved(0L);
308         getFeaturesOutputBuilder.setTables((short) 2);
309         getFeaturesOutputBuilder.setCapabilities(84L);
310         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
311           EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
312         execute(true);
313         
314         // Now send Flow Removed messages
315         FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
316         builder1.setXid(1L);
317         connectionConductor.onFlowRemovedMessage(builder1.build());
318         Assert.assertEquals(1, flowremovedMessageCounter);
319         builder1.setXid(2L);
320         connectionConductor.onFlowRemovedMessage(builder1.build());
321         Assert.assertEquals(2, flowremovedMessageCounter);
322     }
323
324     /**
325      * Test method for
326      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
327      * .
328      */
329     @Test
330     public void testOnMultipartReplyMessage() {
331         // fail("Not yet implemented");
332         // TODO:: add test
333     }
334
335     /**
336      * Test method for
337      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestMessage)}
338      * .
339      */
340     @Test
341     public void testOnMultipartRequestMessage() {
342         // fail("Not yet implemented");
343         // TODO:: add test
344     }
345
346     /**
347      * Test method for
348      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
349      * .
350      * @throws InterruptedException 
351      */
352     @Test
353     public void testOnPacketInMessage() throws InterruptedException {
354         IMDMessageListener objPms = new PacketInMessageService() ;
355         controller.addMessageListener(PacketInMessage.class, objPms);
356         
357         // Complete HandShake
358         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
359         EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
360         eventPlan.add(0,
361         EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
362         eventPlan.add(0,EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
363         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
364         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
365         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
366         getFeaturesOutputBuilder.setBuffers(4L);
367         getFeaturesOutputBuilder.setReserved(0L);
368         getFeaturesOutputBuilder.setTables((short) 2);
369         getFeaturesOutputBuilder.setCapabilities(84L);
370         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
371           EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
372         execute(true);
373         
374         // Now send PacketIn
375         PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
376         builder1.setBufferId((long)1);
377         connectionConductor.onPacketInMessage(builder1.build());
378         Assert.assertEquals(1, packetinMessageCounter);
379         builder1.setBufferId((long)2);
380         connectionConductor.onPacketInMessage(builder1.build());
381         Assert.assertEquals(2, packetinMessageCounter);
382     }
383
384     /**
385      * Test method for
386      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
387      * .
388      * @throws InterruptedException 
389      */
390     @Test
391     public void testOnPortStatusMessage() throws InterruptedException {
392         
393         IMDMessageListener objPSms = new PortStatusMessageService() ;
394         controller.addMessageListener(PortStatusMessage.class, objPSms);
395         
396         // Complete HandShake
397         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
398         EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
399         eventPlan.add(0,
400         EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
401         eventPlan.add(0,EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
402         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
403         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
404         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
405         getFeaturesOutputBuilder.setBuffers(4L);
406         getFeaturesOutputBuilder.setReserved(0L);
407         getFeaturesOutputBuilder.setTables((short) 2);
408         getFeaturesOutputBuilder.setCapabilities(84L);
409         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
410           EventFactory.DEFAULT_VERSION, getFeaturesOutputBuilder));
411         execute(true);
412         
413         // Send Port Status messages
414         PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
415         PortFeatures features = new PortFeatures(true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false);
416         builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
417         connectionConductor.onPortStatusMessage(builder1.build());
418         Assert.assertEquals(1, portstatusAddMessageCounter);
419         builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
420         connectionConductor.onPortStatusMessage(builder1.build());
421         Assert.assertEquals(1, portstatusModifyMessageCounter);
422         builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
423         connectionConductor.onPortStatusMessage(builder1.build());
424         Assert.assertEquals(1, portstatusDeleteMessageCounter);
425     }
426
427     /**
428      * Test method for
429      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#proposeVersion(short)}
430      * .
431      */
432     @Test
433     public void testProposeVersion() {
434         short[] remoteVer = new short[] { 0x05, 0x04, 0x03, 0x02, 0x01, 0x8f,
435                 0xff };
436         short[] expectedProposal = new short[] { 0x04, 0x04, 0x01, 0x01, 0x01,
437                 0x04, 0x04 };
438
439         for (int i = 0; i < remoteVer.length; i++) {
440             short actualProposal = connectionConductor
441                     .proposeVersion(remoteVer[i]);
442             Assert.assertEquals(
443                     String.format("proposing for version: %04x", remoteVer[i]),
444                     expectedProposal[i], actualProposal);
445         }
446
447         try {
448             connectionConductor.proposeVersion((short) 0);
449             Assert.fail("there should be no proposition for this version");
450         } catch (Exception e) {
451             // expected
452         }
453     }
454
455     /**
456      * @throws InterruptedException
457      */
458     private void executeLater() throws InterruptedException {
459         execute(false);
460     }
461
462     /**
463      * @throws InterruptedException
464      */
465     private void executeNow() throws InterruptedException {
466         execute(true);
467     }
468
469     /**
470      * @throws InterruptedException
471      */
472     private void execute(boolean join) throws InterruptedException {
473         libSimulation = new Thread(adapter, "junit-adapter");
474         libSimulation.start();
475         if (join) {
476             libSimulation.join();
477         }
478     }
479
480     //////// Start - Version Negotiation Test //////////////
481
482     /**
483      * Test of version negotiation Where switch version = 1.0
484      *
485      * @throws Exception
486      */
487     @Test
488     public void testVersionNegotiation10() throws Exception {
489         Short version = (short) 0x01;
490         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42, version, new HelloMessageBuilder()));
491         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
492         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
493         eventPlan.add(0,
494                 EventFactory.createDefaultRpcResponseEvent(44, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
495
496         executeNow();
497         Assert.assertEquals(version, connectionConductor.getVersion());
498     }
499
500     /**
501      * Test of version negotiation Where switch version < 1.0
502      *
503      * @throws Exception
504      */
505     @Test
506     public void testVersionNegotiation00() throws Exception {
507         Short version = (short) 0x00;
508         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L, version, new HelloMessageBuilder()));
509         executeNow();
510         Assert.assertNull(connectionConductor.getVersion());
511     }
512
513     /**
514      * Test of version negotiation Where 1.0 < switch version < 1.3
515      *
516      * @throws Exception
517      */
518     @Test
519     public void testVersionNegotiation11() throws Exception {
520         Short version = (short) 0x02;
521         Short expVersion = (short) 0x01;
522         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L, version, new HelloMessageBuilder()));
523         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
524         Assert.assertNull(connectionConductor.getVersion());
525         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44, expVersion, new HelloMessageBuilder()));
526         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(45, "helloReply"));
527         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(46, "getFeatures"));
528         eventPlan.add(0,
529                 EventFactory.createDefaultRpcResponseEvent(46, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
530         executeNow();
531         Assert.assertEquals(expVersion, connectionConductor.getVersion());
532
533     }
534
535     /**
536      * Test of version negotiation Where switch version = 1.3
537      *
538      * @throws Exception
539      */
540     @Test
541     public void testVersionNegotiation13() throws Exception {
542         Short version = (short) 0x04;
543         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L, version, new HelloMessageBuilder()));
544         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
545         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
546         eventPlan.add(0,
547                 EventFactory.createDefaultRpcResponseEvent(44, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
548
549         executeNow();
550         Assert.assertEquals(version, connectionConductor.getVersion());
551     }
552
553     /**
554      * Test of version negotiation Where switch version >= 1.3
555      *
556      * @throws Exception
557      */
558     @Test
559     public void testVersionNegotiation15() throws Exception {
560         Short version = (short) 0x06;
561         Short expVersion = (short) 0x04;
562         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L, version, new HelloMessageBuilder()));
563         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
564         Assert.assertNull(connectionConductor.getVersion());
565         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44, expVersion, new HelloMessageBuilder()));
566         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(45, "helloReply"));
567         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(46, "getFeatures"));
568         eventPlan.add(0,
569                 EventFactory.createDefaultRpcResponseEvent(46, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
570         executeNow();
571         Assert.assertEquals(expVersion, connectionConductor.getVersion());
572     }
573
574     /**
575      * Test of version negotiation Where switch version > 1.3
576      *
577      * @throws Exception
578      */
579     @Test
580     public void testVersionNegotiation15_MultipleCall() throws Exception {
581         Short version = (short) 0x06;
582         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L, version, new HelloMessageBuilder()));
583         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
584         Assert.assertNull(connectionConductor.getVersion());
585         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44, version, new HelloMessageBuilder()));
586         executeNow();
587         // TODO : check for connection termination
588         Assert.assertNull(connectionConductor.getVersion());
589     }
590
591     /**
592      * Test of version negotiation Where bitmap version {0x05,0x01}
593      *
594      * @throws Exception
595      */
596     @Test
597     public void testVersionNegotiation10InBitmap() throws Exception {
598         Short version = (short) 0x01;
599         eventPlan.add(
600                 0,
601                 EventFactory.createDefaultNotificationEvent(42L, (short) 0x05,
602                         getHelloBitmapMessage(Lists.newArrayList((short) 0x05, (short) 0x01))));
603         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
604         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
605         eventPlan.add(0,
606                 EventFactory.createDefaultRpcResponseEvent(44, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
607
608         executeNow();
609         Assert.assertEquals(version, connectionConductor.getVersion());
610     }
611
612     /**
613      * Test of version negotiation Where bitmap version {0x05,0x04}
614      *
615      * @throws Exception
616      */
617     @Test
618     public void testVersionNegotiation13InBitmap() throws Exception {
619         Short version = (short) 0x04;
620         eventPlan.add(
621                 0,
622                 EventFactory.createDefaultNotificationEvent(42L, (short) 0x05,
623                         getHelloBitmapMessage(Lists.newArrayList((short) 0x05, (short) 0x04))));
624         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
625         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures"));
626         eventPlan.add(0,
627                 EventFactory.createDefaultRpcResponseEvent(44, EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
628
629         executeNow();
630         Assert.assertEquals(version, connectionConductor.getVersion());
631     }
632
633     /**
634      * Test of version negotiation Where bitmap version {0x05,0x02}
635      *
636      * @throws Exception
637      */
638     @Test
639     public void testVersionNegotiationNoCommonVersionInBitmap() throws Exception {
640         eventPlan.add(
641                 0,
642                 EventFactory.createDefaultNotificationEvent(42L, (short) 0x05,
643                         getHelloBitmapMessage(Lists.newArrayList((short) 0x05, (short) 0x02))));
644         executeNow();
645         Assert.assertNull(connectionConductor.getVersion());
646     }
647
648     private HelloMessageBuilder getHelloBitmapMessage(List<Short> versionOrder) {
649         short highestVersion = versionOrder.get(0);
650         int elementsCount = highestVersion / Integer.SIZE;
651         ElementsBuilder elementsBuilder = new ElementsBuilder();
652
653         List<Elements> elementList = new ArrayList<>();
654         int orderIndex = versionOrder.size();
655         int value = versionOrder.get(--orderIndex);
656         for (int index = 0; index <= elementsCount; index++) {
657             List<Boolean> booleanList = new ArrayList<>();
658             for (int i = 0; i < Integer.SIZE; i++) {
659                 if (value == ((index * Integer.SIZE) + i)) {
660                     booleanList.add(true);
661                     value = (orderIndex == 0) ? highestVersion : versionOrder.get(--orderIndex);
662                 } else {
663                     booleanList.add(false);
664                 }
665             }
666             elementsBuilder.setType(HelloElementType.forValue(1));
667             elementsBuilder.setVersionBitmap(booleanList);
668             elementList.add(elementsBuilder.build());
669         }
670
671         HelloMessageBuilder builder = new HelloMessageBuilder();
672         builder.setXid(10L);
673         builder.setVersion(highestVersion);
674         builder.setElements(elementList);
675         return builder;
676
677     }
678
679     private GetFeaturesOutputBuilder getFeatureResponseMsg() {
680         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
681         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
682         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
683         getFeaturesOutputBuilder.setBuffers(4L);
684         getFeaturesOutputBuilder.setReserved(0L);
685         getFeaturesOutputBuilder.setTables((short) 2);
686         getFeaturesOutputBuilder.setCapabilities(84L);
687
688         return getFeaturesOutputBuilder;
689     }
690
691     private class ExperimenterMessageService implements IMDMessageListener {
692         @Override
693         public void receive(SwitchConnectionDistinguisher cookie, SessionContext sw, DataObject msg) {
694             LOG.debug("Received a packet in Experimenter Service");
695             experimenterMessageCounter++;
696         }
697     }
698
699     private class PacketInMessageService implements IMDMessageListener {
700         @Override
701         public void receive(SwitchConnectionDistinguisher cookie, SessionContext sw, DataObject msg) {
702             LOG.debug("Received a packet in PacketIn Service");
703             packetinMessageCounter++;
704         }
705     }
706
707     private class FlowRemovedMessageService implements IMDMessageListener {
708         @Override
709         public void receive(SwitchConnectionDistinguisher cookie, SessionContext sw, DataObject msg) {
710             LOG.debug("Received a packet in FlowRemoved Service");
711             flowremovedMessageCounter++;
712         }
713     }
714
715     private class PortStatusMessageService implements IMDMessageListener {
716         @Override
717         public void receive(SwitchConnectionDistinguisher cookie, SessionContext sw, DataObject msg) {
718             LOG.debug("Received a packet in PortStatus Service");
719             if ( (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRADD))  ) {
720                 portstatusAddMessageCounter++;
721             } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRDELETE)){
722                 portstatusDeleteMessageCounter++;
723             } else if (((PortStatusMessage)msg).getReason().equals(PortReason.OFPPRMODIFY)) {
724                 portstatusModifyMessageCounter++;
725             }
726         }
727     }
728
729     /**
730      * Test method for
731      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage)}
732      * .
733      * @throws InterruptedException
734      */
735     @Test
736     public void testOnExperimenterMessage() throws InterruptedException {
737         connectionConductor.setListenerMapping(assembleListenerMapping());
738         ExperimenterMessageBuilder builder1 = new ExperimenterMessageBuilder();
739         builder1.setExperimenter(84L).setExpType(4L);
740         connectionConductor.onExperimenterMessage(builder1.build());
741         Assert.assertEquals(1, experimenterMessageCounter);
742         builder1.setExperimenter(85L).setExpType(4L);
743         connectionConductor.onExperimenterMessage(builder1.build());
744         Assert.assertEquals(2, experimenterMessageCounter);
745     }
746
747     /**
748      * @return listener mapping
749      */
750     private Map<Class<? extends DataObject>, Collection<IMDMessageListener>> assembleListenerMapping() {
751         IMDMessageListener objEms = new ExperimenterMessageService() ;
752         Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping = new HashMap<>();
753         Collection<IMDMessageListener> existingValues = new ArrayList<>();
754         existingValues.add(objEms);
755         listenerMapping.put(ExperimenterMessage.class, existingValues);
756         return listenerMapping;
757     }
758
759 }