/**
* Copyright 2011, Big Switch Networks, Inc.
* Originally created by David Erickson, Stanford University
*
* 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.createNiceMock;
import static org.easymock.EasyMock.createStrictMock;
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.easymock.EasyMock.anyObject;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import io.netty.util.Timer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import net.floodlightcontroller.core.HARole;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitch.SwitchStatus;
import net.floodlightcontroller.core.IOFSwitchBackend;
import net.floodlightcontroller.core.IOFSwitchDriver;
import net.floodlightcontroller.core.IOFSwitchListener;
import net.floodlightcontroller.core.IShutdownListener;
import net.floodlightcontroller.core.IShutdownService;
import net.floodlightcontroller.core.LogicalOFMessageCategory;
import net.floodlightcontroller.core.PortChangeType;
import net.floodlightcontroller.core.SwitchDescription;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.debugcounter.IDebugCounterService;
import net.floodlightcontroller.debugcounter.MockDebugCounterService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.restserver.RestApiServer;
import net.floodlightcontroller.storage.IStorageSourceService;
import net.floodlightcontroller.storage.memory.MemoryStorageSource;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.floodlightcontroller.threadpool.ThreadPool;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortFeatures;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFPort;
import org.sdnplatform.sync.ISyncService;
import org.sdnplatform.sync.test.MockSyncService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
*
* @author David Erickson (daviderickson@cs.stanford.edu)
*/
public class OFSwitchManagerTest{
private Controller controller;
private OFSwitchManager switchManager;
// FIXME:LOJI: For now just work with OF 1.0
private final OFFactory factory = OFFactories.getFactory(OFVersion.OF_10);
private static DatapathId DATAPATH_ID_0 = DatapathId.of(0);
private static DatapathId DATAPATH_ID_1 = DatapathId.of(1);
@Before
public void setUp() throws Exception {
doSetUp(HARole.ACTIVE);
}
public void doSetUp(HARole role) throws Exception {
FloodlightModuleContext fmc = new FloodlightModuleContext();
FloodlightProvider cm = new FloodlightProvider();
fmc.addConfigParam(cm, "role", role.toString());
controller = (Controller)cm.getServiceImpls().get(IFloodlightProviderService.class);
fmc.addService(IFloodlightProviderService.class, controller);
MemoryStorageSource memstorage = new MemoryStorageSource();
fmc.addService(IStorageSourceService.class, memstorage);
RestApiServer restApi = new RestApiServer();
fmc.addService(IRestApiService.class, restApi);
ThreadPool threadPool = new ThreadPool();
fmc.addService(IThreadPoolService.class, threadPool);
// TODO: should mock IDebugCounterService and make sure
// the expected counters are updated.
MockDebugCounterService debugCounterService = new MockDebugCounterService();
fmc.addService(IDebugCounterService.class, debugCounterService);
switchManager = new OFSwitchManager();
fmc.addService(IOFSwitchService.class, switchManager);
MockSyncService syncService = new MockSyncService();
fmc.addService(ISyncService.class, syncService);
IShutdownService shutdownService = createMock(IShutdownService.class);
shutdownService.registerShutdownListener(anyObject(IShutdownListener.class));
expectLastCall().anyTimes();
replay(shutdownService);
fmc.addService(IShutdownService.class, shutdownService);
verify(shutdownService);
threadPool.init(fmc);
syncService.init(fmc);
switchManager.init(fmc);
debugCounterService.init(fmc);
memstorage.init(fmc);
restApi.init(fmc);
cm.init(fmc);
syncService.init(fmc);
switchManager.startUpBase(fmc);
debugCounterService.startUp(fmc);
memstorage.startUp(fmc);
threadPool.startUp(fmc);
restApi.startUp(fmc);
cm.startUp(fmc);
}
@After
public void tearDown(){
}
public Controller getController() {
return controller;
}
private static SwitchDescription createSwitchDescription() {
return new SwitchDescription();
}
private OFFeaturesReply createOFFeaturesReply(DatapathId datapathId) {
OFFeaturesReply fr = factory.buildFeaturesReply()
.setXid(0)
.setDatapathId(datapathId)
.setPorts(ImmutableList.<OFPortDesc>of())
.build();
return fr;
}
/** Set the mock expectations for sw when sw is passed to addSwitch
* The same expectations can be used when a new SwitchSyncRepresentation
* is created from the given mocked switch */
protected void setupSwitchForAddSwitch(IOFSwitch sw, DatapathId datapathId,
SwitchDescription description, OFFeaturesReply featuresReply) {
if (description == null) {
description = createSwitchDescription();
}
if (featuresReply == null) {
featuresReply = createOFFeaturesReply(datapathId);
}
List<OFPortDesc> ports = featuresReply.getPorts();
expect(sw.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_10)).anyTimes();
expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes();
expect(sw.getId()).andReturn(datapathId).anyTimes();
expect(sw.getSwitchDescription()).andReturn(description).anyTimes();
expect(sw.getBuffers())
.andReturn(featuresReply.getNBuffers()).anyTimes();
expect(sw.getNumTables())
.andReturn(featuresReply.getNTables()).anyTimes();
expect(sw.getCapabilities())
.andReturn(featuresReply.getCapabilities()).anyTimes();
expect(sw.getActions())
.andReturn(featuresReply.getActions()).anyTimes();
expect(sw.getPorts())
.andReturn(ports).anyTimes();
expect(sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true))
.andReturn(false).anyTimes();
expect(sw.getInetAddress()).andReturn(null).anyTimes();
}
@Test
/**
* Test switchActivated for a new switch, i.e., a switch that was not
* previously known to the controller cluser. We expect that all
* flow mods are cleared and we expect a switchAdded
*/
public void testNewSwitchActivated() throws Exception {
IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
setupSwitchForAddSwitch(sw, DATAPATH_ID_0, null, null);
// Ensure switch doesn't already exist
assertNull(switchManager.getSwitch(DATAPATH_ID_0));
// strict mock. Order of events matters!
IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class);
listener.switchAdded(DATAPATH_ID_0);
expectLastCall().once();
listener.switchActivated(DATAPATH_ID_0);
expectLastCall().once();
replay(listener);
switchManager.addOFSwitchListener(listener);
replay(sw);
switchManager.switchAdded(sw);
switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
verify(sw);
assertEquals(sw, switchManager.getSwitch(DATAPATH_ID_0));
controller.processUpdateQueueForTesting();
verify(listener);
}
/**
* Test switchActivated for a new switch while in slave: disconnect the switch
*/
@Test
public void testNewSwitchActivatedWhileSlave() throws Exception {
doSetUp(HARole.STANDBY);
IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
IOFSwitchListener listener = createMock(IOFSwitchListener.class);
switchManager.addOFSwitchListener(listener);
expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes();
expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes();
sw.disconnect();
expectLastCall().once();
expect(sw.getOFFactory()).andReturn(factory).once();
replay(sw, listener); // nothing recorded
switchManager.switchAdded(sw);
switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
verify(sw);
controller.processUpdateQueueForTesting();
verify(listener);
}
/**
* Create and activate a switch, either completely new or reconnected
* The mocked switch instance will be returned. It will be reset.
*/
private IOFSwitchBackend doActivateSwitchInt(DatapathId datapathId,
SwitchDescription description,
OFFeaturesReply featuresReply,
boolean clearFlows)
throws Exception {
IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
if (featuresReply == null) {
featuresReply = createOFFeaturesReply(datapathId);
}
if (description == null) {
description = createSwitchDescription();
}
setupSwitchForAddSwitch(sw, datapathId, description, featuresReply);
replay(sw);
switchManager.switchAdded(sw);
switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
verify(sw);
assertEquals(sw, switchManager.getSwitch(datapathId));
// drain updates and ignore
controller.processUpdateQueueForTesting();
reset(sw);
return sw;
}
/**
* Create and activate a new switch with the given dpid, features reply
* and description. If description and/or features reply are null we'll
* allocate the default one
* The mocked switch instance will be returned. It wil be reset.
*/
private IOFSwitchBackend doActivateNewSwitch(DatapathId dpid,
SwitchDescription description,
OFFeaturesReply featuresReply)
throws Exception {
return doActivateSwitchInt(dpid, description, featuresReply, true);
}
/**
* Remove a nonexisting switch. should be ignored
*/
@Test
public void testNonexistingSwitchDisconnected() throws Exception {
IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
expect(sw.getId()).andReturn(DATAPATH_ID_1).anyTimes();
IOFSwitchListener listener = createMock(IOFSwitchListener.class);
switchManager.addOFSwitchListener(listener);
replay(sw, listener);
switchManager.switchDisconnected(sw);
controller.processUpdateQueueForTesting();
verify(sw, listener);
assertNull(switchManager.getSwitch(DATAPATH_ID_1));
}
/**
* Try to remove a switch that's different from what's in the active
* switch map. Should be ignored
*/
@Test
public void testSwitchDisconnectedOther() throws Exception {
IOFSwitch origSw = doActivateNewSwitch(DATAPATH_ID_1, null, null);
// create a new mock switch
IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
expect(sw.getId()).andReturn(DATAPATH_ID_1).anyTimes();
IOFSwitchListener listener = createMock(IOFSwitchListener.class);
switchManager.addOFSwitchListener(listener);
replay(sw, listener);
switchManager.switchDisconnected(sw);
controller.processUpdateQueueForTesting();
verify(sw, listener);
expect(origSw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes();
replay(origSw);
assertSame(origSw, switchManager.getSwitch(DATAPATH_ID_1));
}
/**
* Try to activate a switch that's already active (which can happen if
* two different switches have the same DPIP or if a switch reconnects
* while the old TCP connection is still alive
*/
@Test
public void testSwitchActivatedWithAlreadyActiveSwitch() throws Exception {
SwitchDescription oldDescription = new SwitchDescription(
"", "", "", "", "Ye Olde Switch");
SwitchDescription newDescription = new SwitchDescription(
"", "", "", "", "The new Switch");
OFFeaturesReply featuresReply = createOFFeaturesReply(DATAPATH_ID_0);
// Setup: add a switch to the controller
IOFSwitchBackend oldsw = createMock(IOFSwitchBackend.class);
setupSwitchForAddSwitch(oldsw, DATAPATH_ID_0, oldDescription, featuresReply);
replay(oldsw);
switchManager.switchAdded(oldsw);
switchManager.switchStatusChanged(oldsw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
verify(oldsw);
// drain the queue, we don't care what's in it
controller.processUpdateQueueForTesting();
assertEquals(oldsw, switchManager.getSwitch(DATAPATH_ID_0));
// Now the actual test: add a new switch with the same dpid to
// the controller
reset(oldsw);
expect(oldsw.getId()).andReturn(DATAPATH_ID_0).anyTimes();
oldsw.cancelAllPendingRequests();
expectLastCall().once();
oldsw.disconnect();
expectLastCall().once();
IOFSwitchBackend newsw = createMock(IOFSwitchBackend.class);
setupSwitchForAddSwitch(newsw, DATAPATH_ID_0, newDescription, featuresReply);
// Strict mock. We need to get the removed notification before the
// add notification
IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class);
listener.switchRemoved(DATAPATH_ID_0);
listener.switchAdded(DATAPATH_ID_0);
listener.switchActivated(DATAPATH_ID_0);
replay(listener);
switchManager.addOFSwitchListener(listener);
replay(newsw, oldsw);
switchManager.switchAdded(newsw);
switchManager.switchStatusChanged(newsw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
verify(newsw, oldsw);
assertEquals(newsw, switchManager.getSwitch(DATAPATH_ID_0));
controller.processUpdateQueueForTesting();
verify(listener);
}
/**
* Tests that you can't remove a switch from the map returned by
* getSwitches() (because getSwitches should return an unmodifiable
* map)
*/
@Test
public void testRemoveActiveSwitch() {
IOFSwitchBackend sw = createNiceMock(IOFSwitchBackend.class);
setupSwitchForAddSwitch(sw, DATAPATH_ID_1, null, null);
replay(sw);
switchManager.switchAdded(sw);
switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
assertEquals(sw, switchManager.getSwitch(DATAPATH_ID_1));
try {
switchManager.getAllSwitchMap().remove(DATAPATH_ID_1);
fail("Expected: UnsupportedOperationException");
} catch(UnsupportedOperationException e) {
// expected
}
// we don't care for updates. drain queue.
controller.processUpdateQueueForTesting();
}
/**
* Tests that the switch manager should only return a switch to a getActiveSwitch
* call when the switch is visible/active.
*/
@Test
public void testGetActiveSwitch() {
MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN);
IOFSwitchBackend sw = new MockOFSwitchImpl(connection);
sw.setStatus(SwitchStatus.HANDSHAKE);
assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1));
switchManager.switchAdded(sw);
assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1));
sw.setStatus(SwitchStatus.MASTER);
assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1));
sw.setStatus(SwitchStatus.QUARANTINED);
assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1));
sw.setStatus(SwitchStatus.SLAVE);
assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1));
sw.setStatus(SwitchStatus.DISCONNECTED);
assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1));
// we don't care for updates. drain queue.
controller.processUpdateQueueForTesting();
}
/**
* Test that notifyPortChanged() results in an IOFSwitchListener
* update and that its arguments are passed through to
* the listener call
*/
@Test
public void testNotifySwitchPortChanged() throws Exception {
DatapathId dpid = DatapathId.of(42);
OFPortDesc p1 = factory.buildPortDesc()
.setName("Port1")
.setPortNo(OFPort.of(1))
.build();
OFFeaturesReply fr1 = factory.buildFeaturesReply()
.setXid(0)
.setDatapathId(dpid)
.setPorts(ImmutableList.<OFPortDesc>of(p1))
.build();
OFPortDesc p2 = factory.buildPortDesc()
.setName("Port1")
.setPortNo(OFPort.of(1))
.setAdvertised(ImmutableSet.<OFPortFeatures>of(OFPortFeatures.PF_100MB_FD))
.build();
OFFeaturesReply fr2 = factory.buildFeaturesReply()
.setXid(0)
.setDatapathId(dpid)
.setPorts(ImmutableList.<OFPortDesc>of(p2))
.build();
SwitchDescription desc = createSwitchDescription();
// activate switch
IOFSwitchBackend sw = doActivateNewSwitch(dpid, desc, fr1);
IOFSwitchListener listener = createMock(IOFSwitchListener.class);
switchManager.addOFSwitchListener(listener);
// setup switch with the new, second features reply (and thus ports)
setupSwitchForAddSwitch(sw, dpid, desc, fr2);
listener.switchPortChanged(dpid, p2,
PortChangeType.OTHER_UPDATE);
expectLastCall().once();
replay(listener);
replay(sw);
switchManager.notifyPortChanged(sw, p2,
PortChangeType.OTHER_UPDATE);
controller.processUpdateQueueForTesting();
verify(listener);
verify(sw);
}
/**
* Test the driver registry: test the bind order
*/
@Test
public void testSwitchDriverRegistryBindOrder() {
IOFSwitchDriver driver1 = createMock(IOFSwitchDriver.class);
IOFSwitchDriver driver2 = createMock(IOFSwitchDriver.class);
IOFSwitchDriver driver3 = createMock(IOFSwitchDriver.class);
IOFSwitchBackend returnedSwitch = null;
IOFSwitchBackend mockSwitch = createMock(IOFSwitchBackend.class);
switchManager.addOFSwitchDriver("", driver3);
switchManager.addOFSwitchDriver("test switch", driver1);
switchManager.addOFSwitchDriver("test", driver2);
replay(driver1);
replay(driver2);
replay(driver3);
replay(mockSwitch);
SwitchDescription description = new SwitchDescription(
"test switch", "version 0.9", "", "", "");
reset(driver1);
reset(driver2);
reset(driver3);
reset(mockSwitch);
mockSwitch.setSwitchProperties(description);
expectLastCall().once();
OFFactory factory = OFFactories.getFactory(OFVersion.OF_10);
expect(driver1.getOFSwitchImpl(description, factory)).andReturn(mockSwitch).once();
replay(driver1);
replay(driver2);
replay(driver3);
replay(mockSwitch);
returnedSwitch = switchManager.getOFSwitchInstance(new NullConnection(), description, factory, DatapathId.of(1));
assertSame(mockSwitch, returnedSwitch);
verify(driver1);
verify(driver2);
verify(driver3);
verify(mockSwitch);
description = new SwitchDescription(
"testFooBar", "version 0.9", "", "", "");
reset(driver1);
reset(driver2);
reset(driver3);
reset(mockSwitch);
mockSwitch.setSwitchProperties(description);
expectLastCall().once();
expect(driver2.getOFSwitchImpl(description, factory)).andReturn(mockSwitch).once();
replay(driver1);
replay(driver2);
replay(driver3);
replay(mockSwitch);
returnedSwitch = switchManager.getOFSwitchInstance(new NullConnection(), description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
assertSame(mockSwitch, returnedSwitch);
verify(driver1);
verify(driver2);
verify(driver3);
verify(mockSwitch);
description = new SwitchDescription(
"FooBar", "version 0.9", "", "", "");
reset(driver1);
reset(driver2);
reset(driver3);
reset(mockSwitch);
mockSwitch.setSwitchProperties(description);
expectLastCall().once();
expect(driver3.getOFSwitchImpl(description, factory)).andReturn(mockSwitch).once();
replay(driver1);
replay(driver2);
replay(driver3);
replay(mockSwitch);
returnedSwitch = switchManager.getOFSwitchInstance(new NullConnection(), description, factory, DatapathId.of(1));
assertSame(mockSwitch, returnedSwitch);
verify(driver1);
verify(driver2);
verify(driver3);
verify(mockSwitch);
}
/**
* Test SwitchDriverRegistry
* Test fallback to default if no switch driver is registered for a
* particular prefix
*/
@Test
public void testSwitchDriverRegistryNoDriver() {
IOFSwitchDriver driver = createMock(IOFSwitchDriver.class);
IOFSwitch returnedSwitch = null;
IOFSwitchBackend mockSwitch = createMock(IOFSwitchBackend.class);
switchManager.addOFSwitchDriver("test switch", driver);
replay(driver);
replay(mockSwitch);
SwitchDescription desc = new SwitchDescription("test switch", "version 0.9", "", "", "");
reset(driver);
reset(mockSwitch);
mockSwitch.setSwitchProperties(desc);
expectLastCall().once();
expect(driver.getOFSwitchImpl(desc, factory)).andReturn(mockSwitch).once();
replay(driver);
replay(mockSwitch);
returnedSwitch = switchManager.getOFSwitchInstance(new NullConnection(), desc, factory, DatapathId.of(1));
assertSame(mockSwitch, returnedSwitch);
verify(driver);
verify(mockSwitch);
desc = new SwitchDescription("Foo Bar test switch", "version 0.9", "", "", "");
reset(driver);
reset(mockSwitch);
replay(driver);
replay(mockSwitch);
returnedSwitch = switchManager.getOFSwitchInstance(new NullConnection(), desc,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
assertNotNull(returnedSwitch);
assertTrue("Returned switch should be OFSwitch",
returnedSwitch instanceof OFSwitch);
assertEquals(desc, returnedSwitch.getSwitchDescription());
verify(driver);
verify(mockSwitch);
}
/**
*
*/
@Test
public void testDriverRegistryExceptions() {
IOFSwitchDriver driver = createMock(IOFSwitchDriver.class);
IOFSwitchDriver driver2 = createMock(IOFSwitchDriver.class);
replay(driver, driver2); // no calls expected on driver
//---------------
// Test exception handling when registering driver
try {
switchManager.addOFSwitchDriver("foobar", null);
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
try {
switchManager.addOFSwitchDriver(null, driver);
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
// test that we can register each prefix only once!
switchManager.addOFSwitchDriver("foobar", driver);
try {
switchManager.addOFSwitchDriver("foobar", driver);
fail("Expected IllegalStateException not thrown");
} catch (IllegalStateException e) {
//expected
}
try {
switchManager.addOFSwitchDriver("foobar", driver2);
fail("Expected IllegalStateException not thrown");
} catch (IllegalStateException e) {
//expected
}
//OFDescStatsReply desc = createOFDescStatsReply();
//desc.setDatapathDescription(null);
SwitchDescription description = new SwitchDescription(null, "", "", "", "");
try {
switchManager.getOFSwitchInstance(null, description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
description = new SwitchDescription("", null, "", "", "");
try {
switchManager.getOFSwitchInstance(null, description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
description = new SwitchDescription("", "", null, "", "");
try {
switchManager.getOFSwitchInstance(null, description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
description = new SwitchDescription("", "", "", null, "");
try {
switchManager.getOFSwitchInstance(null, description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
description = new SwitchDescription("", "", "", "", null);
try {
switchManager.getOFSwitchInstance(null, description,
OFFactories.getFactory(OFVersion.OF_10), DatapathId.of(1));
fail("Expected NullPointerException not thrown");
} catch (NullPointerException e) {
//expected
}
verify(driver, driver2);
}
@Test
public void testRegisterCategory() {
// Must be in INIT state
Timer timer = createMock(Timer.class);
replay(timer);
switchManager = new OFSwitchManager();
switchManager.loadLogicalCategories();
assertTrue("Connections should be empty", switchManager.getNumRequiredConnections() == 0);
// Add initial category
switchManager = new OFSwitchManager();
LogicalOFMessageCategory category = new LogicalOFMessageCategory("aux1", 1);
switchManager.registerLogicalOFMessageCategory(category);
switchManager.loadLogicalCategories();
assertTrue("Required connections should be 1", switchManager.getNumRequiredConnections() == 1);
// Multiple categories on the same auxId should produce one required connection
switchManager = new OFSwitchManager();
switchManager.registerLogicalOFMessageCategory(new LogicalOFMessageCategory("aux1", 1));
switchManager.registerLogicalOFMessageCategory(new LogicalOFMessageCategory("aux1-2", 1));
switchManager.loadLogicalCategories();
assertTrue("Required connections should be 1", switchManager.getNumRequiredConnections() == 1);
// Adding a category on a different aux ID should increase the required connection count
switchManager = new OFSwitchManager();
switchManager.registerLogicalOFMessageCategory(new LogicalOFMessageCategory("aux1", 1));
switchManager.registerLogicalOFMessageCategory(new LogicalOFMessageCategory("aux2", 2));
switchManager.loadLogicalCategories();
assertTrue("Required connections should be 2", switchManager.getNumRequiredConnections() == 2);
}
@Test
public void testRegisterCategoryException() {
switchManager = new OFSwitchManager();
switchManager.loadLogicalCategories();
LogicalOFMessageCategory category = new LogicalOFMessageCategory("test", 1);
// Wrong State
try {
switchManager.registerLogicalOFMessageCategory(category);
fail("Expected Unsupported Operation Exception not thrown");
} catch (UnsupportedOperationException e) { /* expected */ }
switchManager = new OFSwitchManager();
// Categories must have category with auxid of 1
LogicalOFMessageCategory bad = new LogicalOFMessageCategory("bad", 2);
switchManager.registerLogicalOFMessageCategory(bad);
try{
switchManager.loadLogicalCategories();
fail("Expected exception not thrown");
} catch (IllegalStateException e) { /* expected */}
// Non contiguous category auxids of (1,3)
switchManager = new OFSwitchManager();
switchManager.registerLogicalOFMessageCategory(category);
LogicalOFMessageCategory nonContiguous = new LogicalOFMessageCategory("bad", 3);
switchManager.registerLogicalOFMessageCategory(nonContiguous);
try{
switchManager.loadLogicalCategories();
fail("Expected exception not thrown");
} catch (IllegalStateException e) { /* expected */}
}
@Test
public void testNewConnectionOpened() {
MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN);
OFFeaturesReply featuresReply = createOFFeaturesReply(DATAPATH_ID_1);
// Assert no switch handlers
assertTrue(switchManager.getSwitchHandshakeHandlers().isEmpty());
switchManager.connectionOpened(connection, featuresReply);
// Ensure a
assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1);
assertTrue(switchManager.getSwitchHandshakeHandlers().get(0).getDpid().equals(DATAPATH_ID_1));
}
@Test
public void testDuplicateConnectionOpened() {
// Seed with 1 connection and handler
testNewConnectionOpened();
MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN);
OFFeaturesReply featuresReply = createOFFeaturesReply(DATAPATH_ID_1);
switchManager.connectionOpened(connection, featuresReply);
// Ensure duplicate connections are
assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1);
assertTrue(switchManager.getSwitchHandshakeHandlers().get(0).getDpid().equals(DATAPATH_ID_1));
}
@Test
public void testHandshakeDisconnected() {
// Seed with 1 connection and handler
testNewConnectionOpened();
assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1);
// Disconnect wrong handshake
switchManager.handshakeDisconnected(DATAPATH_ID_0);
assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 1);
// Disconnect correct handshake
switchManager.handshakeDisconnected(DATAPATH_ID_1);
assertTrue(switchManager.getSwitchHandshakeHandlers().size() == 0);
}
}