PROTON-2058: ensure small/array8 byte array encoding writes element count

Change split out from #34 by Ang Iongchun, plus tests from me.
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java b/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
index 06ece52..418a251 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/codec/ArrayType.java
@@ -717,6 +717,7 @@
                                     a.length * underlyingEncoder.getValueSize(null));
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
             getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(byte b : a)
             {
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
index ea5045b..024534f 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/ArrayTypeCodecTest.java
@@ -16,15 +16,20 @@
  */
 package org.apache.qpid.proton.codec;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.UUID;
 
 import org.apache.qpid.proton.amqp.Symbol;
@@ -301,4 +306,78 @@
         // Check that the ArrayType tries to reserve space, actual encoding size not computed here.
         Mockito.verify(spy).ensureRemaining(Mockito.anyInt());
     }
-}
+
+    @Test
+    public void testEncodeDecodeByteArray() throws IOException {
+        int count = 100;
+        byte[] source = createPayloadArrayBytes(count);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth = count < 254 ? 1 : 4; // less than 254 and not 256, since we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            int arrayPayloadSize =  encodingWidth + 1 + count; // variable width for element count + byte type descriptor + number of elements
+            int expectedEncodedArraySize = 1 + encodingWidth + arrayPayloadSize; // array type code +  variable width for array size + other encoded payload
+            byte[] expectedEncoding = new byte[expectedEncodedArraySize];
+            ByteBuffer expectedEncodingWrapper = ByteBuffer.wrap(expectedEncoding);
+
+            // Write the array encoding code, array size, and element count
+            if(count < 254) {
+                expectedEncodingWrapper.put((byte) 0xE0); // 'array8' type descriptor code
+                expectedEncodingWrapper.put((byte) arrayPayloadSize);
+                expectedEncodingWrapper.put((byte) count);
+            } else {
+                expectedEncodingWrapper.put((byte) 0xF0); // 'array32' type descriptor code
+                expectedEncodingWrapper.putInt(arrayPayloadSize);
+                expectedEncodingWrapper.putInt(count);
+            }
+
+            // Write the type descriptor
+            expectedEncodingWrapper.put((byte) 0x51); // 'byte' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                expectedEncodingWrapper.put(source[i]);
+            }
+
+            assertFalse("Should have filled expected encoding array", expectedEncodingWrapper.hasRemaining());
+
+            // Now verify against the actual encoding of the array
+            assertEquals("Unexpected buffer position", 0, buffer.position());
+            encoder.writeArray(source);
+            assertEquals("Unexpected encoded payload length", expectedEncodedArraySize, buffer.position());
+
+            byte[] actualEncoding = new byte[expectedEncodedArraySize];
+            buffer.flip();
+            buffer.get(actualEncoding);
+            assertFalse("Should have drained the encoder buffer contents", buffer.hasRemaining());
+
+            assertArrayEquals("Unexpected actual array encoding", expectedEncoding, actualEncoding);
+
+            // Now verify against the decoding
+            buffer.flip();
+            Object decoded = decoder.readObject();
+            assertNotNull(decoded);
+            assertTrue(decoded.getClass().isArray());
+            assertTrue(decoded.getClass().getComponentType().isPrimitive());
+            assertEquals(byte.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (byte[]) decoded);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static byte[] createPayloadArrayBytes(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        byte[] payload = new byte[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = (byte) (64 + 1 + rand.nextInt(9));
+        }
+
+        return payload;
+    }
+}
\ No newline at end of file