/*
 * Copyright 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;

import com.google.common.base.Charsets;
import org.junit.Before;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.util.Arrays;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Unit tests for DHCP class.
 */
public class DhcpTest {

    private Deserializer<DHCP> deserializer = DHCP.deserializer();

    private byte opCode = 1;
    private byte hardwareType = 1;
    private byte hardwareAddressLength = Ethernet.DATALAYER_ADDRESS_LENGTH;
    private byte hops = 0;
    private int transactionId = 0x2ed4eb50;
    private short seconds = 0;
    private short flags = 0;
    private int clientIpAddress = 1;
    private int yourIpAddress = 2;
    private int serverIpAddress = 3;
    private int gatewayIpAddress = 4;
    private byte[] clientHardwareAddress = MacAddress.valueOf(500).toBytes();
    private String serverName = "test-server";
    private String bootFileName = "test-file";

    private String hostName = "test-host";
    private DHCPOption hostNameOption = new DHCPOption();

    private byte[] byteHeader;

    @Before
    public void setUp() {
        hostNameOption.setCode((byte) 55);
        hostNameOption.setLength((byte) hostName.length());
        hostNameOption.setData(hostName.getBytes(Charsets.US_ASCII));

        // Packet length is the fixed DHCP header plus option length plus an
        // extra byte to indicate 'end of options'.
        ByteBuffer bb = ByteBuffer.allocate(DHCP.MIN_HEADER_LENGTH +
                                                    2 + hostNameOption.getLength()  + 1);

        bb.put(opCode);
        bb.put(hardwareType);
        bb.put(hardwareAddressLength);
        bb.put(hops);
        bb.putInt(transactionId);
        bb.putShort(seconds);
        bb.putShort(flags);
        bb.putInt(clientIpAddress);
        bb.putInt(yourIpAddress);
        bb.putInt(serverIpAddress);
        bb.putInt(gatewayIpAddress);
        bb.put(clientHardwareAddress);

        // need 16 bytes of zeros to pad out the client hardware address field
        bb.put(new byte[16 - hardwareAddressLength]);

        // Put server name and pad out to 64 bytes
        bb.put(serverName.getBytes(Charsets.US_ASCII));
        bb.put(new byte[64 - serverName.length()]);

        // Put boot file name and pad out to 128 bytes
        bb.put(bootFileName.getBytes(Charsets.US_ASCII));
        bb.put(new byte[128 - bootFileName.length()]);

        // Magic cookie
        bb.put("DHCP".getBytes(Charsets.US_ASCII));

        bb.put(hostNameOption.getCode());
        bb.put(hostNameOption.getLength());
        bb.put(hostNameOption.getData());

        // End of options marker
        bb.put((byte) (0xff & 255));

        byteHeader = bb.array();
    }

    @Test
    public void testDeserializeBadInput() throws Exception {
        PacketTestUtils.testDeserializeBadInput(deserializer);
    }

    @Test
    public void testDeserializeTruncated() throws Exception {
        PacketTestUtils.testDeserializeTruncated(deserializer, byteHeader);
    }

    @Test
    public void testDeserialize() throws Exception {
        DHCP dhcp = deserializer.deserialize(byteHeader, 0, byteHeader.length);

        assertEquals(opCode, dhcp.opCode);
        assertEquals(hardwareType, dhcp.hardwareType);
        assertEquals(hardwareAddressLength, dhcp.hardwareAddressLength);
        assertEquals(hops, dhcp.hops);
        assertEquals(transactionId, dhcp.transactionId);
        assertEquals(seconds, dhcp.seconds);
        assertEquals(flags, dhcp.flags);
        assertEquals(clientIpAddress, dhcp.clientIPAddress);
        assertEquals(yourIpAddress, dhcp.yourIPAddress);
        assertEquals(serverIpAddress, dhcp.serverIPAddress);
        assertEquals(gatewayIpAddress, dhcp.gatewayIPAddress);
        assertTrue(Arrays.equals(clientHardwareAddress, dhcp.clientHardwareAddress));

        assertEquals(serverName, dhcp.serverName);
        assertEquals(bootFileName, dhcp.bootFileName);
        assertEquals(2, dhcp.options.size());
        assertEquals(hostNameOption, dhcp.options.get(0));
    }

}
