/*
 * 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.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
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.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.AmqpValue;
import org.apache.qpid.proton.amqp.messaging.Footer;
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 testPositionMovedOnArrayBounderies() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();

        buffer.append(new byte[] { 1, 2, 3, 4 });
        buffer.append(new byte[] { 5, 6 });
        buffer.append(new byte[] { 7, 8, 9, 10, 11, 12, 13, 14 });
        buffer.append(new byte[] { 15 });

        buffer.getInt();
        assertEquals(5, buffer.get(4));
        buffer.get();
        buffer.get();
        buffer.getLong();
        assertEquals(15, buffer.get(14));
        assertEquals(15, buffer.get(14));

        try {
            buffer.get(15);
        } catch (IndexOutOfBoundsException aiobe) {}

        buffer.position(4);
        assertEquals(5, buffer.get(4));
    }

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

    @Test
    public void testReadUnicodeStringAcrossArrayBoundries() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] slice1 = new byte[] { utf8[0] };
        byte[] slice2 = new byte[utf8.length - 1];

        System.arraycopy(utf8, 1, slice2, 0, slice2.length);

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(slice1);
        composite.append(slice2);

        String result = composite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadUnicodeStringAcrossMultipleArrayBoundries() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] slice1 = new byte[] { utf8[0] };
        byte[] slice2 = new byte[] { utf8[1], utf8[2] };
        byte[] slice3 = new byte[] { utf8[3], utf8[4] };
        byte[] slice4 = new byte[utf8.length - 5];

        System.arraycopy(utf8, 5, slice4, 0, slice4.length);

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(slice1);
        composite.append(slice2);
        composite.append(slice3);
        composite.append(slice4);

        String result = composite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadUnicodeStringEachByteInOwnArray() throws IOException {
        String expected = "\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        assertEquals(4, utf8.length);

        byte[] slice1 = new byte[] { utf8[0] };
        byte[] slice2 = new byte[] { utf8[1] };
        byte[] slice3 = new byte[] { utf8[2] };
        byte[] slice4 = new byte[] { utf8[3] };

        System.arraycopy(utf8, 1, slice2, 0, slice2.length);

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(slice1);
        composite.append(slice2);
        composite.append(slice3);
        composite.append(slice4);

        String result = composite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadSlicedWithInvalidEncodingsOutsideSlicedRange() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] payload = new byte[utf8.length + 2];  // Add two for malformed UTF8

        System.arraycopy(utf8, 0, payload, 0, utf8.length);

        payload[utf8.length] = (byte) 0b11000111;     // Two byte utf8 encoding prefix
        payload[utf8.length + 1] = (byte) 0b00110000; // invalid next byte encoding should be 0b10xxxxxx

        CompositeReadableBuffer composite = new CompositeReadableBuffer().append(payload);
        ReadableBuffer slicedComposite = composite.limit(utf8.length).slice();

        String result = slicedComposite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadSliceWithInvalidEncodingsOutsideSlicedRangeWithArraySpans() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] span1 = new byte[] { utf8[0] };
        byte[] span2 = new byte[utf8.length + 2];  // Add two for malformed UTF8

        System.arraycopy(utf8, 1, span2, 0, utf8.length - 1);

        span2[utf8.length] = (byte) 0b11000111;     // Two byte utf8 encoding prefix
        span2[utf8.length + 1] = (byte) 0b00110000; // invalid next byte encoding should be 0b10xxxxxx

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(span1);
        composite.append(span2);

        ReadableBuffer slicedComposite = composite.limit(utf8.length).slice();

        String result = slicedComposite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadSliceWithInvalidEncodingsOutsideSlicedRangeWithArraySpansAndEarlySpan() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] span1 = new byte[] { 0, 1, 2, 3, 4 };
        byte[] span2 = new byte[] { utf8[0] };
        byte[] span3 = new byte[utf8.length + 2];  // Add two for malformed UTF8

        System.arraycopy(utf8, 1, span3, 0, utf8.length - 1);

        span3[utf8.length] = (byte) 0b11000111;     // Two byte utf8 encoding prefix
        span3[utf8.length + 1] = (byte) 0b00110000; // invalid next byte encoding should be 0b10xxxxxx

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(span1);
        composite.append(span2);
        composite.append(span3);

        ReadableBuffer slicedComposite = composite.position(span1.length).limit(span1.length + utf8.length).slice();

        String result = slicedComposite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testReadSliceWithInvalidEncodingsSurroundingSlicedSpanningRanges() throws IOException {
        String expected = "\u1f4a9\u1f4a9\u1f4a9";

        byte[] utf8 = expected.getBytes(StandardCharsets.UTF_8);

        byte[] span1 = new byte[] { (byte) 0b11000111, 0b00110000, utf8[0] };
        byte[] span2 = new byte[] { utf8[1] };
        byte[] span3 = new byte[utf8.length];  // provides two slots for malformed UTF8

        System.arraycopy(utf8, 2, span3, 0, utf8.length - 2);

        span3[span3.length - 2] = (byte) 0b11000111;     // Two byte utf8 encoding prefix
        span3[span3.length - 1] = (byte) 0b00110000; // invalid next byte encoding should be 0b10xxxxxx

        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(span1);
        composite.append(span2);
        composite.append(span3);

        ReadableBuffer slicedComposite = composite.position(span1.length - 1)             // Start at first utf8 byte
                                                  .limit(span1.length + utf8.length - 1)  // run to end of span 2 minus the trailing
                                                  .slice();

        String result = slicedComposite.readUTF8();

        assertEquals("Failed to round trip String correctly: ", expected, result);
    }

    @Test
    public void testRoundtripUnicodeStringThatSpansArraySlicesButDoesntFillLastContainingArray() throws IOException {
        StringBuilder unicodeStringBuilder = new StringBuilder();

        unicodeStringBuilder.append((char) 1000);
        unicodeStringBuilder.append((char) 1001);
        unicodeStringBuilder.append((char) 1002);
        unicodeStringBuilder.append((char) 1003);

        final DecoderImpl decoder = new DecoderImpl();
        final EncoderImpl encoder = new EncoderImpl(decoder);
        AMQPDefinedTypes.registerAllTypes(decoder, encoder);
        final ByteBuffer bb = ByteBuffer.allocate(1024);

        final AmqpValue inputValue = new AmqpValue(unicodeStringBuilder.toString());
        encoder.setByteBuffer(bb);
        encoder.writeObject(inputValue);

        assertTrue(bb.position() > 1);

        // Now write some trailing content, which will fill the
        // remainder of the last array after the end of the string
        Map<Symbol, Object> footerValues = new HashMap<>();
        footerValues.put(Symbol.valueOf("some-key"), "some-value");

        int startOfFooter = bb.position();
        encoder.writeObject(new Footer(footerValues));
        assertTrue("position did not move as required", bb.position() > startOfFooter);

        // Prepare the array slices
        int firstSliceLength = startOfFooter - 1;

        final byte[] slice1 = new byte[firstSliceLength];
        int remainder = bb.position() - firstSliceLength;
        final byte[] slice2 = new byte[remainder];

        bb.flip();
        bb.get(slice1);
        bb.get(slice2);

        // Create the buffer with them, then read the string and footer back
        CompositeReadableBuffer composite = new CompositeReadableBuffer();
        composite.append(slice1);
        composite.append(slice2);

        decoder.setBuffer(composite);

        final AmqpValue outputValue = (AmqpValue) decoder.readObject();
        assertEquals("Failed to round trip String correctly: ", unicodeStringBuilder.toString(), outputValue.getValue());

        final Footer footer = (Footer) decoder.readObject();
        assertNotNull(footer);
        assertEquals("Failed to round trip Footer correctly: ", footerValues, footer.getValue());
    }

    //----- 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 testHashCodeMatchesByteBufferWhenLimitSetGivesNoRemaining() throws CharacterCodingException {
        byte[] data = new byte[] {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        buffer1.append(data);
        buffer1.limit(10);

        ByteBuffer buffer2 = ByteBuffer.wrap(data);
        buffer2.limit(10);

        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());
    }

    @Test
    public void testHashCodeMatchesByteBufferMultipleArrayContentsWithRangeOfLimits() throws CharacterCodingException {
        byte[] data = new byte[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

        byte[] data1 = new byte[] {10, 9};
        byte[] data2 = new byte[] {8, 7};
        byte[] data3 = new byte[] {6, 5, 4};
        byte[] data4 = new byte[] {3};
        byte[] data5 = new byte[] {2, 1, 0};

        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        buffer1.append(data1).append(data2).append(data3).append(data4).append(data5);

        ByteBuffer buffer2 = ByteBuffer.wrap(data);

        for (int i = 0; i < data.length; ++i) {
            buffer1.limit(i);
            buffer2.limit(i);

            assertEquals(buffer1.hashCode(), buffer2.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());
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentlyPositionedSlicesSame() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesSameTestImpl(false);
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentlyPositionedSlicesSameMultipleArrays() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesSameTestImpl(true);
    }

    private void doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesSameTestImpl(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);
        }

        buffer1 = buffer1.slice();
        buffer2 = buffer2.slice();

        assertEquals(buffer1, buffer2);
        assertEquals(buffer2, buffer1);

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

    @Test
    public void testEqualsWhenContentRemainingWithDifferentlyPositionedSlicesNotSame() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesNotSameTestImpl(false);
    }

    @Test
    public void testEqualsWhenContentRemainingWithDifferentlyPositionedSlicesNotSameMultipleArrays() throws CharacterCodingException {
        doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesNotSameTestImpl(true);
    }

    private void doEqualsWhenContentRemainingWithDifferentlyPositionedSlicesNotSameTestImpl(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);
        }

        buffer1 = buffer1.slice();
        buffer2 = buffer2.slice();

        assertNotEquals(buffer1, buffer2);
        assertNotEquals(buffer2, buffer1);

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

    @Test
    public void testEqualsWhenContentRemainingIsSubsetOfSingleChunkInMultiArrayBufferSame() {
        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);

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

        buffer1.limit(data1.length);
        buffer2.limit(data2.length);

        assertEquals(6, buffer1.remaining());
        assertEquals(6, buffer2.remaining());

        assertEquals(buffer1, buffer2);
        assertEquals(buffer2, buffer1);

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

    @Test
    public void testEqualsWhenContentRemainingIsSubsetOfSingleChunkInMultiArrayBufferNotSame() {
        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);

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

        buffer1.limit(data1.length);
        buffer2.limit(data2.length);

        assertEquals(6, buffer1.remaining());
        assertEquals(6, buffer2.remaining());

        assertNotEquals(buffer1, buffer2);
        assertNotEquals(buffer2, buffer1);

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