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.
 */
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());
    }

    /**
     * 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());

        OFMessage rr = getRoleReply(xid, Role.SLAVE);
        setupMessageEvent(Collections.<OFMessage>singletonList(rr));

        // 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();
        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());
    }

    /**
     * In WAIT_INITIAL_ROLE state the controller is waiting to hear back from
     * the registry service. If it gets mastership it sends a role-request to
     * the switch and if it gets the reply it moves to state MASTER.
     * <p>
     * However if it does not hear from the registry service, the handshake
     * process should timeout, and the controller should move to state EQUAL.
     * This test checks this behavior.
     *
     * @throws Exception
     */
    @Test
    public void moveToRoleEqualFromHandshakeTimeout() throws Exception {
        moveToWaitInitialRole();
        int xid = 2000;
        resetChannel();
        reset(controller);
        reset(swImplBase);
        // simulate that we never heard from registry service and so the
        // handshake times out -- this results in a HandshakeTimeoutException
        // called on the channel.
        ExceptionEvent eeMock = createMock(ExceptionEvent.class);
        expect(eeMock.getCause()).andReturn(new HandshakeTimeoutException())
                .atLeastOnce();
        // controller should move to role EQUAL via the driver handshake
        swImplBase.setRole(Role.EQUAL);
        expectLastCall().once();
        swImplBase.startDriverHandshake();
        expectLastCall().once();
        // assume nothing-to-do in driver handshake by returning true
        // immediately
        expect(swImplBase.isDriverHandshakeComplete())
                .andReturn(true).once();
        expect(swImplBase.getRole()).andReturn(Role.EQUAL).once();
        expect(swImplBase.getId())
                .andReturn(1L).anyTimes();
        expect(controller.addActivatedEqualSwitch(1L, swImplBase))
                .andReturn(true).once();

        replay(channel);
        replay(controller);
        replay(swImplBase);
        replay(eeMock);
        handler.exceptionCaught(ctx, eeMock);
        assertEquals(OFChannelHandler.ChannelState.EQUAL,
                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.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());
    }

    /**
     * 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.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());
    }

    /**
     * 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.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());
    }

    /**
     * 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.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 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.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.EQUAL);
        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);
    }
}
