/*
 * Copyright 2014-2015 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.onlab.packet.ipv6;

import org.junit.BeforeClass;
import org.junit.Test;
import org.onlab.packet.Data;
import org.onlab.packet.UDP;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

/**
 * Tests for class {@link Authentication}.
 */
public class AuthenticationTest {
    private static Data data;
    private static UDP udp;
    private static byte[] icv = {
            (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44
    };
    private static byte[] bytePacket;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        data = new Data();
        data.setData("testSerialize".getBytes());
        udp = new UDP();
        udp.setPayload(data);

        byte[] bytePayload = udp.serialize();
        byte[] byteHeader = {
                (byte) 0x11, (byte) 0x02, (byte) 0x00, (byte) 0x00,
                (byte) 0x13, (byte) 0x57, (byte) 0x24, (byte) 0x68,
                (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0x00,
                (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44
        };
        bytePacket = new byte[byteHeader.length + bytePayload.length];
        System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length);
        System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
    }

    /**
     * Tests serialize and setters.
     */
    @Test
    public void testSerialize() {
        Authentication auth = new Authentication();
        auth.setNextHeader((byte) 0x11);
        auth.setPayloadLength((byte) 0x02);
        auth.setSecurityParamIndex(0x13572468);
        auth.setSequence(0xffff00);
        auth.setIngegrityCheck(icv);
        auth.setPayload(udp);

        assertArrayEquals(auth.serialize(), bytePacket);
    }

    /**
     * Tests deserialize and getters.
     */
    @Test
    public void testDeserialize() {
        Authentication auth = new Authentication();
        auth.deserialize(bytePacket, 0, bytePacket.length);

        assertThat(auth.getNextHeader(), is((byte) 0x11));
        assertThat(auth.getPayloadLength(), is((byte) 0x02));
        assertThat(auth.getSecurityParamIndex(), is(0x13572468));
        assertThat(auth.getSequence(), is(0xffff00));
        assertArrayEquals(auth.getIntegrityCheck(), icv);
    }

    /**
     * Tests comparator.
     */
    @Test
    public void testEqual() {
        Authentication auth1 = new Authentication();
        auth1.setNextHeader((byte) 0x11);
        auth1.setPayloadLength((byte) 0x02);
        auth1.setSecurityParamIndex(0x13572468);
        auth1.setSequence(0xffff00);
        auth1.setIngegrityCheck(icv);

        Authentication auth2 = new Authentication();
        auth2.setNextHeader((byte) 0x11);
        auth2.setPayloadLength((byte) 0x02);
        auth2.setSecurityParamIndex(0x13572467);
        auth2.setSequence(0xffff00);
        auth2.setIngegrityCheck(icv);

        assertTrue(auth1.equals(auth1));
        assertFalse(auth1.equals(auth2));
    }
}
