// 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 OFOxmBsnL3SrcClassIdVer13Test {
    OFOxms factory;

    final static byte[] OXM_BSN_L3_SRC_CLASS_ID_SERIALIZED =
        new byte[] { 0x0, 0x3, 0xa, 0x4, 0x12, 0x34, 0x56, 0x78 };

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

    @Test
    public void testWrite() {
        OFOxmBsnL3SrcClassId.Builder builder = factory.buildBsnL3SrcClassId();
        builder.setValue(ClassId.of(0x12345678));
        OFOxmBsnL3SrcClassId oxmBsnL3SrcClassId = builder.build();
        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
        oxmBsnL3SrcClassId.writeTo(bb);
        byte[] written = new byte[bb.readableBytes()];
        bb.readBytes(written);

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

    @Test
    public void testRead() throws Exception {
        OFOxmBsnL3SrcClassId.Builder builder = factory.buildBsnL3SrcClassId();
        builder.setValue(ClassId.of(0x12345678));
        OFOxmBsnL3SrcClassId oxmBsnL3SrcClassIdBuilt = builder.build();

        ChannelBuffer input = ChannelBuffers.copiedBuffer(OXM_BSN_L3_SRC_CLASS_ID_SERIALIZED);

        // FIXME should invoke the overall reader once implemented
        OFOxmBsnL3SrcClassId oxmBsnL3SrcClassIdRead = OFOxmBsnL3SrcClassIdVer13.READER.readFrom(input);
        assertEquals(OXM_BSN_L3_SRC_CLASS_ID_SERIALIZED.length, input.readerIndex());

        assertEquals(oxmBsnL3SrcClassIdBuilt, oxmBsnL3SrcClassIdRead);
   }

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

       // FIXME should invoke the overall reader once implemented
       OFOxmBsnL3SrcClassId oxmBsnL3SrcClassId = OFOxmBsnL3SrcClassIdVer13.READER.readFrom(input);
       assertEquals(OXM_BSN_L3_SRC_CLASS_ID_SERIALIZED.length, input.readerIndex());

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

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

}
