/**
* Copyright (c) 2013, 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.openflowplugin.openflow.md.core;
import static org.junit.Assert.assertNotNull;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
import org.opendaylight.openflowplugin.openflow.md.core.plan.ConnectionAdapterStackImpl;
import org.opendaylight.openflowplugin.openflow.md.core.plan.EventFactory;
import org.opendaylight.openflowplugin.openflow.md.core.plan.SwitchTestEvent;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
import org.opendaylight.openflowplugin.openflow.md.queue.QueueProcessorLightImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeaturesV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@RunWith(MockitoJUnitRunner.class)
public class ConnectionConductorImplTest {
protected static final Logger LOG = LoggerFactory
.getLogger(ConnectionConductorImplTest.class);
/**
* in [ms]
*/
private final int maxProcessingTimeout = 500;
protected ConnectionAdapterStackImpl adapter;
private ConnectionConductorImpl connectionConductor;
private MDController controller;
private Stack<SwitchTestEvent> eventPlan;
private Thread libSimulation;
private final ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
8);
protected QueueProcessorLightImpl queueProcessor;
private PopListenerCountingImpl<DataObject> popListener;
private int experimenterMessageCounter;
private int packetinMessageCounter;
private int flowremovedMessageCounter;
private int portstatusAddMessageCounter;
private int portstatusDeleteMessageCounter;
private int portstatusModifyMessageCounter;
private int errorMessageCounter;
@Mock
private ErrorHandlerSimpleImpl errorHandler;
private final int expectedErrors = 0;
@Mock
private MessageSpy<DataContainer> messageSpy;
@Mock
HandshakeContext handshakeContext;
private ErrorMessageService objErms;
public void incrExperimenterMessageCounter() {
this.experimenterMessageCounter++;
}
public void incrPacketinMessageCounter() {
this.packetinMessageCounter++;
}
public void incrFlowremovedMessageCounter() {
this.flowremovedMessageCounter++;
}
public void incrPortstatusAddMessageCounter() {
this.portstatusAddMessageCounter++;
}
public void incrPortstatusDeleteMessageCounter() {
this.portstatusDeleteMessageCounter++;
}
public void incrPortstatusModifyMessageCounter() {
this.portstatusModifyMessageCounter++;
}
public void incrErrorMessageCounter() {
this.errorMessageCounter++;
}
@Test
/**
* Test for ConnectionConductorFactory#createConductor
*/
public void testCreateConductor() {
ConnectionConductor connectionConductor = ConnectionConductorFactory.createConductor(adapter, queueProcessor);
assertNotNull(connectionConductor);
}
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
adapter = new ConnectionAdapterStackImpl();
popListener = new PopListenerCountingImpl<>();
final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
controller = new MDController(convertorManager);
controller.init();
controller.getMessageTranslators().putAll(assembleTranslatorMapping());
queueProcessor = new QueueProcessorLightImpl();
queueProcessor.setMessageSpy(messageSpy);
queueProcessor.setPopListenersMapping(assemblePopListenerMapping());
queueProcessor.setTranslatorMapping(controller.getMessageTranslators());
queueProcessor.init();
connectionConductor = new ConnectionConductorImpl(adapter);
connectionConductor.setQueueProcessor(queueProcessor);
connectionConductor.setErrorHandler(errorHandler);
connectionConductor.init();
connectionConductor.setHandshakeContext(handshakeContext);
eventPlan = new Stack<>();
adapter.setEventPlan(eventPlan);
adapter.setProceedTimeout(5000L);
adapter.checkListeners();
}
/**
* @return
*/
private Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> assemblePopListenerMapping() {
Map<Class<? extends DataObject>, Collection<PopListener<DataObject>>> mapping = new HashMap<>();
Collection<PopListener<DataObject>> popListenerBag = new ArrayList<>();
popListenerBag.add(popListener);
//TODO: add testing registered types
mapping.put(DataObject.class, popListenerBag);
return mapping;
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
if (libSimulation != null) {
libSimulation.join();
}
queueProcessor.shutdown();
connectionConductor.getHsPool().shutdown();
for (Exception problem : adapter.getOccuredExceptions()) {
LOG.error("during simulation on adapter side: "
+ problem.getMessage());
}
Assert.assertEquals(0, adapter.getOccuredExceptions().size());
adapter = null;
if (LOG.isDebugEnabled()) {
if (eventPlan.size() > 0) {
LOG.debug("eventPlan size: " + eventPlan.size());
for (SwitchTestEvent event : eventPlan) {
LOG.debug(" # EVENT:: " + event);
}
}
}
Assert.assertTrue("plan is not finished", eventPlan.isEmpty());
eventPlan = null;
controller = null;
// logging errors if occurred
ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
Mockito.verify(errorHandler, Mockito.atMost(1)).handleException(
errorCaptor.capture(), Matchers.any(SessionContext.class));
for (Throwable problem : errorCaptor.getAllValues()) {
LOG.warn(problem.getMessage(), problem);
}
Mockito.verify(errorHandler, Mockito.times(expectedErrors)).handleException(
Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onEchoRequestMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage)}
* .
*
* @throws Exception
*/
@Test
public void testOnEchoRequestMessage() throws Exception {
simulateV13PostHandshakeState(connectionConductor);
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
EventFactory.DEFAULT_VERSION, new EchoRequestMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(42, "echoReply"));
executeNow();
}
/**
* Test of handshake, covering version negotiation and features.
* Switch delivers first helloMessage with default version.
*
* @throws Exception
*/
@Test
public void testHandshake1() throws Exception {
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
eventPlan.add(0, EventFactory.createDefaultWaitForAllEvent(
EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"),
EventFactory.createDefaultWaitForRpcEvent(44, "getFeatures")));
eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(44,
EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
int i = 1;
executeNow();
Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
connectionConductor.getConductorState());
Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
.shortValue());
}
/**
* Test of handshake, covering version negotiation and features.
* Controller sends first helloMessage with default version
*
* @throws Exception
*/
@Test
public void testHandshake1SwitchStarts() throws Exception {
eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
EventFactory.DEFAULT_VERSION, new HelloMessageBuilder()));
eventPlan.add(0, EventFactory.createDefaultWaitForRpcEvent(43, "getFeatures"));
eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(43,
EventFactory.DEFAULT_VERSION, getFeatureResponseMsg()));
executeNow();
Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
connectionConductor.getConductorState());
Assert.assertEquals((short) 0x04, connectionConductor.getVersion()
.shortValue());
}
/**
* Test of handshake, covering version negotiation and features.
* Switch delivers first helloMessage with version 0x05
* and negotiates following versions: 0x03, 0x01
*
* @throws Exception
*/
@Test
public void testHandshake2() throws Exception {
connectionConductor.setBitmapNegotiationEnable(false);
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
(short) 0x05, new HelloMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(43, "helloReply"));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
(short) 0x03, new HelloMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
(short) 0x01, new HelloMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
(short) 0x01, getFeatureResponseMsg()));
executeNow();
Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
connectionConductor.getConductorState());
Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
.shortValue());
}
/**
* Test of handshake, covering version negotiation and features.
* Controller sends first helloMessage with default version
* and switch negotiates following versions: 0x05, 0x03, 0x01
*
* @throws Exception
*/
@Test
public void testHandshake2SwitchStarts() throws Exception {
connectionConductor.setBitmapNegotiationEnable(false);
eventPlan.add(0, EventFactory.createConnectionReadyCallback(connectionConductor));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(21, "helloReply"));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(42L,
(short) 0x05, new HelloMessageBuilder()));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(43L,
(short) 0x03, new HelloMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(44, "helloReply"));
eventPlan.add(0, EventFactory.createDefaultNotificationEvent(44L,
(short) 0x01, new HelloMessageBuilder()));
eventPlan.add(0,
EventFactory.createDefaultWaitForRpcEvent(45, "getFeatures"));
eventPlan.add(0, EventFactory.createDefaultRpcResponseEvent(45,
(short) 0x01, getFeatureResponseMsg()));
executeNow();
Assert.assertEquals(ConnectionConductor.CONDUCTOR_STATE.WORKING,
connectionConductor.getConductorState());
Assert.assertEquals((short) 0x01, connectionConductor.getVersion()
.shortValue());
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onFlowRemovedMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage)}
* .
*
* @throws InterruptedException
*/
@Test
public void testOnFlowRemovedMessage() throws InterruptedException {
FlowRemovedMessageService objFms = new FlowRemovedMessageService();
controller.addMessageTranslator(FlowRemovedMessage.class, 4, objFms);
simulateV13PostHandshakeState(connectionConductor);
objFms.resetLatch(2);
// Now send Flow Removed messages
FlowRemovedMessageBuilder builder1 = new FlowRemovedMessageBuilder();
builder1.setVersion((short) 4);
builder1.setXid(1L);
connectionConductor.onFlowRemovedMessage(builder1.build());
LOG.debug("about to wait for popListener");
builder1.setXid(2L);
connectionConductor.onFlowRemovedMessage(builder1.build());
flushMessageProcessing();
Assert.assertTrue(objFms.await(maxProcessingTimeout, TimeUnit.MILLISECONDS));
Assert.assertEquals(2, flowremovedMessageCounter);
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onMultipartReplyMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage)}
* .
*/
@Test
public void testOnMultipartReplyMessage() {
// fail("Not yet implemented");
// TODO:: add test
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPacketInMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage)}
* .
*
* @throws InterruptedException
*/
@Test
public void testOnPacketInMessage() throws InterruptedException {
PacketInMessageService objPms = new PacketInMessageService();
controller.addMessageTranslator(PacketInMessage.class, 4, objPms);
simulateV13PostHandshakeState(connectionConductor);
// Now send PacketIn
PacketInMessageBuilder builder1 = new PacketInMessageBuilder();
builder1.setVersion((short) 4);
builder1.setBufferId((long) 1);
connectionConductor.onPacketInMessage(builder1.build());
builder1.setBufferId((long) 2);
connectionConductor.onPacketInMessage(builder1.build());
flushMessageProcessing();
Assert.assertTrue(objPms.await(maxProcessingTimeout, TimeUnit.MILLISECONDS));
Assert.assertEquals(2, packetinMessageCounter);
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onPortStatusMessage(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage)}
* .
*
* @throws InterruptedException
*/
@Test
public void testOnPortStatusMessage() throws InterruptedException {
PortStatusMessageService objPSms = new PortStatusMessageService();
controller.addMessageTranslator(PortStatusMessage.class, 4, objPSms);
simulateV13PostHandshakeState(connectionConductor);
// Send Port Status messages
PortStatusMessageBuilder builder1 = new PortStatusMessageBuilder();
builder1.setVersion((short) 4);
PortFeatures features = new PortFeatures(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false);
builder1.setPortNo(90L).setReason(PortReason.OFPPRADD).setCurrentFeatures(features);
objPSms.resetLatch(3);
LOG.debug("sending port message");
connectionConductor.onPortStatusMessage(builder1.build());
builder1.setPortNo(90L).setReason(PortReason.OFPPRMODIFY).setCurrentFeatures(features);
connectionConductor.onPortStatusMessage(builder1.build());
builder1.setPortNo(90L).setReason(PortReason.OFPPRDELETE).setCurrentFeatures(features);
connectionConductor.onPortStatusMessage(builder1.build());
flushMessageProcessing();
Assert.assertTrue(objPSms.await(maxProcessingTimeout, TimeUnit.MILLISECONDS));
Assert.assertEquals(1, portstatusModifyMessageCounter);
Assert.assertEquals(1, portstatusAddMessageCounter);
Assert.assertEquals(1, portstatusDeleteMessageCounter);
}
private void flushMessageProcessing() throws InterruptedException {
// make sure that harvester sleeps deeply
Thread.sleep(maxProcessingTimeout);
// flushing messages
queueProcessor.getHarvesterHandle().ping();
}
/**
* @throws InterruptedException
*/
private void executeLater() throws InterruptedException {
execute(false);
}
/**
* @throws InterruptedException
*/
private void executeNow() throws InterruptedException {
execute(true);
connectionConductor.getHsPool().shutdown();
}
/**
* @throws InterruptedException
*/
private void execute(final boolean join) throws InterruptedException {
libSimulation = new Thread(adapter, "junit-adapter");
libSimulation.start();
if (join) {
libSimulation.join();
}
}
private static GetFeaturesOutputBuilder getFeatureResponseMsg() {
GetFeaturesOutputBuilder getFeaturesOutputBuilder = new GetFeaturesOutputBuilder();
getFeaturesOutputBuilder.setDatapathId(new BigInteger("102030405060"));
getFeaturesOutputBuilder.setAuxiliaryId((short) 0);
getFeaturesOutputBuilder.setBuffers(4L);
getFeaturesOutputBuilder.setReserved(0L);
getFeaturesOutputBuilder.setTables((short) 2);
getFeaturesOutputBuilder.setCapabilities(createCapabilities(84));
return getFeaturesOutputBuilder;
}
/**
* @return
*/
private static Capabilities createCapabilities(final long input) {
final Boolean FLOW_STATS = (input & (1 << 0)) != 0;
final Boolean TABLE_STATS = (input & (1 << 1)) != 0;
final Boolean PORT_STATS = (input & (1 << 2)) != 0;
final Boolean GROUP_STATS = (input & (1 << 3)) != 0;
final Boolean IP_REASM = (input & (1 << 5)) != 0;
final Boolean QUEUE_STATS = (input & (1 << 6)) != 0;
final Boolean PORT_BLOCKED = (input & (1 << 8)) != 0;
Capabilities capabilities = new Capabilities(FLOW_STATS, GROUP_STATS, IP_REASM,
PORT_BLOCKED, PORT_STATS, QUEUE_STATS, TABLE_STATS);
return capabilities;
}
public abstract class ProcessingLatchService {
private CountDownLatch processingLatch = new CountDownLatch(0);
public void resetLatch(int passAmount) {
processingLatch = new CountDownLatch(passAmount);
}
protected void countDown() {
processingLatch.countDown();
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return processingLatch.await(timeout, unit);
}
}
public class ExperimenterMessageService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
@Override
public List<DataObject> translate(final SwitchConnectionDistinguisher cookie, final SessionContext sw, final OfHeader msg) {
LOG.debug("Received a packet in Experimenter Service");
ConnectionConductorImplTest.this.incrExperimenterMessageCounter();
return null;
}
}
public class PacketInMessageService extends ProcessingLatchService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
@Override
public List<DataObject> translate(final SwitchConnectionDistinguisher cookie, final SessionContext sw, final OfHeader msg) {
LOG.debug("Received a packet in PacketIn Service");
ConnectionConductorImplTest.this.incrPacketinMessageCounter();
countDown();
return null;
}
}
public class FlowRemovedMessageService extends ProcessingLatchService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
@Override
public List<DataObject> translate(final SwitchConnectionDistinguisher cookie, final SessionContext sw, final OfHeader msg) {
LOG.debug("Received a packet in FlowRemoved Service");
ConnectionConductorImplTest.this.incrFlowremovedMessageCounter();
countDown();
return null;
}
}
public class PortStatusMessageService extends ProcessingLatchService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
@Override
public List<DataObject> translate(final SwitchConnectionDistinguisher cookie, final SessionContext sw, final OfHeader msg) {
LOG.debug("Received a packet in PortStatus Service");
if ((((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRADD))) {
ConnectionConductorImplTest.this.incrPortstatusAddMessageCounter();
} else if (((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRDELETE)) {
ConnectionConductorImplTest.this.incrPortstatusDeleteMessageCounter();
} else if (((PortStatusMessage) msg).getReason().equals(PortReason.OFPPRMODIFY)) {
ConnectionConductorImplTest.this.incrPortstatusModifyMessageCounter();
}
countDown();
return null;
}
}
public class ErrorMessageService extends ProcessingLatchService implements IMDMessageTranslator<OfHeader, List<DataObject>> {
@Override
public List<DataObject> translate(final SwitchConnectionDistinguisher cookie, final SessionContext sw, final OfHeader msg) {
LOG.debug("Received a packet in Experimenter Service");
ConnectionConductorImplTest.this.incrErrorMessageCounter();
countDown();
return null;
}
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#onExperimenterMessage(ExperimenterMessage)}
* .
*
* @throws InterruptedException
*/
@Test
public void testOnErrorMessage() throws InterruptedException {
simulateV13PostHandshakeState(connectionConductor);
final int messageAmount = 2;
objErms.resetLatch(messageAmount);
ErrorMessageBuilder builder1 = new ErrorMessageBuilder();
builder1.setVersion((short) 4);
builder1.setCode(100);
connectionConductor.onErrorMessage(builder1.build());
builder1.setCode(200);
connectionConductor.onErrorMessage(builder1.build());
flushMessageProcessing();
Assert.assertTrue(objErms.await(maxProcessingTimeout, TimeUnit.MILLISECONDS));
Assert.assertEquals(messageAmount, errorMessageCounter);
}
/**
* @return listener mapping for:
* <ul>
* <li>experimenter</li>
* <li>error</li>
* </ul>
*/
private Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> assembleTranslatorMapping() {
Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping = new HashMap<>();
TranslatorKey tKey;
IMDMessageTranslator<OfHeader, List<DataObject>> objEms = new ExperimenterMessageService();
Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> existingValues = new ArrayList<>();
existingValues.add(objEms);
tKey = new TranslatorKey(4, ExperimenterMessage.class.getName());
translatorMapping.put(tKey, existingValues);
objErms = new ErrorMessageService();
existingValues.add(objErms);
tKey = new TranslatorKey(4, ErrorMessage.class.getName());
translatorMapping.put(tKey, existingValues);
return translatorMapping;
}
/**
* Test method for
* {@link org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductorImpl#processPortStatusMsg(PortStatus)}
* <br><br>
* Tests for getting features from port status message by port version
* <ul>
* <li>features are malformed - one of them is null</li>
* <li>mismatch between port version and port features</li>
* <li>mismatch between port version and port features</li>
* <li>non-existing port version</li>
* <li>port version OF 1.0</li>
* <li>port version OF 1.3</li>
* </ul>
*/
@Test
public void testProcessPortStatusMsg() {
simulateV13PostHandshakeState(connectionConductor);
long portNumber = 90L;
long portNumberV10 = 91L;
PortStatusMessage msg;
PortStatusMessageBuilder builder = new PortStatusMessageBuilder();
PortFeatures features = new PortFeatures(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false);
PortFeatures featuresMal = new PortFeatures(true, false, false, false, null, false, false, false, false, false, false, false, false, false, false, false);
PortFeaturesV10 featuresV10 = new PortFeaturesV10(true, false, false, false, false, false, false, false, false, false, false, false);
//Malformed features
builder.setVersion((short) 1).setPortNo(portNumber).setReason(PortReason.OFPPRADD).setCurrentFeatures(featuresMal);
connectionConductor.processPortStatusMsg(builder.build());
Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
//Version-features mismatch
builder.setCurrentFeatures(features);
connectionConductor.processPortStatusMsg(builder.build());
Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
//Non existing version
builder.setVersion((short) 0);
connectionConductor.processPortStatusMsg(builder.build());
Assert.assertTrue(connectionConductor.getSessionContext().getPortsBandwidth().isEmpty());
Assert.assertTrue(connectionConductor.getSessionContext().getPhysicalPorts().isEmpty());
//Version OF 1.3
builder.setVersion((short) 4);
msg = builder.build();
connectionConductor.processPortStatusMsg(builder.build());
Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumber));
Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumber), msg);
//Version OF 1.0
builder.setVersion((short) 1).setPortNo(portNumberV10).setCurrentFeatures(null).setCurrentFeaturesV10(featuresV10);
msg = builder.build();
connectionConductor.processPortStatusMsg(builder.build());
Assert.assertTrue(connectionConductor.getSessionContext().getPortBandwidth(portNumberV10));
Assert.assertEquals(connectionConductor.getSessionContext().getPhysicalPort(portNumberV10), msg);
}
@Test
public void testHandshakeFailOperations(){
connectionConductor.onHandshakeFailure();
connectionConductor.checkState(ConnectionConductor.CONDUCTOR_STATE.RIP);
}
private static void simulateV13PostHandshakeState(final ConnectionConductorImpl conductor) {
GetFeaturesOutputBuilder featureOutput = getFeatureResponseMsg();
conductor.postHandshakeBasic(featureOutput.build(), OFConstants.OFP_VERSION_1_3);
LOG.debug("simulating post handshake event done");
}
}