diff --git a/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java b/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java
new file mode 100644
index 0000000..f267923
--- /dev/null
+++ b/of/ctl/src/test/java/org/onlab/onos/of/controller/impl/internal/OFChannelHandlerTest.java
@@ -0,0 +1,1569 @@
+package org.onlab.onos.of.controller.impl.internal;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.onlab.onos.of.controller.impl.IOFSwitch;
+import org.onlab.onos.of.controller.impl.Role;
+import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter;
+import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
+import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.RoleRecvStatus;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFHelloElem;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketInReason;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFSetConfig;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.U32;
+
+/**
+ * Channel handler deals with the switch connection and dispatches
+ * switch messages to the appropriate locations. These Unit Testing cases
+ * test the channeler state machine and role changer. In the first release,
+ * we will focus on OF version 1.0. we will add the testing case for
+ * version 1.3 later.
+ */
+public class OFChannelHandlerTest {
+    private Controller controller;
+    private IDebugCounterService debugCounterService;
+    private OFChannelHandler handler;
+    private Channel channel;
+    private ChannelHandlerContext ctx;
+    private MessageEvent messageEvent;
+    private ChannelStateEvent channelStateEvent;
+    private ChannelPipeline pipeline;
+    private Capture<ExceptionEvent> exceptionEventCapture;
+    private Capture<List<OFMessage>> writeCapture;
+    private OFFeaturesReply featuresReply;
+    private Set<Integer> seenXids = null;
+    private IOFSwitch swImplBase;
+    private OFVersion ofVersion = OFVersion.OF_10;
+    private OFFactory factory13;
+    private OFFactory factory10;
+    private OFFactory factory;
+
+    @Before
+    public void setUp() throws Exception {
+        controller = createMock(Controller.class);
+        ctx = createMock(ChannelHandlerContext.class);
+        channelStateEvent = createMock(ChannelStateEvent.class);
+        channel = createMock(Channel.class);
+        messageEvent = createMock(MessageEvent.class);
+        exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL);
+        pipeline = createMock(ChannelPipeline.class);
+        writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL);
+        swImplBase = createMock(IOFSwitch.class);
+        seenXids = null;
+        factory13 = OFFactories.getFactory(OFVersion.OF_13);
+        factory10 = OFFactories.getFactory(OFVersion.OF_10);
+        factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+
+        // TODO: should mock IDebugCounterService and make sure
+        // the expected counters are updated.
+        debugCounterService = new DebugCounter();
+        Controller.Counters counters =
+                new Controller.Counters();
+        counters.createCounters(debugCounterService);
+        expect(controller.getCounters()).andReturn(counters).anyTimes();
+        expect(controller.getOFMessageFactory10()).andReturn(factory10)
+            .anyTimes();
+        expect(controller.getOFMessageFactory13()).andReturn(factory13)
+            .anyTimes();
+        expect(controller.addConnectedSwitch(2000, handler)).andReturn(true)
+            .anyTimes();
+        replay(controller);
+        handler = new OFChannelHandler(controller);
+        verify(controller);
+        reset(controller);
+
+        resetChannel();
+
+        // replay controller. Reset it if you need more specific behavior
+        replay(controller);
+
+        // replay switch. Reset it if you need more specific behavior
+        replay(swImplBase);
+
+        // Mock ctx and channelStateEvent
+        expect(ctx.getChannel()).andReturn(channel).anyTimes();
+        expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes();
+        replay(ctx, channelStateEvent);
+
+        /* Setup an exception event capture on the channel. Right now
+         * we only expect exception events to be send up the channel.
+         * However, it's easy to extend to other events if we need it
+         */
+        pipeline.sendUpstream(capture(exceptionEventCapture));
+        expectLastCall().anyTimes();
+        replay(pipeline);
+        featuresReply = (OFFeaturesReply) buildOFMessage(OFType.FEATURES_REPLY);
+    }
+
+    @After
+    public void tearDown() {
+        /* ensure no exception was thrown */
+        if (exceptionEventCapture.hasCaptured()) {
+            Throwable ex = exceptionEventCapture.getValue().getCause();
+            throw new AssertionError("Unexpected exception: " +
+                    ex.getClass().getName() + "(" + ex + ")");
+        }
+        assertFalse("Unexpected messages have been captured",
+                writeCapture.hasCaptured());
+        // verify all mocks.
+        verify(channel);
+        verify(messageEvent);
+        verify(controller);
+        verify(ctx);
+        verify(channelStateEvent);
+        verify(pipeline);
+        verify(swImplBase);
+
+    }
+
+    /**
+     * Reset the channel mock and set basic method call expectations.
+     *
+     **/
+    void resetChannel() {
+        reset(channel);
+        expect(channel.getPipeline()).andReturn(pipeline).anyTimes();
+        expect(channel.getRemoteAddress()).andReturn(null).anyTimes();
+    }
+
+    /**
+     * reset, setup, and replay the messageEvent mock for the given
+     * messages.
+     */
+    void setupMessageEvent(List<OFMessage> messages) {
+        reset(messageEvent);
+        expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce();
+        replay(messageEvent);
+    }
+
+    /**
+     * reset, setup, and replay the messageEvent mock for the given
+     * messages, mock controller  send message to channel handler.
+     *
+     * This method will reset, start replay on controller, and then verify
+     */
+    void sendMessageToHandlerWithControllerReset(List<OFMessage> messages)
+            throws Exception {
+        verify(controller);
+        reset(controller);
+
+        sendMessageToHandlerNoControllerReset(messages);
+    }
+
+    /**
+     * reset, setup, and replay the messageEvent mock for the given
+     * messages, mock controller  send message to channel handler.
+     *
+     * This method will start replay on controller, and then verify
+     */
+    void sendMessageToHandlerNoControllerReset(List<OFMessage> messages)
+            throws Exception {
+        setupMessageEvent(messages);
+
+        expect(controller.addConnectedSwitch(1000, handler))
+        .andReturn(true).anyTimes();
+        replay(controller);
+
+        handler.messageReceived(ctx, messageEvent);
+        verify(controller);
+    }
+
+    /**
+     * Extract the list of OFMessages that was captured by the Channel.write()
+     * capture. Will check that something was actually captured first. We'll
+     * collapse the messages from multiple writes into a single list of
+     * OFMessages.
+     * Resets the channelWriteCapture.
+     */
+    List<OFMessage> getMessagesFromCapture() {
+        List<OFMessage> msgs = new ArrayList<OFMessage>();
+
+        assertTrue("No write on channel was captured",
+                writeCapture.hasCaptured());
+        List<List<OFMessage>> capturedVals = writeCapture.getValues();
+
+        for (List<OFMessage> oneWriteList: capturedVals) {
+            msgs.addAll(oneWriteList);
+        }
+        writeCapture.reset();
+        return msgs;
+    }
+
+
+    /**
+     * Verify that the given exception event capture (as returned by
+     * getAndInitExceptionCapture) has thrown an exception of the given
+     * expectedExceptionClass.
+     * Resets the capture
+     */
+    void verifyExceptionCaptured(
+            Class<? extends Throwable> expectedExceptionClass) {
+        assertTrue("Excpected exception not thrown",
+                exceptionEventCapture.hasCaptured());
+        Throwable caughtEx = exceptionEventCapture.getValue().getCause();
+        assertEquals(expectedExceptionClass, caughtEx.getClass());
+        exceptionEventCapture.reset();
+    }
+
+    /**
+     * 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<Integer>();
+        }
+        for (OFMessage m: msgs)  {
+            int xid = (int) m.getXid();
+            assertTrue("Xid in messags is 0", xid != 0);
+            assertFalse("Xid " + xid + " has already been used",
+                    seenXids.contains(xid));
+            seenXids.add(xid);
+        }
+    }
+
+
+
+    public void testInitState() throws Exception {
+        OFMessage m = buildOFMessage(OFType.HELLO);
+
+        expect(messageEvent.getMessage()).andReturn(null);
+        replay(channel, messageEvent);
+
+        // We don't expect to receive /any/ messages in init state since
+        // channelConnected moves us to a different state
+        sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
+
+        verifyExceptionCaptured(SwitchStateException.class);
+        assertEquals(OFChannelHandler.ChannelState.INIT,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * move the channel from scratch to WAIT_HELLO state.
+     *
+     */
+    @Test
+    public void moveToWaitHello() throws Exception {
+        resetChannel();
+        channel.write(capture(writeCapture));
+        expectLastCall().andReturn(null).once();
+        replay(channel);
+        // replay unused mocks
+        replay(messageEvent);
+
+        handler.channelConnected(ctx, channelStateEvent);
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        assertEquals(OFType.HELLO, msgs.get(0).getType());
+        assertEquals(OFChannelHandler.ChannelState.WAIT_HELLO,
+                handler.getStateForTesting());
+        //Should verify that the Hello received from the controller
+        //is ALWAYS OF1.3 hello regardless of the switch version
+        assertEquals(OFVersion.OF_13, msgs.get(0).getVersion());
+        verifyUniqueXids(msgs);
+    }
+
+
+    /**
+     * Move the channel from scratch to WAIT_FEATURES_REPLY state.
+     * Builds on moveToWaitHello().
+     * adds testing for WAIT_HELLO state.
+     */
+    @Test
+    public void moveToWaitFeaturesReply() throws Exception {
+        moveToWaitHello();
+        resetChannel();
+        channel.write(capture(writeCapture));
+        expectLastCall().andReturn(null).atLeastOnce();
+        replay(channel);
+
+        OFMessage hello = buildOFMessage(OFType.HELLO);
+        sendMessageToHandlerWithControllerReset(Collections.singletonList(hello));
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        assertEquals(OFType.FEATURES_REQUEST, msgs.get(0).getType());
+        if (ofVersion == OFVersion.OF_10) {
+            assertEquals(OFVersion.OF_10, msgs.get(0).getVersion());
+        }
+        verifyUniqueXids(msgs);
+
+        assertEquals(OFChannelHandler.ChannelState.WAIT_FEATURES_REPLY,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to WAIT_CONFIG_REPLY state.
+     * Builds on moveToWaitFeaturesReply.
+     * adds testing for WAIT_FEATURES_REPLY state.
+     */
+    @Test
+    public void moveToWaitConfigReply() throws Exception {
+        moveToWaitFeaturesReply();
+
+        resetChannel();
+        channel.write(capture(writeCapture));
+        expectLastCall().andReturn(null).atLeastOnce();
+        replay(channel);
+
+        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(featuresReply));
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(3, msgs.size());
+        assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
+        OFSetConfig sc = (OFSetConfig) msgs.get(0);
+        assertEquals((short) 0xffff, sc.getMissSendLen());
+        assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
+        assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
+        verifyUniqueXids(msgs);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_CONFIG_REPLY,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * 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();
+        resetChannel();
+        channel.write(capture(writeCapture));
+        expectLastCall().andReturn(null).atLeastOnce();
+        replay(channel);
+
+        OFGetConfigReply cr = (OFGetConfigReply) buildOFMessage(OFType.GET_CONFIG_REPLY);
+
+        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(cr));
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        assertEquals(OFType.STATS_REQUEST, msgs.get(0).getType());
+        OFStatsRequest<?> sr = (OFStatsRequest<?>) msgs.get(0);
+        assertEquals(OFStatsType.DESC, sr.getStatsType());
+        verifyUniqueXids(msgs);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_DESCRIPTION_STAT_REPLY,
+                handler.getStateForTesting());
+    }
+
+
+    private OFStatsReply createDescriptionStatsReply() throws IOException {
+        OFStatsReply sr = (OFStatsReply) buildOFMessage(OFType.STATS_REPLY);
+        return sr;
+    }
+
+    /**
+     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
+     * for a switch that does not have a sub-handshake.
+     * Builds on moveToWaitDescriptionStatReply().
+     * adds testing for WAIT_DESCRIPTION_STAT_REPLY state.
+     *
+     */
+    @Test
+    public void moveToWaitInitialRole()
+            throws Exception {
+        moveToWaitDescriptionStatReply();
+
+        long xid = 2000;
+
+        // build the stats reply
+        OFStatsReply sr = createDescriptionStatsReply();
+
+        resetChannel();
+        replay(channel);
+
+        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+        controller.submitRegistryRequest(1000);
+        expectLastCall().once();
+        replay(controller);
+
+        //TODO: With the description stats message you are sending in the test,
+        //you will end up with an OFSwitchImplBase object
+        //which by default does NOT support the nicira role messages.
+        //If you wish to test the case where Nicira role messages are supported,
+        //then make a comment here that states that this is different
+        //from the default behavior of switchImplbase /or/
+        //send the right desc-stats (for example send what is expected from OVS 1.0)
+
+        if (ofVersion == OFVersion.OF_10) {
+            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+            .andReturn(true).once();
+
+            swImplBase.write(capture(writeCapture));
+            expectLastCall().anyTimes();
+        }
+
+        swImplBase.setOFVersion(ofVersion);
+        expectLastCall().once();
+        swImplBase.setConnected(true);
+        expectLastCall().once();
+        swImplBase.setChannel(channel);
+        expectLastCall().once();
+        swImplBase.setDebugCounterService(controller.getDebugCounter());
+        expectLastCall().once();
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        swImplBase.setRole(Role.EQUAL);
+        expectLastCall().once();
+
+        expect(swImplBase.getNextTransactionId())
+        .andReturn((int) xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+
+        swImplBase.setFeaturesReply(featuresReply);
+        expectLastCall().once();
+        swImplBase.setPortDescReply((OFPortDescStatsReply) null);
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        assertEquals(OFType.EXPERIMENTER, msgs.get(0).getType());
+        verifyNiciraMessage((OFExperimenter) msgs.get(0));
+
+        verify(controller);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to.
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+     * Builds on moveToWaitInitialRole().
+     */
+    @Test
+    public void moveToWaitSubHandshake()
+            throws Exception {
+        moveToWaitInitialRole();
+
+        int xid = 2000;
+        resetChannel();
+        replay(channel);
+
+        reset(swImplBase);
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+        // build the stats reply
+        OFStatsReply sr = createDescriptionStatsReply();
+        OFMessage rr = getRoleReply(xid, Role.SLAVE);
+        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        swImplBase.setRole(Role.SLAVE);
+        expectLastCall().once();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+        swImplBase.startDriverHandshake();
+        expectLastCall().once();
+
+        //when this flag is false, state machine will move to
+        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(false).once();
+
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
+     * then move the channel to EQUAL state based on the switch Role.
+     * This test basically test the switch with role support.
+     * Builds on moveToWaitInitialRole().
+     *
+     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
+     * and PORT_STATUS), state machine will transit to MASTER or
+     * EQUAL state based on the switch role.
+     */
+    @Test
+    public void moveToSlaveWithHandshakeComplete()
+            throws Exception {
+
+        moveToWaitInitialRole();
+
+        int xid = 2000;
+        resetChannel();
+        replay(channel);
+
+        reset(swImplBase);
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+        // build the stats reply
+        OFStatsReply sr = createDescriptionStatsReply();
+        OFMessage rr = getRoleReply(xid, Role.SLAVE);
+        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        //consult the role in sw to determine the next state.
+        //in this testing case, we are testing that channel handler
+        // will move to EQUAL state when switch role is in SLAVE.
+        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
+        swImplBase.setRole(Role.SLAVE);
+        expectLastCall().once();
+
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+        swImplBase.startDriverHandshake();
+        expectLastCall().once();
+
+        //when this flag is true, don't need to move interim state
+        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE. channel handler will
+        //move to corresponding state after consulting the role in sw
+        //This is essentially the same test as the one above,
+        //except for this line
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(true).once();
+
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.EQUAL,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
+     * then to MASTERL state based on the switch Role.
+     * This test basically test the switch with role support.
+     * Builds on moveToWaitInitialRole().
+     *
+     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
+     * and PORT_STATUS), state machine will transit to MASTER or
+     * EQUAL state based on the switch role.
+     */
+    @Test
+    public void moveToMasterWithHandshakeComplete()
+            throws Exception {
+
+        moveToWaitInitialRole();
+
+        int xid = 2000;
+        resetChannel();
+        replay(channel);
+
+        reset(swImplBase);
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+        // build the stats reply
+        OFStatsReply sr = createDescriptionStatsReply();
+        OFMessage rr = getRoleReply(xid, Role.MASTER);
+        setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+        swImplBase.setRole(Role.MASTER);
+        expectLastCall().once();
+
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+        swImplBase.startDriverHandshake();
+        expectLastCall().once();
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(true).once();
+
+        replay(swImplBase);
+
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+     * Builds on moveToWaitSubHandshake().
+     */
+    @Test
+    public void moveToEqualViaWaitSubHandshake()
+            throws Exception {
+        moveToWaitSubHandshake();
+
+        long xid = 2000;
+        resetChannel();
+        replay(channel);
+
+        // build the stats reply
+        OFStatsReply sr = createDescriptionStatsReply();
+
+        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn((int) xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+
+        swImplBase.processDriverHandshakeMessage(sr);
+        expectLastCall().once();
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(true).once();
+
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.EQUAL,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+     * Builds on moveToWaitSubHandshake().
+     */
+    @Test
+    public void moveToMasterViaWaitSubHandshake()
+            throws Exception {
+        moveToWaitSubHandshake();
+
+        long xid = 2000;
+        resetChannel();
+        replay(channel);
+
+        // In this state, any messages except echo request, port status and
+        // error go to the switch sub driver handshake. Once the switch reports
+        // that its sub driver handshake is complete (#isDriverHandshakeComplete
+        // return true) then the channel handle consults the switch role and
+        // moves the state machine to the appropriate state (MASTER or EQUALS).
+        // In this test we expect the state machine to end up in MASTER state.
+        OFStatsReply sr = createDescriptionStatsReply();
+
+        setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn((int) xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+
+        swImplBase.processDriverHandshakeMessage(sr);
+        expectLastCall().once();
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(true).once();
+
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+        verify(controller);
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+     * ECHO_REQUEST message received case.
+     */
+    @Test
+    public void testWaitSwitchDriverSubhandshake() throws Exception {
+        moveToWaitSubHandshake();
+
+        long xid = 2000;
+        resetChannel();
+        channel.write(capture(writeCapture));
+        expectLastCall().andReturn(null).atLeastOnce();
+        replay(channel);
+
+        OFMessage er = buildOFMessage(OFType.ECHO_REQUEST);
+
+        setupMessageEvent(Collections.<OFMessage>singletonList(er));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFMessageFactory10()).andReturn(factory10);
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn((int) xid).anyTimes();
+
+        replay(swImplBase);
+
+        handler.messageReceived(ctx, messageEvent);
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        assertEquals(OFType.ECHO_REPLY, msgs.get(0).getType());
+        verifyUniqueXids(msgs);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Helper.
+     * Verify that the given OFMessage is a correct Nicira RoleRequest message.
+     */
+    private void verifyNiciraMessage(OFExperimenter ofMessage) {
+
+        int vendor = (int) ofMessage.getExperimenter();
+        assertEquals(vendor, 0x2320); // magic number representing nicira
+    }
+
+    /**
+     * 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 xid The xid to use in the role request
+     * @param role The role to send
+     * @throws IOException
+     */
+    private void setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
+            int xid,
+            Role role) throws IOException {
+
+        RoleRecvStatus expectation = RoleRecvStatus.MATCHED_SET_ROLE;
+
+        expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+        .andReturn(supportsNxRole).atLeastOnce();
+
+        if (supportsNxRole != null && supportsNxRole) {
+            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
+            swImplBase.write(capture(writeCapture));
+            expectLastCall().anyTimes();
+        }
+        replay(swImplBase);
+
+        handler.sendRoleRequest(role, expectation);
+
+        if (supportsNxRole != null && supportsNxRole) {
+            List<OFMessage> msgs = getMessagesFromCapture();
+            assertEquals(1, msgs.size());
+            verifyNiciraMessage((OFExperimenter) msgs.get(0));
+        }
+    }
+
+    /**
+     * 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
+     */
+    private void setupSwitchRoleChangeUnsupported(int xid,
+            Role role) {
+        boolean supportsNxRole = false;
+        RoleRecvStatus expectation = RoleRecvStatus.NO_REPLY;
+        reset(swImplBase);
+        expect(swImplBase.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
+        swImplBase.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
+        expectLastCall().anyTimes();
+
+        replay(swImplBase);
+
+        handler.sendRoleRequest(role, expectation);
+
+        verify(swImplBase);
+    }
+
+    /*
+     * Return a Nicira RoleReply message for the given role.
+     */
+    private OFMessage getRoleReply(long xid, Role role) {
+
+        OFNiciraControllerRole nr = null;
+
+        switch(role) {
+        case MASTER:
+            nr = OFNiciraControllerRole.ROLE_MASTER;
+            break;
+        case EQUAL:
+            nr = OFNiciraControllerRole.ROLE_SLAVE;
+            break;
+        case SLAVE:
+            nr = OFNiciraControllerRole.ROLE_SLAVE;
+            break;
+        default: //handled below
+        }
+        OFMessage m = factory10.buildNiciraControllerRoleReply()
+                .setRole(nr)
+                .setXid(xid)
+                .build();
+        return m;
+    }
+
+    /**
+     * Move the channel from scratch to MASTER state.
+     * Builds on moveToWaitInitialRole().
+     * adds testing for WAIT_INITAL_ROLE state.
+     *
+     * This method tests the case that the switch does NOT support roles.
+     * In ONOS if the switch-driver says that nicira-role messages are not
+     * supported, then ONOS does NOT send role-request messages
+     * (see handleUnsentRoleMessage())
+     */
+    @Test
+    public void testInitialMoveToMasterNoRole() throws Exception {
+        int xid = 43;
+        // first, move us to WAIT_INITIAL_ROLE_STATE
+
+        moveToWaitInitialRole();
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+        OFStatsReply sr = createDescriptionStatsReply();
+
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        replay(controller);
+
+        reset(swImplBase);
+        swImplBase.setRole(Role.MASTER);
+        expectLastCall().once();
+        swImplBase.startDriverHandshake();
+        expectLastCall().once();
+        expect(swImplBase.isDriverHandshakeComplete())
+        .andReturn(true).once();
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(false, xid, Role.MASTER);
+
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
+     * Builds on moveToWaitInitialRole().
+     * 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.
+     */
+    /* TBD
+        @Test
+        public void testInitialMoveToMasterTimeout() throws Exception {
+            int timeout = 50;
+            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+            int xid = 4343;
+
+            // first, move us to WAIT_INITIAL_ROLE_STATE
+
+            moveToWaitInitialRole();
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            // prepare mocks and inject the role reply message
+            reset(swImplBase);
+            // Set the role
+            swImplBase.setRole(Role.MASTER);
+            expectLastCall().once();
+            swImplBase.startDriverHandshake();
+            expectLastCall().once();
+            expect(swImplBase.isDriverHandshakeComplete())
+            .andReturn(false).once();
+            if (ofVersion == OFVersion.OF_10) {
+                expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+                 .andReturn(true).once();
+
+                swImplBase.write(capture(writeCapture),
+                        EasyMock.<FloodlightContext>anyObject());
+                expectLastCall().anyTimes();
+             }
+            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
+
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            // Set the role
+            setupSwitchSendRoleRequestAndVerify(null, xid, Role.MASTER);
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
+
+            setupMessageEvent(Collections.<OFMessage>singletonList(m));
+
+            Thread.sleep(timeout+5);
+
+            verify(controller);
+            reset(controller);
+
+            expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+            .andReturn(true).once();
+            controller.flushAll();
+            expectLastCall().once();
+
+            replay(controller);
+
+            handler.messageReceived(ctx, messageEvent);
+
+            assertEquals(OFChannelHandler.ChannelState.MASTER,
+                    handler.getStateForTesting());
+
+        }
+
+     */
+    /**
+     * 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 {
+        int xid = 44;
+        // first, move us to WAIT_INITIAL_ROLE_STATE
+        moveToWaitInitialRole();
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+        reset(swImplBase);
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(false, xid, Role.SLAVE);
+        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                handler.getStateForTesting());
+
+    }
+
+    /**
+     * 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
+     */
+    /* TBD
+        @Test
+        public void testInitialMoveToSlaveTimeout() throws Exception {
+            int timeout = 50;
+            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+            int xid = 4444;
+
+            // first, move us to WAIT_INITIAL_ROLE_STATE
+            moveToWaitInitialRole();
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            // Set the role
+            setupSwitchSendRoleRequestAndVerify(null, xid, Role.SLAVE);
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            // prepare mocks and inject the role reply message
+            reset(sw);
+            sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+            expectLastCall().once();
+            sw.setRole(Role.SLAVE);
+            expectLastCall().once();
+            sw.disconnectSwitch(); // Make sure we disconnect
+            expectLastCall().once();
+            replay(sw);
+
+            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
+
+            Thread.sleep(timeout+5);
+
+            sendMessageToHandlerWithControllerReset(Collections.singletonList(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;
+        reset(swImplBase);
+        replay(swImplBase);
+
+        reset(controller);
+        replay(controller);
+
+        // First, lets move the state to MASTER without role support
+        testInitialMoveToMasterNoRole();
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+
+        // try to set master role again. should be a no-op
+        setupSwitchRoleChangeUnsupported(xid, Role.MASTER);
+
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+
+        setupSwitchRoleChangeUnsupported(xid, Role.SLAVE);
+        //switch does not support role message. there is no role set
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+
+    }
+
+    /**
+     * Move the channel to MASTER state.
+     * Expects that the channel is in MASTER or SLAVE state.
+     *
+     */
+    public void changeRoleToMasterWithRequest() throws Exception {
+        int xid = 4242;
+
+        assertTrue("This method can only be called when handler is in " +
+                "MASTER or SLAVE role", handler.isHandshakeComplete());
+
+        reset(swImplBase);
+        reset(controller);
+        // Set the role
+        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+
+        // prepare mocks and inject the role reply message
+
+        reset(controller);
+        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+        .andReturn(true).once();
+        OFMessage reply = getRoleReply(xid, Role.MASTER);
+
+        // sendMessageToHandler will verify and rest controller mock
+
+        OFStatsReply sr = createDescriptionStatsReply();
+        setupMessageEvent(Collections.<OFMessage>singletonList(reply));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+        controller.transitionToMasterSwitch(1000);
+        expectLastCall().once();
+
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.EQUAL).atLeastOnce();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+
+        swImplBase.setRole(Role.MASTER);
+        expectLastCall().once();
+        replay(swImplBase);
+
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+    }
+
+    /**
+     * Move the channel to SLAVE state.
+     * Expects that the channel is in MASTER or SLAVE state.
+     *
+     */
+    public void changeRoleToSlaveWithRequest() throws Exception {
+        int xid = 2323;
+
+        assertTrue("This method can only be called when handler is in " +
+                "MASTER or SLAVE role", handler.isHandshakeComplete());
+
+        // Set the role
+        reset(controller);
+        reset(swImplBase);
+
+        swImplBase.write(capture(writeCapture));
+        expectLastCall().anyTimes();
+
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+
+
+        if (ofVersion == OFVersion.OF_10) {
+            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+            .andReturn(true).once();
+
+            swImplBase.write(capture(writeCapture));
+            expectLastCall().anyTimes();
+        }
+        replay(swImplBase);
+
+        handler.sendRoleRequest(Role.SLAVE, RoleRecvStatus.MATCHED_SET_ROLE);
+
+        List<OFMessage> msgs = getMessagesFromCapture();
+        assertEquals(1, msgs.size());
+        verifyNiciraMessage((OFExperimenter) msgs.get(0));
+
+
+        OFMessage reply = getRoleReply(xid, Role.SLAVE);
+        OFStatsReply sr = createDescriptionStatsReply();
+        setupMessageEvent(Collections.<OFMessage>singletonList(reply));
+
+        // mock controller
+        reset(controller);
+        reset(swImplBase);
+
+        controller.transitionToEqualSwitch(1000);
+        expectLastCall().once();
+        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+        .andReturn(swImplBase).anyTimes();
+
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        replay(controller);
+
+        expect(swImplBase.getStringId())
+        .andReturn(null).anyTimes();
+        expect(swImplBase.getRole()).andReturn(Role.MASTER).atLeastOnce();
+        expect(swImplBase.getNextTransactionId())
+        .andReturn(xid).anyTimes();
+
+        // prepare mocks and inject the role reply message
+        swImplBase.setRole(Role.SLAVE);
+        expectLastCall().once();
+        expect(swImplBase.getId())
+        .andReturn(1000L).once();
+        replay(swImplBase);
+
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.EQUAL,
+                handler.getStateForTesting());
+    }
+
+    @Test
+    public void testMultiRoleChange1() throws Exception {
+        moveToMasterWithHandshakeComplete();
+        changeRoleToMasterWithRequest();
+        changeRoleToSlaveWithRequest();
+        changeRoleToSlaveWithRequest();
+        changeRoleToMasterWithRequest();
+        changeRoleToSlaveWithRequest();
+    }
+
+    @Test
+    public void testMultiRoleChange2() throws Exception {
+        moveToSlaveWithHandshakeComplete();
+        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
+     */
+    /* TBD
+        @Test
+        public void testInitialRoleChangeOtherError() throws Exception {
+            int xid = 4343;
+            // first, move us to WAIT_INITIAL_ROLE_STATE
+            moveToWaitInitialRole();
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+            reset(swImplBase);
+            // Set the role
+            setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+                    handler.getStateForTesting());
+
+
+            // FIXME: shouldn't use ordinal(), but OFError is broken
+
+            OFMessage err = factory.errorMsgs().buildBadActionErrorMsg()
+                    .setCode(OFBadActionCode.BAD_LEN)
+                    .setXid(2000)
+                    .build();
+            verify(swImplBase);
+            reset(swImplBase);
+            replay(swImplBase);
+            sendMessageToHandlerWithControllerReset(Collections.singletonList(err));
+
+            verifyExceptionCaptured(SwitchStateException.class);
+        }
+     */
+    /**
+     * Test dispatch of messages while in MASTER role.
+     */
+    @Test
+    public void testMessageDispatchMaster() throws Exception {
+
+        moveToMasterWithHandshakeComplete();
+
+        // Send packet in. expect dispatch
+        OFPacketIn pi = (OFPacketIn)
+                buildOFMessage(OFType.PACKET_IN);
+        setupMessageEvent(Collections.<OFMessage>singletonList(pi));
+
+        reset(swImplBase);
+        swImplBase.handleMessage(pi);
+        expectLastCall().once();
+        replay(swImplBase);
+        // send the description stats reply
+        handler.messageReceived(ctx, messageEvent);
+
+        assertEquals(OFChannelHandler.ChannelState.MASTER,
+                handler.getStateForTesting());
+
+        verify(controller);
+        // TODO: many more to go
+    }
+
+    /**
+     * Test port status message handling while MASTER.
+     *
+     */
+    /* Patrick: TBD
+        @Test
+        public void testPortStatusMessageMaster() throws Exception {
+            long dpid = featuresReply.getDatapathId().getLong();
+            testInitialMoveToMasterWithRole();
+            List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
+            // A dummy port.
+            OFPortDesc p = factory.buildPortDesc()
+                        .setName("Eth1")
+                        .setPortNo(OFPort.ofInt(1))
+                        .build();
+            ports.add(p);
+
+            p.setName("Port1");
+            p.setPortNumber((short)1);
+
+            OFPortStatus ps = (OFPortStatus)buildOFMessage(OFType.PORT_STATUS);
+            ps.setDesc(p);
+
+            // 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>();
+            ImmutablePort p1 = ImmutablePort.create("eth1", (short)1);
+            ImmutablePort p2 = ImmutablePort.create("eth2", (short)2);
+            ImmutablePort p3 = ImmutablePort.create("eth3", (short)3);
+            ImmutablePort p4 = ImmutablePort.create("eth4", (short)4);
+            ImmutablePort p5 = ImmutablePort.create("eth5", (short)5);
+            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()) {
+                ps.setReason(reason.getReasonCode());
+
+                reset(sw);
+                expect(sw.getId()).andReturn(dpid).anyTimes();
+
+                expect(sw.processOFPortStatus(ps)).andReturn(events).once();
+                replay(sw);
+
+                reset(controller);
+                controller.notifyPortChanged(sw, p1, PortChangeType.ADD);
+                controller.notifyPortChanged(sw, p2, PortChangeType.DELETE);
+                controller.notifyPortChanged(sw, p3, PortChangeType.UP);
+                controller.notifyPortChanged(sw, p4, PortChangeType.DOWN);
+                controller.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
+                sendMessageToHandlerNoControllerReset(
+                        Collections.<OFMessage>singletonList(ps));
+                verify(sw);
+                verify(controller);
+            }
+        }
+
+     */
+    /**
+     * Build an OF message.
+     * @throws IOException
+     */
+    private OFMessage buildOFMessage(OFType t) throws IOException {
+        OFMessage m = null;
+        switch (t) {
+
+        case HELLO:
+            // The OF protocol requires us to start things off by sending the highest
+            // version of the protocol supported.
+
+            // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
+            // see Sec. 7.5.1 of the OF1.3.4 spec
+            if (ofVersion == OFVersion.OF_13) {
+                U32 bitmap = U32.ofRaw(0x00000012);
+                OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
+                    .setBitmaps(Collections.singletonList(bitmap))
+                    .build();
+                m = factory13.buildHello()
+                        .setXid(2000)
+                        .setElements(Collections.singletonList(hem))
+                        .build();
+            } else {
+                m = factory10.buildHello()
+                    .setXid(2000)
+                    .build();
+            }
+            break;
+        case FEATURES_REQUEST:
+            m = factory.buildFeaturesRequest()
+            .setXid(2000)
+            .build();
+            break;
+        case FEATURES_REPLY:
+
+            m = factory.buildFeaturesReply()
+            .setDatapathId(DatapathId.of(1000L))
+            .setXid(2000)
+            .build();
+            break;
+        case SET_CONFIG:
+            m = factory.buildSetConfig()
+            .setMissSendLen((short) 0xffff)
+            .setXid(2000)
+            .build();
+            break;
+        case BARRIER_REQUEST:
+            m = factory.buildBarrierRequest()
+            .setXid(2000)
+            .build();
+            break;
+        case GET_CONFIG_REQUEST:
+            m = factory.buildGetConfigRequest()
+            .setXid(2000)
+            .build();
+            break;
+        case GET_CONFIG_REPLY:
+            m = factory.buildGetConfigReply()
+            .setMissSendLen((short) 0xffff)
+            .setXid(2000)
+            .build();
+            break;
+        case STATS_REQUEST:
+            break;
+        case STATS_REPLY:
+            m = factory.buildDescStatsReply()
+            .setDpDesc("Datapath Description")
+            .setHwDesc("Hardware Secription")
+            .setMfrDesc("Manufacturer Desctiption")
+            .setSerialNum("Serial Number")
+            .setSwDesc("Software Desription")
+            .build();
+            break;
+        case ECHO_REQUEST:
+            m = factory.buildEchoRequest()
+            .setXid(2000)
+            .build();
+            break;
+        case FLOW_REMOVED:
+            break;
+
+        case PACKET_IN:
+            m = factory.buildPacketIn()
+            .setReason(OFPacketInReason.NO_MATCH)
+            .setTotalLen(1500)
+            .setXid(2000)
+            .build();
+            break;
+        case PORT_STATUS:
+            m = factory.buildPortStatus()
+            .setXid(2000)
+            .build();
+            break;
+
+        default:
+            m = factory.buildFeaturesRequest()
+            .setXid(2000)
+            .build();
+            break;
+        }
+
+        return (m);
+    }
+}
