Improve the resiliency of the packet deserialization code.

Packet deserializers now check for malformed input while reading the byte
stream. Deserializers are re-implemented as functions that take a byte array
and return a packet object. The old IPacket.deserialize(...) methods have been
deprecated with the goal of eventually moving to immutable packet objects.
Unit tests have been implemented for all Deserializer functions.

ONOS-1589

Change-Id: I9073d5e6e7991e15d43830cfd810989256b71c56
diff --git a/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java b/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
new file mode 100644
index 0000000..ff48331
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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(1, dhcp.options.size());
+        assertEquals(hostNameOption, dhcp.options.get(0));
+    }
+
+}