/*
 * Copyright 2016 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.ospf.protocol.ospfpacket.types;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.util.OspfPacketType;

import java.util.List;
import java.util.Vector;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

/**
 * Unit test class for OspfRouterId.
 */
public class DdPacketTest {

    private byte[] packet;
    private byte[] result2;
    private DdPacket ddPacket;
    private Vector<LsaHeader> lsaHeaderList = new Vector<LsaHeader>();
    private int result;
    private long result1;
    private OpaqueLsaHeader opqueHeader;
    private OpaqueLsaHeader opqueHeader1;
    private List<LsaHeader> header;
    private OspfPacketHeader ospfPacketHeader;
    private ChannelBuffer channelBuffer;
    private LsaHeader lsaHeader;
    private long result3;
    private OspfPacketType ospfPacketType;

    @Before
    public void setUp() throws Exception {
        ddPacket = new DdPacket();
        ddPacket.setAuthType(1);
        ddPacket.setOspftype(2);
        ddPacket.setRouterId(Ip4Address.valueOf("10.226.165.164"));
        ddPacket.setAreaId(Ip4Address.valueOf("10.226.165.100"));
        ddPacket.setChecksum(201);
        ddPacket.setAuthentication(2);
        ddPacket.setOspfPacLength(48);
        ddPacket.setOspfVer(2);
    }

    @After
    public void tearDown() throws Exception {
        ddPacket = null;
        lsaHeaderList.clear();
        opqueHeader = null;
        opqueHeader1 = null;
        header = null;
        ospfPacketHeader = null;
        channelBuffer = null;
        lsaHeader = null;
        ospfPacketType = null;
    }

    /**
     * Tests isOpaqueCapable() getter method.
     */
    @Test
    public void testIsOpaqueCapable() throws Exception {
        ddPacket.setIsOpaqueCapable(true);
        assertThat(ddPacket.isOpaqueCapable(), is(true));
    }

    /**
     * Tests isOpaqueCapable() setter method.
     */
    @Test
    public void testSetIsOpaqueCapable() throws Exception {
        ddPacket.setIsOpaqueCapable(true);
        assertThat(ddPacket.isOpaqueCapable(), is(true));
    }

    /**
     * Tests ims() getter method.
     */
    @Test
    public void testGetIms() throws Exception {
        ddPacket.setIms(1);
        result = ddPacket.ims();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(1));
    }

    /**
     * Tests ims() setter method.
     */
    @Test
    public void testSetIms() throws Exception {
        ddPacket.setIms(1);
        result = ddPacket.ims();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(1));
    }

    /**
     * Tests isMaster() getter method.
     */
    @Test
    public void testGetIsMaster() throws Exception {
        ddPacket.setIsMaster(2);
        result = ddPacket.isMaster();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(2));
    }

    /**
     * Tests isMaster() setter method.
     */
    @Test
    public void testSetIsMaster() throws Exception {
        ddPacket.setIsMaster(2);
        result = ddPacket.isMaster();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(2));
    }

    /**
     * Tests isInitialize() getter method.
     */
    @Test
    public void testGetIsInitialize() throws Exception {
        ddPacket.setIsInitialize(3);
        result = ddPacket.isInitialize();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(3));
    }

    /**
     * Tests isInitialize() setter method.
     */
    @Test
    public void testSetIsInitialize() throws Exception {
        ddPacket.setIsInitialize(3);
        int result = ddPacket.isInitialize();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(3));
    }

    /**
     * Tests isMore() getter method.
     */
    @Test
    public void testGetIsMore() throws Exception {
        ddPacket.setIsMore(4);
        result = ddPacket.isMore();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(4));
    }

    /**
     * Tests isMore() setter method.
     */
    @Test
    public void testSetIsMore() throws Exception {
        ddPacket.setIsMore(4);
        int result = ddPacket.isMore();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(4));
    }

    /**
     * Tests imtu() getter method.
     */
    @Test
    public void testGetImtu() throws Exception {
        ddPacket.setImtu(5);
        result = ddPacket.imtu();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(5));
    }

    /**
     * Tests imtu() setter method.
     */
    @Test
    public void testSetImtu() throws Exception {
        ddPacket.setImtu(5);
        result = ddPacket.imtu();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(5));
    }

    /**
     * Tests options() getter method.
     */
    @Test
    public void testGetOptions() throws Exception {
        ddPacket.setOptions(2);
        result = ddPacket.options();
        assertThat(result, is(notNullValue()));
        assertThat(result, is(2));
    }

    /**
     * Tests options() setter method.
     */
    @Test
    public void testSetOptions() throws Exception {
        ddPacket.setOptions(2);
        result = ddPacket.options();
        Assert.assertNotNull(result);
        Assert.assertEquals(2, result);
    }

    /**
     * Tests sequenceNo() getter method.
     */
    @Test
    public void testGetSequenceno() throws Exception {
        ddPacket.setSequenceNo(2020);
        result1 = ddPacket.sequenceNo();
        assertThat(result1, is(notNullValue()));
        assertThat(result1, is(2020L));
    }

    /**
     * Tests sequenceNo() setter method.
     */
    @Test
    public void testSetSequenceno() throws Exception {
        ddPacket.setSequenceNo(2020);
        result3 = ddPacket.sequenceNo();
        assertThat(result3, is(notNullValue()));
        assertThat(result3, is(2020L));
    }

    /**
     * Tests getLsaHeaderList() getter method.
     */
    @Test
    public void testGetLsaHeaderList() throws Exception {
        ddPacket.addLsaHeader(createLsaHeader());
        opqueHeader = new OpaqueLsaHeader();
        opqueHeader.setLsType(9);
        opqueHeader.setLsPacketLen(48);
        opqueHeader.setLsCheckSum(10);
        opqueHeader.setAge(4);
        opqueHeader.setOpaqueId(9);
        opqueHeader.setOpaqueType(9);
        opqueHeader.setLsSequenceNo(250);
        opqueHeader.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader.setOptions(2);
        ddPacket.setIsOpaqueCapable(true);
        ddPacket.addLsaHeader(opqueHeader);
        opqueHeader1 = new OpaqueLsaHeader();
        opqueHeader1.setLsType(10);
        opqueHeader1.setLsPacketLen(48);
        opqueHeader1.setLsCheckSum(10);
        opqueHeader1.setAge(4);
        opqueHeader1.setOpaqueId(9);
        opqueHeader1.setOpaqueType(9);
        opqueHeader1.setLsSequenceNo(250);
        opqueHeader1.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader1.setOptions(66);
        ddPacket.addLsaHeader(opqueHeader1);
        header = ddPacket.getLsaHeaderList();
        assertThat(header, is(notNullValue()));
    }

    /**
     * Tests getLsaHeaderList() setter method.
     */
    @Test
    public void testSetLsaHeaderList() throws Exception {
        ddPacket.addLsaHeader(createLsaHeader());
        opqueHeader = new OpaqueLsaHeader();
        opqueHeader.setLsType(9);
        opqueHeader.setLsPacketLen(48);
        opqueHeader.setLsCheckSum(10);
        opqueHeader.setAge(4);
        opqueHeader.setOpaqueId(9);
        opqueHeader.setOpaqueType(9);
        opqueHeader.setLsSequenceNo(250);
        opqueHeader.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader.setOptions(66);
        ddPacket.addLsaHeader(opqueHeader);
        opqueHeader1 = new OpaqueLsaHeader();
        opqueHeader1.setLsType(10);
        opqueHeader1.setLsPacketLen(48);
        opqueHeader1.setLsCheckSum(10);
        opqueHeader1.setAge(4);
        opqueHeader1.setOpaqueId(9);
        opqueHeader1.setOpaqueType(9);
        opqueHeader1.setLsSequenceNo(250);
        opqueHeader1.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader1.setOptions(2);
        ddPacket.addLsaHeader(opqueHeader1);
        header = ddPacket.getLsaHeaderList();
        assertThat(header.contains(createLsaHeader()), is(true));
    }

    /**
     * Tests addLsaHeader() method.
     */
    @Test
    public void testAddLsaHeader() throws Exception {
        ddPacket.addLsaHeader(createLsaHeader());
        assertThat(ddPacket, is(notNullValue()));
    }

    /**
     * Tests ospfMessageType() getter method.
     */
    @Test
    public void testGetOspfMessageType() throws Exception {
        ospfPacketType = ddPacket.ospfMessageType();
        assertThat(ospfPacketType, is(notNullValue()));
        assertThat(ospfPacketType, is(OspfPacketType.DD));
    }

    /**
     * Tests readFrom() method.
     */
    @Test
    public void testReadFrom() throws Exception {
        ospfPacketHeader = new OspfPacketHeader();
        ospfPacketHeader.setAreaId(Ip4Address.valueOf("1.1.1.1"));
        ospfPacketHeader.setAuthentication(0);
        ospfPacketHeader.setAuthType(0);
        ospfPacketHeader.setChecksum(12345);
        ospfPacketHeader.setDestinationIp(Ip4Address.valueOf("10.10.10.10"));
        ospfPacketHeader.setOspfPacLength(56);
        ospfPacketHeader.setOspftype(2);
        ospfPacketHeader.setOspfVer(2);
        ospfPacketHeader.setRouterId(Ip4Address.valueOf("2.2.2.2"));
        ospfPacketHeader.setSourceIp(Ip4Address.valueOf("3.3.3.3"));
        ddPacket.setIsOpaqueCapable(true);
        ddPacket.setOptions(66);
        ddPacket = new DdPacket(ospfPacketHeader);
        packet = createByteForDdPacket();
        channelBuffer = ChannelBuffers.copiedBuffer(packet);
        ddPacket.readFrom(channelBuffer);
        assertThat(ddPacket, is(notNullValue()));
        assertThat(ddPacket.ospfMessageType(), is(OspfPacketType.DD));
    }

    /**
     * Tests asBytes() method.
     */
    @Test
    public void testAsBytes() throws Exception {
        result2 = ddPacket.asBytes();
        assertThat(result2, is(notNullValue()));
    }

    /**
     * Tests getDdHeaderAsByteArray() method.
     */
    @Test
    public void testGetDdHeaderAsByteArray() throws Exception {
        opqueHeader = new OpaqueLsaHeader();
        opqueHeader.setLsType(9);
        opqueHeader.setLsPacketLen(48);
        opqueHeader.setLsCheckSum(10);
        opqueHeader.setAge(4);
        opqueHeader.setOpaqueId(9);
        opqueHeader.setOpaqueType(9);
        opqueHeader.setLsSequenceNo(250);
        opqueHeader.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader.setOptions(66);
        ddPacket.addLsaHeader(opqueHeader);
        opqueHeader1 = new OpaqueLsaHeader();
        opqueHeader1.setLsType(10);
        opqueHeader1.setLsPacketLen(48);
        opqueHeader1.setLsCheckSum(10);
        opqueHeader1.setAge(4);
        opqueHeader1.setOpaqueId(9);
        opqueHeader1.setOpaqueType(9);
        opqueHeader1.setLsSequenceNo(250);
        opqueHeader1.setAdvertisingRouter(Ip4Address.valueOf("100.226.165.165"));
        opqueHeader1.setOptions(2);
        ddPacket.addLsaHeader(opqueHeader1);
        result2 = ddPacket.getDdHeaderAsByteArray();
        assertThat(result2, is(notNullValue()));
    }

    /**
     * Tests getDdBodyAsByteArray() method.
     */
    @Test
    public void testGetDdBodyAsByteArray() throws Exception {
        lsaHeader = createLsaHeader();
        ddPacket.addLsaHeader(lsaHeader);
        result2 = ddPacket.getDdBodyAsByteArray();
        assertThat(result2, is(notNullValue()));
    }

    /**
     * Tests to string method.
     */
    @Test
    public void testToString() throws Exception {
        assertThat(ddPacket.toString(), is(notNullValue()));
    }

    /**
     * Utility method used by junit methods.
     */
    private LsaHeader createLsaHeader() {
        lsaHeader = new LsaHeader();
        lsaHeader.setAge(10);
        lsaHeader.setLinkStateId("10.226.165.164");
        lsaHeader.setLsCheckSum(222);
        lsaHeader.setLsPacketLen(48);
        lsaHeader.setLsSequenceNo(2020);
        lsaHeader.setLsType(2);
        lsaHeader.setOptions(2);
        lsaHeader.setAdvertisingRouter(Ip4Address.valueOf("10.226.165.165"));
        return lsaHeader;
    }

    /**
     * Utility method used by junit methods.
     */
    private byte[] createByteForDdPacket() {
        byte[] ddPacket = {5, -36, 66, 1, 65, 119, -87, 126, 0, 23, 2, 1, 10, 10,
                10, 10, 10, 10, 10, 10, -128, 0, 0, 6, -69, 26, 0, 36};

        return ddPacket;
    }
}