http://git-wip-us.apache.org/repos/asf/qpid-proton-j/blob/ec554715/proton-j/src/test/java/org/apache/qpid/proton/codec/CompositeReadableBufferTest.java ---------------------------------------------------------------------- diff --git a/proton-j/src/test/java/org/apache/qpid/proton/codec/CompositeReadableBufferTest.java b/proton-j/src/test/java/org/apache/qpid/proton/codec/CompositeReadableBufferTest.java new file mode 100644 index 0000000..7ed5c3e --- /dev/null +++ b/proton-j/src/test/java/org/apache/qpid/proton/codec/CompositeReadableBufferTest.java @@ -0,0 +1,2305 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.qpid.proton.codec; + +import static org.junit.Assert.*; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.InvalidMarkException; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.StandardCharsets; + +import org.junit.Test; + +/** + * Test for API of the CompositeReadableBuffer class. + */ +public class CompositeReadableBufferTest { + + //----- Test newly create buffer behaviors -------------------------------// + + @Test + public void testDefaultCtor() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + assertFalse(buffer.hasArray()); + assertEquals(0, buffer.remaining()); + assertEquals(0, buffer.position()); + assertEquals(0, buffer.limit()); + } + + //----- Test limit handling ----------------------------------------------// + + @Test + public void testLimitAppliesUpdatesToPositionAndMark() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + buffer.position(10); + buffer.mark(); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + assertEquals(10, buffer.position()); + + buffer.limit(5); + assertEquals(5, buffer.limit()); + assertEquals(5, buffer.position()); + + try { + buffer.reset(); + fail("Should throw a InvalidMarkException"); + } catch (InvalidMarkException e) {} + + buffer.mark(); + buffer.limit(10); + buffer.position(10); + + try { + buffer.reset(); + } catch (InvalidMarkException e) { + fail("Should not throw a InvalidMarkException"); + } + + assertEquals(5, buffer.position()); + } + + @Test + public void testLimitAppliesUpdatesToPositionAndMarkWithTwoArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4}).append(new byte[] { 5, 6, 7, 8, 9 }); + buffer.position(10); + buffer.mark(); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + assertEquals(10, buffer.position()); + + buffer.limit(5); + assertEquals(5, buffer.limit()); + assertEquals(5, buffer.position()); + + try { + buffer.reset(); + fail("Should throw a InvalidMarkException"); + } catch (InvalidMarkException e) {} + + buffer.mark(); + buffer.limit(10); + buffer.position(10); + + try { + buffer.reset(); + } catch (InvalidMarkException e) { + fail("Should not throw a InvalidMarkException"); + } + + assertEquals(5, buffer.position()); + } + + @Test + public void testLimitWithOneArrayAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + + buffer.limit(5); + assertEquals(5, buffer.limit()); + + buffer.limit(6); + assertEquals(6, buffer.limit()); + + try { + buffer.limit(11); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + } + + @Test + public void testLimitWithTwoArraysAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4}).append(new byte[] { 5, 6, 7, 8, 9 }); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + + buffer.limit(5); + assertEquals(5, buffer.limit()); + + buffer.limit(6); + assertEquals(6, buffer.limit()); + + try { + buffer.limit(11); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + } + + @Test + public void testLimitEnforcesPreconditions() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + // test with nothing appended. + try { + buffer.limit(2); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + try { + buffer.limit(-1); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + // Test with something appended + buffer.append(new byte[] { 127 }); + + try { + buffer.limit(2); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + try { + buffer.limit(-1); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + } + + //----- Test position handling -------------------------------------------// + + @Test + public void testPositionWithOneArrayAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + assertEquals(0, buffer.position()); + + buffer.position(5); + assertEquals(5, buffer.position()); + + buffer.position(6); + assertEquals(6, buffer.position()); + + buffer.position(10); + assertEquals(10, buffer.position()); + + try { + buffer.position(11); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + buffer.mark(); + + buffer.position(0); + assertEquals(0, buffer.position()); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException ime) {} + } + + @Test + public void testPositionWithTwoArraysAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4}).append(new byte[] { 5, 6, 7, 8, 9 }); + + assertEquals(10, buffer.capacity()); + assertEquals(10, buffer.limit()); + + buffer.position(5); + assertEquals(5, buffer.position()); + + buffer.position(6); + assertEquals(6, buffer.position()); + + buffer.position(10); + assertEquals(10, buffer.position()); + + try { + buffer.position(11); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + buffer.position(0); + assertEquals(0, buffer.position()); + } + + @Test + public void testPositionEnforcesPreconditions() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + // test with nothing appended. + try { + buffer.position(2); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + try { + buffer.position(-1); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + // Test with something appended + buffer.append(new byte[] { 127 }); + + try { + buffer.position(2); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + + try { + buffer.position(-1); + fail("Should throw a IllegalArgumentException"); + } catch (IllegalArgumentException e) {} + } + + //----- Test buffer get methods ------------------------------------------// + + @Test + public void testGetByteWithNothingAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.get(); + fail("Should throw a BufferUnderflowException"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetByteWithOneArrayWithOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 127 }); + + assertEquals(1, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(127, buffer.get()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(1, buffer.position()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetByteWithOneArrayWithManyElements() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + + assertEquals(10, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + for (int i = 0; i < 10; ++i) { + assertEquals(i, buffer.get()); + assertEquals(i + 1, buffer.position()); + } + + assertEquals(0, buffer.remaining()); + assertEquals(10, buffer.position()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetByteWithManyArraysWithOneElements() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0}) + .append(new byte[] {1}) + .append(new byte[] {2}) + .append(new byte[] {3}) + .append(new byte[] {4}) + .append(new byte[] {5}) + .append(new byte[] {6}) + .append(new byte[] {7}) + .append(new byte[] {8}) + .append(new byte[] {9}); + + assertEquals(10, buffer.remaining()); + assertFalse(buffer.hasArray()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + for (int i = 0; i < 10; ++i) { + assertEquals(i, buffer.get()); + } + + assertEquals(0, buffer.remaining()); + assertEquals(10, buffer.position()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetByteWithManyArraysWithVariedElements() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0}) + .append(new byte[] {1, 2}) + .append(new byte[] {3, 4, 5}) + .append(new byte[] {6}) + .append(new byte[] {7, 8, 9}); + + assertEquals(10, buffer.remaining()); + assertFalse(buffer.hasArray()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + for (int i = 0; i < 10; ++i) { + assertEquals(i, buffer.get()); + } + + assertEquals(0, buffer.remaining()); + assertEquals(10, buffer.position()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetShortByteWithNothingAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.getShort(); + fail("Should throw a BufferUnderflowException"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetShortWithOneArrayWithOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 8, 0 }); + + assertEquals(2, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getShort()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(2, buffer.position()); + + try { + buffer.getShort(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetShortWithTwoArraysContainingOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {8}).append(new byte[] {0}); + + assertEquals(2, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getShort()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(2, buffer.position()); + + try { + buffer.getShort(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetIntByteWithNothingAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.getInt(); + fail("Should throw a BufferUnderflowException"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetIntWithOneArrayWithOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 0, 8, 0 }); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getInt()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(4, buffer.position()); + + try { + buffer.getInt(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetIntWithTwoArraysContainingOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0 ,0 }).append(new byte[] { 8, 0 }); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getInt()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(4, buffer.position()); + + try { + buffer.getInt(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetLongByteWithNothingAppended() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.getLong(); + fail("Should throw a BufferUnderflowException"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetLongWithOneArrayWithOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0, 0, 0, 0, 0, 0, 8, 0 }); + + assertEquals(8, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getLong()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(8, buffer.position()); + + try { + buffer.getLong(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetLongWithTwoArraysContainingOneElement() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] { 0 ,0, 0, 0 }).append(new byte[] { 0, 0, 8, 0 }); + + assertEquals(8, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(2048, buffer.getLong()); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(8, buffer.position()); + + try { + buffer.getLong(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetByteArrayWithContentsInSingleArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + + assertEquals(data.length, buffer.limit()); + byte array[] = new byte[1]; + + for (int i = 0; i < data.length; i++) { + assertEquals(buffer.position(), i); + ReadableBuffer self = buffer.get(array); + assertEquals(array[0], buffer.get(i)); + assertSame(self, buffer); + } + + try { + buffer.get(array); + fail("Should throw BufferUnderflowException"); + } catch (BufferUnderflowException e) { + } + + try { + buffer.get((byte[]) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + } + } + + @Test + public void testGetWritableBufferWithContentsInSingleArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + + assertEquals(data.length, buffer.limit()); + + ByteBuffer destination = ByteBuffer.allocate(1); + WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination); + + for (int i = 0; i < data.length; i++) { + assertEquals(buffer.position(), i); + ReadableBuffer self = buffer.get(target); + assertEquals(destination.get(0), buffer.get(i)); + assertSame(self, buffer); + destination.rewind(); + } + + try { + buffer.get(target); + } catch (Throwable e) { + fail("Should not throw: " + e.getClass().getSimpleName()); + } + + try { + buffer.get((WritableBuffer) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + } + } + + @Test + public void testGetWritableBufferWithContentsInSeveralArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {0, 1, 2, 3, 4}; + byte[] data2 = new byte[] {5, 6, 7, 8, 9}; + byte[] data3 = new byte[] {10, 11, 12}; + + int size = data1.length + data2.length + data3.length; + + buffer.append(data1).append(data2).append(data3); + + assertEquals(size, buffer.limit()); + + ByteBuffer destination = ByteBuffer.allocate(1); + WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination); + + for (int i = 0; i < size; i++) { + assertEquals(buffer.position(), i); + ReadableBuffer self = buffer.get(target); + assertEquals(destination.get(0), buffer.get(i)); + assertSame(self, buffer); + destination.rewind(); + } + + try { + buffer.get(target); + } catch (Throwable e) { + fail("Should not throw: " + e.getClass().getSimpleName()); + } + + try { + buffer.get((WritableBuffer) null); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + } + } + + @Test + public void testGetWritableBufferRespectsOwnLimit() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + buffer.limit(5); + + ByteBuffer destination = ByteBuffer.allocate(data.length); + WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination); + + buffer.get(target); + + assertEquals(5, buffer.position()); + assertEquals(0, buffer.remaining()); + + assertEquals(5, target.position()); + assertEquals(5, target.remaining()); + } + + @Test + public void testGetintWithContentsInSingleArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + + for (int i = 0; i < buffer.capacity(); i++) { + assertEquals(buffer.position(), i); + assertEquals(buffer.get(i), buffer.get()); + } + + buffer.rewind(); + + for (int i = 0; i < buffer.capacity(); i++) { + assertEquals(buffer.position(), i); + assertEquals(buffer.get(), buffer.get(i)); + } + + try { + buffer.get(-1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(buffer.limit()); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + } + + @Test + public void testGetintWithContentsInMultipleArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + for (int i = 0; i < buffer.capacity(); i++) { + assertEquals(buffer.position(), i); + assertEquals(buffer.get(), buffer.get(i)); + } + + try { + buffer.get(-1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(buffer.limit()); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + } + + @Test + public void testGetbyteArrayIntIntWithContentsInSingleArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + + byte array[] = new byte[data.length]; + + try { + buffer.get(new byte[data.length + 1], 0, data.length + 1); + fail("Should throw BufferUnderflowException"); + } catch (BufferUnderflowException e) { + } + + assertEquals(buffer.position(), 0); + + try { + buffer.get(array, -1, array.length); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + buffer.get(array, array.length, 0); + + try { + buffer.get(array, array.length + 1, 1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + assertEquals(buffer.position(), 0); + + try { + buffer.get(array, 2, -1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(array, 2, array.length); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get((byte[])null, -1, 0); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + } + + try { + buffer.get(array, 1, Integer.MAX_VALUE); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(array, Integer.MAX_VALUE, 1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + assertEquals(buffer.position(), 0); + + CompositeReadableBuffer self = buffer.get(array, 0, array.length); + assertEquals(buffer.position(), buffer.capacity()); + assertContentEquals(buffer, array, 0, array.length); + assertSame(self, buffer); + } + + @Test + public void testGetbyteArrayIntIntWithContentsInMultipleArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {0, 1, 2, 3, 4}; + byte[] data2 = new byte[] {5, 6, 7, 8, 9}; + + final int dataLength = data1.length + data2.length; + + buffer.append(data1).append(data2); + + assertEquals(dataLength, buffer.remaining()); + + byte array[] = new byte[buffer.remaining()]; + + try { + buffer.get(new byte[dataLength + 1], 0, dataLength + 1); + fail("Should throw BufferUnderflowException"); + } catch (BufferUnderflowException e) { + } + + assertEquals(buffer.position(), 0); + + try { + buffer.get(array, -1, array.length); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + buffer.get(array, array.length, 0); + + try { + buffer.get(array, array.length + 1, 1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + assertEquals(buffer.position(), 0); + + try { + buffer.get(array, 2, -1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(array, 2, array.length); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get((byte[])null, -1, 0); + fail("Should throw NullPointerException"); + } catch (NullPointerException e) { + } + + try { + buffer.get(array, 1, Integer.MAX_VALUE); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + try { + buffer.get(array, Integer.MAX_VALUE, 1); + fail("Should throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + } + + assertEquals(buffer.position(), 0); + + CompositeReadableBuffer self = buffer.get(array, 0, array.length); + assertEquals(buffer.position(), buffer.capacity()); + assertContentEquals(buffer, array, 0, array.length); + assertSame(self, buffer); + } + + @Test + public void testGetFloat() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(float2bytes(3.14f)); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(3.14f, buffer.getFloat(), 0.1); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(4, buffer.position()); + + try { + buffer.getFloat(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testGetDouble() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(double2bytes(6.11)); + + assertEquals(8, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertEquals(6.11, buffer.getDouble(), 0.1); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(8, buffer.position()); + + try { + buffer.getDouble(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + //----- Test hasArray method ---------------------------------------------// + + @Test + public void testHasArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {0, 1, 2, 3, 4}; + byte[] data2 = new byte[] {5, 6, 7, 8, 9}; + buffer.append(data1); + + assertTrue(buffer.hasArray()); + assertNotNull(buffer.array()); + assertSame(data1, buffer.array()); + assertEquals(0, buffer.arrayOffset()); + + buffer.append(data2); + + assertFalse(buffer.hasArray()); + try { + buffer.array(); + fail("Should throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + try { + buffer.arrayOffset(); + fail("Should throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + + byte[] result1 = new byte[data1.length]; + byte[] result2 = new byte[data1.length]; + + buffer.get(result1); + assertArrayEquals(data1, result1); + assertFalse(buffer.hasArray()); + + buffer.reclaimRead(); + + assertTrue(buffer.hasArray()); + assertNotNull(buffer.array()); + assertSame(data2, buffer.array()); + assertEquals(0, buffer.arrayOffset()); + + buffer.get(result2); + assertArrayEquals(data2, result2); + assertTrue(buffer.hasArray()); + + buffer.reclaimRead(); + assertFalse(buffer.hasArray()); + + try { + buffer.array(); + fail("Should throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + try { + buffer.arrayOffset(); + fail("Should throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + //----- Test appending data to the buffer --------------------------------// + + @Test + public void testAppendOne() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source = new byte[] { 0, 1, 2, 3 }; + + buffer.append(source); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + assertTrue(buffer.hasArray()); + assertSame(source, buffer.array()); + assertEquals(0, buffer.getArrays().size()); + + assertEquals(-1, buffer.getCurrentIndex()); + } + + @Test + public void testAppendMoreThanOne() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source1 = new byte[] { 0, 1, 2, 3 }; + byte[] source2 = new byte[] { 4, 5, 6, 7 }; + + buffer.append(source1); + assertTrue(buffer.hasArray()); + assertSame(source1, buffer.array()); + assertEquals(-1, buffer.getCurrentIndex()); + + buffer.append(source2); + assertFalse(buffer.hasArray()); + assertEquals(2, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + + byte[] source3 = new byte[] { 9, 10, 11, 12 }; + buffer.append(source3); + assertFalse(buffer.hasArray()); + assertEquals(3, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + } + + @Test + public void testAppendNull() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.append(null); + fail("Should not be able to add a null array"); + } catch (IllegalArgumentException iae) {} + } + + @Test + public void testAppendEmpty() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.append(new byte[0]); + fail("Should not be able to add a empty array"); + } catch (IllegalArgumentException iae) {} + } + + //----- Test buffer compaction handling ----------------------------------// + + @Test + public void testCompactEmptyBuffer() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + try { + buffer.reclaimRead(); + } catch (Throwable t) { + fail("Should not fail to compact empty buffer"); + } + + CompositeReadableBuffer slice = buffer.slice(); + + try { + slice.reclaimRead(); + } catch (Throwable t) { + fail("Should not fail to compact empty slice"); + } + } + + @Test + public void testCompactSignleArrayBuffer() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source = new byte[] { 0, 1, 2, 3 }; + + buffer.append(source); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + assertTrue(buffer.hasArray()); + assertSame(source, buffer.array()); + assertEquals(0, buffer.getArrays().size()); + + // Should not have any affect on buffer that is not consumed + buffer.reclaimRead(); + + assertEquals(4, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + assertTrue(buffer.hasArray()); + assertSame(source, buffer.array()); + + // Should not have any affect on buffer that is not consumed + buffer.position(1); + buffer.reclaimRead(); + + assertEquals(3, buffer.remaining()); + assertTrue(buffer.hasRemaining()); + assertEquals(1, buffer.position()); + assertTrue(buffer.hasArray()); + assertSame(source, buffer.array()); + + // Should clear array from buffer as it is now consumed. + buffer.position(source.length); + buffer.reclaimRead(); + + assertEquals(0, buffer.remaining()); + assertFalse(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + assertFalse(buffer.hasArray()); + } + + @Test + public void testCompact() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0}) + .append(new byte[] {1}) + .append(new byte[] {2}) + .append(new byte[] {3}) + .append(new byte[] {4}) + .append(new byte[] {5}) + .append(new byte[] {6}) + .append(new byte[] {7}) + .append(new byte[] {8}) + .append(new byte[] {9}); + + assertEquals(10, buffer.remaining()); + assertEquals(10, buffer.getArrays().size()); + assertFalse(buffer.hasArray()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + for (int i = 0; i < 10; ++i) { + assertEquals(i, buffer.get()); + buffer.reclaimRead(); + assertEquals(0, buffer.position()); + } + + assertTrue(buffer.getArrays().isEmpty()); + assertFalse(buffer.hasArray()); + assertEquals(0, buffer.remaining()); + assertEquals(0, buffer.position()); + assertEquals(0, buffer.getArrays().size()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testCompactWithDifferingBufferSizes() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0}) + .append(new byte[] {1, 2}) + .append(new byte[] {3, 4, 5}) + .append(new byte[] {6}) + .append(new byte[] {7}) + .append(new byte[] {8, 9}); + + assertEquals(10, buffer.remaining()); + assertFalse(buffer.hasArray()); + assertTrue(buffer.hasRemaining()); + assertEquals(0, buffer.position()); + + for (int i = 0; i < 10; ++i) { + assertEquals(i, buffer.get()); + buffer.reclaimRead(); + } + + assertTrue(buffer.getArrays().isEmpty()); + assertFalse(buffer.hasArray()); + assertEquals(0, buffer.remaining()); + assertEquals(0, buffer.position()); + + try { + buffer.get(); + fail("Should not be able to read past end"); + } catch (BufferUnderflowException e) {} + } + + @Test + public void testCompactUpdatesMark() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source1 = new byte[] { 0, 1, 2, 3 }; + byte[] source2 = new byte[] { 4, 5, 6, 7 }; + + buffer.append(source1).append(source2); + + assertFalse(buffer.hasArray()); + assertEquals(2, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + + buffer.position(5); + buffer.mark(); + assertEquals(5, buffer.get()); + buffer.position(8); + buffer.reset(); + assertEquals(5, buffer.position()); + buffer.mark(); + + buffer.reclaimRead(); + buffer.position(buffer.limit()); + buffer.reset(); + assertEquals(5, buffer.get()); + + assertFalse(buffer.getArrays().isEmpty()); + } + + @Test + public void testCompactThreeArraysToNone() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source1 = new byte[] { 0, 1, 2, 3 }; + byte[] source2 = new byte[] { 4, 5, 6, 7 }; + byte[] source3 = new byte[] { 8, 9, 10, 11 }; + + buffer.append(source1).append(source2).append(source3); + + assertFalse(buffer.hasArray()); + assertEquals(3, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + assertEquals(12, buffer.limit()); + assertEquals(12, buffer.capacity()); + + buffer.position(4); + buffer.reclaimRead(); + + assertFalse(buffer.hasArray()); + assertEquals(2, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + assertEquals(8, buffer.limit()); + assertEquals(8, buffer.capacity()); + + buffer.position(4); + buffer.reclaimRead(); + + // TODO - Right now we hold off purging the array list until everything is consumed. + assertTrue(buffer.hasArray()); + assertEquals(1, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + assertEquals(4, buffer.limit()); + assertEquals(4, buffer.capacity()); + + buffer.position(4); + buffer.reclaimRead(); + + assertFalse(buffer.hasArray()); + assertEquals(0, buffer.getArrays().size()); + assertEquals(-1, buffer.getCurrentIndex()); + assertEquals(0, buffer.limit()); + assertEquals(0, buffer.capacity()); + } + + @Test + public void testCompactAllBuffersInOneShot() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source1 = new byte[] { 0, 1, 2, 3 }; + byte[] source2 = new byte[] { 4, 5, 6, 7 }; + byte[] source3 = new byte[] { 8, 9, 10, 11 }; + byte[] source4 = new byte[] { 12, 13, 14, 15 }; + + int size = source1.length + source2.length + source3.length + source4.length; + + buffer.append(source1).append(source2).append(source3).append(source4); + + assertFalse(buffer.hasArray()); + assertEquals(4, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + assertEquals(size, buffer.limit()); + assertEquals(size, buffer.capacity()); + + buffer.position(buffer.limit()); + buffer.reclaimRead(); + + assertFalse(buffer.hasArray()); + assertEquals(0, buffer.getArrays().size()); + assertEquals(-1, buffer.getCurrentIndex()); + assertEquals(0, buffer.limit()); + assertEquals(0, buffer.capacity()); + } + + @Test + public void testAppendAfterCompact() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] source1 = new byte[] { 0, 1, 2, 3 }; + byte[] source2 = new byte[] { 4, 5, 6, 7 }; + + buffer.append(source1).append(source2); + + assertFalse(buffer.hasArray()); + assertEquals(2, buffer.getArrays().size()); + assertEquals(0, buffer.getCurrentIndex()); + + buffer.position(4); + buffer.reclaimRead(); + + assertEquals(0, buffer.position()); + assertEquals(4, buffer.limit()); + assertEquals(4, buffer.capacity()); + assertEquals(1, buffer.getArrays().size()); + + byte[] source3 = new byte[] { 8, 9, 10, 11 }; + + buffer.append(source3); + + buffer.position(4); + + for (int i = 0; i < source3.length; ++i) { + assertEquals(source3[i], buffer.get()); + } + + assertFalse(buffer.getArrays().isEmpty()); + buffer.reclaimRead(); + assertTrue(buffer.getArrays().isEmpty()); + } + + //----- Tests on Mark ----------------------------------------------------// + + @Test + public void testMark() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + // save state + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + assertEquals(0, oldPosition); + assertEquals(10, oldLimit); + + CompositeReadableBuffer self = buffer.mark(); + assertSame(self, buffer); + + buffer.mark(); + buffer.position(buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), oldPosition); + + buffer.mark(); + buffer.position(buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), oldPosition); + + // restore state + buffer.limit(oldLimit); + buffer.position(oldPosition); + } + + //----- Tests on Reset ---------------------------------------------------// + + @Test + public void testReset() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException when not marked."); + } catch (InvalidMarkException e) { + } + + // save state + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + assertEquals(0, oldPosition); + assertEquals(10, oldLimit); + + buffer.mark(); + buffer.position(buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), oldPosition); + + buffer.mark(); + buffer.position(buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), oldPosition); + + // Can call as mark is not cleared on reset. + CompositeReadableBuffer self = buffer.reset(); + assertSame(self, buffer); + } + + //----- Tests on Rewind --------------------------------------------------// + + @Test + public void testRewind() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + // save state + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + assertEquals(0, oldPosition); + assertEquals(10, oldLimit); + + CompositeReadableBuffer self = buffer.rewind(); + assertEquals(buffer.position(), 0); + assertSame(self, buffer); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + } + + //----- Tests on Flip ----------------------------------------------------// + + @Test + public void testFlipWhenEmpty() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + CompositeReadableBuffer ret = buffer.flip(); + + assertSame(ret, buffer); + assertEquals(buffer.position(), 0); + assertEquals(buffer.limit(), 0); + } + + @Test + public void testFlipWithOneArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + + // save state + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + assertEquals(0, oldPosition); + assertEquals(10, oldLimit); + + CompositeReadableBuffer ret = buffer.flip(); + assertSame(ret, buffer); + assertEquals(buffer.position(), 0); + assertEquals(buffer.limit(), oldPosition); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + } + + @Test + public void testFlipWithMultipleArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + // save state + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + assertEquals(0, oldPosition); + assertEquals(10, oldLimit); + + CompositeReadableBuffer ret = buffer.flip(); + assertSame(ret, buffer); + assertEquals(buffer.position(), 0); + assertEquals(buffer.limit(), oldPosition); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + } + + @Test + public void testFlipSliceWithOneArray() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + + buffer.mark(); + buffer.position(1); + buffer.limit(buffer.remaining() - 1); + + ReadableBuffer slice = buffer.slice(); + + assertEquals(1, slice.get(0)); + slice.position(1); + slice.mark(); + slice.flip(); + + assertEquals(1, slice.get(0)); + assertEquals(1, slice.limit()); + + try { + slice.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + + buffer.reset(); + assertEquals(0, buffer.position()); + assertEquals(buffer.remaining(), buffer.limit()); + } + + @Test + public void testFlipSliceWithMultipleArrays() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + buffer.mark(); + buffer.position(5); + + ReadableBuffer slice = buffer.slice(); + + assertEquals(5, slice.get(0)); + slice.position(1); + slice.mark(); + slice.flip(); + + assertEquals(5, slice.get(0)); + assertEquals(1, slice.limit()); + + try { + slice.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + + buffer.reset(); + assertEquals(0, buffer.position()); + assertEquals(buffer.remaining(), buffer.limit()); + } + + //----- Tests on Clear --------------------------------------------------// + + @Test + public void testClear() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + assertEquals(0, buffer.position()); + assertEquals(10, buffer.limit()); + + buffer.position(5); + assertEquals(5, buffer.position()); + buffer.mark(); + + CompositeReadableBuffer self = buffer.clear(); + assertEquals(0, buffer.position()); + assertEquals(10, buffer.limit()); + assertSame(self, buffer); + + try { + buffer.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + } + + //----- Test various cases of Duplicate ----------------------------------// + + @Test + public void testDuplicateWithSingleArrayContent() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + buffer.mark(); + buffer.position(buffer.limit()); + + // duplicate's contents should be the same as buffer + CompositeReadableBuffer duplicate = buffer.duplicate(); + assertNotSame(buffer, duplicate); + assertEquals(buffer.capacity(), duplicate.capacity()); + assertEquals(buffer.position(), duplicate.position()); + assertEquals(buffer.limit(), duplicate.limit()); + assertContentEquals(buffer, duplicate); + + // duplicate's position, mark, and limit should be independent to buffer + duplicate.reset(); + assertEquals(duplicate.position(), 0); + duplicate.clear(); + assertEquals(buffer.position(), buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), 0); + + // One array buffer should share backing array + assertTrue(buffer.hasArray()); + assertTrue(duplicate.hasArray()); + assertSame(buffer.array(), duplicate.array()); + assertTrue(buffer.getArrays().isEmpty()); + assertTrue(duplicate.getArrays().isEmpty()); + assertSame(buffer.getArrays(), duplicate.getArrays()); // Same Empty Buffer + } + + @Test + public void testDuplicateWithSingleArrayContentCompactionIsNoOpWhenNotRead() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + + CompositeReadableBuffer duplicate = buffer.duplicate(); + + assertEquals(10, buffer.capacity()); + assertEquals(buffer.capacity(), duplicate.capacity()); + + buffer.reclaimRead(); + assertEquals(10, buffer.capacity()); + assertEquals(buffer.capacity(), duplicate.capacity()); + + duplicate.reclaimRead(); + assertEquals(10, buffer.capacity()); + assertEquals(buffer.capacity(), duplicate.capacity()); + } + + @Test + public void testDuplicateWithSingleArrayContentCompactionLeavesOtherIntact() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + + CompositeReadableBuffer duplicate = buffer.duplicate(); + + assertEquals(10, buffer.capacity()); + assertEquals(buffer.capacity(), duplicate.capacity()); + + duplicate.position(duplicate.limit()); + assertFalse(duplicate.hasRemaining()); + + assertTrue(duplicate.hasArray()); + duplicate.reclaimRead(); + assertFalse(duplicate.hasArray()); + assertEquals(0, duplicate.capacity()); + + // Buffer should be unaffected + assertEquals(10, buffer.capacity()); + assertTrue(buffer.hasArray()); + } + + @Test + public void testDuplicateWithMulitiArrayContent() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + buffer.mark(); + buffer.position(buffer.limit()); + + // duplicate's contents should be the same as buffer + CompositeReadableBuffer duplicate = buffer.duplicate(); + assertNotSame(buffer, duplicate); + assertEquals(buffer.capacity(), duplicate.capacity()); + assertEquals(buffer.position(), duplicate.position()); + assertEquals(buffer.limit(), duplicate.limit()); + assertContentEquals(buffer, duplicate); + + // duplicate's position, mark, and limit should be independent to buffer + duplicate.reset(); + assertEquals(duplicate.position(), 0); + duplicate.clear(); + assertEquals(buffer.position(), buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), 0); + + // One array buffer should share backing array + assertFalse(buffer.hasArray()); + assertFalse(duplicate.hasArray()); + assertFalse(buffer.getArrays().isEmpty()); + assertFalse(duplicate.getArrays().isEmpty()); + assertNotSame(buffer.getArrays(), duplicate.getArrays()); + } + + @Test + public void testDuplicateWithMultiArrayContentCompactionLeavesOtherIntact() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + + CompositeReadableBuffer duplicate = buffer.duplicate(); + + assertEquals(10, buffer.capacity()); + assertEquals(buffer.capacity(), duplicate.capacity()); + + duplicate.position(duplicate.limit()); + assertFalse(duplicate.hasRemaining()); + + assertFalse(duplicate.hasArray()); + duplicate.reclaimRead(); + assertFalse(duplicate.hasArray()); + assertEquals(0, duplicate.capacity()); + assertEquals(0, duplicate.getArrays().size()); + + // Buffer should be unaffected + assertEquals(10, buffer.capacity()); + assertFalse(buffer.hasArray()); + assertEquals(2, buffer.getArrays().size()); + } + + //----- Test various cases of Slice --------------------------------------// + + @Test + public void testSlice() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + buffer.append(data); + + assertEquals(buffer.capacity(), data.length); + buffer.position(1); + buffer.limit(buffer.capacity() - 2); + + ReadableBuffer slice = buffer.slice(); + assertEquals(slice.position(), 0); + assertEquals(slice.limit(), buffer.remaining()); + assertEquals(slice.capacity(), buffer.remaining()); + assertEquals(1, slice.get()); + + try { + slice.reset(); + fail("Should throw InvalidMarkException"); + } catch (InvalidMarkException e) { + } + } + + @Test + public void testSliceOnEmptyBuffer() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + CompositeReadableBuffer slice = buffer.slice(); + + // Sliced contents should be the same as buffer + assertNotSame(buffer, slice); + assertEquals(buffer.capacity(), slice.capacity()); + assertEquals(buffer.position(), slice.position()); + assertEquals(buffer.limit(), slice.limit()); + assertContentEquals(buffer, slice); + + try { + slice.reclaimRead(); + } catch (Throwable t) { + fail("Compacting an empty slice should not fail"); + } + } + + @Test + public void testSliceIgnoresAppends() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + + // Sliced contents should be the same as buffer + CompositeReadableBuffer slice = buffer.slice(); + assertNotSame(buffer, slice); + + try { + slice.append(new byte[] { 10 }); + fail("Should not be allowed to append to a slice, must throw ReadOnlyBufferException"); + } catch (IllegalStateException ise) {} + } + + @Test + public void testSliceWithSingleArrayContent() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + buffer.mark(); + + // Sliced contents should be the same as buffer + CompositeReadableBuffer slice = buffer.slice(); + assertNotSame(buffer, slice); + assertEquals(buffer.capacity(), slice.capacity()); + assertEquals(buffer.position(), slice.position()); + assertEquals(buffer.limit(), slice.limit()); + assertContentEquals(buffer, slice); + + // Sliced position, mark, and limit should be independent to buffer + try { + slice.reset(); + fail("Mark should be undefined in the slice and throw InvalidMarkException"); + } catch (InvalidMarkException e) {} + + assertEquals(slice.position(), 0); + slice.clear(); + assertEquals(10, buffer.limit()); + buffer.reset(); + assertEquals(buffer.position(), 0); + + // One array buffer should share backing array + assertTrue(buffer.hasArray()); + assertTrue(slice.hasArray()); + assertSame(buffer.array(), slice.array()); + assertTrue(buffer.getArrays().isEmpty()); + assertTrue(slice.getArrays().isEmpty()); + assertSame(buffer.getArrays(), slice.getArrays()); // Same Empty Buffer + } + + @Test + public void testSliceWithSingleArrayContentSourcePartiallyRead() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + buffer.position(5); + + // Sliced contents should be the same as buffer + CompositeReadableBuffer slice = buffer.slice(); + assertNotSame(buffer, slice); + assertEquals(10, buffer.capacity()); + assertEquals(5, slice.capacity()); + assertEquals(5, buffer.position()); + assertEquals(0, slice.position()); + assertEquals(10, buffer.limit()); + assertEquals(5, slice.limit()); + assertSpanEquals(buffer, slice); + + slice.position(1); + assertEquals(6, slice.get()); + assertEquals(5, slice.get(0)); + + try { + slice.limit(6); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException iae) {} + + try { + slice.position(6); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException iae) {} + } + + @Test + public void testSliceWithMulitpleArraysContentSourcePartiallyRead() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {0, 1, 2, 3, 4}).append(new byte[] {5, 6, 7, 8, 9}); + buffer.position(5); + + // Sliced contents should be the same as buffer + CompositeReadableBuffer slice = buffer.slice(); + assertNotSame(buffer, slice); + assertEquals(10, buffer.capacity()); + assertEquals(5, slice.capacity()); + assertEquals(5, buffer.position()); + assertEquals(0, slice.position()); + assertEquals(10, buffer.limit()); + assertEquals(5, slice.limit()); + assertSpanEquals(buffer, slice); + + slice.position(1); + assertEquals(6, slice.get()); + assertEquals(5, slice.get(0)); + + try { + slice.limit(6); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException iae) {} + + try { + slice.position(6); + fail("should throw IllegalArgumentException"); + } catch (IllegalArgumentException iae) {} + } + + //----- Test various cases of byteBuffer ---------------------------------// + + @Test + public void testByteBufferFromEmptyBuffer() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + ByteBuffer byteBuffer = buffer.byteBuffer(); + + assertNotNull(byteBuffer); + assertEquals(0, byteBuffer.position()); + assertEquals(0, byteBuffer.limit()); + assertEquals(0, byteBuffer.capacity()); + + // Our ByteBuffer results should be read-only and indicate no array. + assertTrue(byteBuffer.isReadOnly()); + assertFalse(byteBuffer.hasArray()); + } + + @Test + public void testByteBufferOnSingleArrayContent() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}); + + ByteBuffer byteBuffer = buffer.byteBuffer(); + + assertNotNull(byteBuffer); + assertEquals(0, byteBuffer.position()); + assertEquals(10, byteBuffer.limit()); + assertEquals(10, byteBuffer.capacity()); + + // Our ByteBuffer results should be read-only and indicate no array. + assertTrue(byteBuffer.isReadOnly()); + assertFalse(byteBuffer.hasArray()); + + for (int i = 0; i < 10; ++i) { + assertEquals(buffer.get(i), byteBuffer.get(i)); + } + } + + @Test + public void testByteBufferOnMultipleArrayContent() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {9, 8, 7, 6, 5}).append(new byte[] {4, 3, 2, 1, 0}); + + ByteBuffer byteBuffer = buffer.byteBuffer(); + + assertNotNull(byteBuffer); + assertEquals(0, byteBuffer.position()); + assertEquals(10, byteBuffer.limit()); + assertEquals(10, byteBuffer.capacity()); + + // Our ByteBuffer results should be read-only and indicate no array. + assertTrue(byteBuffer.isReadOnly()); + assertFalse(byteBuffer.hasArray()); + + for (int i = 0; i < 10; ++i) { + assertEquals(buffer.get(i), byteBuffer.get(i)); + } + } + + @Test + public void testByteBufferOnMultipleArrayContentWithLimits() { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + buffer.append(new byte[] {9, 8, 7, 6, 5}).append(new byte[] {4, 3, 2, 1, 0}); + + buffer.position(3); + buffer.limit(9); + + assertEquals(6, buffer.remaining()); + + ByteBuffer byteBuffer = buffer.byteBuffer(); + + assertNotNull(byteBuffer); + assertEquals(0, byteBuffer.position()); + assertEquals(6, byteBuffer.limit()); + assertEquals(6, byteBuffer.capacity()); + + // Our ByteBuffer results should be read-only and indicate no array. + assertTrue(byteBuffer.isReadOnly()); + assertFalse(byteBuffer.hasArray()); + + for (int i = 0; i < 6; ++i) { + assertEquals(buffer.get(), byteBuffer.get()); + } + } + + //----- Test put ReadableBuffer ------------------------------------------// + + @Test + public void testReadStringFromEmptyBuffer() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + assertNull(buffer.readString(StandardCharsets.UTF_8.newDecoder())); + } + + @Test + public void testReadStringFromUTF8InSingleArray() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + final String testString = "Test String to Decode!"; + byte[] encoded = testString.getBytes(StandardCharsets.UTF_8); + + buffer.append(encoded); + + assertEquals(testString, buffer.readString(StandardCharsets.UTF_8.newDecoder())); + } + + @Test + public void testReadStringFromUTF8InSingleArrayWithLimits() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + final String testString = "Test String to Decode!"; + byte[] encoded = testString.getBytes(StandardCharsets.UTF_8); + + // Only read the first character + buffer.append(encoded); + buffer.limit(1); + + assertEquals("T", buffer.readString(StandardCharsets.UTF_8.newDecoder())); + } + + @Test + public void testReadStringFromUTF8InMulitpleArrays() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + final String testString = "Test String to Decode!!"; + byte[] encoded = testString.getBytes(StandardCharsets.UTF_8); + + byte[] first = new byte[encoded.length / 2]; + byte[] second = new byte[encoded.length - (encoded.length / 2)]; + + System.arraycopy(encoded, 0, first, 0, first.length); + System.arraycopy(encoded, first.length, second, 0, second.length); + + buffer.append(first).append(second); + + String result = buffer.readString(StandardCharsets.UTF_8.newDecoder()); + + assertEquals(testString, result); + } + + @Test + public void testReadStringFromUTF8InMultipleArraysWithLimits() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + final String testString = "Test String to Decode!"; + byte[] encoded = testString.getBytes(StandardCharsets.UTF_8); + + byte[] first = new byte[encoded.length / 2]; + byte[] second = new byte[encoded.length - (encoded.length / 2)]; + + System.arraycopy(encoded, 0, first, 0, first.length); + System.arraycopy(encoded, first.length, second, 0, second.length); + + buffer.append(first).append(second); + + // Only read the first character + buffer.limit(1); + + assertEquals("T", buffer.readString(StandardCharsets.UTF_8.newDecoder())); + } + + //----- Tests for hashCode -----------------------------------------------// + + @Test + public void testHashCodeNotFromIdentity() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + assertEquals(1, buffer.hashCode()); + + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + buffer.append(data); + + assertTrue(buffer.hashCode() != 1); + assertNotEquals(buffer.hashCode(), System.identityHashCode(buffer)); + assertEquals(buffer.hashCode(), buffer.hashCode()); + } + + @Test + public void testHashCodeOnSameBackingBuffer() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer3 = new CompositeReadableBuffer(); + + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + buffer1.append(data); + buffer2.append(data); + buffer3.append(data); + + assertEquals(buffer1.hashCode(), buffer2.hashCode()); + assertEquals(buffer2.hashCode(), buffer3.hashCode()); + assertEquals(buffer3.hashCode(), buffer1.hashCode()); + } + + @Test + public void testHashCodeOnDifferentBackingBuffer() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1); + buffer2.append(data2); + + assertNotEquals(buffer1.hashCode(), buffer2.hashCode()); + } + + @Test + public void testHashCodeOnSplitBufferContentsNotSame() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1).append(data2); + buffer2.append(data2).append(data1); + + assertNotEquals(buffer1.hashCode(), buffer2.hashCode()); + } + + @Test + public void testHashCodeOnSplitBufferContentsSame() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1).append(data2); + buffer2.append(data1).append(data2); + + assertEquals(buffer1.hashCode(), buffer2.hashCode()); + } + + @Test + public void testHashCodeMatchesByteBufferSingleArrayContents() throws CharacterCodingException { + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + buffer1.append(data); + + ByteBuffer buffer2 = ByteBuffer.wrap(data); + + assertEquals(buffer1.hashCode(), buffer2.hashCode()); + } + + @Test + public void testHashCodeMatchesByteBufferSingleArrayContentsWithSlice() throws CharacterCodingException { + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + buffer1.append(data); + + ByteBuffer buffer2 = ByteBuffer.wrap(data); + + ReadableBuffer slice1 = buffer1.position(1).slice(); + ByteBuffer slice2 = ((ByteBuffer) buffer2.position(1)).slice(); + + assertEquals(slice1.hashCode(), slice2.hashCode()); + } + + @Test + public void testHashCodeMatchesByteBufferMultipleArrayContents() throws CharacterCodingException { + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + byte[] data1 = new byte[] {9, 8, 7, 6, 5}; + byte[] data2 = new byte[] {4, 3, 2, 1, 0}; + + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + buffer1.append(data1); + buffer1.append(data2); + + ByteBuffer buffer2 = ByteBuffer.wrap(data); + + assertEquals(buffer1.hashCode(), buffer2.hashCode()); + } + + @Test + public void testHashCodeMatchesByteBufferMultipleArrayContentsWithSlice() throws CharacterCodingException { + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + byte[] data1 = new byte[] {9, 8, 7, 6, 5}; + byte[] data2 = new byte[] {4, 3, 2, 1, 0}; + + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + buffer1.append(data1); + buffer1.append(data2); + + ByteBuffer buffer2 = ByteBuffer.wrap(data); + + ReadableBuffer slice1 = buffer1.position(1).limit(4).slice(); + ByteBuffer slice2 = ((ByteBuffer) buffer2.position(1).limit(4)).slice(); + + assertEquals(slice1.hashCode(), slice2.hashCode()); + } + + //----- Tests for equals -------------------------------------------------// + + @Test + public void testEqualsSelf() throws CharacterCodingException { + CompositeReadableBuffer buffer = new CompositeReadableBuffer(); + + assertEquals(buffer, buffer); + + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + buffer.append(data); + + assertEquals(buffer, buffer); + } + + @Test + public void testEqualsOnSameBackingBuffer() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer3 = new CompositeReadableBuffer(); + + byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + buffer1.append(data); + buffer2.append(data); + buffer3.append(data); + + assertEquals(buffer1, buffer2); + assertEquals(buffer2, buffer3); + assertEquals(buffer3, buffer1); + } + + @Test + public void testEqualsOnDifferentBackingBuffer() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1); + buffer2.append(data2); + + assertNotEquals(buffer1, buffer2); + } + + @Test + public void testEqualsWhenContentsInMultipleArraysNotSame() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1).append(data2); + buffer2.append(data2).append(data1); + + assertNotEquals(buffer1, buffer2); + } + + @Test + public void testEqualsWhenContentsInMultipleArraysSame() throws CharacterCodingException { + CompositeReadableBuffer buffer1 = new CompositeReadableBuffer(); + CompositeReadableBuffer buffer2 = new CompositeReadableBuffer(); + + byte[] data1 = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + byte[] data2 = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + buffer1.append(data1).append(data2); + buffer2.append(data1).append(data2); + + assertEquals(buffer1, buffer2); + } + + //----- Utility Methods --------------------------------------------------// + + private void assertContentEquals(CompositeReadableBuffer buffer, byte array[], int offset, int length) { + for (int i = 0; i < length; i++) { + assertEquals(buffer.get(i), array[offset + i]); + } + } + + private void assertSpanEquals(ReadableBuffer source, ReadableBuffer other) { + assertEquals(source.remaining(), other.remaining()); + for (int i = 0; i < source.remaining(); i++) { + assertEquals(source.get(), other.get()); + } + } + + private void assertContentEquals(ReadableBuffer source, ReadableBuffer other) { + assertEquals(source.capacity(), other.capacity()); + for (int i = 0; i < source.capacity(); i++) { + assertEquals(source.get(i), other.get(i)); + } + } + + private byte[] int2bytes(int value) { + byte bytes[] = new byte[Integer.BYTES]; + int index = 0; + + bytes[index++] = (byte) (value >>> 24); + bytes[index++] = (byte) (value >>> 16); + bytes[index++] = (byte) (value >>> 8); + bytes[index++] = (byte) (value >>> 0); + + return bytes; + } + + private byte[] long2bytes(long value) { + byte bytes[] = new byte[Long.BYTES]; + int index = 0; + + bytes[index++] = (byte) (value >>> 56); + bytes[index++] = (byte) (value >>> 48); + bytes[index++] = (byte) (value >>> 40); + bytes[index++] = (byte) (value >>> 32); + bytes[index++] = (byte) (value >>> 24); + bytes[index++] = (byte) (value >>> 16); + bytes[index++] = (byte) (value >>> 8); + bytes[index++] = (byte) (value >>> 0); + + return bytes; + } + + private byte[] float2bytes(float value) { + return int2bytes(Float.floatToRawIntBits(value)); + } + + private byte[] double2bytes(double value) { + return long2bytes(Double.doubleToRawLongBits(value)); + } +}
--------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org