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