// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
// Copyright (c) 2011, 2012 Open Networking Foundation
// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
// This library was generated by the LoxiGen Compiler.
// See the file LICENSE.txt which should have been included in the source distribution

// Automatically generated by LOXI from template unit_test.java
// Do not modify

package org.projectfloodlight.openflow.protocol.ver13;

import org.projectfloodlight.openflow.protocol.*;
import org.projectfloodlight.openflow.protocol.action.*;
import org.projectfloodlight.openflow.protocol.actionid.*;
import org.projectfloodlight.openflow.protocol.bsntlv.*;
import org.projectfloodlight.openflow.protocol.errormsg.*;
import org.projectfloodlight.openflow.protocol.meterband.*;
import org.projectfloodlight.openflow.protocol.instruction.*;
import org.projectfloodlight.openflow.protocol.instructionid.*;
import org.projectfloodlight.openflow.protocol.match.*;
import org.projectfloodlight.openflow.protocol.oxm.*;
import org.projectfloodlight.openflow.protocol.queueprop.*;
import org.projectfloodlight.openflow.types.*;
import org.projectfloodlight.openflow.util.*;
import org.projectfloodlight.openflow.exceptions.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.hamcrest.CoreMatchers;



public class OFBadRequestErrorMsgVer13Test {
    OFErrorMsgs factory;

    final static byte[] BAD_REQUEST_ERROR_MSG_SERIALIZED =
        new byte[] { 0x4, 0x1, 0x0, 0xf, 0x12, 0x34, 0x56, 0x78, 0x0, 0x1, 0x0, 0x8, 0x61, 0x62, 0x63 };

    @Before
    public void setup() {
        factory = OFErrorMsgsVer13.INSTANCE;
    }

    @Test
    public void testWrite() {
        OFBadRequestErrorMsg.Builder builder = factory.buildBadRequestErrorMsg();
        builder.setXid(0x12345678)
    .setCode(OFBadRequestCode.BUFFER_UNKNOWN)
    .setData(OFErrorCauseData.of(new byte[] { 0x61, 0x62, 0x63 }, OFVersion.OF_13));;
        OFBadRequestErrorMsg badRequestErrorMsg = builder.build();
        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
        badRequestErrorMsg.writeTo(bb);
        byte[] written = new byte[bb.readableBytes()];
        bb.readBytes(written);

        assertThat(written, CoreMatchers.equalTo(BAD_REQUEST_ERROR_MSG_SERIALIZED));
    }

    @Test
    public void testRead() throws Exception {
        OFBadRequestErrorMsg.Builder builder = factory.buildBadRequestErrorMsg();
        builder.setXid(0x12345678)
    .setCode(OFBadRequestCode.BUFFER_UNKNOWN)
    .setData(OFErrorCauseData.of(new byte[] { 0x61, 0x62, 0x63 }, OFVersion.OF_13));;
        OFBadRequestErrorMsg badRequestErrorMsgBuilt = builder.build();

        ChannelBuffer input = ChannelBuffers.copiedBuffer(BAD_REQUEST_ERROR_MSG_SERIALIZED);

        // FIXME should invoke the overall reader once implemented
        OFBadRequestErrorMsg badRequestErrorMsgRead = OFBadRequestErrorMsgVer13.READER.readFrom(input);
        assertEquals(BAD_REQUEST_ERROR_MSG_SERIALIZED.length, input.readerIndex());

        assertEquals(badRequestErrorMsgBuilt, badRequestErrorMsgRead);
   }

   @Test
   public void testReadWrite() throws Exception {
       ChannelBuffer input = ChannelBuffers.copiedBuffer(BAD_REQUEST_ERROR_MSG_SERIALIZED);

       // FIXME should invoke the overall reader once implemented
       OFBadRequestErrorMsg badRequestErrorMsg = OFBadRequestErrorMsgVer13.READER.readFrom(input);
       assertEquals(BAD_REQUEST_ERROR_MSG_SERIALIZED.length, input.readerIndex());

       // write message again
       ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
       badRequestErrorMsg.writeTo(bb);
       byte[] written = new byte[bb.readableBytes()];
       bb.readBytes(written);

       assertThat(written, CoreMatchers.equalTo(BAD_REQUEST_ERROR_MSG_SERIALIZED));
   }

}
