You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2019/05/29 18:52:13 UTC

[qpid-proton-j] branch master updated (1ef7bbd -> 3294a40)

This is an automated email from the ASF dual-hosted git repository.

robbie pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-proton-j.git.


    from 1ef7bbd  PROTON-2043: update to apache parent pom v21
     new b666d6a  PROTON-2058: ensure small/array8 byte array encoding writes element count
     new 3294a40  PROTON-2057: fix small/array8 array encodings over 128 bytes

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/qpid/proton/codec/ArrayType.java    |  49 +-
 .../qpid/proton/codec/ArrayTypeCodecTest.java      | 803 ++++++++++++++++++++-
 2 files changed, 827 insertions(+), 25 deletions(-)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[qpid-proton-j] 01/02: PROTON-2058: ensure small/array8 byte array encoding writes element count

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

robbie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-proton-j.git

commit b666d6a165af7835bde12e0e41de2ca6109126d9
Author: Robbie Gemmell <ro...@apache.org>
AuthorDate: Wed May 29 14:19:00 2019 +0100

    PROTON-2058: ensure small/array8 byte array encoding writes element count
    
    Change split out from #34 by Ang Iongchun, plus tests from me.
---
 .../org/apache/qpid/proton/codec/ArrayType.java    |  1 +
 .../qpid/proton/codec/ArrayTypeCodecTest.java      | 81 +++++++++++++++++++++-
 2 files changed, 81 insertions(+), 1 deletion(-)

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 @@ public class ArrayType implements PrimitiveType<Object[]>
                                     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 @@ public class ArrayTypeCodecTest extends CodecTestSupport {
         // 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


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


[qpid-proton-j] 02/02: PROTON-2057: fix small/array8 array encodings over 128 bytes

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

robbie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-proton-j.git

commit 3294a4019af6ab4ec0f89fff11bd53a83d8e9788
Author: Ang Iongchun <an...@gmail.com>
AuthorDate: Wed May 29 14:31:03 2019 +0800

    PROTON-2057: fix small/array8 array encodings over 128 bytes
    
    Changes split out from #34 by Ang Iongchun, plus tests from me (Robbie).
    See also b666d6a165af7835bde12e0e41de2ca6109126d9.
    This closes #34.
---
 .../org/apache/qpid/proton/codec/ArrayType.java    |  48 +-
 .../qpid/proton/codec/ArrayTypeCodecTest.java      | 726 ++++++++++++++++++++-
 2 files changed, 748 insertions(+), 26 deletions(-)

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 418a251..7d4de49 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
@@ -697,10 +697,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final boolean[] a)
         {
             BooleanType.BooleanEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(boolean b : a)
@@ -713,10 +713,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final byte[] a)
         {
             ByteType.ByteEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(byte b : a)
@@ -729,10 +729,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final short[] a)
         {
             ShortType.ShortEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(short b : a)
@@ -745,10 +745,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final int[] a)
         {
             IntegerType.IntegerEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(int b : a)
@@ -761,10 +761,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final long[] a)
         {
             LongType.LongEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(long b : a)
@@ -777,10 +777,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final float[] a)
         {
             FloatType.FloatEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(float b : a)
@@ -793,10 +793,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final double[] a)
         {
             DoubleType.DoubleEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(double b : a)
@@ -809,10 +809,10 @@ public class ArrayType implements PrimitiveType<Object[]>
         public void writeValue(final char[] a)
         {
             CharacterType.CharacterEncoding underlyingEncoder = getUnderlyingEncoding(a);
-            byte encodedValueSize = (byte)(1 + underlyingEncoder.getConstructorSize() +
-                                    a.length * underlyingEncoder.getValueSize(null));
+            int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
+                                    a.length * underlyingEncoder.getValueSize(null);
             getEncoder().getBuffer().ensureRemaining(encodedValueSize);
-            getEncoder().writeRaw(encodedValueSize);
+            getEncoder().writeRaw((byte)encodedValueSize);
             getEncoder().writeRaw((byte)a.length);
             underlyingEncoder.writeConstructor();
             for(char 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 024534f..2b50723 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
@@ -308,8 +308,24 @@ public class ArrayTypeCodecTest extends CodecTestSupport {
     }
 
     @Test
-    public void testEncodeDecodeByteArray() throws IOException {
-        int count = 100;
+    public void testEncodeDecodeByteArray100() throws Throwable {
+        // byte array8 less than 128 bytes
+        doEncodeDecodeByteArrayTestImpl(100);
+    }
+
+    @Test
+    public void testEncodeDecodeByteArray192() throws Throwable {
+        // byte array8 greater than 128 bytes
+        doEncodeDecodeByteArrayTestImpl(192);
+    }
+
+    @Test
+    public void testEncodeDecodeByteArray384() throws Throwable {
+        // byte array32
+        doEncodeDecodeByteArrayTestImpl(384);
+    }
+
+    private void doEncodeDecodeByteArrayTestImpl(int count) throws Throwable {
         byte[] source = createPayloadArrayBytes(count);
 
         try {
@@ -380,4 +396,710 @@ public class ArrayTypeCodecTest extends CodecTestSupport {
 
         return payload;
     }
+
+    @Test
+    public void testEncodeDecodeBooleanArray100() throws Throwable {
+        // boolean array8 less than 128 bytes
+        doEncodeDecodeBooleanArrayTestImpl(100);
+    }
+
+    @Test
+    public void testEncodeDecodeBooleanArray192() throws Throwable {
+        // boolean array8 greater than 128 bytes
+        doEncodeDecodeBooleanArrayTestImpl(192);
+    }
+
+    @Test
+    public void testEncodeDecodeBooleanArray384() throws Throwable {
+        // boolean array32
+        doEncodeDecodeBooleanArrayTestImpl(384);
+    }
+
+    private void doEncodeDecodeBooleanArrayTestImpl(int count) throws Throwable {
+        boolean[] source = createPayloadArrayBooleans(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) 0x56); // 'boolean' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                byte booleanCode = (byte) (source[i] ? 0x01 : 0x00); //  0x01 true, 0x00 false.
+                expectedEncodingWrapper.put(booleanCode);
+            }
+
+            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(boolean.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (boolean[]) decoded);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static boolean[] createPayloadArrayBooleans(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        boolean[] payload = new boolean[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = rand.nextBoolean();
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeDecodeShortArray50() throws Throwable {
+        // short array8 less than 128 bytes
+        doEncodeDecodeShortArrayTestImpl(50);
+    }
+
+    @Test
+    public void testEncodeDecodeShortArray100() throws Throwable {
+        // short array8 greater than 128 bytes
+        doEncodeDecodeShortArrayTestImpl(100);
+    }
+
+    @Test
+    public void testEncodeDecodeShortArray384() throws Throwable {
+        // short array32
+        doEncodeDecodeShortArrayTestImpl(384);
+    }
+
+    private void doEncodeDecodeShortArrayTestImpl(int count) throws Throwable {
+        short[] source = createPayloadArrayShorts(count);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth = count < 127 ? 1 : 4; // less than 127, since each element is 2 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            int arrayPayloadSize =  encodingWidth + 1 + (count * 2); // variable width for element count + byte type descriptor + (number of elements * size)
+            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) 0x61); // 'short' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                expectedEncodingWrapper.putShort(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(short.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (short[]) decoded);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static short[] createPayloadArrayShorts(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        short[] payload = new short[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = (short) (64 + 1 + rand.nextInt(9));
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeDecodeIntArray10() throws Throwable {
+        // int array8 less than 128 bytes
+        doEncodeDecodeIntArrayTestImpl(10, false);
+    }
+
+    @Test
+    public void testEncodeDecodeIntArray50() throws Throwable {
+        // int array8 greater than 128 bytes
+        doEncodeDecodeIntArrayTestImpl(50, false);
+    }
+
+    @Test
+    public void testEncodeDecodeIntArray384() throws Throwable {
+        // int array32
+        doEncodeDecodeIntArrayTestImpl(384, false);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallIntArray100() throws Throwable {
+        // small-int array8 less than 128 bytes
+        doEncodeDecodeIntArrayTestImpl(100, true);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallIntArray192() throws Throwable {
+        // small-int array8 greater than 128 bytes
+        doEncodeDecodeIntArrayTestImpl(192, true);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallIntArray384() throws Throwable {
+        // small-int array32
+        doEncodeDecodeIntArrayTestImpl(384, true);
+    }
+
+    private void doEncodeDecodeIntArrayTestImpl(int count, boolean smallInt) throws Throwable {
+        int[] source = createPayloadArrayInts(count, smallInt);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth;
+            int elementWidth;
+            if(smallInt) {
+                elementWidth = 1;
+                encodingWidth = count < 254 ? 1 : 4; // less than 254 and not 256, since each element is 1 byte, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            } else {
+                elementWidth = 4;
+                encodingWidth = count < 63 ? 1 : 4; // less than 63, since each element is 4 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            }
+
+            int arrayPayloadSize =  encodingWidth + 1 + (count * elementWidth); // variable width for element count + byte type descriptor + (number of elements * size)
+            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
+            if(smallInt) {
+                expectedEncodingWrapper.put((byte) 0x54); // 'small int' type descriptor code
+            } else {
+                expectedEncodingWrapper.put((byte) 0x71); // 'int' type descriptor code
+            }
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                int j = source[i];
+                if(smallInt) {
+                    // Using put as small int is 1 byte
+                    assertTrue("Unexpected value: + j", j <= 127 && j >=-128);
+                    expectedEncodingWrapper.put((byte) j);
+                } else {
+                    expectedEncodingWrapper.putInt(j);
+                }
+            }
+
+            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(int.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (int[]) decoded);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static int[] createPayloadArrayInts(int length, boolean smallInt) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        int[] payload = new int[length];
+        for (int i = 0; i < length; i++) {
+            if(smallInt) {
+                payload[i] = 64 + 1 + rand.nextInt(9);
+            } else {
+                payload[i] = 128 + 1 + rand.nextInt(9);
+            }
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeDecodeLongArray10() throws Throwable {
+        // long array8 less than 128 bytes
+        doEncodeDecodeLongArrayTestImpl(10, false);
+    }
+
+    @Test
+    public void testEncodeDecodeLongArray25() throws Throwable {
+        // long array8 greater than 128 bytes
+        doEncodeDecodeLongArrayTestImpl(25, false);
+    }
+
+    @Test
+    public void testEncodeDecodeLongArray384() throws Throwable {
+        // long array32
+        doEncodeDecodeLongArrayTestImpl(384, false);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallLongArray100() throws Throwable {
+        // small-long array8 less than 128 bytes
+        doEncodeDecodeLongArrayTestImpl(100, true);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallLongArray192() throws Throwable {
+        // small-long array8 greater than 128 bytes
+        doEncodeDecodeLongArrayTestImpl(192, true);
+    }
+
+    @Test
+    public void testEncodeDecodeSmallLongArray384() throws Throwable {
+        // small-long array32
+        doEncodeDecodeLongArrayTestImpl(384, true);
+    }
+
+    private void doEncodeDecodeLongArrayTestImpl(int count, boolean smallLong) throws Throwable {
+        long[] source = createPayloadArrayLongs(count, smallLong);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth;
+            int elementWidth;
+            if(smallLong) {
+                elementWidth = 1;
+                encodingWidth = count < 254 ? 1 : 4; // less than 254 and not 256, since each element is 1 byte, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            } else {
+                elementWidth = 8;
+                encodingWidth = count < 31 ? 1 : 4; // less than 31, since each element is 8 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            }
+
+            int arrayPayloadSize =  encodingWidth + 1 + (count * elementWidth); // variable width for element count + byte type descriptor + (number of elements * size)
+            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
+            if(smallLong) {
+                expectedEncodingWrapper.put((byte) 0x55); // 'small long' type descriptor code
+            } else {
+                expectedEncodingWrapper.put((byte) 0x81); // 'long' type descriptor code
+            }
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                long j = source[i];
+                if(smallLong) {
+                    // Using put as small long is 1 byte
+                    assertTrue("Unexpected value: + j", j <= 127 && j >=-128);
+                    expectedEncodingWrapper.put((byte) j);
+                } else {
+                    expectedEncodingWrapper.putLong(j);
+                }
+            }
+
+            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(long.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (long[]) decoded);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static long[] createPayloadArrayLongs(int length, boolean smallLong) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        long[] payload = new long[length];
+        for (int i = 0; i < length; i++) {
+            if(smallLong) {
+                payload[i] = 64 + 1 + rand.nextInt(9);
+            } else {
+                payload[i] = 128 + 1 + rand.nextInt(9);
+            }
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeDecodeFloatArray25() throws Throwable {
+        // float array8 less than 128 bytes
+        doEncodeDecodeFloatArrayTestImpl(25);
+    }
+
+    @Test
+    public void testEncodeDecodeFloatArray50() throws Throwable {
+        // float array8 greater than 128 bytes
+        doEncodeDecodeFloatArrayTestImpl(50);
+    }
+
+    @Test
+    public void testEncodeDecodeFloatArray384() throws Throwable {
+        // float array32
+        doEncodeDecodeFloatArrayTestImpl(384);
+    }
+
+    private void doEncodeDecodeFloatArrayTestImpl(int count) throws Throwable {
+        float[] source = createPayloadArrayFloats(count);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth = count < 63 ? 1 : 4; // less than 63, since each element is 4 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            int arrayPayloadSize =  encodingWidth + 1 + (count * 4); // variable width for element count + byte type descriptor + (number of elements * size)
+            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) 0x72); // 'float' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                expectedEncodingWrapper.putFloat(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(float.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (float[]) decoded, 0.0F);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static float[] createPayloadArrayFloats(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        float[] payload = new float[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = 64 + 1 + rand.nextInt(9);
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeDecodeDoubleArray10() throws Throwable {
+        // double array8 less than 128 bytes
+        doEncodeDecodeDoubleArrayTestImpl(10);
+    }
+
+    @Test
+    public void testEncodeDecodeDoubleArray25() throws Throwable {
+        // double array8 greater than 128 bytes
+        doEncodeDecodeDoubleArrayTestImpl(25);
+    }
+
+    @Test
+    public void testEncodeDecodeDoubleArray384() throws Throwable {
+        // double array32
+        doEncodeDecodeDoubleArrayTestImpl(384);
+    }
+
+    private void doEncodeDecodeDoubleArrayTestImpl(int count) throws Throwable {
+        double[] source = createPayloadArrayDoubles(count);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth = count < 31 ? 1 : 4; // less than 31, since each element is 8 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            int arrayPayloadSize =  encodingWidth + 1 + (count * 8); // variable width for element count + byte type descriptor + (number of elements * size)
+            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) 0x82); // 'double' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                expectedEncodingWrapper.putDouble(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(double.class, decoded.getClass().getComponentType());
+
+            assertArrayEquals("Unexpected decoding", source, (double[]) decoded, 0.0F);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static double[] createPayloadArrayDoubles(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        double[] payload = new double[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = 64 + 1 + rand.nextInt(9);
+        }
+
+        return payload;
+    }
+
+    @Test
+    public void testEncodeCharArray25() throws Throwable {
+        // char array8 less than 128 bytes
+        doEncodeCharArrayTestImpl(25);
+    }
+
+    @Test
+    public void testEncodeCharArray50() throws Throwable {
+        // char array8 greater than 128 bytes
+        doEncodeCharArrayTestImpl(50);
+    }
+
+    @Test
+    public void testEncodeCharArray384() throws Throwable {
+        // char array32
+        doEncodeCharArrayTestImpl(384);
+    }
+
+    private void doEncodeCharArrayTestImpl(int count) throws Throwable {
+        char[] source = createPayloadArrayChars(count);
+
+        try {
+            assertEquals("Unexpected source array length", count, source.length);
+
+            int encodingWidth = count < 63 ? 1 : 4; // less than 63, since each element is 4 bytes, but we also need 1 byte for element count, and (in this case) 1 byte for primitive element type constructor.
+            int arrayPayloadSize =  encodingWidth + 1 + (count * 4); // variable width for element count + byte type descriptor + (number of elements * size)
+            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) 0x73); // 'char' type descriptor code
+
+            // Write the elements
+            for (int i = 0; i < count; i++) {
+                expectedEncodingWrapper.putInt(source[i]); //4 byte encoding
+            }
+
+            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);
+        }
+        catch (Throwable t) {
+            System.err.println("Error during test, source array: " + Arrays.toString(source));
+            throw t;
+        }
+    }
+
+    private static char[] createPayloadArrayChars(int length) {
+        Random rand = new Random(System.currentTimeMillis());
+
+        char[] payload = new char[length];
+        for (int i = 0; i < length; i++) {
+            payload[i] = (char) (64 + 1 + rand.nextInt(9));
+        }
+
+        return payload;
+    }
+
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org