diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
index a14ca20199c549213544d85c73a4b7ade72058ed..47edf3a08a1db86de881f516ea607134f9ebe34b 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
@@ -27,8 +27,8 @@ import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
 import org.projectfloodlight.openflow.protocol.OFPortStatus;
-import org.projectfloodlight.openflow.protocol.OFTableFeatures;
 import org.projectfloodlight.openflow.protocol.OFTableFeaturesStatsReply;
+import org.projectfloodlight.openflow.types.TableId;
 
 import net.floodlightcontroller.util.OrderedCollection;
 
@@ -194,4 +194,35 @@ public interface IOFSwitchBackend extends IOFSwitch {
      * @return true if another viable master exists
      */
     boolean hasAnotherMaster();
+    
+    /**
+     * In OF1.3+ switches, the table miss behavior is defined by a flow.
+     * We assume the default behavior is to forward to the controller, but
+     * not all tables need that behavior if a limited set of tables are used.
+     * So, we can cap the number of tables we set this flow in to reduce
+     * clutter in API output and to reduce memory consumption on the switch.
+     * 
+     * This gets the TableId cap set for this particular switch.
+     * 
+     * @return, the highest TableId that should receive a table-miss flow
+     */
+    TableId getMaxTableForTableMissFlow();
+    
+    /**
+     * In OF1.3+ switches, the table miss behavior is defined by a flow.
+     * We assume the default behavior is to forward to the controller, but
+     * not all tables need that behavior if a limited set of tables are used.
+     * So, we can cap the number of tables we set this flow in to reduce
+     * clutter in API output and to reduce memory consumption on the switch.
+     * 
+     * This sets the TableId cap set for this particular switch. If the max
+     * desired is higher than the number of tables this switch supports, the
+     * max table supported will be used:
+     * 
+     * set_max_table = max_supported <= max ? max_supported-1 : max
+     * 
+ 	 * @param max, the highest TableId that should receive a table-miss flow
+     * @return the TableId set as the highest
+     */
+    TableId setMaxTableForTableMissFlow(TableId max);
 }
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
index 8b401dad680cdda48eccaa36fad5db0b987d08a3..5360eb33d76c8594c9d246234f8487c9aab67b38 100644
--- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
@@ -112,8 +112,6 @@ public class OFSwitch implements IOFSwitchBackend {
 	 */
 	private final PortManager portManager;
 
-	//private final TableManager tableManager;
-
 	private volatile boolean connected;
 
 	private volatile OFControllerRole role;
@@ -125,6 +123,8 @@ public class OFSwitch implements IOFSwitchBackend {
 	private SwitchStatus status;
 
 	public static final int OFSWITCH_APP_ID = ident(5);
+	
+	private TableId maxTableToGetTableMissFlow = TableId.of(4); /* this should cover most HW switches that have a couple SW flow tables */
 
 	static {
 		AppCookie.registerApp(OFSwitch.OFSWITCH_APP_ID, "switch");
@@ -816,7 +816,7 @@ public class OFSwitch implements IOFSwitchBackend {
 		this.buffers = featuresReply.getNBuffers();
 
 		if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0 ) {
-			// FIXME:LOJI: OF1.3 has per table actions. This needs to be modeled / handled here
+			/* OF1.3+ Per-table actions are set later in the OFTableFeaturesRequest/Reply */
 			this.actions = featuresReply.getActions();
 		}
 		this.tables = featuresReply.getNTables();
@@ -1208,4 +1208,19 @@ public class OFSwitch implements IOFSwitchBackend {
 	public TableFeatures getTableFeatures(TableId table) {
 		return tableFeaturesByTableId.get(table);
 	}
+
+	@Override
+	public TableId getMaxTableForTableMissFlow() {
+		return maxTableToGetTableMissFlow;
+	}
+	
+	@Override
+	public TableId setMaxTableForTableMissFlow(TableId max) {
+		if (max.getValue() >= tables) {
+			maxTableToGetTableMissFlow = TableId.of(tables - 1 < 0 ? 0 : tables - 1);
+		} else {
+			maxTableToGetTableMissFlow = max;
+		}
+		return maxTableToGetTableMissFlow;
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
index a17e7d5ae859978d5d7832ae10eed3273d7dc7b2..081f177d3f2a6525731c57f97c4270c55c63b676 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
@@ -475,11 +475,13 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
 	}
 
 	/** 
-	 * Adds an initial table-miss flow to each
-	 * and every table on the switch. This replaces the default behavior of
-	 * forwarding table-miss packets to the controller. The table-miss flows
-	 * inserted will forward all packets that do not match a flow to the 
-	 * controller for processing.
+	 * Adds an initial table-miss flow to tables on the switch. 
+	 * This replaces the default behavior of forwarding table-miss packets 
+	 * to the controller. The table-miss flows inserted will forward all 
+	 * packets that do not match a flow to the controller for processing.
+	 * 
+	 * The OFSwitchManager is checked for used-defined behavior and default
+	 * max table to try to use.
 	 * 
 	 * Adding the default flow only applies to OpenFlow 1.3+ switches, which 
 	 * remove the default forward-to-controller behavior of flow tables.
@@ -502,7 +504,7 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
 			ArrayList<OFAction> actions = new ArrayList<OFAction>(1);
 			actions.add(factory.actions().output(OFPort.CONTROLLER, 0xffFFffFF));
 			ArrayList<OFMessage> flows = new ArrayList<OFMessage>();
-			for (int tableId = 0; tableId < this.sw.getTables(); tableId++) {
+			for (int tableId = 0; tableId <= this.sw.getMaxTableForTableMissFlow().getValue(); tableId++) {
 				OFFlowAdd defaultFlow = this.factory.buildFlowAdd()
 						.setTableId(TableId.of(tableId))
 						.setPriority(0)
@@ -1014,7 +1016,6 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
 			OFDescStatsReply descStatsReply = (OFDescStatsReply) m;
 			SwitchDescription description = new SwitchDescription(descStatsReply);
 			sw = switchManager.getOFSwitchInstance(mainConnection, description, factory, featuresReply.getDatapathId());
-			switchManager.switchAdded(sw);
 			// set switch information
 			// set features reply and channel first so we a DPID and
 			// channel info.
@@ -1022,6 +1023,11 @@ public class OFSwitchHandshakeHandler implements IOFConnectionListener {
 			if (portDescStats != null) {
 				sw.setPortDescStats(portDescStats);
 			}
+			/*
+			 * Need to add after setting the features.
+			 */
+			switchManager.switchAdded(sw);
+
 
 			// Handle pending messages now that we have a sw object
 			handlePendingPortStatusMessages(description);
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
index 3c5ea1085267f0e30bec55659d0bdd049e5052ec..a1dbced1e2a00696280e56d3b6a6e4843b5bf01e 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
@@ -1,5 +1,6 @@
 package net.floodlightcontroller.core.internal;
 
+import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -55,8 +56,10 @@ import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFAuxId;
+import org.projectfloodlight.openflow.types.TableId;
 import org.sdnplatform.sync.IStoreClient;
 import org.sdnplatform.sync.IStoreListener;
 import org.sdnplatform.sync.ISyncService;
@@ -65,6 +68,10 @@ import org.sdnplatform.sync.error.SyncException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.MappingJsonFactory;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -93,10 +100,13 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 	private static String keyStorePassword;
 	private static String keyStore;
 	private static boolean useSsl = false;
-	
+
 	protected static boolean clearTablesOnInitialConnectAsMaster = false;
 	protected static boolean clearTablesOnEachTransitionToMaster = false;
 
+	protected static Map<DatapathId, TableId> forwardToControllerFlowsUpToTableByDpid;
+	protected static TableId forwardToControllerFlowsUpToTable = TableId.of(4); /* this should cover most HW switches that have a couple SW-based flow tables */
+
 	private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers;
 	private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches;
 	private ConcurrentHashMap<DatapathId, IOFSwitch> syncedSwitches;
@@ -167,6 +177,16 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 			oldSw.disconnect();
 		}
 
+		/*
+		 * Set other config options for this switch.
+		 */
+		if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
+			if (forwardToControllerFlowsUpToTableByDpid.containsKey(sw.getId())) {
+				sw.setMaxTableForTableMissFlow(forwardToControllerFlowsUpToTableByDpid.get(sw.getId()));
+			} else {
+				sw.setMaxTableForTableMissFlow(forwardToControllerFlowsUpToTable);
+			}
+		}
 	}
 
 	@LogMessageDocs({
@@ -679,13 +699,13 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 			OFSwitchManager.keyStore = null;
 			OFSwitchManager.keyStorePassword = null;
 		} else {
-			log.warn("SSL enabled. Using secure connections between Floodlight and switches.");
+			log.info("SSL enabled. Using secure connections between Floodlight and switches.");
 			log.info("SSL keystore path: {}, password: {}", path, (pass == null ? "" : pass)); 
 			OFSwitchManager.useSsl = true;
 			OFSwitchManager.keyStore = path;
 			OFSwitchManager.keyStorePassword = (pass == null ? "" : pass);
 		}
-		
+
 		/*
 		 * Get config to define what to do when a switch connects.
 		 * 
@@ -693,33 +713,122 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen
 		 */
 		String clearInitial = configParams.get("clearTablesOnInitialHandshakeAsMaster");
 		String clearLater = configParams.get("clearTablesOnEachTransitionToMaster");
-		
+
 		if (clearInitial == null || clearInitial.isEmpty() || 
 				(!clearInitial.equalsIgnoreCase("yes") && !clearInitial.equalsIgnoreCase("true") &&
-				!clearInitial.equalsIgnoreCase("yep") && !clearInitial.equalsIgnoreCase("ja") &&
-				!clearInitial.equalsIgnoreCase("stimmt"))) {
-			log.warn("Clear switch flow tables on initial handshake as master: FALSE");
+						!clearInitial.equalsIgnoreCase("yep") && !clearInitial.equalsIgnoreCase("ja") &&
+						!clearInitial.equalsIgnoreCase("stimmt"))) {
+			log.info("Clear switch flow tables on initial handshake as master: FALSE");
 			OFSwitchManager.clearTablesOnInitialConnectAsMaster = false;
 		} else {
-			log.warn("Clear switch flow tables on initial handshake as master: TRUE");
+			log.info("Clear switch flow tables on initial handshake as master: TRUE");
 			OFSwitchManager.clearTablesOnInitialConnectAsMaster = true;
 		}
-		
+
 		if (clearLater == null || clearLater.isEmpty() || 
 				(!clearLater.equalsIgnoreCase("yes") && !clearLater.equalsIgnoreCase("true") &&
-				!clearLater.equalsIgnoreCase("yep") && !clearLater.equalsIgnoreCase("ja") &&
-				!clearLater.equalsIgnoreCase("stimmt"))) {
-			log.warn("Clear switch flow tables on each transition to master: FALSE");
+						!clearLater.equalsIgnoreCase("yep") && !clearLater.equalsIgnoreCase("ja") &&
+						!clearLater.equalsIgnoreCase("stimmt"))) {
+			log.info("Clear switch flow tables on each transition to master: FALSE");
 			OFSwitchManager.clearTablesOnEachTransitionToMaster = false;
 		} else {
-			log.warn("Clear switch flow tables on each transition to master: TRUE");
+			log.info("Clear switch flow tables on each transition to master: TRUE");
 			OFSwitchManager.clearTablesOnEachTransitionToMaster = true;
 		}
-		
-		String tablesToGetFTCFlow = configParams.get("addDefaultSendToControllerFlowInTables");
-		if (tablesToGetFTCFlow == null || tablesToGetFTCFlow.isEmpty()) {
-			
+
+		/*
+		 * Get default max table for forward to controller flows. 
+		 * Internal default set as class variable at top of OFSwitchManager.
+		 */
+		String defaultFlowsUpToTable = configParams.get("defaultMaxTableToReceiveTableMissFlow");
+		if (defaultFlowsUpToTable != null && !defaultFlowsUpToTable.isEmpty()) {
+			defaultFlowsUpToTable = defaultFlowsUpToTable.toLowerCase().trim();
+			try {
+				forwardToControllerFlowsUpToTable = TableId.of(defaultFlowsUpToTable.startsWith("0x") 
+						? Integer.parseInt(defaultFlowsUpToTable.replaceFirst("0x", ""), 16) 
+								: Integer.parseInt(defaultFlowsUpToTable));
+				log.info("Setting {} as the default max table to receive table-miss flow", forwardToControllerFlowsUpToTable.toString());
+			} catch (IllegalArgumentException e) {
+				log.error("Invalid table ID {} for default max table to receive table-miss flow. Using pre-set of {}", 
+						defaultFlowsUpToTable, forwardToControllerFlowsUpToTable.toString());
+			}
+		} else {
+			log.info("Default max table to receive table-miss flow not configured. Using {}", forwardToControllerFlowsUpToTable.toString());
+		}
+
+		/*
+		 * Get config to define which tables per switch will get a
+		 * default forward-to-controller flow. This can be used to
+		 * reduce the number of such flows if only a reduced set of
+		 * tables are being used.
+		 * 
+		 * By default, 
+		 */
+		forwardToControllerFlowsUpToTableByDpid = jsonToSwitchTableIdMap(configParams.get("maxTableToReceiveTableMissFlowPerDpid"));
+	}
+
+	private static Map<DatapathId, TableId> jsonToSwitchTableIdMap(String json) {
+		MappingJsonFactory f = new MappingJsonFactory();
+		JsonParser jp;
+		Map<DatapathId, TableId> retValue = new HashMap<DatapathId, TableId>();
+
+		if (json == null || json.isEmpty()) {
+			return retValue;
+		}
+
+		try {
+			try {
+				jp = f.createJsonParser(json);
+			} catch (JsonParseException e) {
+				throw new IOException(e);
+			}
+
+			jp.nextToken();
+			if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
+				throw new IOException("Expected START_OBJECT");
+			}
+
+			while (jp.nextToken() != JsonToken.END_OBJECT) {
+				if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
+					throw new IOException("Expected FIELD_NAME");
+				}
+
+				String n = jp.getCurrentName();
+				jp.nextToken();
+				if (jp.getText().equals("")) {
+					continue;
+				}
+
+				DatapathId dpid;
+				try {
+					n = n.trim();
+					dpid = DatapathId.of(n);
+
+					TableId tablesToGetDefaultFlow;
+					String value = jp.getText();
+					if (value != null && !value.isEmpty()) {
+						value = value.trim().toLowerCase();
+						try {
+							tablesToGetDefaultFlow = TableId.of(
+									value.startsWith("0x") 
+									? Integer.parseInt(value.replaceFirst("0x", ""), 16) 
+											: Integer.parseInt(value)
+									); /* will throw exception if outside valid TableId number range */
+							retValue.put(dpid, tablesToGetDefaultFlow);
+							log.info("Setting max table to receive table-miss flow to {} for DPID {}", 
+									tablesToGetDefaultFlow.toString(), dpid.toString());
+						} catch (IllegalArgumentException e) { /* catches both IllegalArgumentExcpt. and NumberFormatExcpt. */
+							log.error("Invalid value of {} for max table to receive table-miss flow for DPID {}. Using default of {}.", value, dpid.toString());
+						}
+					}
+				} catch (NumberFormatException e) {
+					log.error("Invalid DPID format {} for max table to receive table-miss flow for specific DPID. Using default for the intended DPID.", n);
+				}
+			}
+		} catch (IOException e) {
+			log.error("Using default for remaining DPIDs. JSON formatting error in max table to receive table-miss flow for DPID input String: {}", e);
 		}
+		return retValue;
 	}
 
 	@Override
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 13ce05be948ee7b2cc60665f69491cb92fbc4f18..2a4786bf21b600aa31c233d9f0378eee61d99948 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -23,7 +23,8 @@ org.sdnplatform.sync.internal.SyncManager.port=6642
 net.floodlightcontroller.forwarding.Forwarding.match=vlan, mac, ip, transport
 net.floodlightcontroller.core.internal.FloodlightProvider.openflowPort=6653
 net.floodlightcontroller.core.internal.FloodlightProvider.role=ACTIVE
-net.floodlightcontroller.core.internal.OFSwitchManager.addDefaultSendToControllerFlowInTables='{"all":"0,1,2"}'
+net.floodlightcontroller.core.internal.OFSwitchManager.defaultMaxTableToReceiveTableMissFlow=4
+net.floodlightcontroller.core.internal.OFSwitchManager.maxTableToReceiveTableMissFlowPerDpid={"00:00:00:00:00:00:00:01":"4","2":"4"}
 net.floodlightcontroller.core.internal.OFSwitchManager.clearTablesOnInitialHandshakeAsMaster=YES
 net.floodlightcontroller.core.internal.OFSwitchManager.clearTablesOnEachTransitionToMaster=YES
 net.floodlightcontroller.core.internal.OFSwitchManager.keyStorePath=/path/to/your/keystore-file.jks
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java
index e7590df1c838b059a9bdfc33f4387bfc8aecc66b..f035adf653f336c244c064f522c1a23fa75fd3c5 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandlerTestBase.java
@@ -66,6 +66,7 @@ import org.projectfloodlight.openflow.protocol.OFStatsType;
 import org.projectfloodlight.openflow.protocol.OFTableFeatureProp;
 import org.projectfloodlight.openflow.protocol.OFTableFeaturesStatsReply;
 import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.protocol.match.Match;
 import org.projectfloodlight.openflow.types.DatapathId;
 import org.projectfloodlight.openflow.types.OFAuxId;
@@ -81,1085 +82,1101 @@ import com.google.common.collect.ImmutableList;
 
 
 public abstract class OFSwitchHandlerTestBase {
-    protected static final DatapathId dpid = DatapathId.of(0x42L);
-
-    protected IOFSwitchManager switchManager;
-    protected RoleManager roleManager;
-
-    private IDebugCounterService debugCounterService;
-    protected OFSwitchHandshakeHandler switchHandler;
-    protected MockOFConnection connection;
-    // Use a 1.0 factory for the 1.0 test
-    protected final OFFactory factory = getFactory();
-
-    protected OFFeaturesReply featuresReply;
-    protected List<IAppHandshakePluginFactory> plugins;
-
-    private HashSet<Long> seenXids = null;
-    protected IOFSwitchBackend sw;
-    private Timer timer;
-    private TestHandshakePlugin handshakePlugin;
-
-    private class TestHandshakePlugin extends OFSwitchAppHandshakePlugin {
-        protected TestHandshakePlugin(PluginResult defaultResult, int timeoutS) {
-            super(defaultResult, timeoutS);
-        }
-
-        @Override
-        protected void processOFMessage(OFMessage m) {
-        }
-
-        @Override
-        protected void enterPlugin() {
-        }
-    }
-
-    @Before
-    public void setUpFeaturesReply() {
-        getFeaturesReply();
-        this.featuresReply = getFeaturesReply();
-
-        // Plugin set
-        IAppHandshakePluginFactory factory = createMock(IAppHandshakePluginFactory.class);
-        PluginResult result = new PluginResult(PluginResultType.QUARANTINE, "test quarantine");
-        handshakePlugin = new TestHandshakePlugin(result, 5);
-        expect(factory.createPlugin()).andReturn(handshakePlugin).anyTimes();
-        replay(factory);
-        plugins = ImmutableList.of(factory);
-    }
-
-
-    @Before
-    public void setUp() throws Exception {
-        switchManager = createMock(IOFSwitchManager.class);
-        roleManager = createMock(RoleManager.class);
-        sw = createMock(IOFSwitchBackend.class);
-        timer = createMock(Timer.class);
-        expect(timer.newTimeout(anyObject(TimerTask.class), anyLong(), anyObject(TimeUnit.class))).andReturn(EasyMock.createNiceMock(Timeout.class));
-        replay(timer);
-        seenXids = null;
-
-        // TODO: should mock IDebugCounterService and make sure
-        // the expected counters are updated.
-        debugCounterService = new DebugCounterServiceImpl();
-        SwitchManagerCounters counters =
-                new SwitchManagerCounters(debugCounterService);
-        expect(switchManager.getCounters()).andReturn(counters).anyTimes();
-        replay(switchManager);
-        connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN);
-        switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer);
-        
-        // replay sw. Reset it if you need more specific behavior
-        replay(sw);
-    }
-
-
-    @After
-    public void tearDown() {
-        verifyAll();
-    }
-
-    private void verifyAll() {
-        assertThat("Unexpected messages have been captured",
-                   connection.getMessages(),
-                    Matchers.empty());
-        // verify all mocks.
-        verify(sw);
-    }
-
-    void verifyUniqueXids(OFMessage... msgs) {
-        verifyUniqueXids(Arrays.asList(msgs));
-    }
-
-    /** make sure that the transaction ids in the given messages are
-     * not 0 and differ between each other.
-     * While it's not a defect per se if the xids are we want to ensure
-     * we use different ones for each message we send.
-     */
-    void verifyUniqueXids(List<OFMessage> msgs) {
-        if (seenXids == null)
-            seenXids = new HashSet<Long>();
-        for (OFMessage m: msgs)  {
-            long xid = m.getXid();
-            assertTrue("Xid in messags is 0", xid != 0);
-            assertFalse("Xid " + xid + " has already been used",
-                        seenXids.contains(xid));
-            seenXids.add(xid);
-        }
-    }
-
-
-    /*************************** abstract phases / utilities to be filled in by the subclasses */
-
-    // Factory + messages
-
-    /** @return the version-appropriate factory */
-    public abstract OFFactory getFactory();
-
-    /**
-     * @return a version appropriate features reply (different in 1.3 because it
-     * doesn't have ports)
-     */
-    abstract OFFeaturesReply getFeaturesReply();
-    /** @return the class that's used for role requests/replies (OFNiciraRoleRequest vs.
-     *  OFRequest)
-     */
-
-    /// Role differences
-
-    abstract Class<?> getRoleRequestClass();
-    /** Verify that the given OFMessage is a correct RoleRequest message
-     * for the given role using the given xid (for the version).
-     */
-    public abstract void verifyRoleRequest(OFMessage m,
-                                   OFControllerRole expectedRole);
-    /** Return a RoleReply message for the given role */
-    protected abstract OFMessage getRoleReply(long xid, OFControllerRole role);
-
-    /// Difference in the handshake sequence
-
-    /** OF1.3 has the PortDescStatsRequest, OF1.0 not */
-    abstract void moveToPreConfigReply() throws Exception;
-    /**
-     * Move the channel from scratch to WaitAppHandshakeState
-     * Different for OF1.0 and OF1.3 because of GenTables.
-     * @throws Exception
-     */
-    @Test
-    public abstract void moveToWaitAppHandshakeState() throws Exception;
-
-    /**
-     * Move the channel from scratch to WaitSwitchDriverSubHandshake
-     * Different for OF1.0 and OF1.3 because of GenTables.
-     * @throws Exception
-     */
-    @Test
-    public abstract void moveToWaitSwitchDriverSubHandshake() throws Exception;
-
-    /**
-     * Move the channel from scratch to WaitInitialRole
-     * Different for OF1.0 and OF1.3 because of Controller Connections.
-     * @throws Exception
-     */
-    @Test
-    public abstract void moveToWaitInitialRole() throws Exception;
-
-    /*******************************************************************************************/
-
-
-    /** Move the channel from scratch to INIT state
+	protected static final DatapathId dpid = DatapathId.of(0x42L);
+
+	protected IOFSwitchManager switchManager;
+	protected RoleManager roleManager;
+
+	private IDebugCounterService debugCounterService;
+	protected OFSwitchHandshakeHandler switchHandler;
+	protected MockOFConnection connection;
+	// Use a 1.0 factory for the 1.0 test
+	protected final OFFactory factory = getFactory();
+
+	protected OFFeaturesReply featuresReply;
+	protected List<IAppHandshakePluginFactory> plugins;
+
+	private HashSet<Long> seenXids = null;
+	protected IOFSwitchBackend sw;
+	private Timer timer;
+	private TestHandshakePlugin handshakePlugin;
+
+	private class TestHandshakePlugin extends OFSwitchAppHandshakePlugin {
+		protected TestHandshakePlugin(PluginResult defaultResult, int timeoutS) {
+			super(defaultResult, timeoutS);
+		}
+
+		@Override
+		protected void processOFMessage(OFMessage m) {
+		}
+
+		@Override
+		protected void enterPlugin() {
+		}
+	}
+
+	@Before
+	public void setUpFeaturesReply() {
+		getFeaturesReply();
+		this.featuresReply = getFeaturesReply();
+
+		// Plugin set
+		IAppHandshakePluginFactory factory = createMock(IAppHandshakePluginFactory.class);
+		PluginResult result = new PluginResult(PluginResultType.QUARANTINE, "test quarantine");
+		handshakePlugin = new TestHandshakePlugin(result, 5);
+		expect(factory.createPlugin()).andReturn(handshakePlugin).anyTimes();
+		replay(factory);
+		plugins = ImmutableList.of(factory);
+	}
+
+
+	@Before
+	public void setUp() throws Exception {
+		switchManager = createMock(IOFSwitchManager.class);
+		roleManager = createMock(RoleManager.class);
+		sw = createMock(IOFSwitchBackend.class);
+		timer = createMock(Timer.class);
+		expect(timer.newTimeout(anyObject(TimerTask.class), anyLong(), anyObject(TimeUnit.class))).andReturn(EasyMock.createNiceMock(Timeout.class));
+		replay(timer);
+		seenXids = null;
+
+		// TODO: should mock IDebugCounterService and make sure
+		// the expected counters are updated.
+		debugCounterService = new DebugCounterServiceImpl();
+		SwitchManagerCounters counters =
+				new SwitchManagerCounters(debugCounterService);
+		expect(switchManager.getCounters()).andReturn(counters).anyTimes();
+		replay(switchManager);
+		connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN);
+		switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer);
+
+		// replay sw. Reset it if you need more specific behavior
+		replay(sw);
+	}
+
+
+	@After
+	public void tearDown() {
+		verifyAll();
+	}
+
+	private void verifyAll() {
+		assertThat("Unexpected messages have been captured",
+				connection.getMessages(),
+				Matchers.empty());
+		// verify all mocks.
+		verify(sw);
+	}
+
+	void verifyUniqueXids(OFMessage... msgs) {
+		verifyUniqueXids(Arrays.asList(msgs));
+	}
+
+	/** make sure that the transaction ids in the given messages are
+	 * not 0 and differ between each other.
+	 * While it's not a defect per se if the xids are we want to ensure
+	 * we use different ones for each message we send.
+	 */
+	void verifyUniqueXids(List<OFMessage> msgs) {
+		if (seenXids == null)
+			seenXids = new HashSet<Long>();
+		for (OFMessage m: msgs)  {
+			long xid = m.getXid();
+			assertTrue("Xid in messags is 0", xid != 0);
+			assertFalse("Xid " + xid + " has already been used",
+					seenXids.contains(xid));
+			seenXids.add(xid);
+		}
+	}
+
+
+	/*************************** abstract phases / utilities to be filled in by the subclasses */
+
+	// Factory + messages
+
+	/** @return the version-appropriate factory */
+	public abstract OFFactory getFactory();
+
+	/**
+	 * @return a version appropriate features reply (different in 1.3 because it
+	 * doesn't have ports)
+	 */
+	abstract OFFeaturesReply getFeaturesReply();
+	/** @return the class that's used for role requests/replies (OFNiciraRoleRequest vs.
+	 *  OFRequest)
+	 */
+
+	/// Role differences
+
+	abstract Class<?> getRoleRequestClass();
+	/** Verify that the given OFMessage is a correct RoleRequest message
+	 * for the given role using the given xid (for the version).
+	 */
+	public abstract void verifyRoleRequest(OFMessage m,
+			OFControllerRole expectedRole);
+	/** Return a RoleReply message for the given role */
+	protected abstract OFMessage getRoleReply(long xid, OFControllerRole role);
+
+	/// Difference in the handshake sequence
+
+	/** OF1.3 has the PortDescStatsRequest, OF1.0 not */
+	abstract void moveToPreConfigReply() throws Exception;
+	/**
+	 * Move the channel from scratch to WaitAppHandshakeState
+	 * Different for OF1.0 and OF1.3 because of GenTables.
+	 * @throws Exception
+	 */
+	@Test
+	public abstract void moveToWaitAppHandshakeState() throws Exception;
+
+	/**
+	 * Move the channel from scratch to WaitSwitchDriverSubHandshake
+	 * Different for OF1.0 and OF1.3 because of GenTables.
+	 * @throws Exception
+	 */
+	@Test
+	public abstract void moveToWaitSwitchDriverSubHandshake() throws Exception;
+
+	/**
+	 * Move the channel from scratch to WaitInitialRole
+	 * Different for OF1.0 and OF1.3 because of Controller Connections.
+	 * @throws Exception
+	 */
+	@Test
+	public abstract void moveToWaitInitialRole() throws Exception;
+
+	/*******************************************************************************************/
+
+
+	/** Move the channel from scratch to INIT state
         This occurs upon creation of the switch handler
-     */
-    @Test
-    public void testInitState() throws Exception {
-        assertThat(connection.getListener(), notNullValue());
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.InitState.class));
-    }
-
-
-    /** Move the channel from scratch to WAIT_CONFIG_REPLY state
-     * adds testing for beginHandshake() which moves the state from
-     * InitState to WaitConfigReply.
-     */
-    @Test
-    public void moveToWaitConfigReply() throws Exception {
-        moveToPreConfigReply();
-
-        List<OFMessage> msgs = connection.getMessages();
-        assertEquals(3, msgs.size());
-        assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
-        OFSetConfig sc = (OFSetConfig)msgs.get(0);
-        assertEquals(0xffff, sc.getMissSendLen());
-        assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
-        assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
-        verifyUniqueXids(msgs);
-        msgs.clear();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitConfigReplyState.class));
-        verifyAll();
-    }
-
-
-
-    /** Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state
-     * Builds on moveToWaitConfigReply()
-     * adds testing for WAIT_CONFIG_REPLY state
-     */
-    @Test
-    public void moveToWaitDescriptionStatReply() throws Exception {
-        moveToWaitConfigReply();
-
-        connection.clearMessages();
-        OFGetConfigReply cr = factory.buildGetConfigReply()
-                .setMissSendLen(0xFFFF)
-                .build();
-
-        switchHandler.processOFMessage(cr);
-
-        OFMessage msg = connection.retrieveMessage();
-        assertEquals(OFType.STATS_REQUEST, msg.getType());
-        OFStatsRequest<?> sr = (OFStatsRequest<?>)msg;
-        assertEquals(OFStatsType.DESC, sr.getStatsType());
-        verifyUniqueXids(msg);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitDescriptionStatReplyState.class));
-    }
-
-    protected OFDescStatsReply createDescriptionStatsReply() {
-        OFDescStatsReply statsReply = factory.buildDescStatsReply()
-                .setDpDesc("Datapath Description")
-                .setHwDesc("Hardware Description")
-                .setMfrDesc("Manufacturer Description")
-                .setSwDesc("Software Description")
-                .setSerialNum("Serial Number")
-                .build();
-        return statsReply;
-    }
-    
-    protected OFTableFeaturesStatsReply createTableFeaturesStatsReply() {
-    	OFTableFeaturesStatsReply statsReply = factory.buildTableFeaturesStatsReply()
-    			.setEntries(Collections.singletonList(factory.buildTableFeatures()
-    					.setConfig(0)
-    					.setMaxEntries(100)
-    					.setMetadataMatch(U64.NO_MASK)
-    					.setMetadataWrite(U64.NO_MASK)
-    					.setName("MyTable")
-    					.setTableId(TableId.of(1))
-    					.setProperties(Collections.singletonList((OFTableFeatureProp)factory.buildTableFeaturePropMatch()
-    							.setOxmIds(Collections.singletonList(U32.of(100)))
-    							.build())
-    				).build()
-    			)
-    			
-    		).build();
-    	return statsReply;
-    }
-
-    /**
-     * setup the expectations for the mock switch that are needed
-     * after the switch is instantiated in the WAIT_DESCRIPTION_STATS STATE
-     * Will reset the switch
-     * @throws CounterException
-     */
-    protected void setupSwitchForInstantiationWithReset()
-            throws Exception {
-        reset(sw);
-        sw.setFeaturesReply(featuresReply);
-        expectLastCall().once();
-    }
-
-    /**
-     * Tests a situation where a switch returns a QUARANTINE result. This means
-     * we should move the handshake handler to a quarantine state and also
-     * quarantine the switch in the controller.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void moveQuarantine() throws Exception {
-        moveToWaitAppHandshakeState();
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.QUARANTINED);
-        expectLastCall().once();
-        replay(switchManager);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(WaitAppHandshakeState.class));
-        WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting();
-        assertThat(state.getCurrentPlugin(), CoreMatchers.<OFSwitchAppHandshakePlugin>equalTo(handshakePlugin));
-
-        reset(sw);
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE);
-        sw.setStatus(SwitchStatus.QUARANTINED);
-        expectLastCall().once();
-        replay(sw);
-
-        PluginResult result = new PluginResult(PluginResultType.QUARANTINE, "test quarantine");
-        handshakePlugin.exitPlugin(result);
-
-        assertThat(switchHandler.getStateForTesting(),
-                   CoreMatchers.instanceOf(QuarantineState.class));
-        verify(switchManager);
-    }
-
-    /**
-     * Tests a situation where a plugin returns a DISCONNECT result. This means
-     * we should disconnect the connection and the state should not change.
-     *
-     * @throws Exception
-     */
-    @Test
-    public void failedAppHandshake() throws Exception {
-        moveToWaitAppHandshakeState();
-
-        assertThat(switchHandler.getStateForTesting(),
-                   CoreMatchers.instanceOf(WaitAppHandshakeState.class));
-
-        WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting();
-        assertThat(state.getCurrentPlugin(), CoreMatchers.<OFSwitchAppHandshakePlugin>equalTo(handshakePlugin));
-
-        PluginResult result = new PluginResult(PluginResultType.DISCONNECT);
-        handshakePlugin.exitPlugin(result);
-
-        assertThat(connection.isConnected(), equalTo(false));
-    }
-
-
-    @Test
-    public void validAppHandshakePluginReason() throws Exception {
-        try{
-            new PluginResult(PluginResultType.QUARANTINE,"This should not cause an exception");
-        }catch(IllegalStateException e) {
-            fail("This should cause an illegal state exception");
-        }
-    }
-
-    @Test
-    public void invalidAppHandshakePluginReason() throws Exception {
-        try{
-            new PluginResult(PluginResultType.CONTINUE,"This should cause an exception");
-            fail("This should cause an illegal state exception");
-        }catch(IllegalStateException e) { /* Expected */ }
-
-        try{
-            new PluginResult(PluginResultType.DISCONNECT,"This should cause an exception");
-            fail("This should cause an illegal state exception");
-        }catch(IllegalStateException e) { /* Expected */ }
-    }
-
-    /**
-     * Move the channel from scratch to WAIT_INITIAL_ROLE state via
-     * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
-     * Does extensive testing for the WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
-     *
-     */
-    @Test
-    public void testSwitchDriverSubHandshake()
-            throws Exception {
-        moveToWaitSwitchDriverSubHandshake();
-
-        //-------------------------------------------------
-        //-------------------------------------------------
-        // Send a message to the handler, it should be passed to the
-        // switch's sub-handshake handling. After this message the
-        // sub-handshake will be complete
-        // FIXME:LOJI: With Andi's fix for a default Match object we won't
-        // need to build/set this match object
-
-        Match match = factory.buildMatch().build();
-        OFMessage m = factory.buildFlowRemoved().setMatch(match).build();
-        resetToStrict(sw);
-        sw.processDriverHandshakeMessage(m);
-        expectLastCall().once();
-        expect(sw.isDriverHandshakeComplete()).andReturn(true).once();
-        replay(sw);
-
-        switchHandler.processOFMessage(m);
-
-        assertThat(switchHandler.getStateForTesting(),
-                   CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitAppHandshakeState.class));
-        assertThat("Unexpected message captured", connection.getMessages(), Matchers.empty());
-        verify(sw);
-    }
-
-    @Test
-    /** Test WaitDescriptionReplyState */
-    public void testWaitDescriptionReplyState() throws Exception {
-        moveToWaitInitialRole();
-    }
-
-    /**
-     * Setup the mock switch and write capture for a role request, set the
-     * role and verify mocks.
-     * @param supportsNxRole whether the switch supports role request messages
-     * to setup the attribute. This must be null (don't yet know if roles
-     * supported: send to check) or true.
-     * @param role The role to send
-     * @throws IOException
-     */
-    private long setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
-                                           OFControllerRole role) throws IOException {
-        assertTrue("This internal test helper method most not be called " +
-                   "with supportsNxRole==false. Test setup broken",
-                   supportsNxRole == null || supportsNxRole == true);
-        reset(sw);
-        expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-                .andReturn(supportsNxRole).atLeastOnce();
-        replay(sw);
-
-        switchHandler.sendRoleRequest(role);
-
-        OFMessage msg = connection.retrieveMessage();
-        verifyRoleRequest(msg, role);
-        verify(sw);
-        return msg.getXid();
-    }
-
-
-    /**
-     * Setup the mock switch for a role change request where the switch
-     * does not support roles.
-     *
-     * Needs to verify and reset the controller since we need to set
-     * an expectation
-     */
-    @SuppressWarnings("unchecked")
+	 */
+	@Test
+	public void testInitState() throws Exception {
+		assertThat(connection.getListener(), notNullValue());
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.InitState.class));
+	}
+
+
+	/** Move the channel from scratch to WAIT_CONFIG_REPLY state
+	 * adds testing for beginHandshake() which moves the state from
+	 * InitState to WaitConfigReply.
+	 */
+	@Test
+	public void moveToWaitConfigReply() throws Exception {
+		moveToPreConfigReply();
+
+		List<OFMessage> msgs = connection.getMessages();
+		assertEquals(3, msgs.size());
+		assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
+		OFSetConfig sc = (OFSetConfig)msgs.get(0);
+		assertEquals(0xffff, sc.getMissSendLen());
+		assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
+		assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
+		verifyUniqueXids(msgs);
+		msgs.clear();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitConfigReplyState.class));
+		verifyAll();
+	}
+
+
+
+	/** Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state
+	 * Builds on moveToWaitConfigReply()
+	 * adds testing for WAIT_CONFIG_REPLY state
+	 */
+	@Test
+	public void moveToWaitDescriptionStatReply() throws Exception {
+		moveToWaitConfigReply();
+
+		connection.clearMessages();
+		OFGetConfigReply cr = factory.buildGetConfigReply()
+				.setMissSendLen(0xFFFF)
+				.build();
+
+		switchHandler.processOFMessage(cr);
+
+		OFMessage msg = connection.retrieveMessage();
+		assertEquals(OFType.STATS_REQUEST, msg.getType());
+		OFStatsRequest<?> sr = (OFStatsRequest<?>)msg;
+		assertEquals(OFStatsType.DESC, sr.getStatsType());
+		verifyUniqueXids(msg);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitDescriptionStatReplyState.class));
+	}
+
+	protected OFDescStatsReply createDescriptionStatsReply() {
+		OFDescStatsReply statsReply = factory.buildDescStatsReply()
+				.setDpDesc("Datapath Description")
+				.setHwDesc("Hardware Description")
+				.setMfrDesc("Manufacturer Description")
+				.setSwDesc("Software Description")
+				.setSerialNum("Serial Number")
+				.build();
+		return statsReply;
+	}
+
+	protected OFTableFeaturesStatsReply createTableFeaturesStatsReply() {
+		OFTableFeaturesStatsReply statsReply = factory.buildTableFeaturesStatsReply()
+				.setEntries(Collections.singletonList(factory.buildTableFeatures()
+						.setConfig(0)
+						.setMaxEntries(100)
+						.setMetadataMatch(U64.NO_MASK)
+						.setMetadataWrite(U64.NO_MASK)
+						.setName("MyTable")
+						.setTableId(TableId.of(1))
+						.setProperties(Collections.singletonList((OFTableFeatureProp)factory.buildTableFeaturePropMatch()
+								.setOxmIds(Collections.singletonList(U32.of(100)))
+								.build())
+								).build()
+						)
+
+						).build();
+		return statsReply;
+	}
+
+	/**
+	 * setup the expectations for the mock switch that are needed
+	 * after the switch is instantiated in the WAIT_DESCRIPTION_STATS STATE
+	 * Will reset the switch
+	 * @throws CounterException
+	 */
+	protected void setupSwitchForInstantiationWithReset()
+			throws Exception {
+		reset(sw);
+		sw.setFeaturesReply(featuresReply);
+		expectLastCall().once();
+	}
+
+	/**
+	 * Tests a situation where a switch returns a QUARANTINE result. This means
+	 * we should move the handshake handler to a quarantine state and also
+	 * quarantine the switch in the controller.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void moveQuarantine() throws Exception {
+		moveToWaitAppHandshakeState();
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.QUARANTINED);
+		expectLastCall().once();
+		replay(switchManager);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(WaitAppHandshakeState.class));
+		WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting();
+		assertThat(state.getCurrentPlugin(), CoreMatchers.<OFSwitchAppHandshakePlugin>equalTo(handshakePlugin));
+
+		reset(sw);
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE);
+		sw.setStatus(SwitchStatus.QUARANTINED);
+		expectLastCall().once();
+		replay(sw);
+
+		PluginResult result = new PluginResult(PluginResultType.QUARANTINE, "test quarantine");
+		handshakePlugin.exitPlugin(result);
+
+		assertThat(switchHandler.getStateForTesting(),
+				CoreMatchers.instanceOf(QuarantineState.class));
+		verify(switchManager);
+	}
+
+	/**
+	 * Tests a situation where a plugin returns a DISCONNECT result. This means
+	 * we should disconnect the connection and the state should not change.
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void failedAppHandshake() throws Exception {
+		moveToWaitAppHandshakeState();
+
+		assertThat(switchHandler.getStateForTesting(),
+				CoreMatchers.instanceOf(WaitAppHandshakeState.class));
+
+		WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting();
+		assertThat(state.getCurrentPlugin(), CoreMatchers.<OFSwitchAppHandshakePlugin>equalTo(handshakePlugin));
+
+		PluginResult result = new PluginResult(PluginResultType.DISCONNECT);
+		handshakePlugin.exitPlugin(result);
+
+		assertThat(connection.isConnected(), equalTo(false));
+	}
+
+
+	@Test
+	public void validAppHandshakePluginReason() throws Exception {
+		try{
+			new PluginResult(PluginResultType.QUARANTINE,"This should not cause an exception");
+		}catch(IllegalStateException e) {
+			fail("This should cause an illegal state exception");
+		}
+	}
+
+	@Test
+	public void invalidAppHandshakePluginReason() throws Exception {
+		try{
+			new PluginResult(PluginResultType.CONTINUE,"This should cause an exception");
+			fail("This should cause an illegal state exception");
+		}catch(IllegalStateException e) { /* Expected */ }
+
+		try{
+			new PluginResult(PluginResultType.DISCONNECT,"This should cause an exception");
+			fail("This should cause an illegal state exception");
+		}catch(IllegalStateException e) { /* Expected */ }
+	}
+
+	/**
+	 * Move the channel from scratch to WAIT_INITIAL_ROLE state via
+	 * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
+	 * Does extensive testing for the WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+	 *
+	 */
+	@Test
+	public void testSwitchDriverSubHandshake()
+			throws Exception {
+		moveToWaitSwitchDriverSubHandshake();
+
+		//-------------------------------------------------
+		//-------------------------------------------------
+		// Send a message to the handler, it should be passed to the
+		// switch's sub-handshake handling. After this message the
+		// sub-handshake will be complete
+		// FIXME:LOJI: With Andi's fix for a default Match object we won't
+		// need to build/set this match object
+
+		Match match = factory.buildMatch().build();
+		OFMessage m = factory.buildFlowRemoved().setMatch(match).build();
+		resetToStrict(sw);
+		sw.processDriverHandshakeMessage(m);
+		expectLastCall().once();
+		expect(sw.isDriverHandshakeComplete()).andReturn(true).once();
+		replay(sw);
+
+		switchHandler.processOFMessage(m);
+
+		assertThat(switchHandler.getStateForTesting(),
+				CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitAppHandshakeState.class));
+		assertThat("Unexpected message captured", connection.getMessages(), Matchers.empty());
+		verify(sw);
+	}
+
+	@Test
+	/** Test WaitDescriptionReplyState */
+	public void testWaitDescriptionReplyState() throws Exception {
+		moveToWaitInitialRole();
+	}
+
+	/**
+	 * Setup the mock switch and write capture for a role request, set the
+	 * role and verify mocks.
+	 * @param supportsNxRole whether the switch supports role request messages
+	 * to setup the attribute. This must be null (don't yet know if roles
+	 * supported: send to check) or true.
+	 * @param role The role to send
+	 * @throws IOException
+	 */
+	private long setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
+			OFControllerRole role) throws IOException {
+		assertTrue("This internal test helper method most not be called " +
+				"with supportsNxRole==false. Test setup broken",
+				supportsNxRole == null || supportsNxRole == true);
+		reset(sw);
+		expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+		.andReturn(supportsNxRole).atLeastOnce();
+		replay(sw);
+
+		switchHandler.sendRoleRequest(role);
+
+		OFMessage msg = connection.retrieveMessage();
+		verifyRoleRequest(msg, role);
+		verify(sw);
+		return msg.getXid();
+	}
+
+
+	/**
+	 * Setup the mock switch for a role change request where the switch
+	 * does not support roles.
+	 *
+	 * Needs to verify and reset the controller since we need to set
+	 * an expectation
+	 */
+	@SuppressWarnings("unchecked")
 	private void setupSwitchRoleChangeUnsupported(int xid,
-                                                  OFControllerRole role) {
-        SwitchStatus newStatus = role != OFControllerRole.ROLE_SLAVE ? SwitchStatus.MASTER : SwitchStatus.SLAVE;
-        boolean supportsNxRole = false;
-        verify(switchManager);
-        reset(sw, switchManager);
-        expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
-                .andReturn(supportsNxRole).atLeastOnce();
-        // TODO: hmmm. While it's not incorrect that we set the attribute
-        // again it looks odd. Maybe change
-        expect(sw.getOFFactory()).andReturn(factory).anyTimes();
-        sw.write(anyObject(OFMessage.class));
-        expectLastCall().anyTimes();
-        sw.write(anyObject(Iterable.class));
-        expectLastCall().anyTimes();
-        expect(sw.getTables()).andStubReturn((short)0);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
-        expectLastCall().anyTimes();
-        sw.setControllerRole(role);
-        expectLastCall().once();
-
-        if (role == OFControllerRole.ROLE_SLAVE) {
-            sw.disconnect();
-            expectLastCall().once();
-        } else {
-            expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-            sw.setStatus(newStatus);
-            expectLastCall().once();
-            switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, newStatus);
-        }
-        replay(sw, switchManager);
-
-        switchHandler.sendRoleRequest(role);
-
-        verify(sw, switchManager);
-    }
-
-    /** Return a bad request error message with the given xid/code */
-    private OFMessage getBadRequestErrorMessage(OFBadRequestCode code, long xid) {
-        OFErrorMsg msg = factory.errorMsgs().buildBadRequestErrorMsg()
-                .setXid(xid)
-                .setCode(code)
-                .build();
-        return msg;
-    }
-
-    /** Return a bad action error message with the given xid/code */
-    private OFMessage getBadActionErrorMessage(OFBadActionCode code, long xid) {
-        OFErrorMsg msg = factory.errorMsgs().buildBadActionErrorMsg()
-                .setXid(xid)
-                .setCode(code)
-                .build();
-        return msg;
-    }
-
-
-    /** Move the channel from scratch to MASTER state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * This method tests only the simple case that the switch supports roles
-     * and transitions to MASTER
-     */
-    @SuppressWarnings("unchecked")
+			OFControllerRole role) {
+		SwitchStatus newStatus = role != OFControllerRole.ROLE_SLAVE ? SwitchStatus.MASTER : SwitchStatus.SLAVE;
+		boolean supportsNxRole = false;
+		verify(switchManager);
+		reset(sw, switchManager);
+		expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+		.andReturn(supportsNxRole).atLeastOnce();
+		// TODO: hmmm. While it's not incorrect that we set the attribute
+		// again it looks odd. Maybe change
+		expect(sw.getOFFactory()).andReturn(factory).anyTimes();
+		sw.write(anyObject(OFMessage.class));
+		expectLastCall().anyTimes();
+		sw.write(anyObject(Iterable.class));
+		expectLastCall().anyTimes();
+		expect(sw.getTables()).andStubReturn((short)0);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
+		expectLastCall().anyTimes();
+		if (SwitchStatus.MASTER == newStatus) {
+			if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) {
+				expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2);
+			}
+		}
+
+		sw.setControllerRole(role);
+		expectLastCall().once();
+
+		if (role == OFControllerRole.ROLE_SLAVE) {
+			sw.disconnect();
+			expectLastCall().once();
+		} else {
+			expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+			sw.setStatus(newStatus);
+			expectLastCall().once();
+			switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, newStatus);
+		}
+		replay(sw, switchManager);
+
+		switchHandler.sendRoleRequest(role);
+
+		verify(sw, switchManager);
+	}
+
+	/** Return a bad request error message with the given xid/code */
+	private OFMessage getBadRequestErrorMessage(OFBadRequestCode code, long xid) {
+		OFErrorMsg msg = factory.errorMsgs().buildBadRequestErrorMsg()
+				.setXid(xid)
+				.setCode(code)
+				.build();
+		return msg;
+	}
+
+	/** Return a bad action error message with the given xid/code */
+	private OFMessage getBadActionErrorMessage(OFBadActionCode code, long xid) {
+		OFErrorMsg msg = factory.errorMsgs().buildBadActionErrorMsg()
+				.setXid(xid)
+				.setCode(code)
+				.build();
+		return msg;
+	}
+
+
+	/** Move the channel from scratch to MASTER state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * This method tests only the simple case that the switch supports roles
+	 * and transitions to MASTER
+	 */
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testInitialMoveToMasterWithRole() throws Exception {
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		expect(sw.getOFFactory()).andReturn(factory).anyTimes();
+		sw.write(anyObject(OFMessage.class));
+		expectLastCall().anyTimes();
+		sw.write(anyObject(Iterable.class));
+		expectLastCall().anyTimes();
+		expect(sw.getTables()).andStubReturn((short)0);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_MASTER);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+		sw.setStatus(SwitchStatus.MASTER);
+		expectLastCall().once();
+		if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) {
+			expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2);
+		}
+		replay(sw);
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
+		expectLastCall().once();
+		replay(switchManager);
+		OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_MASTER);
+
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(reply);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+	}
+
+	/** Move the channel from scratch to SLAVE state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * This method tests only the simple case that the switch supports roles
+	 * and transitions to SLAVE
+	 */
+	@Test
+	public void testInitialMoveToSlaveWithRole() throws Exception {
+
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		sw.setAttribute(IOFSwitchBackend.SWITCH_SUPPORTS_NX_ROLE, true);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+		sw.setStatus(SwitchStatus.SLAVE);
+		expectLastCall().once();
+		replay(sw);
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.SLAVE);
+		expectLastCall().once();
+		replay(switchManager);
+
+		OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE);
+
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(reply);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class));
+	}
+
+	/** Move the channel from scratch to MASTER state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * This method tests the case that the switch does NOT support roles.
+	 * The channel handler still needs to send the initial request to find
+	 * out that whether the switch supports roles.
+	 */
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testInitialMoveToMasterNoRole() throws Exception {
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		expect(sw.getOFFactory()).andReturn(factory).anyTimes();
+		sw.write(anyObject(OFMessage.class));
+		expectLastCall().anyTimes();
+		sw.write(anyObject(Iterable.class));
+		expectLastCall().anyTimes();
+		expect(sw.getTables()).andStubReturn((short)0);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_MASTER);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+		sw.setStatus(SwitchStatus.MASTER);
+		expectLastCall().once();
+		if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) {
+			expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2);
+		}
+		replay(sw);
+
+		// FIXME: shouldn't use ordinal(), but OFError is broken
+
+		// Error with incorrect xid and type. Should be ignored.
+		OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid+1);
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(err);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Error with correct xid. Should trigger state transition
+		err = getBadRequestErrorMessage(OFBadRequestCode.BAD_EXPERIMENTER, xid);
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
+		expectLastCall().once();
+		replay(switchManager);
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(err);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+	}
+
+	/** Move the channel from scratch to MASTER state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * We let the initial role request time out. Role support should be
+	 * disabled but the switch should be activated.
+	 */
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testInitialMoveToMasterTimeout() throws Exception {
+		int timeout = 50;
+		switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		expect(sw.getOFFactory()).andReturn(factory).anyTimes();
+		sw.write(anyObject(OFMessage.class));
+		expectLastCall().anyTimes();
+		sw.write(anyObject(Iterable.class));
+		expectLastCall().anyTimes();
+		expect(sw.getTables()).andStubReturn((short)0);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_MASTER);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+		sw.setStatus(SwitchStatus.MASTER);
+		expectLastCall().once();
+		if (factory.getVersion().compareTo(OFVersion.OF_13) >= 0) {
+			expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2);
+		}
+		replay(sw);
+
+		OFMessage m = factory.buildBarrierReply().build();
+
+		Thread.sleep(timeout+5);
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
+		expectLastCall().once();
+		replay(switchManager);
+		switchHandler.processOFMessage(m);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+
+	}
+
+
+	/** Move the channel from scratch to SLAVE state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * This method tests the case that the switch does NOT support roles.
+	 * The channel handler still needs to send the initial request to find
+	 * out that whether the switch supports roles.
+	 *
+	 */
 	@Test
-    public void testInitialMoveToMasterWithRole() throws Exception {
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        expect(sw.getOFFactory()).andReturn(factory).anyTimes();
-        sw.write(anyObject(OFMessage.class));
-        expectLastCall().anyTimes();
-        sw.write(anyObject(Iterable.class));
-        expectLastCall().anyTimes();
-        expect(sw.getTables()).andStubReturn((short)0);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_MASTER);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-        sw.setStatus(SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(sw);
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(switchManager);
-        OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_MASTER);
-
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(reply);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-    }
-
-    /** Move the channel from scratch to SLAVE state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * This method tests only the simple case that the switch supports roles
-     * and transitions to SLAVE
-     */
-    @Test
-    public void testInitialMoveToSlaveWithRole() throws Exception {
-
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        sw.setAttribute(IOFSwitchBackend.SWITCH_SUPPORTS_NX_ROLE, true);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-        sw.setStatus(SwitchStatus.SLAVE);
-        expectLastCall().once();
-        replay(sw);
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.SLAVE);
-        expectLastCall().once();
-        replay(switchManager);
-
-        OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE);
-
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(reply);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class));
-    }
-
-    /** Move the channel from scratch to MASTER state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * This method tests the case that the switch does NOT support roles.
-     * The channel handler still needs to send the initial request to find
-     * out that whether the switch supports roles.
-     */
-    @SuppressWarnings("unchecked")
+	public void testInitialMoveToSlaveNoRole() throws Exception {
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
+		expectLastCall().once();
+		sw.disconnect(); // Make sure we disconnect
+		expectLastCall().once();
+		replay(sw);
+
+
+		// FIXME: shouldn't use ordinal(), but OFError is broken
+
+		// Error with incorrect xid and type. Should be ignored.
+		OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid+1);
+
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(err);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Error with correct xid. Should trigger state transition
+		err = getBadRequestErrorMessage(OFBadRequestCode.BAD_EXPERIMENTER, xid);
+		// sendMessageToHandler will verify and rest controller mock
+		switchHandler.processOFMessage(err);
+	}
+
+
+	/** Move the channel from scratch to SLAVE state
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 *
+	 * We let the initial role request time out. The switch should be
+	 * disconnected
+	 */
 	@Test
-    public void testInitialMoveToMasterNoRole() throws Exception {
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        expect(sw.getOFFactory()).andReturn(factory).anyTimes();
-        sw.write(anyObject(OFMessage.class));
-        expectLastCall().anyTimes();
-        sw.write(anyObject(Iterable.class));
-        expectLastCall().anyTimes();
-        expect(sw.getTables()).andStubReturn((short)0);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_MASTER);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-        sw.setStatus(SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(sw);
-
-        // FIXME: shouldn't use ordinal(), but OFError is broken
-
-        // Error with incorrect xid and type. Should be ignored.
-        OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid+1);
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(err);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Error with correct xid. Should trigger state transition
-        err = getBadRequestErrorMessage(OFBadRequestCode.BAD_EXPERIMENTER, xid);
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(switchManager);
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(err);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-    }
-
-    /** Move the channel from scratch to MASTER state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * We let the initial role request time out. Role support should be
-     * disabled but the switch should be activated.
-     */
-    @SuppressWarnings("unchecked")
+	public void testInitialMoveToSlaveTimeout() throws Exception {
+		int timeout = 50;
+		switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
+		expectLastCall().once();
+		sw.disconnect(); // Make sure we disconnect
+		expectLastCall().once();
+		replay(sw);
+
+		// Apparently this can be any type of message for this test?!
+		OFMessage m = factory.buildBarrierReply().build();
+
+		Thread.sleep(timeout+5);
+		switchHandler.processOFMessage(m);
+	}
+
+
+	/** Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
+	 * then SLAVE for cases where the switch does not support roles.
+	 * I.e., the final SLAVE transition should disconnect the switch.
+	 */
 	@Test
-    public void testInitialMoveToMasterTimeout() throws Exception {
-        int timeout = 50;
-        switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout);
-
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        expect(sw.getOFFactory()).andReturn(factory).anyTimes();
-        sw.write(anyObject(OFMessage.class));
-        expectLastCall().anyTimes();
-        sw.write(anyObject(Iterable.class));
-        expectLastCall().anyTimes();
-        expect(sw.getTables()).andStubReturn((short)0);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_MASTER);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-        sw.setStatus(SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(sw);
-
-        OFMessage m = factory.buildBarrierReply().build();
-
-        Thread.sleep(timeout+5);
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(switchManager);
-        switchHandler.processOFMessage(m);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-
-    }
-
-
-    /** Move the channel from scratch to SLAVE state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * This method tests the case that the switch does NOT support roles.
-     * The channel handler still needs to send the initial request to find
-     * out that whether the switch supports roles.
-     *
-     */
-    @Test
-    public void testInitialMoveToSlaveNoRole() throws Exception {
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
-        expectLastCall().once();
-        sw.disconnect(); // Make sure we disconnect
-        expectLastCall().once();
-        replay(sw);
-
-
-        // FIXME: shouldn't use ordinal(), but OFError is broken
-
-        // Error with incorrect xid and type. Should be ignored.
-        OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid+1);
-
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(err);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Error with correct xid. Should trigger state transition
-        err = getBadRequestErrorMessage(OFBadRequestCode.BAD_EXPERIMENTER, xid);
-        // sendMessageToHandler will verify and rest controller mock
-        switchHandler.processOFMessage(err);
-    }
-
-
-    /** Move the channel from scratch to SLAVE state
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     *
-     * We let the initial role request time out. The switch should be
-     * disconnected
-     */
-    @Test
-    public void testInitialMoveToSlaveTimeout() throws Exception {
-        int timeout = 50;
-        switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout);
-
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
-        expectLastCall().once();
-        sw.disconnect(); // Make sure we disconnect
-        expectLastCall().once();
-        replay(sw);
-
-        // Apparently this can be any type of message for this test?!
-        OFMessage m = factory.buildBarrierReply().build();
-
-        Thread.sleep(timeout+5);
-        switchHandler.processOFMessage(m);
-    }
-
-
-    /** Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
-     * then SLAVE for cases where the switch does not support roles.
-     * I.e., the final SLAVE transition should disconnect the switch.
-     */
-    @Test
-    public void testNoRoleInitialToMasterToSlave() throws Exception {
-        int xid = 46;
-        // First, lets move the state to MASTER without role support
-        testInitialMoveToMasterNoRole();
-        assertThat(switchHandler.getStateForTesting(),
-                CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-
-        assertThat("Unexpected messages have been captured",
-                connection.getMessages(),
-                 Matchers.empty());
-
-        // try to set master role again. should be a no-op
-        setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_MASTER);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-
-        assertThat("Unexpected messages have been captured",
-                connection.getMessages(),
-                 Matchers.empty());
-
-        setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_SLAVE);
-        assertThat(connection.isConnected(), equalTo(false));
-
-        assertThat("Unexpected messages have been captured",
-                connection.getMessages(),
-                 Matchers.empty());
-    }
-
-    /** Move the channel to MASTER state
-     * Expects that the channel is in MASTER or SLAVE state.
-     *
-     */
-    @SuppressWarnings("unchecked")
+	public void testNoRoleInitialToMasterToSlave() throws Exception {
+		int xid = 46;
+		// First, lets move the state to MASTER without role support
+		testInitialMoveToMasterNoRole();
+		assertThat(switchHandler.getStateForTesting(),
+				CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+
+		assertThat("Unexpected messages have been captured",
+				connection.getMessages(),
+				Matchers.empty());
+
+		// try to set master role again. should be a no-op
+		setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_MASTER);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+
+		assertThat("Unexpected messages have been captured",
+				connection.getMessages(),
+				Matchers.empty());
+
+		setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_SLAVE);
+		assertThat(connection.isConnected(), equalTo(false));
+
+		assertThat("Unexpected messages have been captured",
+				connection.getMessages(),
+				Matchers.empty());
+	}
+
+	/** Move the channel to MASTER state
+	 * Expects that the channel is in MASTER or SLAVE state.
+	 *
+	 */
+	@SuppressWarnings("unchecked")
 	public void changeRoleToMasterWithRequest() throws Exception {
-        assertTrue("This method can only be called when handler is in " +
-                   "MASTER or SLAVE role", switchHandler.isHandshakeComplete());
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_MASTER);
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        expect(sw.getOFFactory()).andReturn(factory).anyTimes();
-        sw.write(anyObject(OFMessage.class));
-        expectLastCall().anyTimes();
-        sw.write(anyObject(Iterable.class));
-        expectLastCall().anyTimes();
-        expect(sw.getTables()).andStubReturn((short)0);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_MASTER);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
-        sw.setStatus(SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(sw);
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
-        expectLastCall().once();
-        replay(switchManager);
-
-        OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_MASTER);
-
-        switchHandler.processOFMessage(reply);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
-    }
-
-    /** Move the channel to SLAVE state
-     * Expects that the channel is in MASTER or SLAVE state.
-     *
-     */
-    public void changeRoleToSlaveWithRequest() throws Exception {
-        assertTrue("This method can only be called when handler is in " +
-                   "MASTER or SLAVE role", switchHandler.isHandshakeComplete());
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_SLAVE);
-
-        // prepare mocks and inject the role reply message
-        reset(sw);
-        sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
-        expectLastCall().once();
-        sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
-        expectLastCall().once();
-        expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).once();
-        sw.setStatus(SwitchStatus.SLAVE);
-        expectLastCall().once();
-        replay(sw);
-
-        reset(switchManager);
-        switchManager.switchStatusChanged(sw, SwitchStatus.MASTER, SwitchStatus.SLAVE);
-        expectLastCall().once();
-        replay(switchManager);
-
-        OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE);
-        connection.getListener().messageReceived(connection, reply);
-
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class));
-    }
-
-    @Test
-    public void testMultiRoleChange1() throws Exception {
-        testInitialMoveToMasterWithRole();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-    }
-
-    @Test
-    public void testMultiRoleChange2() throws Exception {
-        testInitialMoveToSlaveWithRole();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToSlaveWithRequest();
-        changeRoleToMasterWithRequest();
-        changeRoleToSlaveWithRequest();
-    }
-
-    /** Start from scratch and reply with an unexpected error to the role
-     * change request
-     * Builds on doMoveToWaitInitialRole()
-     * adds testing for WAIT_INITAL_ROLE state
-     */
-    @Test
-    public void testInitialRoleChangeOtherError() throws Exception {
-        // first, move us to WAIT_INITIAL_ROLE_STATE
-        moveToWaitInitialRole();
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        // Set the role
-        long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
-        assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
-
-        OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid);
-
-        verifyExceptionCaptured(err, SwitchStateException.class);
-    }
-
-    /**
-     * Test dispatch of messages while in MASTER role
-     */
-    @Test
-    public void testMessageDispatchMaster() throws Exception {
-        testInitialMoveToMasterWithRole();
-
-        // Send packet in. expect dispatch
-        OFPacketIn pi = factory.buildPacketIn()
-                .setReason(OFPacketInReason.NO_MATCH)
-                .build();
-        reset(switchManager);
-        switchManager.handleMessage(sw, pi, null);
-        expectLastCall().once();
-        replay(switchManager);
-        switchHandler.processOFMessage(pi);
-
-        // TODO: many more to go
-    }
-
-    /**
-     * Test port status message handling while MASTER
-     *
-     */
-    @Test
-    public void testPortStatusMessageMaster() throws Exception {
-        DatapathId dpid = featuresReply.getDatapathId();
-        testInitialMoveToMasterWithRole();
-
-        OFPortDesc portDesc = factory.buildPortDesc()
-                .setName("Port1")
-                .setPortNo(OFPort.of(1))
-                .build();
-        OFPortStatus.Builder portStatusBuilder = factory.buildPortStatus()
-                .setDesc(portDesc);
-
-        // The events we expect sw.handlePortStatus to return
-        // We'll just use the same list for all valid OFPortReasons and add
-        // arbitrary events for arbitrary ports that are not necessarily
-        // related to the port status message. Our goal
-        // here is not to return the correct set of events but the make sure
-        // that a) sw.handlePortStatus is called
-        //      b) the list of events sw.handlePortStatus returns is sent
-        //         as IOFSwitchListener notifications.
-        OrderedCollection<PortChangeEvent> events =
-                new LinkedHashSetWrapper<PortChangeEvent>();
-        OFPortDesc.Builder pb = factory.buildPortDesc();
-        OFPortDesc p1 = pb.setName("eth1").setPortNo(OFPort.of(1)).build();
-        OFPortDesc p2 = pb.setName("eth2").setPortNo(OFPort.of(2)).build();
-        OFPortDesc p3 = pb.setName("eth3").setPortNo(OFPort.of(3)).build();
-        OFPortDesc p4 = pb.setName("eth4").setPortNo(OFPort.of(4)).build();
-        OFPortDesc p5 = pb.setName("eth5").setPortNo(OFPort.of(5)).build();
-
-        
-        events.add(new PortChangeEvent(p1, PortChangeType.ADD));
-        events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
-        events.add(new PortChangeEvent(p3, PortChangeType.UP));
-        events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
-        events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));
-
-
-        for (OFPortReason reason: OFPortReason.values()) {
-            OFPortStatus portStatus = portStatusBuilder.setReason(reason).build();
-
-            reset(sw);
-            expect(sw.getId()).andReturn(dpid).anyTimes();
-
-            expect(sw.processOFPortStatus(portStatus)).andReturn(events).once();
-            replay(sw);
-
-            reset(switchManager);
-            switchManager.notifyPortChanged(sw, p1, PortChangeType.ADD);
-            switchManager.notifyPortChanged(sw, p2, PortChangeType.DELETE);
-            switchManager.notifyPortChanged(sw, p3, PortChangeType.UP);
-            switchManager.notifyPortChanged(sw, p4, PortChangeType.DOWN);
-            switchManager.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
-            replay(switchManager);
-
-            switchHandler.processOFMessage(portStatus);
-
-            verify(sw);
-        }
-    }
-
-    /**
-     * Test re-assert MASTER
-     *
-     */
-    @Test
-    public void testReassertMaster() throws Exception {
-        testInitialMoveToMasterWithRole();
-
-        OFMessage err = getBadRequestErrorMessage(OFBadRequestCode.EPERM, 42);
-
-        reset(roleManager);
-        roleManager.reassertRole(switchHandler, HARole.ACTIVE);
-        expectLastCall().once();
-        replay(roleManager);
-
-        reset(switchManager);
-        switchManager.handleMessage(sw, err, null);
-        expectLastCall().once();
-        replay(switchManager);
-
-        switchHandler.processOFMessage(err);
-
-        verify(sw);
-    }
-
-    /**
-     * Verify that the given exception event capture (as returned by
-     * getAndInitExceptionCapture) has thrown an exception of the given
-     * expectedExceptionClass.
-     * Resets the capture
-     * @param err
-     */
-    void verifyExceptionCaptured(
-            OFMessage err, Class<? extends Throwable> expectedExceptionClass) {
-
-        Throwable caughtEx = null;
-        // This should purposely cause an exception
-        try{
-            switchHandler.processOFMessage(err);
-        }
-        catch(Exception e){
-            // Capture the exception
-            caughtEx = e;
-        }
-
-        assertThat(caughtEx, CoreMatchers.instanceOf(expectedExceptionClass));
-    }
-
-    /**
-     * Tests the connection closed functionality before the switch handshake is complete.
-     * Essentially when the switch handshake is only aware of the IOFConnection.
-     */
-    @Test
-    public void testConnectionClosedBeforeHandshakeComplete() {
-
-        // Test connection closed prior to being finished
-        reset(switchManager);
-        switchManager.handshakeDisconnected(dpid);
-        expectLastCall().once();
-        replay(switchManager);
-
-        switchHandler.connectionClosed(connection);
-
-        verify(switchManager);
-    }
-
-    /**
-     * Tests the connection closed functionality after the switch handshake is complete.
-     * Essentially when the switch handshake is aware of an IOFSwitch.
-     * @throws Exception
-     */
-    @Test
-    public void testConnectionClosedAfterHandshakeComplete() throws Exception {
-
-        testInitialMoveToMasterWithRole();
-        // Test connection closed prior to being finished
-        reset(switchManager);
-        switchManager.handshakeDisconnected(dpid);
-        expectLastCall().once();
-        switchManager.switchDisconnected(sw);
-        expectLastCall().once();
-        replay(switchManager);
-
-        reset(sw);
-        expect(sw.getStatus()).andReturn(SwitchStatus.DISCONNECTED).anyTimes();
-        replay(sw);
-
-        switchHandler.connectionClosed(connection);
-
-        verify(switchManager);
-        verify(sw);
-    }
+		assertTrue("This method can only be called when handler is in " +
+				"MASTER or SLAVE role", switchHandler.isHandshakeComplete());
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_MASTER);
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		expect(sw.getOFFactory()).andReturn(factory).anyTimes();
+		sw.write(anyObject(OFMessage.class));
+		expectLastCall().anyTimes();
+		sw.write(anyObject(Iterable.class));
+		expectLastCall().anyTimes();
+		expect(sw.getTables()).andStubReturn((short)0);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_MASTER);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once();
+		sw.setStatus(SwitchStatus.MASTER);
+		expectLastCall().once();
+		expect(sw.getMaxTableForTableMissFlow()).andReturn(TableId.ZERO).times(2);
+		replay(sw);
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER);
+		expectLastCall().once();
+		replay(switchManager);
+
+		OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_MASTER);
+
+		switchHandler.processOFMessage(reply);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class));
+	}
+
+	/** Move the channel to SLAVE state
+	 * Expects that the channel is in MASTER or SLAVE state.
+	 *
+	 */
+	public void changeRoleToSlaveWithRequest() throws Exception {
+		assertTrue("This method can only be called when handler is in " +
+				"MASTER or SLAVE role", switchHandler.isHandshakeComplete());
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_SLAVE);
+
+		// prepare mocks and inject the role reply message
+		reset(sw);
+		sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
+		expectLastCall().once();
+		sw.setControllerRole(OFControllerRole.ROLE_SLAVE);
+		expectLastCall().once();
+		expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).once();
+		sw.setStatus(SwitchStatus.SLAVE);
+		expectLastCall().once();
+		replay(sw);
+
+		reset(switchManager);
+		switchManager.switchStatusChanged(sw, SwitchStatus.MASTER, SwitchStatus.SLAVE);
+		expectLastCall().once();
+		replay(switchManager);
+
+		OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE);
+		connection.getListener().messageReceived(connection, reply);
+
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class));
+	}
+
+	@Test
+	public void testMultiRoleChange1() throws Exception {
+		testInitialMoveToMasterWithRole();
+		changeRoleToMasterWithRequest();
+		changeRoleToSlaveWithRequest();
+		changeRoleToSlaveWithRequest();
+		changeRoleToMasterWithRequest();
+		changeRoleToSlaveWithRequest();
+	}
+
+	@Test
+	public void testMultiRoleChange2() throws Exception {
+		testInitialMoveToSlaveWithRole();
+		changeRoleToMasterWithRequest();
+		changeRoleToSlaveWithRequest();
+		changeRoleToSlaveWithRequest();
+		changeRoleToMasterWithRequest();
+		changeRoleToSlaveWithRequest();
+	}
+
+	/** Start from scratch and reply with an unexpected error to the role
+	 * change request
+	 * Builds on doMoveToWaitInitialRole()
+	 * adds testing for WAIT_INITAL_ROLE state
+	 */
+	@Test
+	public void testInitialRoleChangeOtherError() throws Exception {
+		// first, move us to WAIT_INITIAL_ROLE_STATE
+		moveToWaitInitialRole();
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		// Set the role
+		long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_MASTER);
+		assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class));
+
+		OFMessage err = getBadActionErrorMessage(OFBadActionCode.BAD_TYPE, xid);
+
+		verifyExceptionCaptured(err, SwitchStateException.class);
+	}
+
+	/**
+	 * Test dispatch of messages while in MASTER role
+	 */
+	@Test
+	public void testMessageDispatchMaster() throws Exception {
+		testInitialMoveToMasterWithRole();
+
+		// Send packet in. expect dispatch
+		OFPacketIn pi = factory.buildPacketIn()
+				.setReason(OFPacketInReason.NO_MATCH)
+				.build();
+		reset(switchManager);
+		switchManager.handleMessage(sw, pi, null);
+		expectLastCall().once();
+		replay(switchManager);
+		switchHandler.processOFMessage(pi);
+
+		// TODO: many more to go
+	}
+
+	/**
+	 * Test port status message handling while MASTER
+	 *
+	 */
+	@Test
+	public void testPortStatusMessageMaster() throws Exception {
+		DatapathId dpid = featuresReply.getDatapathId();
+		testInitialMoveToMasterWithRole();
+
+		OFPortDesc portDesc = factory.buildPortDesc()
+				.setName("Port1")
+				.setPortNo(OFPort.of(1))
+				.build();
+		OFPortStatus.Builder portStatusBuilder = factory.buildPortStatus()
+				.setDesc(portDesc);
+
+		// The events we expect sw.handlePortStatus to return
+		// We'll just use the same list for all valid OFPortReasons and add
+		// arbitrary events for arbitrary ports that are not necessarily
+		// related to the port status message. Our goal
+		// here is not to return the correct set of events but the make sure
+		// that a) sw.handlePortStatus is called
+		//      b) the list of events sw.handlePortStatus returns is sent
+		//         as IOFSwitchListener notifications.
+		OrderedCollection<PortChangeEvent> events =
+				new LinkedHashSetWrapper<PortChangeEvent>();
+		OFPortDesc.Builder pb = factory.buildPortDesc();
+		OFPortDesc p1 = pb.setName("eth1").setPortNo(OFPort.of(1)).build();
+		OFPortDesc p2 = pb.setName("eth2").setPortNo(OFPort.of(2)).build();
+		OFPortDesc p3 = pb.setName("eth3").setPortNo(OFPort.of(3)).build();
+		OFPortDesc p4 = pb.setName("eth4").setPortNo(OFPort.of(4)).build();
+		OFPortDesc p5 = pb.setName("eth5").setPortNo(OFPort.of(5)).build();
+
+
+		events.add(new PortChangeEvent(p1, PortChangeType.ADD));
+		events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
+		events.add(new PortChangeEvent(p3, PortChangeType.UP));
+		events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
+		events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));
+
+
+		for (OFPortReason reason: OFPortReason.values()) {
+			OFPortStatus portStatus = portStatusBuilder.setReason(reason).build();
+
+			reset(sw);
+			expect(sw.getId()).andReturn(dpid).anyTimes();
+
+			expect(sw.processOFPortStatus(portStatus)).andReturn(events).once();
+			replay(sw);
+
+			reset(switchManager);
+			switchManager.notifyPortChanged(sw, p1, PortChangeType.ADD);
+			switchManager.notifyPortChanged(sw, p2, PortChangeType.DELETE);
+			switchManager.notifyPortChanged(sw, p3, PortChangeType.UP);
+			switchManager.notifyPortChanged(sw, p4, PortChangeType.DOWN);
+			switchManager.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
+			replay(switchManager);
+
+			switchHandler.processOFMessage(portStatus);
+
+			verify(sw);
+		}
+	}
+
+	/**
+	 * Test re-assert MASTER
+	 *
+	 */
+	@Test
+	public void testReassertMaster() throws Exception {
+		testInitialMoveToMasterWithRole();
+
+		OFMessage err = getBadRequestErrorMessage(OFBadRequestCode.EPERM, 42);
+
+		reset(roleManager);
+		roleManager.reassertRole(switchHandler, HARole.ACTIVE);
+		expectLastCall().once();
+		replay(roleManager);
+
+		reset(switchManager);
+		switchManager.handleMessage(sw, err, null);
+		expectLastCall().once();
+		replay(switchManager);
+
+		switchHandler.processOFMessage(err);
+
+		verify(sw);
+	}
+
+	/**
+	 * Verify that the given exception event capture (as returned by
+	 * getAndInitExceptionCapture) has thrown an exception of the given
+	 * expectedExceptionClass.
+	 * Resets the capture
+	 * @param err
+	 */
+	void verifyExceptionCaptured(
+			OFMessage err, Class<? extends Throwable> expectedExceptionClass) {
+
+		Throwable caughtEx = null;
+		// This should purposely cause an exception
+		try{
+			switchHandler.processOFMessage(err);
+		}
+		catch(Exception e){
+			// Capture the exception
+			caughtEx = e;
+		}
+
+		assertThat(caughtEx, CoreMatchers.instanceOf(expectedExceptionClass));
+	}
+
+	/**
+	 * Tests the connection closed functionality before the switch handshake is complete.
+	 * Essentially when the switch handshake is only aware of the IOFConnection.
+	 */
+	@Test
+	public void testConnectionClosedBeforeHandshakeComplete() {
+
+		// Test connection closed prior to being finished
+		reset(switchManager);
+		switchManager.handshakeDisconnected(dpid);
+		expectLastCall().once();
+		replay(switchManager);
+
+		switchHandler.connectionClosed(connection);
+
+		verify(switchManager);
+	}
+
+	/**
+	 * Tests the connection closed functionality after the switch handshake is complete.
+	 * Essentially when the switch handshake is aware of an IOFSwitch.
+	 * @throws Exception
+	 */
+	@Test
+	public void testConnectionClosedAfterHandshakeComplete() throws Exception {
+
+		testInitialMoveToMasterWithRole();
+		// Test connection closed prior to being finished
+		reset(switchManager);
+		switchManager.handshakeDisconnected(dpid);
+		expectLastCall().once();
+		switchManager.switchDisconnected(sw);
+		expectLastCall().once();
+		replay(switchManager);
+
+		reset(sw);
+		expect(sw.getStatus()).andReturn(SwitchStatus.DISCONNECTED).anyTimes();
+		replay(sw);
+
+		switchHandler.connectionClosed(connection);
+
+		verify(switchManager);
+		verify(sw);
+	}
 }
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java
index 0a4ff826de222f4307ba98e4e83d2b305768206a..0de8b2b66bae472f183b8255429f7c40bf830bf9 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchManagerTest.java
@@ -258,6 +258,7 @@ public class OFSwitchManagerTest{
         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);