Fix for Bug 8005. Parsing Sub Tlv for multiple neighbors

Change-Id: I32c86793db14698280199dd24f9a0e3731fb9771
(cherry picked from commit 8bfea5ec60caa14aa61b4efba1758f0394be8a4e)
diff --git a/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIs.java b/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIs.java
index 41265d1..b248dec 100644
--- a/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIs.java
+++ b/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIs.java
@@ -102,7 +102,11 @@
         this.setMetric(channelBuffer.readUnsignedMedium());
         int nTlvPresent = channelBuffer.readByte();
         if (nTlvPresent > 0) {
-            while (channelBuffer.readableBytes() > IsisUtil.TWO_BYTES) {
+            /* ntlvPresent=0 infers that all Sub TLVs,
+               for a particular neighbor,
+               have been parsed and the loop has to be terminated
+             */
+            while (channelBuffer.readableBytes() > IsisUtil.TWO_BYTES && nTlvPresent > 0) {
                 TlvHeader tlvHeader = new TlvHeader();
                 tlvHeader.setTlvType(channelBuffer.readByte());
                 tlvHeader.setTlvLength(channelBuffer.readByte());
@@ -115,10 +119,18 @@
                         if (subTlv != null) {
                             this.addSubTlv(subTlv);
                         }
+                        /*As one Sub TLV is parsed, its length is
+                        subtracted from total length to be read
+                         */
+                        nTlvPresent = nTlvPresent - (tlvLength + IsisUtil.TWO_BYTES);
                     }
                 } else {
                     if (channelBuffer.readableBytes() >= tlvLength) {
                         channelBuffer.readBytes(tlvLength);
+                        /*As one Sub TLV is parsed, its length is
+                        subtracted from total length to be read
+                         */
+                        nTlvPresent = nTlvPresent - (tlvLength + IsisUtil.TWO_BYTES);
                     }
                 }
             }
@@ -151,4 +163,4 @@
                 .add("teSubTlv", teSubTlv)
                 .toString();
     }
-}
\ No newline at end of file
+}
diff --git a/protocols/isis/isisio/src/test/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIsTest.java b/protocols/isis/isisio/src/test/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIsTest.java
new file mode 100644
index 0000000..72c93c0
--- /dev/null
+++ b/protocols/isis/isisio/src/test/java/org/onosproject/isis/io/isispacket/tlv/NeighborForExtendedIsTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.isis.io.isispacket.tlv;
+
+import org.easymock.EasyMock;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Unit test class for NeighborForExtendedIs.
+ *
+ * Here we have passed a byte array containing data for 2 neighbors along with
+ * their Sub TLVs. The test case checks whether the code is able to parse the Sub TLVs
+ * for each neighbor or not. Along with this it also checks for neighbor id and metric
+ * assigned to each neighbor.
+ */
+public class NeighborForExtendedIsTest {
+    private final byte[] tlv = {
+            (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x0a, (byte) 0x3f, (byte) 0x06, (byte) 0x04, (byte) 0x14, (byte) 0x14, (byte) 0x14,
+            (byte) 0xbe, (byte) 0x08, (byte) 0x04, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xd1, (byte) 0x09,
+            (byte) 0x04, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x0a, (byte) 0x04, (byte) 0x49,
+            (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x0b, (byte) 0x20, (byte) 0x49, (byte) 0x98, (byte) 0x96,
+            (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96,
+            (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96,
+            (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96,
+            (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x12, (byte) 0x03, (byte) 0x00,
+            (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x01,
+            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0a, (byte) 0x3f, (byte) 0x06, (byte) 0x04, (byte) 0x1e,
+            (byte) 0x1e, (byte) 0x1e, (byte) 0xce, (byte) 0x08, (byte) 0x04, (byte) 0x1e, (byte) 0x1e, (byte) 0x1e,
+            (byte) 0xa9, (byte) 0x09, (byte) 0x04, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x0a,
+            (byte) 0x04, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x0b, (byte) 0x20, (byte) 0x49,
+            (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49,
+            (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49,
+            (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49,
+            (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x49, (byte) 0x98, (byte) 0x96, (byte) 0x80, (byte) 0x12,
+            (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00
+    };
+
+    //tlv2 bytes are for testing the else part of readFrom() method
+    private final byte[] tlv2 = {
+            (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x10, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+            (byte) 0x00, (byte) 0x0a, (byte) 0x06, (byte) 0x2D, (byte) 0x04, (byte) 0x14, (byte) 0x14, (byte) 0x14,
+            (byte) 0xbe, (byte) 0x2D, (byte) 0xd1, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0xd1, (byte) 0x09
+    };
+    private final String neighborId1 = "1000.1000.1002.00";
+    private final String neighborId2 = "1000.1000.1001.00";
+    private final int metric = 10;
+    private final int subTlvLength = 6;
+    private NeighborForExtendedIs neighborForExtendedIs;
+    private ChannelBuffer channelBuffer;
+
+    @Before
+    public void setUp() throws Exception {
+        neighborForExtendedIs = new NeighborForExtendedIs();
+        channelBuffer = EasyMock.createMock(ChannelBuffer.class);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        neighborForExtendedIs = null;
+        channelBuffer = null;
+    }
+
+    /**
+     * Tests readFrom() method.
+     */
+    @Test
+    public void testReadFrom() throws Exception {
+        channelBuffer = ChannelBuffers.copiedBuffer(tlv);
+        neighborForExtendedIs.readFrom(channelBuffer);
+        assertThat(neighborForExtendedIs.teSubTlv().size(), is(subTlvLength));
+        assertThat(neighborForExtendedIs.neighborId(), is(neighborId1));
+        assertThat(neighborForExtendedIs.metric(), is(metric));
+
+        neighborForExtendedIs = new NeighborForExtendedIs();
+        neighborForExtendedIs.readFrom(channelBuffer);
+        assertThat(neighborForExtendedIs.teSubTlv().size(), is(subTlvLength));
+        assertThat(neighborForExtendedIs.neighborId(), is(neighborId2));
+        assertThat(neighborForExtendedIs.metric(), is(metric));
+    }
+
+    /**
+     * Tests else condition of readFrom() method.
+     */
+    @Test
+    public void testElsePartOfReadFrom() throws Exception {
+        channelBuffer = ChannelBuffers.copiedBuffer(tlv2);
+        neighborForExtendedIs = new NeighborForExtendedIs();
+        neighborForExtendedIs.readFrom(channelBuffer);
+        assertThat(neighborForExtendedIs.neighborId(), is(neighborId1));
+        assertThat(neighborForExtendedIs.metric(), is(metric));
+    }
+}