Bug 1764 - moved Session related interfaces to openflowplugin-api
[openflowplugin.git] / openflowplugin / src / test / java / org / opendaylight / openflowplugin / openflow / md / core / ConnectionConductorImplTest.java
1 /**
2  * Copyright (c) 2013-2014 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 static org.junit.Assert.assertNotNull;
12
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Stack;
20 import java.util.concurrent.ScheduledThreadPoolExecutor;
21 import org.junit.After;
22 import org.junit.Assert;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.ArgumentCaptor;
27 import org.mockito.Matchers;
28 import org.mockito.Mock;
29 import org.mockito.Mockito;
30 import org.mockito.runners.MockitoJUnitRunner;
31 import org.opendaylight.openflowplugin.api.OFConstants;
32 import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
33 import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
34 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
35 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
36 import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
37 import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
38 import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
39 import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
40 import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
41 import org.opendaylight.openflowplugin.openflow.md.queue.QueueProcessorLightImpl;
42 import org.opendaylight.openflowplugin.api.statistics.MessageSpy;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
60 import org.opendaylight.yangtools.yang.binding.DataContainer;
61 import org.opendaylight.yangtools.yang.binding.DataObject;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @RunWith(MockitoJUnitRunner.class)
66 public class ConnectionConductorImplTest {
67
68     protected static final Logger LOG = LoggerFactory
69             .getLogger(ConnectionConductorImplTest.class);
70
71     /**
72      * in [ms]
73      */
74     private final int maxProcessingTimeout = 500;
75
76     protected ConnectionAdapterStackImpl adapter;
77     private ConnectionConductorImpl connectionConductor;
78     private MDController controller;
79     private Stack<SwitchTestEvent> eventPlan;
80
81     private Thread libSimulation;
82     private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
83             8);
84
85     protected QueueProcessorLightImpl queueProcessor;
86
87     private PopListener<DataObject> popListener;
88
89     private int experimenterMessageCounter;
90     private int packetinMessageCounter;
91     private int flowremovedMessageCounter;
92     private int portstatusAddMessageCounter;
93     private int portstatusDeleteMessageCounter;
94     private int portstatusModifyMessageCounter;
95     private int errorMessageCounter;
96
97     @Mock
98     private ErrorHandlerSimpleImpl errorHandler;
99
100     private int expectedErrors = 0;
101     @Mock
102     private MessageSpy<DataContainer> messageSpy;
103
104     public void incrExperimenterMessageCounter() {
105         this.experimenterMessageCounter++;
106     }
107
108     public void incrPacketinMessageCounter() {
109         this.packetinMessageCounter++;
110     }
111
112     public void incrFlowremovedMessageCounter() {
113         this.flowremovedMessageCounter++;
114     }
115
116     public void incrPortstatusAddMessageCounter() {
117         this.portstatusAddMessageCounter++;
118     }
119
120     public void incrPortstatusDeleteMessageCounter() {
121         this.portstatusDeleteMessageCounter++;
122     }
123
124     public void incrPortstatusModifyMessageCounter() {
125         this.portstatusModifyMessageCounter++;
126     }
127
128     public void incrErrorMessageCounter() {
129         this.errorMessageCounter++;
130     }
131
132     @Test
133     /**
134      * Test for ConnectionConductorFactory#createConductor
135      */
136     public void testCreateConductor() {
137         ConnectionConductor connectionConductor = ConnectionConductorFactory.createConductor(adapter, queueProcessor);
138         assertNotNull(connectionConductor);
139     }
140
141     /**
142      * @throws java.lang.Exception
143      */
144     @Before
145     public void setUp() throws Exception {
146         adapter = new ConnectionAdapterStackImpl();
147
148         popListener = new PopListenerCountingImpl<>();
149
150         controller = new MDController();
151         controller.init();
152         controller.getMessageTranslators().putAll(assembleTranslatorMapping());
153
154         queueProcessor = new QueueProcessorLightImpl();
155         queueProcessor.setMessageSpy(messageSpy);
156         queueProcessor.setPopListenersMapping(assemblePopListenerMapping());
157         queueProcessor.setTranslatorMapping(controller.getMessageTranslators());
158         queueProcessor.init();
159
160         connectionConductor = new ConnectionConductorImpl(adapter);
161         connectionConductor.setQueueProcessor(queueProcessor);
162         connectionConductor.setErrorHandler(errorHandler);
163         connectionConductor.init();
164         eventPlan = new Stack<>();
165         adapter.setEventPlan(eventPlan);
166         adapter.setProceedTimeout(5000L);
167         adapter.checkListeners();
168     }
169
170     /**
171      * @return
172      */
173     private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> assemblePopListenerMapping() {
174         Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> mapping = new HashMap<>();
175         Collection<PopListener<DataObject>> popListenerBag = new ArrayList<>();
176         popListenerBag.add(popListener);
177         //TODO: add testing registered types
178         mapping.put(DataObject.class, popListenerBag);
179         return mapping;
180     }
181
182     /**
183      * @throws java.lang.Exception
184      */
185     @After
186     public void tearDown() throws Exception {
187         if (libSimulation != null) {
188             libSimulation.join();
189         }
190         queueProcessor.shutdown();
191         connectionConductor.shutdownPool();
192
193         for (Exception problem : adapter.getOccuredExceptions()) {
194             LOG.error("during simulation on adapter side: "
195                     + problem.getMessage());
196         }
197         Assert.assertEquals(0, adapter.getOccuredExceptions().size());
198         adapter = null;
199         if (LOG.isDebugEnabled()) {
200             if (eventPlan.size() > 0) {
201                 LOG.debug("eventPlan size: " + eventPlan.size());
202                 for (SwitchTestEvent event : eventPlan) {
203                     LOG.debug(" # EVENT:: " + event.toString());
204                 }
205             }
206         }
207         Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
208         eventPlan = null;
209         controller = null;
210
211         // logging errors if occurred
212         ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
213         Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
214                 errorCaptor.capture(), Matchers.any(SessionContext.class));
215         for (Throwable problem : errorCaptor.getAllValues()) {
216             LOG.warn(problem.getMessage(), problem);
217         }
218
219         Mockito.verify(errorHandler, Mockito.times(expectedErrors)).handleException(
220                 Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
221     }
222
223     /**
224      * Test method for
225      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
226      * .
227      *
228      * @throws Exception
229      */
230     @Test
231     public void testOnEchoRequestMessage() throws Exception {
232         simulateV13PostHandshakeState(connectionConductor);
233
234         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
235                 EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
236         eventPlan.add(0,
237                 EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
238         executeNow();
239     }
240
241     /**
242      * Test of handshake, covering version negotiation and features.
243      * Switch delivers first helloMessage with default version.
244      *
245      * @throws Exception
246      */
247     @Test
248     public void testHandshake1() throws Exception {
249         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
250                 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
251         eventPlan.add(0, EventFactory.createDefaultWaitForAllEvent(
252                 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"),
253                 EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures")));
254         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
255                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
256
257         int i = 1;
258         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "setConfig"));
259         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
260         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
261         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
262         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
263         executeNow();
264
265         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
266                 connectionConductor.getConductorState());
267         Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
268                 .shortValue());
269     }
270
271     /**
272      * Test of handshake, covering version negotiation and features.
273      * Controller sends first helloMessage with default version
274      *
275      * @throws Exception
276      */
277     @Test
278     public void testHandshake1SwitchStarts() throws Exception {
279         eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
280         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
281         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
282                 EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
283         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "getFeatures"));
284         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
285                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
286
287         int i = 1;
288         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "setConfig"));
289         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
290         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
291         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
292         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
293
294         executeNow();
295
296         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
297                 connectionConductor.getConductorState());
298         Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
299                 .shortValue());
300     }
301
302     /**
303      * Test of handshake, covering version negotiation and features.
304      * Switch delivers first helloMessage with version 0x05
305      * and negotiates following versions: 0x03, 0x01
306      *
307      * @throws Exception
308      */
309     @Test
310     public void testHandshake2() throws Exception {
311         connectionConductor.setBitmapNegotiationEnable(false);
312         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
313                 (short) 0x05, new HelloMessageBuilder()));
314         eventPlan.add(0,
315                 EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
316         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
317                 (short) 0x03, new HelloMessageBuilder()));
318         eventPlan.add(0,
319                 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
320         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
321                 (short) 0x01, new HelloMessageBuilder()));
322         eventPlan.add(0,
323                 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
324
325         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
326                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
327
328         int i = 1;
329         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "setConfig"));
330         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
331
332         executeNow();
333
334         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
335                 connectionConductor.getConductorState());
336         Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
337                 .shortValue());
338     }
339
340     /**
341      * Test of handshake, covering version negotiation and features.
342      * Controller sends first helloMessage with default version
343      * and switch negotiates following versions: 0x05, 0x03, 0x01
344      *
345      * @throws Exception
346      */
347     @Test
348     public void testHandshake2SwitchStarts() throws Exception {
349         connectionConductor.setBitmapNegotiationEnable(false);
350         eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
351         eventPlan.add(0,
352                 EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
353         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
354                 (short) 0x05, new HelloMessageBuilder()));
355         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
356                 (short) 0x03, new HelloMessageBuilder()));
357         eventPlan.add(0,
358                 EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
359         eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
360                 (short) 0x01, new HelloMessageBuilder()));
361         eventPlan.add(0,
362                 EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
363
364         eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
365                 EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
366
367         int i = 1;
368         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "setConfig"));
369         eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(i++, "multipartRequestInput"));
370
371         executeNow();
372
373         Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
374                 connectionConductor.getConductorState());
375         Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
376                 .shortValue());
377     }
378
379     /**
380      * Test method for
381      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
382      * .
383      *
384      * @throws InterruptedException
385      */
386     @Test
387     public void testOnFlowRemovedMessage() throws InterruptedException {
388         IMDMessageTranslator<OfHeader, List<DataObject>> objFms = new FlowRemovedMessageService();
389         controller.addMessageTranslator(FlowRemovedMessage.class, 4, objFms);
390
391         simulateV13PostHandshakeState(connectionConductor);
392
393         // Now send Flow Removed messages
394         FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
395         builder1.setVersion((short) 4);
396         builder1.setXid(1L);
397         connectionConductor.onFlowRemovedMessage(builder1.build());
398         synchronized (popListener) {
399             LOG.debug("about to wait for popListener");
400             popListener.wait(maxProcessingTimeout);
401         }
402         Assert.assertEquals(1, flowremovedMessageCounter);
403         builder1.setXid(2L);
404         connectionConductor.onFlowRemovedMessage(builder1.build());
405         synchronized (popListener) {
406             popListener.wait(maxProcessingTimeout);
407         }
408         Assert.assertEquals(2, flowremovedMessageCounter);
409     }
410
411     /**
412      * Test method for
413      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
414      * .
415      */
416     @Test
417     public void testOnMultipartReplyMessage() {
418         // fail("Not yet implemented");
419         // TODO:: add test
420     }
421
422     /**
423      * Test method for
424      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
425      * .
426      *
427      * @throws InterruptedException
428      */
429     @Test
430     public void testOnPacketInMessage() throws InterruptedException {
431         IMDMessageTranslator<OfHeader, List<DataObject>> objPms = new PacketInMessageService();
432         controller.addMessageTranslator(PacketInMessage.class, 4, objPms);
433
434         simulateV13PostHandshakeState(connectionConductor);
435
436         // Now send PacketIn
437         PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
438         builder1.setVersion((short) 4);
439         builder1.setBufferId((long) 1);
440         connectionConductor.onPacketInMessage(builder1.build());
441         synchronized (popListener) {
442             popListener.wait(maxProcessingTimeout);
443         }
444         Assert.assertEquals(1, packetinMessageCounter);
445         builder1.setBufferId((long) 2);
446         connectionConductor.onPacketInMessage(builder1.build());
447         synchronized (popListener) {
448             popListener.wait(maxProcessingTimeout);
449         }
450         Assert.assertEquals(2, packetinMessageCounter);
451     }
452
453     /**
454      * Test method for
455      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
456      * .
457      *
458      * @throws InterruptedException
459      */
460     @Test
461     public void testOnPortStatusMessage() throws InterruptedException {
462         IMDMessageTranslator<OfHeader, List<DataObject>> objPSms = new PortStatusMessageService();
463         controller.addMessageTranslator(PortStatusMessage.class, 4, objPSms);
464
465         simulateV13PostHandshakeState(connectionConductor);
466
467         // Send Port Status messages
468         PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
469         builder1.setVersion((short) 4);
470         PortFeatures features = new PortFeatures(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false);
471         builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
472         connectionConductor.onPortStatusMessage(builder1.build());
473         synchronized (popListener) {
474             popListener.wait(maxProcessingTimeout);
475         }
476         Assert.assertEquals(1, portstatusAddMessageCounter);
477         builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
478         connectionConductor.onPortStatusMessage(builder1.build());
479         synchronized (popListener) {
480             popListener.wait(maxProcessingTimeout);
481         }
482         Assert.assertEquals(1, portstatusModifyMessageCounter);
483         builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
484         connectionConductor.onPortStatusMessage(builder1.build());
485         synchronized (popListener) {
486             popListener.wait(maxProcessingTimeout);
487         }
488         Assert.assertEquals(1, portstatusDeleteMessageCounter);
489     }
490
491     /**
492      * @throws InterruptedException
493      */
494     private void executeLater() throws InterruptedException {
495         execute(false);
496     }
497
498     /**
499      * @throws InterruptedException
500      */
501     private void executeNow() throws InterruptedException {
502         execute(true);
503         connectionConductor.shutdownPool();
504     }
505
506     /**
507      * @throws InterruptedException
508      */
509     private void execute(boolean join) throws InterruptedException {
510         libSimulation = new Thread(adapter, "junit-adapter");
511         libSimulation.start();
512         if (join) {
513             libSimulation.join();
514         }
515     }
516
517     private static GetFeaturesOutputBuilder getFeatureResponseMsg() {
518         GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
519         getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
520         getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
521         getFeaturesOutputBuilder.setBuffers(4L);
522         getFeaturesOutputBuilder.setReserved(0L);
523         getFeaturesOutputBuilder.setTables((short) 2);
524         getFeaturesOutputBuilder.setCapabilities(createCapabilities(84));
525
526         return getFeaturesOutputBuilder;
527     }
528
529     /**
530      * @return
531      */
532     private static Capabilities createCapabilities(long input) {
533         final Boolean FLOW_STATS = (input & (1 << 0)) != 0;
534         final Boolean TABLE_STATS = (input & (1 << 1)) != 0;
535         final Boolean PORT_STATS = (input & (1 << 2)) != 0;
536         final Boolean GROUP_STATS = (input & (1 << 3)) != 0;
537         final Boolean IP_REASM = (input & (1 << 5)) != 0;
538         final Boolean QUEUE_STATS = (input & (1 << 6)) != 0;
539         final Boolean PORT_BLOCKED = (input & (1 << 8)) != 0;
540         Capabilities capabilities = new Capabilities(FLOW_STATS, GROUP_STATS, IP_REASM,
541                 PORT_BLOCKED, PORT_STATS, QUEUE_STATS, TABLE_STATS);
542         return capabilities;
543     }
544
545     public class ExperimenterMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
546         @Override
547         public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
548             LOG.debug("Received a packet in Experimenter Service");
549             ConnectionConductorImplTest.this.incrExperimenterMessageCounter();
550             return null;
551         }
552     }
553
554     public class PacketInMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
555         @Override
556         public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
557             LOG.debug("Received a packet in PacketIn Service");
558             ConnectionConductorImplTest.this.incrPacketinMessageCounter();
559             return null;
560         }
561     }
562
563     public class FlowRemovedMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
564         @Override
565         public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
566             LOG.debug("Received a packet in FlowRemoved Service");
567             ConnectionConductorImplTest.this.incrFlowremovedMessageCounter();
568             return null;
569         }
570     }
571
572     public class PortStatusMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
573         @Override
574         public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
575             LOG.debug("Received a packet in PortStatus Service");
576             if ((((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRADD))) {
577                 ConnectionConductorImplTest.this.incrPortstatusAddMessageCounter();
578             } else if (((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRDELETE)) {
579                 ConnectionConductorImplTest.this.incrPortstatusDeleteMessageCounter();
580             } else if (((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRMODIFY)) {
581                 ConnectionConductorImplTest.this.incrPortstatusModifyMessageCounter();
582             }
583             return null;
584         }
585     }
586
587     public class ErrorMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
588         @Override
589         public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sw, OfHeader msg) {
590             LOG.debug("Received a packet in Experimenter Service");
591             ConnectionConductorImplTest.this.incrErrorMessageCounter();
592             return null;
593         }
594     }
595
596     /**
597      * Test method for
598      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage)}
599      * .
600      *
601      * @throws InterruptedException
602      */
603     @Test
604     public void testOnErrorMessage() throws InterruptedException {
605         simulateV13PostHandshakeState(connectionConductor);
606
607         ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
608         builder1.setVersion((short) 4);
609         builder1.setCode(100);
610         connectionConductor.onErrorMessage(builder1.build());
611         synchronized (popListener) {
612             popListener.wait(maxProcessingTimeout);
613         }
614         Assert.assertEquals(1, errorMessageCounter);
615         builder1.setCode(200);
616         connectionConductor.onErrorMessage(builder1.build());
617         synchronized (popListener) {
618             popListener.wait(maxProcessingTimeout);
619         }
620         Assert.assertEquals(2, errorMessageCounter);
621     }
622
623     /**
624      * @return listener mapping for:
625      * <ul>
626      * <li>experimenter</li>
627      * <li>error</li>
628      * </ul>
629      */
630     private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> assembleTranslatorMapping() {
631         Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping = new HashMap<>();
632         TranslatorKey tKey;
633
634         IMDMessageTranslator<OfHeader, List<DataObject>> objEms = new ExperimenterMessageService();
635         Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = new ArrayList<>();
636         existingValues.add(objEms);
637         tKey = new TranslatorKey(4, ExperimenterMessage.class.getName());
638         translatorMapping.put(tKey, existingValues);
639         IMDMessageTranslator<OfHeader, List<DataObject>> objErms = new ErrorMessageService();
640         existingValues.add(objErms);
641         tKey = new TranslatorKey(4, ErrorMessage.class.getName());
642         translatorMapping.put(tKey, existingValues);
643         return translatorMapping;
644     }
645
646     /**
647      * Test method for
648      * {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#processPortStatusMsg(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
649      * <br><br>
650      * Tests for getting features from port status message by port version
651      * <ul>
652      * <li>features are malformed - one of them is null</li>
653      * <li>mismatch between port version and port features</li>
654      * <li>mismatch between port version and port features</li>
655      * <li>non-existing port version</li>
656      * <li>port version OF 1.0</li>
657      * <li>port version OF 1.3</li>
658      * </ul>
659      */
660     @Test
661     public void testProcessPortStatusMsg() {
662         simulateV13PostHandshakeState(connectionConductor);
663
664         long portNumber = 90L;
665         long portNumberV10 = 91L;
666         PortStatusMessage msg;
667
668         PortStatusMessageBuilder builder = new PortStatusMessageBuilder();
669         PortFeatures features = new PortFeatures(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false);
670         PortFeatures featuresMal = new PortFeatures(true, false, false, false, null, false, false, false, false, false, false, false, false, false, false, false);
671         PortFeaturesV10 featuresV10 = new PortFeaturesV10(true, false, false, false, false, false, false, false, false, false, false, false);
672
673         //Malformed features            
674         builder.setVersion((short) 1).setPortNo(portNumber).setReason(PortReason.OFPPRADD).setCurrentFeatures(featuresMal);
675         connectionConductor.processPortStatusMsg(builder.build());
676         Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
677         Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
678
679         //Version-features mismatch             
680         builder.setCurrentFeatures(features);
681         connectionConductor.processPortStatusMsg(builder.build());
682         Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
683         Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
684
685         //Non existing version
686         builder.setVersion((short) 0);
687         connectionConductor.processPortStatusMsg(builder.build());
688         Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
689         Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
690
691         //Version OF 1.3
692         builder.setVersion((short) 4);
693         msg = builder.build();
694         connectionConductor.processPortStatusMsg(builder.build());
695         Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumber));
696         Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumber), msg);
697
698         //Version OF 1.0
699         builder.setVersion((short) 1).setPortNo(portNumberV10).setCurrentFeatures(null).setCurrentFeaturesV10(featuresV10);
700         msg = builder.build();
701         connectionConductor.processPortStatusMsg(builder.build());
702         Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumberV10));
703         Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumberV10), msg);
704     }
705
706     private void simulateV13PostHandshakeState(ConnectionConductorImpl conductor) {
707         GetFeaturesOutputBuilder featureOutput = getFeatureResponseMsg();
708         conductor.postHandshakeBasic(featureOutput.build(), OFConstants.OFP_VERSION_1_3);
709     }
710 }