package org.onlab.onos.of.controller.impl.internal;

import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.onlab.onos.of.controller.impl.IOFSwitch;
import org.onlab.onos.of.controller.impl.Role;
import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter;
import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.RoleRecvStatus;

import org.easymock.Capture;
import org.easymock.CaptureType;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFExperimenter;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
import org.projectfloodlight.openflow.protocol.OFHelloElem;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPacketInReason;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFSetConfig;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsRequest;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.U32;

/**
 * Channel handler deals with the switch connection and dispatches
 * switch messages to the appropriate locations. These Unit Testing cases
 * test the channeler state machine and role changer. In the first release,
 * we will focus on OF version 1.0. we will add the testing case for
 * version 1.3 later.
 */
public class OFChannelHandlerTest {
    private Controller controller;
    private IDebugCounterService debugCounterService;
    private OFChannelHandler handler;
    private Channel channel;
    private ChannelHandlerContext ctx;
    private MessageEvent messageEvent;
    private ChannelStateEvent channelStateEvent;
    private ChannelPipeline pipeline;
    private Capture<ExceptionEvent> exceptionEventCapture;
    private Capture<List<OFMessage>> writeCapture;
    private OFFeaturesReply featuresReply;
    private Set<Integer> seenXids = null;
    private IOFSwitch swImplBase;
    private OFVersion ofVersion = OFVersion.OF_10;
    private OFFactory factory13;
    private OFFactory factory10;
    private OFFactory factory;

    @Before
    public void setUp() throws Exception {
        controller = createMock(Controller.class);
        ctx = createMock(ChannelHandlerContext.class);
        channelStateEvent = createMock(ChannelStateEvent.class);
        channel = createMock(Channel.class);
        messageEvent = createMock(MessageEvent.class);
        exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL);
        pipeline = createMock(ChannelPipeline.class);
        writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL);
        swImplBase = createMock(IOFSwitch.class);
        seenXids = null;
        factory13 = OFFactories.getFactory(OFVersion.OF_13);
        factory10 = OFFactories.getFactory(OFVersion.OF_10);
        factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;

        // TODO: should mock IDebugCounterService and make sure
        // the expected counters are updated.
        debugCounterService = new DebugCounter();
        Controller.Counters counters =
                new Controller.Counters();
        counters.createCounters(debugCounterService);
        expect(controller.getCounters()).andReturn(counters).anyTimes();
        expect(controller.getOFMessageFactory10()).andReturn(factory10)
            .anyTimes();
        expect(controller.getOFMessageFactory13()).andReturn(factory13)
            .anyTimes();
        expect(controller.addConnectedSwitch(2000, handler)).andReturn(true)
            .anyTimes();
        replay(controller);
        handler = new OFChannelHandler(controller);
        verify(controller);
        reset(controller);

        resetChannel();

        // replay controller. Reset it if you need more specific behavior
        replay(controller);

        // replay switch. Reset it if you need more specific behavior
        replay(swImplBase);

        // Mock ctx and channelStateEvent
        expect(ctx.getChannel()).andReturn(channel).anyTimes();
        expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes();
        replay(ctx, channelStateEvent);

        /* Setup an exception event capture on the channel. Right now
         * we only expect exception events to be send up the channel.
         * However, it's easy to extend to other events if we need it
         */
        pipeline.sendUpstream(capture(exceptionEventCapture));
        expectLastCall().anyTimes();
        replay(pipeline);
        featuresReply = (OFFeaturesReply) buildOFMessage(OFType.FEATURES_REPLY);
    }

    @After
    public void tearDown() {
        /* ensure no exception was thrown */
        if (exceptionEventCapture.hasCaptured()) {
            Throwable ex = exceptionEventCapture.getValue().getCause();
            throw new AssertionError("Unexpected exception: " +
                    ex.getClass().getName() + "(" + ex + ")");
        }
        assertFalse("Unexpected messages have been captured",
                writeCapture.hasCaptured());
        // verify all mocks.
        verify(channel);
        verify(messageEvent);
        verify(controller);
        verify(ctx);
        verify(channelStateEvent);
        verify(pipeline);
        verify(swImplBase);

    }

    /**
     * Reset the channel mock and set basic method call expectations.
     *
     **/
    void resetChannel() {
        reset(channel);
        expect(channel.getPipeline()).andReturn(pipeline).anyTimes();
        expect(channel.getRemoteAddress()).andReturn(null).anyTimes();
    }

    /**
     * reset, setup, and replay the messageEvent mock for the given
     * messages.
     */
    void setupMessageEvent(List<OFMessage> messages) {
        reset(messageEvent);
        expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce();
        replay(messageEvent);
    }

    /**
     * reset, setup, and replay the messageEvent mock for the given
     * messages, mock controller  send message to channel handler.
     *
     * This method will reset, start replay on controller, and then verify
     */
    void sendMessageToHandlerWithControllerReset(List<OFMessage> messages)
            throws Exception {
        verify(controller);
        reset(controller);

        sendMessageToHandlerNoControllerReset(messages);
    }

    /**
     * reset, setup, and replay the messageEvent mock for the given
     * messages, mock controller  send message to channel handler.
     *
     * This method will start replay on controller, and then verify
     */
    void sendMessageToHandlerNoControllerReset(List<OFMessage> messages)
            throws Exception {
        setupMessageEvent(messages);

        expect(controller.addConnectedSwitch(1000, handler))
        .andReturn(true).anyTimes();
        replay(controller);

        handler.messageReceived(ctx, messageEvent);
        verify(controller);
    }

    /**
     * Extract the list of OFMessages that was captured by the Channel.write()
     * capture. Will check that something was actually captured first. We'll
     * collapse the messages from multiple writes into a single list of
     * OFMessages.
     * Resets the channelWriteCapture.
     */
    List<OFMessage> getMessagesFromCapture() {
        List<OFMessage> msgs = new ArrayList<OFMessage>();

        assertTrue("No write on channel was captured",
                writeCapture.hasCaptured());
        List<List<OFMessage>> capturedVals = writeCapture.getValues();

        for (List<OFMessage> oneWriteList: capturedVals) {
            msgs.addAll(oneWriteList);
        }
        writeCapture.reset();
        return msgs;
    }


    /**
     * Verify that the given exception event capture (as returned by
     * getAndInitExceptionCapture) has thrown an exception of the given
     * expectedExceptionClass.
     * Resets the capture
     */
    void verifyExceptionCaptured(
            Class<? extends Throwable> expectedExceptionClass) {
        assertTrue("Excpected exception not thrown",
                exceptionEventCapture.hasCaptured());
        Throwable caughtEx = exceptionEventCapture.getValue().getCause();
        assertEquals(expectedExceptionClass, caughtEx.getClass());
        exceptionEventCapture.reset();
    }

    /**
     * Make sure that the transaction ids in the given messages are
     * not 0 and differ between each other.
     * While it's not a defect per se if the xids are we want to ensure
     * we use different ones for each message we send.
     */
    void verifyUniqueXids(List<OFMessage> msgs) {
        if (seenXids == null) {
            seenXids = new HashSet<Integer>();
        }
        for (OFMessage m: msgs)  {
            int xid = (int) m.getXid();
            assertTrue("Xid in messags is 0", xid != 0);
            assertFalse("Xid " + xid + " has already been used",
                    seenXids.contains(xid));
            seenXids.add(xid);
        }
    }



    public void testInitState() throws Exception {
        OFMessage m = buildOFMessage(OFType.HELLO);

        expect(messageEvent.getMessage()).andReturn(null);
        replay(channel, messageEvent);

        // We don't expect to receive /any/ messages in init state since
        // channelConnected moves us to a different state
        sendMessageToHandlerWithControllerReset(Collections.singletonList(m));

        verifyExceptionCaptured(SwitchStateException.class);
        assertEquals(OFChannelHandler.ChannelState.INIT,
                handler.getStateForTesting());
    }

    /**
     * move the channel from scratch to WAIT_HELLO state.
     *
     */
    @Test
    public void moveToWaitHello() throws Exception {
        resetChannel();
        channel.write(capture(writeCapture));
        expectLastCall().andReturn(null).once();
        replay(channel);
        // replay unused mocks
        replay(messageEvent);

        handler.channelConnected(ctx, channelStateEvent);

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        assertEquals(OFType.HELLO, msgs.get(0).getType());
        assertEquals(OFChannelHandler.ChannelState.WAIT_HELLO,
                handler.getStateForTesting());
        //Should verify that the Hello received from the controller
        //is ALWAYS OF1.3 hello regardless of the switch version
        assertEquals(OFVersion.OF_13, msgs.get(0).getVersion());
        verifyUniqueXids(msgs);
    }


    /**
     * Move the channel from scratch to WAIT_FEATURES_REPLY state.
     * Builds on moveToWaitHello().
     * adds testing for WAIT_HELLO state.
     */
    @Test
    public void moveToWaitFeaturesReply() throws Exception {
        moveToWaitHello();
        resetChannel();
        channel.write(capture(writeCapture));
        expectLastCall().andReturn(null).atLeastOnce();
        replay(channel);

        OFMessage hello = buildOFMessage(OFType.HELLO);
        sendMessageToHandlerWithControllerReset(Collections.singletonList(hello));

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        assertEquals(OFType.FEATURES_REQUEST, msgs.get(0).getType());
        if (ofVersion == OFVersion.OF_10) {
            assertEquals(OFVersion.OF_10, msgs.get(0).getVersion());
        }
        verifyUniqueXids(msgs);

        assertEquals(OFChannelHandler.ChannelState.WAIT_FEATURES_REPLY,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to WAIT_CONFIG_REPLY state.
     * Builds on moveToWaitFeaturesReply.
     * adds testing for WAIT_FEATURES_REPLY state.
     */
    @Test
    public void moveToWaitConfigReply() throws Exception {
        moveToWaitFeaturesReply();

        resetChannel();
        channel.write(capture(writeCapture));
        expectLastCall().andReturn(null).atLeastOnce();
        replay(channel);

        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(featuresReply));
        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(3, msgs.size());
        assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
        OFSetConfig sc = (OFSetConfig) msgs.get(0);
        assertEquals((short) 0xffff, sc.getMissSendLen());
        assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
        assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
        verifyUniqueXids(msgs);
        assertEquals(OFChannelHandler.ChannelState.WAIT_CONFIG_REPLY,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state.
     * Builds on moveToWaitConfigReply().
     * adds testing for WAIT_CONFIG_REPLY state.
     */
    @Test
    public void moveToWaitDescriptionStatReply() throws Exception {
        moveToWaitConfigReply();
        resetChannel();
        channel.write(capture(writeCapture));
        expectLastCall().andReturn(null).atLeastOnce();
        replay(channel);

        OFGetConfigReply cr = (OFGetConfigReply) buildOFMessage(OFType.GET_CONFIG_REPLY);

        sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(cr));

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        assertEquals(OFType.STATS_REQUEST, msgs.get(0).getType());
        OFStatsRequest<?> sr = (OFStatsRequest<?>) msgs.get(0);
        assertEquals(OFStatsType.DESC, sr.getStatsType());
        verifyUniqueXids(msgs);
        assertEquals(OFChannelHandler.ChannelState.WAIT_DESCRIPTION_STAT_REPLY,
                handler.getStateForTesting());
    }


    private OFStatsReply createDescriptionStatsReply() throws IOException {
        OFStatsReply sr = (OFStatsReply) buildOFMessage(OFType.STATS_REPLY);
        return sr;
    }

    /**
     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
     * for a switch that does not have a sub-handshake.
     * Builds on moveToWaitDescriptionStatReply().
     * adds testing for WAIT_DESCRIPTION_STAT_REPLY state.
     *
     */
    @Test
    public void moveToWaitInitialRole()
            throws Exception {
        moveToWaitDescriptionStatReply();

        long xid = 2000;

        // build the stats reply
        OFStatsReply sr = createDescriptionStatsReply();

        resetChannel();
        replay(channel);

        setupMessageEvent(Collections.<OFMessage>singletonList(sr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();
        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();
        controller.submitRegistryRequest(1000);
        expectLastCall().once();
        replay(controller);

        //TODO: With the description stats message you are sending in the test,
        //you will end up with an OFSwitchImplBase object
        //which by default does NOT support the nicira role messages.
        //If you wish to test the case where Nicira role messages are supported,
        //then make a comment here that states that this is different
        //from the default behavior of switchImplbase /or/
        //send the right desc-stats (for example send what is expected from OVS 1.0)

        if (ofVersion == OFVersion.OF_10) {
            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
            .andReturn(true).once();

            swImplBase.write(capture(writeCapture));
            expectLastCall().anyTimes();
        }

        swImplBase.setOFVersion(ofVersion);
        expectLastCall().once();
        swImplBase.setConnected(true);
        expectLastCall().once();
        swImplBase.setChannel(channel);
        expectLastCall().once();
        swImplBase.setDebugCounterService(controller.getDebugCounter());
        expectLastCall().once();
        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        swImplBase.setRole(Role.EQUAL);
        expectLastCall().once();

        expect(swImplBase.getNextTransactionId())
        .andReturn((int) xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();

        swImplBase.setFeaturesReply(featuresReply);
        expectLastCall().once();
        swImplBase.setPortDescReply((OFPortDescStatsReply) null);
        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        assertEquals(OFType.EXPERIMENTER, msgs.get(0).getType());
        verifyNiciraMessage((OFExperimenter) msgs.get(0));

        verify(controller);
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to.
     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
     * Builds on moveToWaitInitialRole().
     */
    @Test
    public void moveToWaitSubHandshake()
            throws Exception {
        moveToWaitInitialRole();

        int xid = 2000;
        resetChannel();
        replay(channel);

        reset(swImplBase);
        // Set the role
        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

        // build the stats reply
        OFStatsReply sr = createDescriptionStatsReply();
        OFMessage rr = getRoleReply(xid, Role.SLAVE);
        setupMessageEvent(Collections.<OFMessage>singletonList(rr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();
        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        swImplBase.setRole(Role.SLAVE);
        expectLastCall().once();
        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();
        swImplBase.startDriverHandshake();
        expectLastCall().once();

        //when this flag is false, state machine will move to
        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(false).once();

        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
     * then move the channel to EQUAL state based on the switch Role.
     * This test basically test the switch with role support.
     * Builds on moveToWaitInitialRole().
     *
     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
     * and PORT_STATUS), state machine will transit to MASTER or
     * EQUAL state based on the switch role.
     */
    @Test
    public void moveToSlaveWithHandshakeComplete()
            throws Exception {

        moveToWaitInitialRole();

        int xid = 2000;
        resetChannel();
        replay(channel);

        reset(swImplBase);
        // Set the role
        setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

        // build the stats reply
        OFStatsReply sr = createDescriptionStatsReply();
        OFMessage rr = getRoleReply(xid, Role.SLAVE);
        setupMessageEvent(Collections.<OFMessage>singletonList(rr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
        .andReturn(true).once();
        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        //consult the role in sw to determine the next state.
        //in this testing case, we are testing that channel handler
        // will move to EQUAL state when switch role is in SLAVE.
        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
        swImplBase.setRole(Role.SLAVE);
        expectLastCall().once();

        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();
        swImplBase.startDriverHandshake();
        expectLastCall().once();

        //when this flag is true, don't need to move interim state
        //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE. channel handler will
        //move to corresponding state after consulting the role in sw
        //This is essentially the same test as the one above,
        //except for this line
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(true).once();

        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.EQUAL,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to WAIT_INITIAL_ROLE state,
     * then to MASTERL state based on the switch Role.
     * This test basically test the switch with role support.
     * Builds on moveToWaitInitialRole().
     *
     * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
     * and PORT_STATUS), state machine will transit to MASTER or
     * EQUAL state based on the switch role.
     */
    @Test
    public void moveToMasterWithHandshakeComplete()
            throws Exception {

        moveToWaitInitialRole();

        int xid = 2000;
        resetChannel();
        replay(channel);

        reset(swImplBase);
        // Set the role
        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

        // build the stats reply
        OFStatsReply sr = createDescriptionStatsReply();
        OFMessage rr = getRoleReply(xid, Role.MASTER);
        setupMessageEvent(Collections.<OFMessage>singletonList(rr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
        .andReturn(true).once();
        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
        swImplBase.setRole(Role.MASTER);
        expectLastCall().once();

        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();
        swImplBase.startDriverHandshake();
        expectLastCall().once();
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(true).once();

        replay(swImplBase);


        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to
     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
     * Builds on moveToWaitSubHandshake().
     */
    @Test
    public void moveToEqualViaWaitSubHandshake()
            throws Exception {
        moveToWaitSubHandshake();

        long xid = 2000;
        resetChannel();
        replay(channel);

        // build the stats reply
        OFStatsReply sr = createDescriptionStatsReply();

        setupMessageEvent(Collections.<OFMessage>singletonList(sr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();
        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        expect(controller.addActivatedEqualSwitch(1000, swImplBase))
        .andReturn(true).once();
        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
        expect(swImplBase.getNextTransactionId())
        .andReturn((int) xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();

        swImplBase.processDriverHandshakeMessage(sr);
        expectLastCall().once();
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(true).once();

        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.EQUAL,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to
     *  WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
     * Builds on moveToWaitSubHandshake().
     */
    @Test
    public void moveToMasterViaWaitSubHandshake()
            throws Exception {
        moveToWaitSubHandshake();

        long xid = 2000;
        resetChannel();
        replay(channel);

        // In this state, any messages except echo request, port status and
        // error go to the switch sub driver handshake. Once the switch reports
        // that its sub driver handshake is complete (#isDriverHandshakeComplete
        // return true) then the channel handle consults the switch role and
        // moves the state machine to the appropriate state (MASTER or EQUALS).
        // In this test we expect the state machine to end up in MASTER state.
        OFStatsReply sr = createDescriptionStatsReply();

        setupMessageEvent(Collections.<OFMessage>singletonList(sr));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();
        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
        .andReturn(true).once();
        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
        expect(swImplBase.getNextTransactionId())
        .andReturn((int) xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();

        swImplBase.processDriverHandshakeMessage(sr);
        expectLastCall().once();
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(true).once();

        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);
        verify(controller);
        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());
    }

    /**
     * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
     * ECHO_REQUEST message received case.
     */
    @Test
    public void testWaitSwitchDriverSubhandshake() throws Exception {
        moveToWaitSubHandshake();

        long xid = 2000;
        resetChannel();
        channel.write(capture(writeCapture));
        expectLastCall().andReturn(null).atLeastOnce();
        replay(channel);

        OFMessage er = buildOFMessage(OFType.ECHO_REQUEST);

        setupMessageEvent(Collections.<OFMessage>singletonList(er));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFMessageFactory10()).andReturn(factory10);
        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getNextTransactionId())
        .andReturn((int) xid).anyTimes();

        replay(swImplBase);

        handler.messageReceived(ctx, messageEvent);

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        assertEquals(OFType.ECHO_REPLY, msgs.get(0).getType());
        verifyUniqueXids(msgs);
        assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
                handler.getStateForTesting());
    }

    /**
     * Helper.
     * Verify that the given OFMessage is a correct Nicira RoleRequest message.
     */
    private void verifyNiciraMessage(OFExperimenter ofMessage) {

        int vendor = (int) ofMessage.getExperimenter();
        assertEquals(vendor, 0x2320); // magic number representing nicira
    }

    /**
     * Setup the mock switch and write capture for a role request, set the
     * role and verify mocks.
     * @param supportsNxRole whether the switch supports role request messages
     * to setup the attribute. This must be null (don't yet know if roles
     * supported: send to check) or true.
     * @param xid The xid to use in the role request
     * @param role The role to send
     * @throws IOException
     */
    private void setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
            int xid,
            Role role) throws IOException {

        RoleRecvStatus expectation = RoleRecvStatus.MATCHED_SET_ROLE;

        expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
        .andReturn(supportsNxRole).atLeastOnce();

        if (supportsNxRole != null && supportsNxRole) {
            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
            swImplBase.write(capture(writeCapture));
            expectLastCall().anyTimes();
        }
        replay(swImplBase);

        handler.sendRoleRequest(role, expectation);

        if (supportsNxRole != null && supportsNxRole) {
            List<OFMessage> msgs = getMessagesFromCapture();
            assertEquals(1, msgs.size());
            verifyNiciraMessage((OFExperimenter) msgs.get(0));
        }
    }

    /**
     * Setup the mock switch for a role change request where the switch
     * does not support roles.
     *
     * Needs to verify and reset the controller since we need to set
     * an expectation
     */
    private void setupSwitchRoleChangeUnsupported(int xid,
            Role role) {
        boolean supportsNxRole = false;
        RoleRecvStatus expectation = RoleRecvStatus.NO_REPLY;
        reset(swImplBase);
        expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
        .andReturn(supportsNxRole).atLeastOnce();
        // TODO: hmmm. While it's not incorrect that we set the attribute
        // again it looks odd. Maybe change
        swImplBase.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
        expectLastCall().anyTimes();

        replay(swImplBase);

        handler.sendRoleRequest(role, expectation);

        verify(swImplBase);
    }

    /*
     * Return a Nicira RoleReply message for the given role.
     */
    private OFMessage getRoleReply(long xid, Role role) {

        OFNiciraControllerRole nr = null;

        switch(role) {
        case MASTER:
            nr = OFNiciraControllerRole.ROLE_MASTER;
            break;
        case EQUAL:
            nr = OFNiciraControllerRole.ROLE_SLAVE;
            break;
        case SLAVE:
            nr = OFNiciraControllerRole.ROLE_SLAVE;
            break;
        default: //handled below
        }
        OFMessage m = factory10.buildNiciraControllerRoleReply()
                .setRole(nr)
                .setXid(xid)
                .build();
        return m;
    }

    /**
     * Move the channel from scratch to MASTER state.
     * Builds on moveToWaitInitialRole().
     * adds testing for WAIT_INITAL_ROLE state.
     *
     * This method tests the case that the switch does NOT support roles.
     * In ONOS if the switch-driver says that nicira-role messages are not
     * supported, then ONOS does NOT send role-request messages
     * (see handleUnsentRoleMessage())
     */
    @Test
    public void testInitialMoveToMasterNoRole() throws Exception {
        int xid = 43;
        // first, move us to WAIT_INITIAL_ROLE_STATE

        moveToWaitInitialRole();
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

        OFStatsReply sr = createDescriptionStatsReply();

        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
        .andReturn(true).once();
        replay(controller);

        reset(swImplBase);
        swImplBase.setRole(Role.MASTER);
        expectLastCall().once();
        swImplBase.startDriverHandshake();
        expectLastCall().once();
        expect(swImplBase.isDriverHandshakeComplete())
        .andReturn(true).once();
        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.MASTER).once();

        expect(swImplBase.getId())
        .andReturn(1000L).once();
        // Set the role
        setupSwitchSendRoleRequestAndVerify(false, xid, Role.MASTER);

        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());
    }

    /**
     * Move the channel from scratch to WAIT_INITIAL_ROLE state.
     * Builds on moveToWaitInitialRole().
     * adds testing for WAIT_INITAL_ROLE state
     *
     * We let the initial role request time out. Role support should be
     * disabled but the switch should be activated.
     */
    /* TBD
        @Test
        public void testInitialMoveToMasterTimeout() throws Exception {
            int timeout = 50;
            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
            int xid = 4343;

            // first, move us to WAIT_INITIAL_ROLE_STATE

            moveToWaitInitialRole();
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            // prepare mocks and inject the role reply message
            reset(swImplBase);
            // Set the role
            swImplBase.setRole(Role.MASTER);
            expectLastCall().once();
            swImplBase.startDriverHandshake();
            expectLastCall().once();
            expect(swImplBase.isDriverHandshakeComplete())
            .andReturn(false).once();
            if (ofVersion == OFVersion.OF_10) {
                expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
                 .andReturn(true).once();

                swImplBase.write(capture(writeCapture),
                        EasyMock.<FloodlightContext>anyObject());
                expectLastCall().anyTimes();
             }
            expect(swImplBase.getNextTransactionId()).andReturn(xid).once();

            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            // Set the role
            setupSwitchSendRoleRequestAndVerify(null, xid, Role.MASTER);
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);

            setupMessageEvent(Collections.<OFMessage>singletonList(m));

            Thread.sleep(timeout+5);

            verify(controller);
            reset(controller);

            expect(controller.addActivatedMasterSwitch(1000, swImplBase))
            .andReturn(true).once();
            controller.flushAll();
            expectLastCall().once();

            replay(controller);

            handler.messageReceived(ctx, messageEvent);

            assertEquals(OFChannelHandler.ChannelState.MASTER,
                    handler.getStateForTesting());

        }

     */
    /**
     * Move the channel from scratch to SLAVE state.
     * Builds on doMoveToWaitInitialRole().
     * adds testing for WAIT_INITAL_ROLE state
     *
     * This method tests the case that the switch does NOT support roles.
     * The channel handler still needs to send the initial request to find
     * out that whether the switch supports roles.
     *
     */
    @Test
    public void testInitialMoveToSlaveNoRole() throws Exception {
        int xid = 44;
        // first, move us to WAIT_INITIAL_ROLE_STATE
        moveToWaitInitialRole();
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

        reset(swImplBase);
        // Set the role
        setupSwitchSendRoleRequestAndVerify(false, xid, Role.SLAVE);
        assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                handler.getStateForTesting());

    }

    /**
     * Move the channel from scratch to SLAVE state.
     * Builds on doMoveToWaitInitialRole().
     * adds testing for WAIT_INITAL_ROLE state
     *
     * We let the initial role request time out. The switch should be
     * disconnected
     */
    /* TBD
        @Test
        public void testInitialMoveToSlaveTimeout() throws Exception {
            int timeout = 50;
            handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
            int xid = 4444;

            // first, move us to WAIT_INITIAL_ROLE_STATE
            moveToWaitInitialRole();
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            // Set the role
            setupSwitchSendRoleRequestAndVerify(null, xid, Role.SLAVE);
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            // prepare mocks and inject the role reply message
            reset(sw);
            sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
            expectLastCall().once();
            sw.setRole(Role.SLAVE);
            expectLastCall().once();
            sw.disconnectSwitch(); // Make sure we disconnect
            expectLastCall().once();
            replay(sw);

            OFMessage m = buildOFMessage(OFType.ECHO_REPLY);

            Thread.sleep(timeout+5);

            sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
        }

     */
    /**
     * Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
     * then SLAVE for cases where the switch does not support roles.
     * I.e., the final SLAVE transition should disconnect the switch.
     */
    @Test
    public void testNoRoleInitialToMasterToSlave() throws Exception {
        int xid = 46;
        reset(swImplBase);
        replay(swImplBase);

        reset(controller);
        replay(controller);

        // First, lets move the state to MASTER without role support
        testInitialMoveToMasterNoRole();
        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());

        // try to set master role again. should be a no-op
        setupSwitchRoleChangeUnsupported(xid, Role.MASTER);

        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());

        setupSwitchRoleChangeUnsupported(xid, Role.SLAVE);
        //switch does not support role message. there is no role set
        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());

    }

    /**
     * Move the channel to MASTER state.
     * Expects that the channel is in MASTER or SLAVE state.
     *
     */
    public void changeRoleToMasterWithRequest() throws Exception {
        int xid = 4242;

        assertTrue("This method can only be called when handler is in " +
                "MASTER or SLAVE role", handler.isHandshakeComplete());

        reset(swImplBase);
        reset(controller);
        // Set the role
        setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);

        // prepare mocks and inject the role reply message

        reset(controller);
        expect(controller.addActivatedMasterSwitch(1000, swImplBase))
        .andReturn(true).once();
        OFMessage reply = getRoleReply(xid, Role.MASTER);

        // sendMessageToHandler will verify and rest controller mock

        OFStatsReply sr = createDescriptionStatsReply();
        setupMessageEvent(Collections.<OFMessage>singletonList(reply));

        // mock controller
        reset(controller);
        reset(swImplBase);

        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();
        controller.transitionToMasterSwitch(1000);
        expectLastCall().once();

        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.EQUAL).atLeastOnce();
        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();
        expect(swImplBase.getId())
        .andReturn(1000L).once();

        swImplBase.setRole(Role.MASTER);
        expectLastCall().once();
        replay(swImplBase);

        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());
    }

    /**
     * Move the channel to SLAVE state.
     * Expects that the channel is in MASTER or SLAVE state.
     *
     */
    public void changeRoleToSlaveWithRequest() throws Exception {
        int xid = 2323;

        assertTrue("This method can only be called when handler is in " +
                "MASTER or SLAVE role", handler.isHandshakeComplete());

        // Set the role
        reset(controller);
        reset(swImplBase);

        swImplBase.write(capture(writeCapture));
        expectLastCall().anyTimes();

        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();


        if (ofVersion == OFVersion.OF_10) {
            expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
            .andReturn(true).once();

            swImplBase.write(capture(writeCapture));
            expectLastCall().anyTimes();
        }
        replay(swImplBase);

        handler.sendRoleRequest(Role.SLAVE, RoleRecvStatus.MATCHED_SET_ROLE);

        List<OFMessage> msgs = getMessagesFromCapture();
        assertEquals(1, msgs.size());
        verifyNiciraMessage((OFExperimenter) msgs.get(0));


        OFMessage reply = getRoleReply(xid, Role.SLAVE);
        OFStatsReply sr = createDescriptionStatsReply();
        setupMessageEvent(Collections.<OFMessage>singletonList(reply));

        // mock controller
        reset(controller);
        reset(swImplBase);

        controller.transitionToEqualSwitch(1000);
        expectLastCall().once();
        expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
        .andReturn(swImplBase).anyTimes();

        expect(controller.getDebugCounter())
        .andReturn(debugCounterService).anyTimes();

        replay(controller);

        expect(swImplBase.getStringId())
        .andReturn(null).anyTimes();
        expect(swImplBase.getRole()).andReturn(Role.MASTER).atLeastOnce();
        expect(swImplBase.getNextTransactionId())
        .andReturn(xid).anyTimes();

        // prepare mocks and inject the role reply message
        swImplBase.setRole(Role.SLAVE);
        expectLastCall().once();
        expect(swImplBase.getId())
        .andReturn(1000L).once();
        replay(swImplBase);

        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.EQUAL,
                handler.getStateForTesting());
    }

    @Test
    public void testMultiRoleChange1() throws Exception {
        moveToMasterWithHandshakeComplete();
        changeRoleToMasterWithRequest();
        changeRoleToSlaveWithRequest();
        changeRoleToSlaveWithRequest();
        changeRoleToMasterWithRequest();
        changeRoleToSlaveWithRequest();
    }

    @Test
    public void testMultiRoleChange2() throws Exception {
        moveToSlaveWithHandshakeComplete();
        changeRoleToMasterWithRequest();
        changeRoleToSlaveWithRequest();
        changeRoleToSlaveWithRequest();
        changeRoleToMasterWithRequest();
        changeRoleToSlaveWithRequest();
    }

    /**
     * Start from scratch and reply with an unexpected error to the role
     * change request.
     * Builds on doMoveToWaitInitialRole()
     * adds testing for WAIT_INITAL_ROLE state
     */
    /* TBD
        @Test
        public void testInitialRoleChangeOtherError() throws Exception {
            int xid = 4343;
            // first, move us to WAIT_INITIAL_ROLE_STATE
            moveToWaitInitialRole();
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());

            reset(swImplBase);
            // Set the role
            setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
            assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
                    handler.getStateForTesting());


            // FIXME: shouldn't use ordinal(), but OFError is broken

            OFMessage err = factory.errorMsgs().buildBadActionErrorMsg()
                    .setCode(OFBadActionCode.BAD_LEN)
                    .setXid(2000)
                    .build();
            verify(swImplBase);
            reset(swImplBase);
            replay(swImplBase);
            sendMessageToHandlerWithControllerReset(Collections.singletonList(err));

            verifyExceptionCaptured(SwitchStateException.class);
        }
     */
    /**
     * Test dispatch of messages while in MASTER role.
     */
    @Test
    public void testMessageDispatchMaster() throws Exception {

        moveToMasterWithHandshakeComplete();

        // Send packet in. expect dispatch
        OFPacketIn pi = (OFPacketIn)
                buildOFMessage(OFType.PACKET_IN);
        setupMessageEvent(Collections.<OFMessage>singletonList(pi));

        reset(swImplBase);
        swImplBase.handleMessage(pi);
        expectLastCall().once();
        replay(swImplBase);
        // send the description stats reply
        handler.messageReceived(ctx, messageEvent);

        assertEquals(OFChannelHandler.ChannelState.MASTER,
                handler.getStateForTesting());

        verify(controller);
        // TODO: many more to go
    }

    /**
     * Test port status message handling while MASTER.
     *
     */
    /* Patrick: TBD
        @Test
        public void testPortStatusMessageMaster() throws Exception {
            long dpid = featuresReply.getDatapathId().getLong();
            testInitialMoveToMasterWithRole();
            List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
            // A dummy port.
            OFPortDesc p = factory.buildPortDesc()
                        .setName("Eth1")
                        .setPortNo(OFPort.ofInt(1))
                        .build();
            ports.add(p);

            p.setName("Port1");
            p.setPortNumber((short)1);

            OFPortStatus ps = (OFPortStatus)buildOFMessage(OFType.PORT_STATUS);
            ps.setDesc(p);

            // The events we expect sw.handlePortStatus to return
            // We'll just use the same list for all valid OFPortReasons and add
            // arbitrary events for arbitrary ports that are not necessarily
            // related to the port status message. Our goal
            // here is not to return the correct set of events but the make sure
            // that a) sw.handlePortStatus is called
            //      b) the list of events sw.handlePortStatus returns is sent
            //         as IOFSwitchListener notifications.
            OrderedCollection<PortChangeEvent> events =
                    new LinkedHashSetWrapper<PortChangeEvent>();
            ImmutablePort p1 = ImmutablePort.create("eth1", (short)1);
            ImmutablePort p2 = ImmutablePort.create("eth2", (short)2);
            ImmutablePort p3 = ImmutablePort.create("eth3", (short)3);
            ImmutablePort p4 = ImmutablePort.create("eth4", (short)4);
            ImmutablePort p5 = ImmutablePort.create("eth5", (short)5);
            events.add(new PortChangeEvent(p1, PortChangeType.ADD));
            events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
            events.add(new PortChangeEvent(p3, PortChangeType.UP));
            events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
            events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));


            for (OFPortReason reason: OFPortReason.values()) {
                ps.setReason(reason.getReasonCode());

                reset(sw);
                expect(sw.getId()).andReturn(dpid).anyTimes();

                expect(sw.processOFPortStatus(ps)).andReturn(events).once();
                replay(sw);

                reset(controller);
                controller.notifyPortChanged(sw, p1, PortChangeType.ADD);
                controller.notifyPortChanged(sw, p2, PortChangeType.DELETE);
                controller.notifyPortChanged(sw, p3, PortChangeType.UP);
                controller.notifyPortChanged(sw, p4, PortChangeType.DOWN);
                controller.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
                sendMessageToHandlerNoControllerReset(
                        Collections.<OFMessage>singletonList(ps));
                verify(sw);
                verify(controller);
            }
        }

     */
    /**
     * Build an OF message.
     * @throws IOException
     */
    private OFMessage buildOFMessage(OFType t) throws IOException {
        OFMessage m = null;
        switch (t) {

        case HELLO:
            // The OF protocol requires us to start things off by sending the highest
            // version of the protocol supported.

            // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
            // see Sec. 7.5.1 of the OF1.3.4 spec
            if (ofVersion == OFVersion.OF_13) {
                U32 bitmap = U32.ofRaw(0x00000012);
                OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
                    .setBitmaps(Collections.singletonList(bitmap))
                    .build();
                m = factory13.buildHello()
                        .setXid(2000)
                        .setElements(Collections.singletonList(hem))
                        .build();
            } else {
                m = factory10.buildHello()
                    .setXid(2000)
                    .build();
            }
            break;
        case FEATURES_REQUEST:
            m = factory.buildFeaturesRequest()
            .setXid(2000)
            .build();
            break;
        case FEATURES_REPLY:

            m = factory.buildFeaturesReply()
            .setDatapathId(DatapathId.of(1000L))
            .setXid(2000)
            .build();
            break;
        case SET_CONFIG:
            m = factory.buildSetConfig()
            .setMissSendLen((short) 0xffff)
            .setXid(2000)
            .build();
            break;
        case BARRIER_REQUEST:
            m = factory.buildBarrierRequest()
            .setXid(2000)
            .build();
            break;
        case GET_CONFIG_REQUEST:
            m = factory.buildGetConfigRequest()
            .setXid(2000)
            .build();
            break;
        case GET_CONFIG_REPLY:
            m = factory.buildGetConfigReply()
            .setMissSendLen((short) 0xffff)
            .setXid(2000)
            .build();
            break;
        case STATS_REQUEST:
            break;
        case STATS_REPLY:
            m = factory.buildDescStatsReply()
            .setDpDesc("Datapath Description")
            .setHwDesc("Hardware Secription")
            .setMfrDesc("Manufacturer Desctiption")
            .setSerialNum("Serial Number")
            .setSwDesc("Software Desription")
            .build();
            break;
        case ECHO_REQUEST:
            m = factory.buildEchoRequest()
            .setXid(2000)
            .build();
            break;
        case FLOW_REMOVED:
            break;

        case PACKET_IN:
            m = factory.buildPacketIn()
            .setReason(OFPacketInReason.NO_MATCH)
            .setTotalLen(1500)
            .setXid(2000)
            .build();
            break;
        case PORT_STATUS:
            m = factory.buildPortStatus()
            .setXid(2000)
            .build();
            break;

        default:
            m = factory.buildFeaturesRequest()
            .setXid(2000)
            .build();
            break;
        }

        return (m);
    }
}
