/**
* Copyright 2013, Big Switch Networks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
**/
package net.floodlightcontroller.core.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import net.floodlightcontroller.core.IOFConnectionBackend;
import net.floodlightcontroller.core.IOFSwitchBackend;
import net.floodlightcontroller.core.LogicalOFMessageCategory;
import net.floodlightcontroller.core.PortChangeEvent;
import net.floodlightcontroller.core.PortChangeType;
import net.floodlightcontroller.core.SwitchDescription;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
import net.floodlightcontroller.core.internal.IOFSwitchManager;
import net.floodlightcontroller.core.internal.OFSwitch;
import net.floodlightcontroller.core.internal.SwitchManagerCounters;
import net.floodlightcontroller.debugcounter.DebugCounterServiceImpl;
import net.floodlightcontroller.debugcounter.IDebugCounterService;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortFeatures;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortState;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFPort;
public class OFSwitchBaseTest {
IOFSwitchManager switchManager;
Map<DatapathId, IOFSwitchBackend> switches;
//OFFactory factory = OFFactories.getFactory(OFVersion.OF_10);
private OFMessage testMessage;
private static class OFSwitchTest extends OFSwitch {
public OFSwitchTest(IOFConnectionBackend connection, IOFSwitchManager switchManager) {
super(connection, OFFactories.getFactory(OFVersion.OF_13), switchManager, DatapathId.of(1));
}
@Override
public void setSwitchProperties(SwitchDescription description) {
}
@Override
public OFFactory getOFFactory() {
return OFFactories.getFactory(OFVersion.OF_13);
}
@Override
public String toString() {
return "OFSwitchTest";
}
}
private OFSwitchTest sw;
private OFPortDesc p1a;
private OFPortDesc p1b;
private OFPortDesc p2a;
private OFPortDesc p2b;
private OFPortDesc p3;
private final OFPortDesc portFoo1 = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc().setPortNo(OFPort.of(11)).setName("foo").build();
private final OFPortDesc portFoo2 = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc().setPortNo(OFPort.of(12)).setName("foo").build();
private final OFPortDesc portBar1 = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc().setPortNo(OFPort.of(11)).setName("bar").build();
private final OFPortDesc portBar2 = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc().setPortNo(OFPort.of(12)).setName("bar").build();
private final PortChangeEvent portFoo1Add =
new PortChangeEvent(portFoo1, PortChangeType.ADD);
private final PortChangeEvent portFoo2Add =
new PortChangeEvent(portFoo2, PortChangeType.ADD);
private final PortChangeEvent portBar1Add =
new PortChangeEvent(portBar1, PortChangeType.ADD);
private final PortChangeEvent portBar2Add =
new PortChangeEvent(portBar2, PortChangeType.ADD);
private final PortChangeEvent portFoo1Del =
new PortChangeEvent(portFoo1, PortChangeType.DELETE);
private final PortChangeEvent portFoo2Del =
new PortChangeEvent(portFoo2, PortChangeType.DELETE);
private final PortChangeEvent portBar1Del =
new PortChangeEvent(portBar1, PortChangeType.DELETE);
private final PortChangeEvent portBar2Del =
new PortChangeEvent(portBar2, PortChangeType.DELETE);
private Capture<Iterable<OFMessage>> capturedMessage;
private OFFactory factory;
@Before
public void setUp() throws Exception {
// Build our test packet
IDebugCounterService debugCounter = new DebugCounterServiceImpl();
switchManager = createMock(IOFSwitchManager.class);
SwitchManagerCounters counters = new SwitchManagerCounters(debugCounter);
expect(switchManager.getCounters()).andReturn(counters).anyTimes();
replay(switchManager);
factory = OFFactories.getFactory(OFVersion.OF_13);
testMessage = factory.buildRoleReply()
.setXid(1)
.setRole(OFControllerRole.ROLE_MASTER)
.build();
IOFConnectionBackend conn = EasyMock.createNiceMock(IOFConnectionBackend.class);
capturedMessage = EasyMock.newCapture();
expect(conn.write(EasyMock.capture(capturedMessage))).andReturn(Collections.<OFMessage>emptyList()).atLeastOnce();
expect(conn.getOFFactory()).andReturn(factory).anyTimes();
expect(conn.getAuxId()).andReturn(OFAuxId.MAIN).anyTimes();
EasyMock.replay(conn);
IOFConnectionBackend auxConn = EasyMock.createNiceMock(IOFConnectionBackend.class);
expect(auxConn.getOFFactory()).andReturn(factory).anyTimes();
expect(auxConn.getAuxId()).andReturn(OFAuxId.of(1)).anyTimes();
expect(auxConn.write(EasyMock.capture(capturedMessage))).andReturn(Collections.<OFMessage>emptyList()).once();
EasyMock.replay(auxConn);
sw = new OFSwitchTest(conn, switchManager);
sw.registerConnection(auxConn);
sw.setControllerRole(OFControllerRole.ROLE_MASTER); /* must supply role now, otherwise write() will be blocked if not master/equal/other */
switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>();
switches.put(sw.getId(), sw);
reset(switchManager);
//expect(switchManager.getSwitch(sw.getId())).andReturn(sw).anyTimes();
setUpPorts();
}
public void setUpPorts() {
OFPortDesc.Builder pdb = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc();
// p1a is disabled
pdb.setName("port1");
pdb.setPortNo(OFPort.of(1));
Set<OFPortState> portState = new HashSet<OFPortState>();
portState.add(OFPortState.LINK_DOWN);
pdb.setState(portState);
p1a = pdb.build();
assertFalse("Sanity check portEnabled", !p1a.getState().contains(OFPortState.LINK_DOWN));
// p1b is enabled
// p1b has different feature from p1a
pdb = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc();
pdb.setName("port1");
pdb.setPortNo(OFPort.of(1));
Set<OFPortFeatures> portFeatures = new HashSet<OFPortFeatures>();
portFeatures.add(OFPortFeatures.PF_1GB_FD);
pdb.setCurr(portFeatures);
p1b = pdb.build();
assertTrue("Sanity check portEnabled", !p1b.getState().contains(OFPortState.LIVE));
// p2 is disabled
// p2 has mixed case
pdb = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc();
portState = new HashSet<OFPortState>();
Set<OFPortConfig> portConfig = new HashSet<OFPortConfig>();
portFeatures = new HashSet<OFPortFeatures>();
pdb.setName("Port2");
pdb.setPortNo(OFPort.of(2));
portConfig.add(OFPortConfig.PORT_DOWN);
pdb.setConfig(portConfig);
p2a = pdb.build();
// p2b only differs in PortFeatures
pdb = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc();
portState = new HashSet<OFPortState>();
portConfig = new HashSet<OFPortConfig>();
portFeatures = new HashSet<OFPortFeatures>();
pdb.setName("Port2");
pdb.setPortNo(OFPort.of(2));
portConfig.add(OFPortConfig.PORT_DOWN);
pdb.setConfig(portConfig);
portFeatures.add(OFPortFeatures.PF_100MB_HD);
pdb.setCurr(portFeatures);
p2b = pdb.build();
assertFalse("Sanity check portEnabled", p2a.getState().contains(OFPortState.LIVE));
// p3 is enabled
// p3 has mixed case
pdb = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc();
pdb.setName("porT3");
pdb.setPortNo(OFPort.of(3));
p3 = pdb.build();
assertTrue("Sanity check portEnabled", !p3.getState().contains(OFPortState.LINK_DOWN));
}
/**
* Test whether two collections contains the same elements, regardless
* of the order in which the elements appear in the collections
* @param expected
* @param actual
*/
private static <T> void assertCollectionEqualsNoOrder(Collection<T> expected,
Collection<T> actual) {
String msg = String.format("expected=%s, actual=%s",
expected.toString(), actual.toString());
assertEquals(msg, expected.size(), actual.size());
for(T e: expected) {
if (!actual.contains(e)) {
msg = String.format("Expected element %s not found in " +
"actual. expected=%s, actual=%s",
e, expected, actual);
fail(msg);
}
}
}
/**
* Test "normal" setPorts() and comparePorts() methods. No name<->number
* conflicts or exception testing.
*/
@Test
public void testBasicSetPortOperations() {
Collection<OFPortDesc> oldPorts = Collections.emptyList();
Collection<OFPortDesc> oldEnabledPorts = Collections.emptyList();
Collection<OFPort> oldEnabledPortNumbers = Collections.emptyList();
List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
Collection<PortChangeEvent> expectedChanges =
new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = sw.comparePorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
//---------------------------------------------
// Add port p1a and p2a
ports.add(p1a);
ports.add(p2a);
PortChangeEvent evP1aAdded =
new PortChangeEvent(p1a, PortChangeType.ADD);
PortChangeEvent evP2aAdded =
new PortChangeEvent(p2a, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1aAdded);
expectedChanges.add(evP2aAdded);
actualChanges = sw.comparePorts(ports);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
actualChanges = sw.setPorts(ports);
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(3)));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Set the same ports again. No changes
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
expectedChanges.clear();
actualChanges = sw.comparePorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(3)));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1a, add p1b. Should receive a port up
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2a);
ports.add(p1b);
// comparePorts
PortChangeEvent evP1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertEquals(1, actualChanges.size());
assertTrue("No UP event for port1", actualChanges.contains(evP1bUp));
// setPorts
actualChanges = sw.setPorts(ports);
assertEquals(1, actualChanges.size());
assertTrue("No UP event for port1", actualChanges.contains(evP1bUp));
assertCollectionEqualsNoOrder(ports, sw.getPorts());
List<OFPortDesc> enabledPorts = new ArrayList<OFPortDesc>();
enabledPorts.add(p1b);
List<OFPort> enabledPortNumbers = new ArrayList<OFPort>();
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(3)));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p2a, add p2b. Should receive a port modify
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2b);
ports.add(p1b);
PortChangeEvent evP2bModified =
new PortChangeEvent(p2b, PortChangeType.OTHER_UPDATE);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertEquals(1, actualChanges.size());
assertTrue("No OTHER_CHANGE event for port2",
actualChanges.contains(evP2bModified));
// setPorts
actualChanges = sw.setPorts(ports);
assertEquals(1, actualChanges.size());
assertTrue("No OTHER_CHANGE event for port2",
actualChanges.contains(evP2bModified));
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts = new ArrayList<OFPortDesc>();
enabledPorts.add(p1b);
enabledPortNumbers = new ArrayList<OFPort>();
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort(OFPort.of(2)));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(3)));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1b, add p1a. Should receive a port DOWN
// Remove p2b, add p2a. Should receive a port modify
// Add p3, should receive an add
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2a);
ports.add(p1a);
ports.add(p3);
PortChangeEvent evP1aDown =
new PortChangeEvent(p1a, PortChangeType.DOWN);
PortChangeEvent evP2aModified =
new PortChangeEvent(p2a, PortChangeType.OTHER_UPDATE);
PortChangeEvent evP3Add =
new PortChangeEvent(p3, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1aDown);
expectedChanges.add(evP2aModified);
expectedChanges.add(evP3Add);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
// setPorts
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add(OFPort.of(3));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort(OFPort.of(3)));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1b Should receive a port DELETE
// Remove p2b Should receive a port DELETE
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p3);
PortChangeEvent evP1aDel =
new PortChangeEvent(p1a, PortChangeType.DELETE);
PortChangeEvent evP2aDel =
new PortChangeEvent(p2a, PortChangeType.DELETE);
expectedChanges.clear();
expectedChanges.add(evP1aDel);
expectedChanges.add(evP2aDel);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
// setPorts
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add(OFPort.of(3));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p3, sw.getPort(OFPort.of(3)));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
}
/**
* Test "normal" OFPortStatus handling. No name<->number
* conflicts or exception testing.
*/
@Test
public void testBasicPortStatusOperation() {
OFPortStatus.Builder builder = sw.getOFFactory().buildPortStatus();
List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
ports.add(p1a);
ports.add(p2a);
// Set p1a and p2a as baseline
PortChangeEvent evP1aAdded =
new PortChangeEvent(p1a, PortChangeType.ADD);
PortChangeEvent evP2aAdded =
new PortChangeEvent(p2a, PortChangeType.ADD);
Collection<PortChangeEvent> expectedChanges =
new ArrayList<PortChangeEvent>();
expectedChanges.add(evP1aAdded);
expectedChanges.add(evP2aAdded);
Collection<PortChangeEvent> actualChanges = sw.comparePorts(ports);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
actualChanges = sw.setPorts(ports);
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// P1a -> p1b. Should receive a port up
ports.clear();
ports.add(p2a);
ports.add(p1b);
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(p1b);
PortChangeEvent evP1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP1bUp);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
List<OFPortDesc> enabledPorts = new ArrayList<OFPortDesc>();
enabledPorts.add(p1b);
List<OFPort> enabledPortNumbers = new ArrayList<OFPort>();
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// p2a -> p2b. Should receive a port modify
ports.clear();
ports.add(p2b);
ports.add(p1b);
PortChangeEvent evP2bModified =
new PortChangeEvent(p2b, PortChangeType.OTHER_UPDATE);
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(p2b);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP2bModified);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts = new ArrayList<OFPortDesc>();
enabledPorts.add(p1b);
enabledPortNumbers = new ArrayList<OFPort>();
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort(OFPort.of(2)));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(3)));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// p1b -> p1a. Via an ADD, Should receive a port DOWN
ports.clear();
ports.add(p2b);
ports.add(p1a);
// we use an ADD here. We treat ADD and MODIFY the same way
builder.setReason(OFPortReason.ADD);
builder.setDesc(p1a);
PortChangeEvent evP1aDown =
new PortChangeEvent(p1a, PortChangeType.DOWN);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP1aDown);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort(OFPort.of(2)));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// p2b -> p2a. Via an ADD, Should receive a port MODIFY
ports.clear();
ports.add(p2a);
ports.add(p1a);
// we use an ADD here. We treat ADD and MODIFY the same way
builder.setReason(OFPortReason.ADD);
builder.setDesc(p2a);
PortChangeEvent evP2aModify =
new PortChangeEvent(p2a, PortChangeType.OTHER_UPDATE);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP2aModify);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort(OFPort.of(2)));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p2a
ports.clear();
ports.add(p1a);
builder.setReason(OFPortReason.DELETE);
builder.setDesc(p2a);
PortChangeEvent evP2aDel =
new PortChangeEvent(p2a, PortChangeType.DELETE);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP2aDel);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p2a again. Nothing should happen.
ports.clear();
ports.add(p1a);
builder.setReason(OFPortReason.DELETE);
builder.setDesc(p2a);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort(OFPort.of(1)));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p1a
ports.clear();
builder.setReason(OFPortReason.DELETE);
builder.setDesc(p1a);
PortChangeEvent evP1aDel =
new PortChangeEvent(p1a, PortChangeType.DELETE);
actualChanges = sw.processOFPortStatus(builder.build());
expectedChanges.clear();
expectedChanges.add(evP1aDel);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(null, sw.getPort(OFPort.of(1)));
assertEquals(null, sw.getPort("port1"));
assertEquals(null, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Add p3, should receive an add
ports.clear();
ports.add(p3);
PortChangeEvent evP3Add =
new PortChangeEvent(p3, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP3Add);
builder.setReason(OFPortReason.ADD);
builder.setDesc(p3);
actualChanges = sw.processOFPortStatus(builder.build());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add(OFPort.of(3));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(null, sw.getPort(OFPort.of(1)));
assertEquals(null, sw.getPort("port1"));
assertEquals(null, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort(OFPort.of(3)));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Add p1b, back should receive an add
ports.clear();
ports.add(p1b);
ports.add(p3);
PortChangeEvent evP1bAdd =
new PortChangeEvent(p1b, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1bAdd);
// use a modify to add the port
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(p1b);
actualChanges = sw.processOFPortStatus(builder.build());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPorts.add(p1b);
enabledPortNumbers.clear();
enabledPortNumbers.add(OFPort.of(3));
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort(OFPort.of(3)));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Modify, but nothing really changed
ports.clear();
ports.add(p1b);
ports.add(p3);
expectedChanges.clear();
// use a modify to add the port
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(p1b);
actualChanges = sw.processOFPortStatus(builder.build());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPorts.add(p1b);
enabledPortNumbers.clear();
enabledPortNumbers.add(OFPort.of(3));
enabledPortNumbers.add(OFPort.of(1));
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort(OFPort.of(1)));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort(OFPort.of(2)));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort(OFPort.of(3)));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
}
/**
* Test exception handling for setPorts() and comparePorts()
*/
@Test
public void testSetPortExceptions() {
try {
sw.setPorts(null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
// two ports with same name
List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(2)).build());
try {
sw.setPorts(ports);
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { };
// two ports with same number
ports.clear();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(sw.getOFFactory().buildPortDesc().setName("port2").setPortNo(OFPort.of(1)).build());
try {
sw.setPorts(ports);
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { };
// null port in list
ports.clear();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(null);
try {
sw.setPorts(ports);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
// try getPort(null)
try {
sw.getPort((String)null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
//--------------------------
// comparePorts()
try {
sw.comparePorts(null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
// two ports with same name
ports = new ArrayList<OFPortDesc>();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(2)).build());
try {
sw.comparePorts(ports);
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { };
// two ports with same number
ports.clear();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(sw.getOFFactory().buildPortDesc().setName("port2").setPortNo(OFPort.of(1)).build());
try {
sw.comparePorts(ports);
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { };
// null port in list
ports.clear();
ports.add(sw.getOFFactory().buildPortDesc().setName("port1").setPortNo(OFPort.of(1)).build());
ports.add(null);
try {
sw.comparePorts(ports);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
// try getPort(null)
try {
sw.getPort((String)null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { };
}
@Test
public void testPortStatusExceptions() {
OFPortStatus.Builder builder = sw.getOFFactory().buildPortStatus();
try {
sw.processOFPortStatus(null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { }
/* There's no way with the new LOXI openflowj to create messages with
* invalid fields.
// illegal reason code
builder.setReason((byte)0x42);
builder.setDesc(ImmutablePort.create("p1", OFPort.of(1)).toOFPortDesc(sw));
try {
sw.processOFPortStatus(builder.build());
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { }
*/
// null port
builder.setReason(OFPortReason.ADD);
builder.setDesc(null);
try {
sw.processOFPortStatus(builder.build());
fail("Expected exception not thrown");
} catch (NullPointerException e) { }
}
/**
* Assert that the expected PortChangeEvents have been recevied, asserting
* the expected ordering.
*
* All events in earlyEvents have to appear in actualEvents before any
* event in lateEvent appears. Events in anytimeEvents can appear at any
* given time. earlyEvents, lateEvents, and anytimeEvents must be mutually
* exclusive (their intersection must be none) and their union must
* contain all elements from actualEvents
* @param earlyEvents
* @param lateEvents
* @param anytimeEvents
* @param actualEvents
*/
private static void assertChangeEvents(Collection<PortChangeEvent> earlyEvents,
Collection<PortChangeEvent> lateEvents,
Collection<PortChangeEvent> anytimeEvents,
Collection<PortChangeEvent> actualEvents) {
String inputDesc = String.format("earlyEvents=%s, lateEvents=%s, " +
"anytimeEvents=%s, actualEvents=%s",
earlyEvents.toString(), lateEvents.toString(), anytimeEvents.toString(), actualEvents.toString());
// Make copies of expected lists, so we can modify them
Collection<PortChangeEvent> early =
new ArrayList<PortChangeEvent>(earlyEvents);
Collection<PortChangeEvent> late =
new ArrayList<PortChangeEvent>(lateEvents);
Collection<PortChangeEvent> any =
new ArrayList<PortChangeEvent>(anytimeEvents);
// Sanity check: no overlap between early, late, and anytime events
for (PortChangeEvent ev: early) {
assertFalse("Test setup error. Early and late overlap",
late.contains(ev));
assertFalse("Test setup error. Early and anytime overlap",
any.contains(ev));
}
for (PortChangeEvent ev: late) {
assertFalse("Test setup error. Late and early overlap",
early.contains(ev));
assertFalse("Test setup error. Late and any overlap",
any.contains(ev));
}
for (PortChangeEvent ev: any) {
assertFalse("Test setup error. Anytime and early overlap",
early.contains(ev));
assertFalse("Test setup error. Anytime and late overlap",
late.contains(ev));
}
for (PortChangeEvent a: actualEvents) {
if (early.remove(a)) {
continue;
}
if (any.remove(a)) {
continue;
}
if (late.remove(a)) {
if (!early.isEmpty()) {
fail(a + " is in late list, but haven't seen all required " +
"early events. " + inputDesc);
} else {
continue;
}
}
fail(a + " was not expected. " + inputDesc);
}
if (!early.isEmpty())
fail("Elements left in early: " + early + ". " + inputDesc);
if (!late.isEmpty())
fail("Elements left in late: " + late + ". " + inputDesc);
if (!any.isEmpty())
fail("Elements left in any: " + any + ". " + inputDesc);
}
/**
* Test setPort() with changing name / number mappings
* We don't test comparePorts() here. We assume setPorts() and
* comparePorts() use the same underlying implementation
*/
@Test
public void testSetPortNameNumberMappingChange() {
List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
Collection<PortChangeEvent> early = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> late = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> anytime = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = null;
ports.add(portFoo1);
ports.add(p1a);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo2: name collision
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo1Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portBar2: number collision
ports.clear();
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo2Del);
late.add(portBar2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2. No collisions in this step
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
anytime.add(portFoo1Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo2: name and number collision
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo1Del);
early.add(portBar2Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo2, portBar1. No collisions in this step
ports.clear();
ports.add(portFoo2);
ports.add(portBar1);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
anytime.add(portBar1Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo1, portBar2 name and number collision
// Also change p1a -> p1b: expect modify for it
// Also add p3: expect add for it
PortChangeEvent p1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
PortChangeEvent p3Add = new PortChangeEvent(p3, PortChangeType.ADD);
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
ports.add(p1b);
ports.add(p3);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo2Del);
early.add(portBar1Del);
late.add(portFoo1Add);
late.add(portBar2Add);
anytime.add(p1bUp);
anytime.add(p3Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
}
@Test
public void testPortStatusNameNumberMappingChange() {
List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
Collection<PortChangeEvent> early = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> late = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> anytime = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = null;
// init: add portFoo1, p1a
ports.add(portFoo1);
ports.add(p1a);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
OFPortStatus.Builder builder = sw.getOFFactory().buildPortStatus();
// portFoo1 -> portFoo2 via MODIFY : name collision
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(portFoo2);
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
early.add(portFoo1Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// portFoo2 -> portBar2 via ADD number collision
builder.setReason(OFPortReason.ADD);
builder.setDesc(portBar2);
ports.clear();
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
early.add(portFoo2Del);
late.add(portBar2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// portFoo1 + portBar2 -> portFoo2: name and number collision
builder.setReason(OFPortReason.MODIFY);
builder.setDesc(portFoo2);
ports.clear();
ports.add(portFoo2);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
early.add(portFoo1Del);
early.add(portBar2Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
//----------------------
// Test DELETEs
// del portFoo1: name exists (portFoo2), but number doesn't.
builder.setReason(OFPortReason.DELETE);
builder.setDesc(portFoo1);
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
anytime.add(portFoo2Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1
ports.clear();
ports.add(portFoo1);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// del portBar1: number exists (portFoo1), but name doesn't.
builder.setReason(OFPortReason.DELETE);
builder.setDesc(portBar1);
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
anytime.add(portFoo1Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// del portFoo2: name and number exists
builder.setReason(OFPortReason.DELETE);
builder.setDesc(portFoo2);
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(builder.build());
anytime.add(portFoo1Del);
anytime.add(portBar2Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
}
@Test
public void testSubHandshake() {
OFMessage m = sw.getOFFactory().buildRoleReply()
.setXid(1)
.setRole(OFControllerRole.ROLE_MASTER)
.build();
// test execptions before handshake is started
try {
sw.processDriverHandshakeMessage(m);
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeNotStarted e) { /* expected */ }
try {
sw.isDriverHandshakeComplete();
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeNotStarted e) { /* expected */ }
// start the handshake -- it should immediately complete
sw.startDriverHandshake();
assertTrue("Handshake should be complete",
sw.isDriverHandshakeComplete());
// test exceptions after handshake is completed
try {
sw.processDriverHandshakeMessage(m);
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeCompleted e) { /* expected */ }
try {
sw.startDriverHandshake();
fail("Expected exception not thrown");
} catch (SwitchDriverSubHandshakeAlreadyStarted e) { /* expected */ }
}
// This should throw an error
@Test
public void testMissingConnection() {
// Just to make sure so this test is worth it
assertFalse("Switch should not have a connection with auxId 5", sw.getConnections().contains(OFAuxId.of(5)));
try{
sw.getConnection(OFAuxId.of(5));
fail("Expected exception not thrown");
}
catch(IllegalArgumentException e){ /* expected */ }
}
// This should throw an error
@Test
public void testInvalidLogicalOFMessageCategory() {
LogicalOFMessageCategory bad = new LogicalOFMessageCategory("bad", 2);
assertFalse("Controller should not any logical OFMessage categories", switchManager.isCategoryRegistered(bad));
reset(switchManager);
expect(switchManager.isCategoryRegistered(bad)).andReturn(false);
replay(switchManager);
try{
sw.write(testMessage, bad);
fail("Expected exception not thrown");
}
catch(IllegalArgumentException e){ /* expected */ }
verify(switchManager);
}
// This should not throw an error
@Test
public void testValidLogicalOFMessageCategory() {
LogicalOFMessageCategory category = new LogicalOFMessageCategory("test", 1);
assertFalse("Controller should not have any logical OFMessage categories", switchManager.isCategoryRegistered(category));
reset(switchManager);
expect(switchManager.isCategoryRegistered(category)).andReturn(true);
switchManager.handleOutgoingMessage(sw, testMessage);
expectLastCall().once();
replay(switchManager);
sw.write(testMessage, category);
verify(switchManager);
}
@Test
public void testMasterSlaveWrites() {
OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
OFFlowAdd fa = factory.buildFlowAdd().build();
OFFlowStatsRequest fsr = factory.buildFlowStatsRequest().build();
List<OFMessage> msgList = new ArrayList<OFMessage>();
msgList.add(fa);
msgList.add(fsr);
reset(switchManager);
expect(switchManager.isCategoryRegistered(LogicalOFMessageCategory.MAIN)).andReturn(true).times(6);
switchManager.handleOutgoingMessage(sw, fa);
expectLastCall().times(2);
switchManager.handleOutgoingMessage(sw, fsr);
expectLastCall().times(4);
replay(switchManager);
/* test master -- both messages should be written */
sw.setControllerRole(OFControllerRole.ROLE_MASTER);
assertTrue(sw.write(fa));
assertTrue(sw.write(fsr));
assertEquals(Collections.<OFMessage>emptyList(), sw.write(msgList));
/* test slave -- flow-add (mod op) should fail each time; flow stats (read op) should pass */
sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
assertFalse(sw.write(fa)); /* flow-add should be stopped (mod op) */
assertTrue(sw.write(fsr)); /* stats request makes it (read op) */
assertEquals(Collections.<OFMessage>singletonList(fa), sw.write(msgList)); /* return bad flow-add */
}
}