/*
 * 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 java.util.List;

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 arrayOffset method ------------------------------------------//

    @Test
    public void testArrayOffsetIsZeroRegardlessOfPositionOnNonSlicedBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

        buffer.append(data);

        assertTrue(buffer.hasArray());
        assertEquals(0, buffer.arrayOffset());

        buffer.position(1);

        assertEquals(0, buffer.arrayOffset());

        buffer.position(buffer.limit());

        assertEquals(0, buffer.arrayOffset());

        buffer.position(0);

        assertEquals(0, buffer.arrayOffset());
    }

    @Test
    public void testArrayOffsetIsFixedOnSliceRegardlessOfPosition() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

        buffer.append(data);

        assertTrue(buffer.hasArray());
        assertEquals(0, buffer.arrayOffset());

        buffer.position(1);
        ReadableBuffer slice = buffer.slice();

        assertEquals(1, slice.arrayOffset());

        slice.position(slice.limit());

        assertEquals(1, slice.arrayOffset());

        slice.position(0);

        assertEquals(1, slice.arrayOffset());

        slice.position(1);

        ReadableBuffer anotherSlice = slice.slice();

        assertEquals(2, anotherSlice.arrayOffset());
    }

    @Test
    public void testArrayOffset() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        assertFalse(buffer.hasArray());
        try {
            buffer.arrayOffset();
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException e) {
            // Expected
        }

        buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});

        assertTrue(buffer.hasArray());
        assertEquals("Unexpected array offset", 0, buffer.arrayOffset());
    }

    @Test
    public void testArrayOffsetAfterDuplicate() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});

        assertEquals("Unexpected get result", 0, buffer.get());

        CompositeReadableBuffer duplicate = buffer.duplicate();

        assertTrue(duplicate.hasArray());
        assertEquals("Unexpected array offset after duplication", 0, duplicate.arrayOffset());

        assertEquals("Unexpected get result", 1, duplicate.get());

        assertEquals("Unexpected array offset after duplicate use", 0, duplicate.arrayOffset());
        assertEquals("Unexpected get result", 2, duplicate.get());

        assertEquals("Unexpected array offset on original", 0, buffer.arrayOffset());
    }

    @Test
    public void testArrayOffsetAfterSliceDuplicated() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});

        assertEquals("Unexpected get result", 0, buffer.get());

        CompositeReadableBuffer slice = buffer.slice();
        CompositeReadableBuffer sliceDuplicated = slice.duplicate();

        assertTrue(sliceDuplicated.hasArray());
        assertEquals("Unexpected array offset after duplication", 1, sliceDuplicated.arrayOffset());

        assertEquals("Unexpected get result", 1, sliceDuplicated.get());

        assertEquals("Unexpected array offset after duplicate use", 1, sliceDuplicated.arrayOffset());
        assertEquals("Unexpected get result", 2, sliceDuplicated.get());

        assertEquals("Unexpected array offset on original", 0, buffer.arrayOffset());
        assertEquals("Unexpected array offset on slice", 1, slice.arrayOffset());
    }

    //----- Test getCurrentArrayPosition method ------------------------------------------//

    @Test
    public void testGetCurrentArrayPosition() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] source1 = new byte[] { 0, 1, 2 };
        byte[] source2 = new byte[] { 3, 4, 5, 6 };
        byte[] source3 = new byte[] { 7, 8, 9, 10, 11 };

        assertEquals(0, buffer.getCurrentArrayPosition());
        buffer.append(source1);
        assertEquals(0, buffer.getCurrentArrayPosition());
        buffer.append(source2);
        assertEquals(0, buffer.getCurrentArrayPosition());
        buffer.append(source3);

        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(0, buffer.getCurrentIndex());
        assertFalse(buffer.hasArray());
        assertEquals(3, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(12, buffer.limit());
        assertEquals(12, buffer.capacity());

        // Check each position in the first array
        for(int i = 0; i < source1.length; i++) {
            assertEquals(i, buffer.getCurrentArrayPosition());
            assertEquals(i, buffer.get());
        }

        // Should have moved into second array, verify array position reset
        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(1, buffer.getCurrentIndex());

        assertFalse(buffer.hasArray());
        assertEquals(3, buffer.getArrays().size());
        assertEquals(12, buffer.limit());
        assertEquals(12, buffer.capacity());

        // Check each position in the second array
        for(int i = 0; i < source2.length; i++) {
            assertEquals(i, buffer.getCurrentArrayPosition());
            assertEquals(i + source1.length, buffer.get());
        }

        // Should have moved into third array, verify array position reset
        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(2, buffer.getCurrentIndex());

        assertFalse(buffer.hasArray());
        assertEquals(3, buffer.getArrays().size());
        assertEquals(12, buffer.limit());
        assertEquals(12, buffer.capacity());

        // Check each position in the third array
        for(int i = 0; i < source3.length; i++) {
            assertEquals(i, buffer.getCurrentArrayPosition());
            assertEquals(i + source1.length + source2.length, buffer.get());
        }

        // Should have reached end, verify index is now out of bounds
        assertEquals(source3.length, buffer.getCurrentArrayPosition());
        assertEquals(2, buffer.getCurrentIndex());
    }

    //----- Test appending data to the buffer --------------------------------//

    @Test
    public void testAppendToBufferAtEndOfContentArray() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] source1 = new byte[] { 0, 1, 2, 3 };

        buffer.append(source1);

        assertTrue(buffer.hasArray());
        assertEquals(0, buffer.getArrays().size());
        assertEquals(-1, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());

        buffer.position(source1.length);

        assertFalse(buffer.hasRemaining());
        assertEquals(0, buffer.remaining());
        assertEquals(-1, buffer.getCurrentIndex());
        assertEquals(source1.length, buffer.getCurrentArrayPosition());

        byte[] source2 = new byte[] { 4, 5, 6, 7 };
        buffer.append(source2);

        assertTrue(buffer.hasRemaining());
        assertEquals(source2.length, buffer.remaining());
        assertFalse(buffer.hasArray());
        assertEquals(2, buffer.getArrays().size());
        assertEquals(1, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(source1.length, buffer.position());

        // Check each position in the array is read
        for(int i = 0; i < source2.length; i++) {
            assertEquals(i, buffer.getCurrentArrayPosition());
            assertEquals(1, buffer.getCurrentIndex());
            assertEquals(source1.length + i, buffer.get());
            assertEquals(i + 1, buffer.getCurrentArrayPosition());
        }
    }

    @Test
    public void testAppendToBufferAtEndOfContentList() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] source1 = new byte[] { 0, 1, 2, 3 };
        byte[] source2 = new byte[] { 4, 5, 6, 7 };

        buffer.append(source1);
        buffer.append(source2);

        assertFalse(buffer.hasArray());
        assertEquals(2, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());

        buffer.position(source1.length + source2.length);

        assertFalse(buffer.hasRemaining());
        assertEquals(0, buffer.remaining());
        assertEquals(1, buffer.getCurrentIndex());
        assertEquals(source2.length, buffer.getCurrentArrayPosition());

        byte[] source3 = new byte[] { 8, 9, 10, 11 };
        buffer.append(source3);

        assertTrue(buffer.hasRemaining());
        assertEquals(source3.length, buffer.remaining());
        assertFalse(buffer.hasArray());
        assertEquals(3, buffer.getArrays().size());
        assertEquals(2, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());
        assertEquals(source1.length + source2.length, buffer.position());

        // Check each position in the array is read
        for(int i = 0; i < source3.length; i++) {
            assertEquals(i, buffer.getCurrentArrayPosition());
            assertEquals(2, buffer.getCurrentIndex());
            assertEquals(source1.length + source2.length + i, buffer.get());
            assertEquals(i + 1, buffer.getCurrentArrayPosition());
        }
    }

    @Test
    public void testAppendOneArray() {
        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());
        assertEquals(0, buffer.getCurrentArrayPosition());
    }

    @Test
    public void testAppendMoreThanOneArray() {
        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());
        assertEquals(0, buffer.getCurrentArrayPosition());

        buffer.append(source2);
        assertFalse(buffer.hasArray());
        assertEquals(2, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());

        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 testAppendOneComposite() {
        doAppendOneCompositeTestImpl(false);
    }

    @Test
    public void testAppendOneCompositeAsReadableBuffer() {
        doAppendOneCompositeTestImpl(true);
    }

    private void doAppendOneCompositeTestImpl(boolean castToReadableBuffer) {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create a buffer to append
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6 };
        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);

        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertTrue(source.hasArray());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(-1, source.getCurrentIndex());

        // Append the buffer, check state of source+target buffers
        if(castToReadableBuffer) {
            target.append((ReadableBuffer) source);
        } else {
            target.append(source);
        }

        assertTrue(target.hasRemaining());
        assertEquals(7, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(2, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertSame(sourceBufferArray1, arrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertFalse(target.hasRemaining());
    }

    @Test
    public void testAppendOneCompositeWithMultipleArrays() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create a buffer to append
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6 };
        byte[] sourceBufferArray2 = new byte[] { 7, 8, 9, 10 };

        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);
        source.append(sourceBufferArray2);

        assertEquals(7, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertFalse(source.hasArray());
        assertEquals(0, source.getCurrentIndex());
        assertEquals(0, source.getCurrentArrayPosition());
        List<byte[]> sourceArrays = source.getArrays();
        assertEquals(2, sourceArrays.size());
        assertSame(sourceBufferArray1, sourceArrays.get(0));
        assertSame(sourceBufferArray2, sourceArrays.get(1));

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(11, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(7, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray());
        List<byte[]> targetArrays = target.getArrays();
        assertEquals(3, targetArrays.size());
        assertSame(targetBufferArray1, targetArrays.get(0));
        assertSame(sourceBufferArray1, targetArrays.get(1));
        assertSame(sourceBufferArray2, targetArrays.get(2));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check each position in the second array
        int secondChunkLength = sourceBufferArray1.length;
        for(int i = 0; i < secondChunkLength; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(2, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check each position in the third array
        for(int i = 0; i < sourceBufferArray2.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(initialChunkLength + secondChunkLength + i, target.get());
            assertEquals(2, target.getCurrentIndex());
        }

        assertFalse(target.hasRemaining());
    }

    @Test
    public void testAppendOneCompositeWithMultipleArraysPartiallyUsed() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create a buffer to append. We wont use the first and last bytes so set them -1.
        byte[] sourceBufferArray1 = new byte[] { -1, -1, 4 };
        byte[] sourceBufferArray2 = new byte[] { 5, 6 };
        byte[] sourceBufferArray3 = new byte[] { 7, 8, 9, -1 , -1, -1 };

        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);
        source.append(sourceBufferArray2);
        source.append(sourceBufferArray3);

        assertEquals(11, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertFalse(source.hasArray());
        assertEquals(0, source.getCurrentIndex());
        assertEquals(0, source.getCurrentArrayPosition());
        List<byte[]> sourceArrays = source.getArrays();
        assertEquals(3, sourceArrays.size());
        assertSame(sourceBufferArray1, sourceArrays.get(0));
        assertSame(sourceBufferArray2, sourceArrays.get(1));
        assertSame(sourceBufferArray3, sourceArrays.get(2));

        // Skip a couple bytes at start
        source.position(2);

        // Miss a few bytes at end
        source.limit(8);

        assertEquals(6, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(2, source.position());
        assertFalse(source.hasArray());
        assertEquals(0, source.getCurrentIndex());
        assertEquals(2, source.getCurrentArrayPosition());
        sourceArrays = source.getArrays();
        assertEquals(3, sourceArrays.size());
        assertSame(sourceBufferArray1, sourceArrays.get(0));
        assertSame(sourceBufferArray2, sourceArrays.get(1));
        assertSame(sourceBufferArray3, sourceArrays.get(2));

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(8, source.position());
        assertEquals(2, source.getCurrentIndex());
        assertEquals(3, source.getCurrentArrayPosition());

        assertTrue(target.hasRemaining());
        assertEquals(targetBufferArray1.length + 6, target.remaining());
        assertEquals(0, target.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray());
        List<byte[]> targetArrays = target.getArrays();
        assertEquals(4, targetArrays.size());

        // Expect it to contain the original target array, a new array containing the partial bytes
        // from the first source buffer array, then the original middle array, then a new array
        // containing the partial bytes from the third source buffer array.
        assertSame(targetBufferArray1, targetArrays.get(0));
        assertNotSame(sourceBufferArray1, targetArrays.get(1));
        assertSame(sourceBufferArray2, targetArrays.get(2));
        assertNotSame(sourceBufferArray3, targetArrays.get(3));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check sole byte in the second array
        assertEquals(initialChunkLength, target.get());

        assertEquals(2, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check each position in the third array
        int thirdChunkLength = sourceBufferArray2.length;
        for(int i = 0; i < thirdChunkLength; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(2, target.getCurrentIndex());
            assertEquals(initialChunkLength + 1 + i, target.get());
        }

        assertEquals(3, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check each position in the 4th array
        for(int i = 0; i < 3; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(initialChunkLength + 1 + thirdChunkLength + i, target.get());
            assertEquals(3, target.getCurrentIndex());
        }

        assertFalse(target.hasRemaining());
    }

    @Test
    public void testAppendOneCompositeWithMultipleArraysOnlySomeUsed() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create a buffer to append. We wont use the first and last arrays so set them -1.
        byte[] sourceBufferArray1 = new byte[] { -1, -1, -1 };
        byte[] sourceBufferArray2 = new byte[] { 4, 5 };
        byte[] sourceBufferArray3 = new byte[] { -1 };

        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);
        source.append(sourceBufferArray2);
        source.append(sourceBufferArray3);

        assertEquals(6, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertFalse(source.hasArray());
        assertEquals(0, source.getCurrentIndex());
        assertEquals(0, source.getCurrentArrayPosition());
        List<byte[]> sourceArrays = source.getArrays();
        assertEquals(3, sourceArrays.size());
        assertSame(sourceBufferArray1, sourceArrays.get(0));
        assertSame(sourceBufferArray2, sourceArrays.get(1));
        assertSame(sourceBufferArray3, sourceArrays.get(2));

        // Skip array at start
        source.position(sourceBufferArray1.length);

        // Skip array at end
        source.limit(sourceBufferArray1.length + sourceBufferArray2.length);

        assertEquals(2, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(3, source.position());
        assertFalse(source.hasArray());
        assertEquals(1, source.getCurrentIndex());
        assertEquals(0, source.getCurrentArrayPosition());
        sourceArrays = source.getArrays();
        assertEquals(3, sourceArrays.size());
        assertSame(sourceBufferArray1, sourceArrays.get(0));
        assertSame(sourceBufferArray2, sourceArrays.get(1));
        assertSame(sourceBufferArray3, sourceArrays.get(2));

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(5, source.position());
        assertEquals(2, source.getCurrentIndex());
        assertEquals(0, source.getCurrentArrayPosition());

        assertTrue(target.hasRemaining());
        assertEquals(targetBufferArray1.length + 2, target.remaining());
        assertEquals(0, target.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray());
        List<byte[]> targetArrays = target.getArrays();
        assertEquals(2, targetArrays.size());

        // Expect it to contain the original target array, then
        // the middle array from the source buffer
        assertSame(targetBufferArray1, targetArrays.get(0));
        assertSame(sourceBufferArray2, targetArrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(0, target.getCurrentArrayPosition());

        // Check each position in the second array
        int secondChunkLength = sourceBufferArray2.length;
        for(int i = 0; i < secondChunkLength; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertFalse(target.hasRemaining());
    }

    @Test
    public void testAppendMoreThanOneComposite() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create buffers to append
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6 };
        CompositeReadableBuffer source1 = new CompositeReadableBuffer();
        source1.append(sourceBufferArray1);

        byte[] sourceBufferArray2 = new byte[] { 7, 8, 9, 10 };
        CompositeReadableBuffer source2 = new CompositeReadableBuffer();
        source2.append(sourceBufferArray2);

        // Check their state another buffer to append
        assertEquals(3, source1.remaining());
        assertTrue(source1.hasRemaining());
        assertEquals(0, source1.position());
        assertTrue(source1.hasArray());
        assertSame(sourceBufferArray1, source1.array());
        assertEquals(-1, source1.getCurrentIndex());

        assertEquals(4, source2.remaining());
        assertTrue(source2.hasRemaining());
        assertEquals(0, source2.position());
        assertTrue(source2.hasArray());
        assertSame(sourceBufferArray2, source2.array());
        assertEquals(-1, source2.getCurrentIndex());

        // Append the buffer, check state of source+target buffers
        target.append(source1);
        target.append(source2);

        assertTrue(target.hasRemaining());
        assertEquals(11, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source1.hasRemaining());
        assertEquals(0, source1.remaining());
        assertEquals(3, source1.position());

        assertFalse(source2.hasRemaining());
        assertEquals(0, source2.remaining());
        assertEquals(4, source2.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(3, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertSame(sourceBufferArray1, arrays.get(1));
        assertSame(sourceBufferArray2, arrays.get(2));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(2, target.getCurrentIndex());

        // Check each position in the third array
        int secondChunkLength = sourceBufferArray1.length;
        for(int i = 0; i < sourceBufferArray2.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(initialChunkLength + secondChunkLength + i, target.get());
            assertEquals(2, target.getCurrentIndex());
        }
    }

    @Test
    public void testAppendReadableBufferWithLimitPartialArray() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create buffer to append, with a limit before array end
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6, -1};
        ReadableBuffer source = ReadableBuffer.ByteBufferReader.wrap(sourceBufferArray1);
        int limitRemainder  = 1;
        source.limit(source.remaining() - limitRemainder);
        source = source.slice();

        assertTrue(source.hasArray());
        assertEquals(0, source.arrayOffset());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(7, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(2, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertNotSame(sourceBufferArray1, arrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length - limitRemainder; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(sourceBufferArray1.length - limitRemainder, target.getCurrentArrayPosition());

        assertFalse(source.hasRemaining());
    }

    @Test
    public void testAppendReadableBufferWithOffsetPartialArray() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create buffer to append, with an offset
        byte[] sourceBufferArray1 = new byte[] { -1, 4, 5, 6 };
        ReadableBuffer source = ReadableBuffer.ByteBufferReader.wrap(sourceBufferArray1);
        int offset  = 1;
        source.position(offset);
        source = source.slice();

        assertTrue(source.hasArray());
        assertEquals(1, source.arrayOffset());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(7, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(2, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertNotSame(sourceBufferArray1, arrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length - offset; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(sourceBufferArray1.length - offset, target.getCurrentArrayPosition());

        assertFalse(source.hasRemaining());
    }

    @Test
    public void testAppendReadableBufferWithArray() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create buffer to append
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6 };
        ReadableBuffer source = ReadableBuffer.ByteBufferReader.wrap(sourceBufferArray1);

        assertTrue(source.hasArray());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(7, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(2, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertSame(sourceBufferArray1, arrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(sourceBufferArray1.length, target.getCurrentArrayPosition());

        assertFalse(source.hasRemaining());
    }

    @Test
    public void testAppendReadableBufferWithoutArray() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);

        assertEquals(4, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertTrue(target.hasArray());
        assertSame(targetBufferArray1, target.array());
        assertEquals(-1, target.getCurrentIndex());

        // Create buffer to append, 'without an array' (read only bt=ye buffer)
        byte[] sourceBufferArray1 = new byte[] { 4, 5, 6 };
        ByteBuffer readOnly = ByteBuffer.wrap(sourceBufferArray1).asReadOnlyBuffer();
        assertFalse(readOnly.hasArray());

        ReadableBuffer source = ReadableBuffer.ByteBufferReader.wrap(readOnly);

        assertFalse(source.hasArray());
        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(7, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(0, target.getCurrentIndex());
        assertFalse(target.hasArray()); // Now composite, must answer false
        List<byte[]> arrays = target.getArrays();
        assertEquals(2, arrays.size());
        assertSame(targetBufferArray1, arrays.get(0));
        assertNotSame(sourceBufferArray1, arrays.get(1));

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = targetBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(0, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());

        // Check each position in the second array
        for(int i = 0; i < sourceBufferArray1.length; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(1, target.getCurrentIndex());
            assertEquals(initialChunkLength + i, target.get());
        }

        assertEquals(1, target.getCurrentIndex());
        assertEquals(sourceBufferArray1.length, target.getCurrentArrayPosition());

        assertFalse(source.hasRemaining());
    }

    @Test
    public void testAppendOneCompositeToEmpty() {
        // Create an empty buffer to append into
        CompositeReadableBuffer target = new CompositeReadableBuffer();

        assertEquals(0, target.remaining());
        assertFalse(target.hasRemaining());
        assertEquals(0, target.position());
        assertFalse(target.hasArray());
        assertEquals(-1, target.getCurrentIndex());

        // Create a buffer to append
        byte[] sourceBufferArray1 = new byte[] { 0, 1, 2 };
        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);

        assertEquals(3, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertTrue(source.hasArray());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(-1, source.getCurrentIndex());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(3, target.remaining());
        assertEquals(0, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(3, source.position());

        assertEquals(-1, target.getCurrentIndex());
        assertTrue(target.hasArray());
        assertEquals(0, target.getArrays().size());
        assertSame(sourceBufferArray1, target.array());

        // Now read the data back and verify behaviour.

        // Check each position in the first array
        int initialChunkLength = sourceBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(-1, target.getCurrentIndex());
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i, target.get());
        }

        assertEquals(-1, target.getCurrentIndex());
    }

    @Test
    public void testAppendOneCompositeToBufferWithListButNothingRemaining() {
        // Create a buffer to append into
        byte[] targetBufferArray1 = new byte[] { 0, 1, 2, 3 };
        byte[] targetBufferArray2 = new byte[] { 4, 5, 6 };

        CompositeReadableBuffer target = new CompositeReadableBuffer();
        target.append(targetBufferArray1);
        target.append(targetBufferArray2);

        assertEquals(7, target.remaining());
        assertTrue(target.hasRemaining());
        assertEquals(0, target.position());
        assertFalse(target.hasArray());
        assertEquals(0, target.getCurrentIndex());

        // Move position to the end
        target.position(7);
        assertFalse(target.hasRemaining());
        assertEquals(0, target.remaining());
        assertEquals(1, target.getCurrentIndex());

        // Create buffer to append
        byte[] sourceBufferArray1 = new byte[] { 7, 8, 9, 10 };
        CompositeReadableBuffer source = new CompositeReadableBuffer();
        source.append(sourceBufferArray1);

        assertEquals(4, source.remaining());
        assertTrue(source.hasRemaining());
        assertEquals(0, source.position());
        assertTrue(source.hasArray());
        assertSame(sourceBufferArray1, source.array());
        assertEquals(-1, source.getCurrentIndex());

        // Append the buffer, check state of source+target buffers
        target.append(source);

        assertTrue(target.hasRemaining());
        assertEquals(4, target.remaining());
        assertEquals(7, target.position());

        assertFalse(source.hasRemaining());
        assertEquals(0, source.remaining());
        assertEquals(4, source.position());

        assertFalse(target.hasArray());
        assertEquals(3, target.getArrays().size());
        assertEquals(2, target.getCurrentIndex());

        // Now read the data back and verify behaviour.
        int initialChunkLength = sourceBufferArray1.length;
        for(int i = 0; i < initialChunkLength; i++) {
            assertEquals(i, target.getCurrentArrayPosition());
            assertEquals(i + targetBufferArray1.length + targetBufferArray2.length, target.get());
            assertEquals(i+1, target.getCurrentArrayPosition());
            assertEquals(2, target.getCurrentIndex());
            assertSame(sourceBufferArray1, target.getArrays().get(2));
        }

        assertEquals(2, target.getCurrentIndex());
    }

    @Test
    public void testAppendNullByteArray() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append((byte[]) null);
            fail("Should not be able to add a null array");
        } catch (IllegalArgumentException iae) {}
    }

    @Test
    public void testAppendNullCompositeBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append((CompositeReadableBuffer) null);
            fail("Should not be able to add a null composite");
        } catch (IllegalArgumentException iae) {}
    }

    @Test
    public void testAppendNullReadableBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append((ReadableBuffer) null);
            fail("Should not be able to add a null readable");
        } catch (IllegalArgumentException iae) {}
    }

    @Test
    public void testAppendEmptyByteArray() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append(new byte[0]);
            fail("Should not be able to add a empty array");
        } catch (IllegalArgumentException iae) {}
    }

    @Test
    public void testAppendEmptyCompositeBuffer() {
        CompositeReadableBuffer empty = new CompositeReadableBuffer();

        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append(empty);
            fail("Should not be able to append an empty composite");
        } catch (IllegalArgumentException iae) {}
    }

    @Test
    public void testAppendEmptyReadableBuffer() {
        ReadableBuffer empty = ReadableBuffer.ByteBufferReader.allocate(0);

        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        try {
            buffer.append(empty);
            fail("Should not be able to append an empty readable");
        } 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 testCompactSingleArrayBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        byte[] source = new byte[] { 0, 1, 2, 3 };

        buffer.append(source);

        assertEquals(4, buffer.remaining());
        assertEquals(4, buffer.limit());
        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());
        assertEquals(4, buffer.limit());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());
        assertTrue(buffer.hasArray());
        assertSame(source, buffer.array());
        assertEquals(0, buffer.getCurrentArrayPosition());

        // Should not have any affect on buffer that is not consumed
        buffer.position(1);
        assertEquals(1, buffer.getCurrentArrayPosition());
        buffer.reclaimRead();

        assertEquals(3, buffer.remaining());
        assertEquals(4, buffer.limit());
        assertTrue(buffer.hasRemaining());
        assertEquals(1, buffer.position());
        assertEquals(1, buffer.getCurrentArrayPosition());
        assertTrue(buffer.hasArray());
        assertSame(source, buffer.array());

        // Should clear array from buffer as it is now consumed.
        buffer.position(source.length);
        assertEquals(source.length, buffer.getCurrentArrayPosition());
        buffer.reclaimRead();

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(0, buffer.position());
        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.getCurrentArrayPosition());
    }

    @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(0, buffer.getCurrentArrayPosition());
        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(0, buffer.getCurrentArrayPosition());
        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(0, buffer.getCurrentArrayPosition());
        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.getCurrentArrayPosition());
        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(0, buffer.getCurrentArrayPosition());
        assertEquals(size, buffer.limit());
        assertEquals(size, buffer.capacity());

        buffer.position(buffer.limit());
        assertEquals(4, buffer.getCurrentArrayPosition());
        buffer.reclaimRead();

        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.getArrays().size());
        assertEquals(-1, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());
        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());
        assertEquals(0, buffer.getCurrentArrayPosition());

        buffer.position(4);
        assertEquals(1, buffer.getCurrentIndex());
        assertEquals(0, buffer.getCurrentArrayPosition());

        buffer.reclaimRead();

        assertEquals(0, buffer.position());
        assertEquals(4, buffer.limit());
        assertEquals(4, buffer.capacity());
        assertEquals(1, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentArrayPosition());

        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 testDuplicateOnEmptyBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        CompositeReadableBuffer dup = buffer.duplicate();

        assertNotSame(buffer, dup);
        assertEquals(0, dup.capacity());
        assertEquals(0, buffer.capacity());
        assertEquals(0, dup.position());
        assertEquals(0, buffer.position());
        assertEquals(0, dup.limit());
        assertEquals(0, buffer.limit());
        assertContentEquals(buffer, dup);

        try {
            dup.reclaimRead();
        } catch (Throwable t) {
            fail("Compacting an empty duplicate should not fail");
        }
    }

    @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 testSliceWithNoRemainderRefusesAppends() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        buffer.append(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9});

        // Empty slice at end of buffer
        assertEquals(10, buffer.remaining());
        buffer.position(10);
        assertEquals(0, buffer.remaining());

        CompositeReadableBuffer emptySlice = buffer.slice();
        assertNotSame(buffer, emptySlice);
        assertEquals(0, emptySlice.remaining());

        try {
            emptySlice.append(new byte[] { 10 });
            fail("Should not be allowed to append to empty slice, must throw IllegalStateException");
        } catch (IllegalStateException ise) {}

        // Empty slice at start of buffer
        buffer.position(0);
        assertEquals(10, buffer.remaining());
        buffer.limit(0);
        assertEquals(0, buffer.remaining());

        emptySlice = buffer.slice();
        assertNotSame(buffer, emptySlice);
        assertEquals(0, emptySlice.remaining());

        try {
            emptySlice.append(new byte[] { 10 });
            fail("Should not be allowed to append to empty slice, must throw IllegalStateException");
        } catch (IllegalStateException ise) {}
    }

    @Test
    public void testSliceRefusesAppends() {
        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 IllegalStateException");
        } catch (IllegalStateException ise) {}

        CompositeReadableBuffer crb = new CompositeReadableBuffer();
        crb.append(new byte[] { 10 });
        try {
            slice.append(crb);
            fail("Should not be allowed to append to a slice, must throw IllegalStateException");
        } catch (IllegalStateException ise) {}

        ReadableBuffer rb = ReadableBuffer.ByteBufferReader.wrap(new byte[] { 10 });
        try {
            slice.append(rb);
            fail("Should not be allowed to append to a slice, must throw IllegalStateException");
        } 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 readString ------------------------------------------//

    @Test
    public void testReadStringFromEmptyBuffer() throws CharacterCodingException {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        assertEquals("", 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);

        assertEquals(0, buffer.position());
    }

    @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);

        assertEquals(0, buffer1.position());
        assertEquals(0, buffer2.position());
        assertEquals(0, buffer3.position());
    }

    @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);

        assertEquals(0, buffer1.position());
        assertEquals(0, buffer2.position());
    }

    @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);

        assertEquals(0, buffer1.position());
        assertEquals(0, buffer2.position());
    }

    @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);

        assertEquals(0, buffer1.position());
        assertEquals(0, buffer2.position());
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentStartPositionsSame() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentStartPositionsSameTestImpl(false);
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentStartPositionsSameMultipleArrays() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentStartPositionsSameTestImpl(true);
    }

    private void doEqualsWhenContentRemainingWithDifferentStartPositionsSameTestImpl(boolean multipleArrays) {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

        byte[] data1 = new byte[] {-1, -1, 0, 1, 2, 3, 4, 5};
        byte[] data2 = new byte[] {-1, -1, -1, 0, 1, 2, 3, 4, 5};

        buffer1.append(data1);
        buffer1.position(2);

        buffer2.append(data2);
        buffer2.position(3);

        if (multipleArrays) {
            byte[] data3 = new byte[] { 5, 4, 3, 2, 1 };
            buffer1.append(data3);
            buffer2.append(data3);
        }

        assertEquals(buffer1, buffer2);

        assertEquals(2, buffer1.position());
        assertEquals(3, buffer2.position());
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentStartPositionsNotSame() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentStartPositionsNotSameTestImpl(false);
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentStartPositionsNotSameMultipleArrays() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentStartPositionsNotSameTestImpl(true);
    }

    private void doEqualsWhenContentRemainingWithDifferentStartPositionsNotSameTestImpl(boolean multipleArrays) {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

        byte[] data1 = new byte[] {-1, -1, 0, 1, 2, 3, 4, 5};
        byte[] data2 = new byte[] {-1, -1, -1, 0, 1, 2, 3, 4, -1};

        buffer1.append(data1);
        buffer1.position(2);

        buffer2.append(data2);
        buffer2.position(3);

        if (multipleArrays) {
            byte[] data3 = new byte[] { 5, 4, 3, 2, 1 };
            buffer1.append(data3);
            buffer2.append(data3);
        }

        assertNotEquals(buffer1, buffer2);

        assertEquals(2, buffer1.position());
        assertEquals(3, buffer2.position());
    }

    //----- 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[4];
        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[8];
        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));
    }
}
