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 );
        swImplBase.setPortDescReplies((List<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);
    }
}
