// 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.ver10;

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 OFFlowStatsEntryVer10Test {
    OFFactory factory;

    final static byte[] FLOW_STATS_ENTRY_SERIALIZED =
        new byte[] { 0x0, 0x68, 0x3, 0x0, 0x0, 0x30, 0x0, (byte) 0xe2, 0x0, 0x3, 0x1, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef, 0x1, 0x23, 0x45, 0x67, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, (byte) 0xc0, (byte) 0xa8, 0x3, 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x64, 0x0, 0x5, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, (byte) 0xe8, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x2, 0x0, 0x0 };

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

    @Test
    public void testWrite() {
        OFFlowStatsEntry.Builder builder = factory.buildFlowStatsEntry();
            builder
      .setTableId(TableId.of(3))
      .setMatch(
        factory.buildMatch()
            .setExact(MatchField.IN_PORT, OFPort.of(3))
            .setExact(MatchField.ETH_TYPE, EthType.IPv4)
            .setExact(MatchField.IPV4_SRC, IPv4Address.of(0xc0a8037f))
            .setExact(MatchField.IPV4_DST, IPv4Address.of(0xffffffff))
            .setExact(MatchField.ETH_SRC, MacAddress.of("01:23:45:67:89:ab"))
            .setExact(MatchField.ETH_DST, MacAddress.of("cd:ef:01:23:45:67"))
            .build()
      )
      .setDurationSec(1)
      .setDurationNsec(2)
      .setPriority(100)
      .setIdleTimeout(5)
      .setHardTimeout(10)
      .setCookie(U64.of(0x0123456789abcdefL))
      .setPacketCount(U64.of(10))
      .setByteCount(U64.of(1000))
      .setActions(
            ImmutableList.<OFAction>of(
                   factory.actions().output(OFPort.of(1), 0),
                   factory.actions().output(OFPort.of(2), 0)
                   )
      );;
        OFFlowStatsEntry flowStatsEntry = builder.build();
        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
        flowStatsEntry.writeTo(bb);
        byte[] written = new byte[bb.readableBytes()];
        bb.readBytes(written);

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

    @Test
    public void testRead() throws Exception {
        OFFlowStatsEntry.Builder builder = factory.buildFlowStatsEntry();
            builder
      .setTableId(TableId.of(3))
      .setMatch(
        factory.buildMatch()
            .setExact(MatchField.IN_PORT, OFPort.of(3))
            .setExact(MatchField.ETH_TYPE, EthType.IPv4)
            .setExact(MatchField.IPV4_SRC, IPv4Address.of(0xc0a8037f))
            .setExact(MatchField.IPV4_DST, IPv4Address.of(0xffffffff))
            .setExact(MatchField.ETH_SRC, MacAddress.of("01:23:45:67:89:ab"))
            .setExact(MatchField.ETH_DST, MacAddress.of("cd:ef:01:23:45:67"))
            .build()
      )
      .setDurationSec(1)
      .setDurationNsec(2)
      .setPriority(100)
      .setIdleTimeout(5)
      .setHardTimeout(10)
      .setCookie(U64.of(0x0123456789abcdefL))
      .setPacketCount(U64.of(10))
      .setByteCount(U64.of(1000))
      .setActions(
            ImmutableList.<OFAction>of(
                   factory.actions().output(OFPort.of(1), 0),
                   factory.actions().output(OFPort.of(2), 0)
                   )
      );;
        OFFlowStatsEntry flowStatsEntryBuilt = builder.build();

        ChannelBuffer input = ChannelBuffers.copiedBuffer(FLOW_STATS_ENTRY_SERIALIZED);

        // FIXME should invoke the overall reader once implemented
        OFFlowStatsEntry flowStatsEntryRead = OFFlowStatsEntryVer10.READER.readFrom(input);
        assertEquals(FLOW_STATS_ENTRY_SERIALIZED.length, input.readerIndex());

        assertEquals(flowStatsEntryBuilt, flowStatsEntryRead);
   }

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

       // FIXME should invoke the overall reader once implemented
       OFFlowStatsEntry flowStatsEntry = OFFlowStatsEntryVer10.READER.readFrom(input);
       assertEquals(FLOW_STATS_ENTRY_SERIALIZED.length, input.readerIndex());

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

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

}
