diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
new file mode 100644
index 0000000..0e50d0c
--- /dev/null
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
@@ -0,0 +1,1609 @@
+package net.floodlightcontroller.core.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 net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.internal.OFChannelHandler.RoleRecvStatus;
+import net.floodlightcontroller.debugcounter.DebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.easymock.EasyMock;
+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.
+ *
+ * @author Patrick liu (patrick.liu@huawei.com)
+ */
+public class OFChannelHandlerTest {
+    private Controller controller;
+    private IThreadPoolService threadPool;
+    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 OFSwitchImplBase 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);
+        threadPool = createMock(IThreadPoolService.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(OFSwitchImplBase.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.getOFMessageFactory_10()).andReturn(factory10).anyTimes();
+        expect(controller.getOFMessageFactory_13()).andReturn(factory13).anyTimes();
+        expect(controller.addConnectedSwitch(2000,handler)).andReturn(true).anyTimes();
+        replay(controller);
+        handler = new OFChannelHandler(controller);
+        verify(controller);
+        reset(controller);
+
+        resetChannel();
+
+        // thread pool is usually not called, so start empty replay
+        replay(threadPool);
+
+        // 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(threadPool);
+        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);
+
+        // mock controller
+        controller.flushAll();
+        expectLastCall().anyTimes();
+        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);
+        }
+    }
+
+
+    @Test
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+        controller.submitRegistryRequest(1000);
+        expectLastCall().once();
+        controller.flushAll();
+        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),
+                    EasyMock.<FloodlightContext>anyObject());
+            expectLastCall().anyTimes();
+        }
+
+        swImplBase.setOFVersion(ofVersion);
+        expectLastCall().once();
+        swImplBase.setConnected(true);
+        expectLastCall().once();
+        swImplBase.setChannel(channel);
+        expectLastCall().once();
+        swImplBase.setFloodlightProvider(controller);
+        expectLastCall().once();
+        swImplBase.setThreadPoolService(controller.getThreadPoolService());
+        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());
+    }
+
+    @Test
+    /**
+     * Move the channel from scratch to
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+     * Builds on moveToWaitInitialRole()
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+
+        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());
+    }
+
+    @Test
+    /**
+     * 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.
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+        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());
+    }
+
+
+    @Test
+    /**
+     * 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.
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+        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());
+    }
+    @Test
+    /** Move the channel from scratch to
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+     * Builds on moveToWaitSubHandshake()
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+        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());
+    }
+
+    @Test
+    /** Move the channel from scratch to
+     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+     * Builds on moveToWaitSubHandshake()
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+        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
+    /**
+     * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+     * ECHO_REQUEST message received case
+     */
+    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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+
+        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),
+                    EasyMock.<FloodlightContext>anyObject());
+            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.getThreadPoolService())
+        .andReturn(threadPool).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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+        controller.transitionToMasterSwitch(1000);
+        expectLastCall().once();
+
+        controller.flushAll();
+        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),
+                EasyMock.<FloodlightContext>anyObject());
+        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),
+                    EasyMock.<FloodlightContext>anyObject());
+            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.getThreadPoolService())
+        .andReturn(threadPool).anyTimes();
+        expect(controller.getDebugCounter())
+        .andReturn(debugCounterService).anyTimes();
+
+        controller.flushAll();
+        expectLastCall().once();
+        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(controller);
+        controller.handleMessage(swImplBase, pi, null);
+        expectLastCall().once();
+        controller.flushAll();
+        expectLastCall().once();
+
+        replay(controller);
+
+
+        // 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);
+    }
+}
