// 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 java.util.List;
import com.google.common.collect.ImmutableList;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.hamcrest.CoreMatchers;



public class OFBsnGentableEntryStatsReplyVer13Test {
    OFFactory factory;

    final static byte[] BSN_GENTABLE_ENTRY_STATS_REPLY_SERIALIZED =
        new byte[] { 0x4, 0x13, 0x0, 0x60, 0x12, 0x34, 0x56, 0x78, (byte) 0xff, (byte) 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0x16, (byte) 0xc7, 0x0, 0x0, 0x0, 0x3, 0x0, 0x24, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x5, 0x0, 0x2, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x3, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65, 0x0, 0x24, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x6, 0x0, 0x2, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0x0, 0x3, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x65 };

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

    @Test
    public void testWrite() {
        OFBsnGentableEntryStatsReply.Builder builder = factory.buildBsnGentableEntryStatsReply();
        builder.setXid(0x12345678)
    .setEntries(
        ImmutableList.<OFBsnGentableEntryStatsEntry>of(
            factory.bsnGentableEntryStatsEntry(
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().port(OFPort.of(5))
                ),
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().rxPackets(U64.of(100)),
                    factory.bsnTlvs().txPackets(U64.of(101))
                )
            ),
            factory.bsnGentableEntryStatsEntry(
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().port(OFPort.of(6))
                ),
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().rxPackets(U64.of(100)),
                    factory.bsnTlvs().txPackets(U64.of(101))
                )
            )
        )
    );
        OFBsnGentableEntryStatsReply bsnGentableEntryStatsReply = builder.build();
        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
        bsnGentableEntryStatsReply.writeTo(bb);
        byte[] written = new byte[bb.readableBytes()];
        bb.readBytes(written);

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

    @Test
    public void testRead() throws Exception {
        OFBsnGentableEntryStatsReply.Builder builder = factory.buildBsnGentableEntryStatsReply();
        builder.setXid(0x12345678)
    .setEntries(
        ImmutableList.<OFBsnGentableEntryStatsEntry>of(
            factory.bsnGentableEntryStatsEntry(
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().port(OFPort.of(5))
                ),
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().rxPackets(U64.of(100)),
                    factory.bsnTlvs().txPackets(U64.of(101))
                )
            ),
            factory.bsnGentableEntryStatsEntry(
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().port(OFPort.of(6))
                ),
                ImmutableList.<OFBsnTlv>of(
                    factory.bsnTlvs().rxPackets(U64.of(100)),
                    factory.bsnTlvs().txPackets(U64.of(101))
                )
            )
        )
    );
        OFBsnGentableEntryStatsReply bsnGentableEntryStatsReplyBuilt = builder.build();

        ChannelBuffer input = ChannelBuffers.copiedBuffer(BSN_GENTABLE_ENTRY_STATS_REPLY_SERIALIZED);

        // FIXME should invoke the overall reader once implemented
        OFBsnGentableEntryStatsReply bsnGentableEntryStatsReplyRead = OFBsnGentableEntryStatsReplyVer13.READER.readFrom(input);
        assertEquals(BSN_GENTABLE_ENTRY_STATS_REPLY_SERIALIZED.length, input.readerIndex());

        assertEquals(bsnGentableEntryStatsReplyBuilt, bsnGentableEntryStatsReplyRead);
   }

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

       // FIXME should invoke the overall reader once implemented
       OFBsnGentableEntryStatsReply bsnGentableEntryStatsReply = OFBsnGentableEntryStatsReplyVer13.READER.readFrom(input);
       assertEquals(BSN_GENTABLE_ENTRY_STATS_REPLY_SERIALIZED.length, input.readerIndex());

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

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

}
