/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.qpid.proton.codec;

import static org.junit.Assert.*;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.InvalidMarkException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.StandardCharsets;

import org.junit.Test;

/**
 * Test for API of the CompositeReadableBuffer class.
 */
public class CompositeReadableBufferTest {

    //----- Test newly create buffer behaviors -------------------------------//

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

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

    //----- Test limit handling ----------------------------------------------//

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());
        assertEquals(10, buffer.position());

        buffer.limit(5);
        assertEquals(5, buffer.limit());
        assertEquals(5, buffer.position());

        try {
            buffer.reset();
            fail("Should throw a InvalidMarkException");
        } catch (InvalidMarkException e) {}

        buffer.mark();
        buffer.limit(10);
        buffer.position(10);

        try {
            buffer.reset();
        } catch (InvalidMarkException e) {
            fail("Should not throw a InvalidMarkException");
        }

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

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());
        assertEquals(10, buffer.position());

        buffer.limit(5);
        assertEquals(5, buffer.limit());
        assertEquals(5, buffer.position());

        try {
            buffer.reset();
            fail("Should throw a InvalidMarkException");
        } catch (InvalidMarkException e) {}

        buffer.mark();
        buffer.limit(10);
        buffer.position(10);

        try {
            buffer.reset();
        } catch (InvalidMarkException e) {
            fail("Should not throw a InvalidMarkException");
        }

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

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());

        buffer.limit(5);
        assertEquals(5, buffer.limit());

        buffer.limit(6);
        assertEquals(6, buffer.limit());

        try {
            buffer.limit(11);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}
    }

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());

        buffer.limit(5);
        assertEquals(5, buffer.limit());

        buffer.limit(6);
        assertEquals(6, buffer.limit());

        try {
            buffer.limit(11);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}
    }

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

        // test with nothing appended.
        try {
            buffer.limit(2);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        try {
            buffer.limit(-1);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        // Test with something appended
        buffer.append(new byte[] { 127 });

        try {
            buffer.limit(2);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        try {
            buffer.limit(-1);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}
    }

    //----- Test position handling -------------------------------------------//

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());
        assertEquals(0, buffer.position());

        buffer.position(5);
        assertEquals(5, buffer.position());

        buffer.position(6);
        assertEquals(6, buffer.position());

        buffer.position(10);
        assertEquals(10, buffer.position());

        try {
            buffer.position(11);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        buffer.mark();

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

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException ime) {}
    }

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

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

        assertEquals(10, buffer.capacity());
        assertEquals(10, buffer.limit());

        buffer.position(5);
        assertEquals(5, buffer.position());

        buffer.position(6);
        assertEquals(6, buffer.position());

        buffer.position(10);
        assertEquals(10, buffer.position());

        try {
            buffer.position(11);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

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

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

        // test with nothing appended.
        try {
            buffer.position(2);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        try {
            buffer.position(-1);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        // Test with something appended
        buffer.append(new byte[] { 127 });

        try {
            buffer.position(2);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}

        try {
            buffer.position(-1);
            fail("Should throw a IllegalArgumentException");
        } catch (IllegalArgumentException e) {}
    }

    //----- Test buffer get methods ------------------------------------------//

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

        try {
            buffer.get();
            fail("Should throw a BufferUnderflowException");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 127 });

        assertEquals(1, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(127, buffer.get());

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(1, buffer.position());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

        assertEquals(10, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        for (int i = 0; i < 10; ++i) {
            assertEquals(i, buffer.get());
            assertEquals(i + 1, buffer.position());
        }

        assertEquals(0, buffer.remaining());
        assertEquals(10, buffer.position());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

        assertEquals(10, buffer.remaining());
        assertFalse(buffer.hasArray());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        for (int i = 0; i < 10; ++i) {
            assertEquals(i, buffer.get());
        }

        assertEquals(0, buffer.remaining());
        assertEquals(10, buffer.position());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

        assertEquals(10, buffer.remaining());
        assertFalse(buffer.hasArray());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        for (int i = 0; i < 10; ++i) {
            assertEquals(i, buffer.get());
        }

        assertEquals(0, buffer.remaining());
        assertEquals(10, buffer.position());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        try {
            buffer.getShort();
            fail("Should throw a BufferUnderflowException");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 8, 0 });

        assertEquals(2, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getShort());

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(2, buffer.position());

        try {
            buffer.getShort();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] {8}).append(new byte[] {0});

        assertEquals(2, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getShort());

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(2, buffer.position());

        try {
            buffer.getShort();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        try {
            buffer.getInt();
            fail("Should throw a BufferUnderflowException");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 0, 0, 8, 0 });

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getInt());

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

        try {
            buffer.getInt();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 0 ,0 }).append(new byte[] { 8, 0 });

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getInt());

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

        try {
            buffer.getInt();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        try {
            buffer.getLong();
            fail("Should throw a BufferUnderflowException");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 0, 0, 0, 0, 0, 0, 8, 0 });

        assertEquals(8, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getLong());

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(8, buffer.position());

        try {
            buffer.getLong();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(new byte[] { 0 ,0, 0, 0 }).append(new byte[] { 0, 0, 8, 0 });

        assertEquals(8, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(2048, buffer.getLong());

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(8, buffer.position());

        try {
            buffer.getLong();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

        assertEquals(data.length, buffer.limit());
        byte array[] = new byte[1];

        for (int i = 0; i < data.length; i++) {
            assertEquals(buffer.position(), i);
            ReadableBuffer self = buffer.get(array);
            assertEquals(array[0], buffer.get(i));
            assertSame(self, buffer);
        }

        try {
            buffer.get(array);
            fail("Should throw BufferUnderflowException");
        } catch (BufferUnderflowException e) {
        }

        try {
            buffer.get((byte[]) null);
            fail("Should throw NullPointerException");
        } catch (NullPointerException e) {
        }
    }

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

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

        assertEquals(data.length, buffer.limit());

        ByteBuffer destination = ByteBuffer.allocate(1);
        WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination);

        for (int i = 0; i < data.length; i++) {
            assertEquals(buffer.position(), i);
            ReadableBuffer self = buffer.get(target);
            assertEquals(destination.get(0), buffer.get(i));
            assertSame(self, buffer);
            destination.rewind();
        }

        try {
            buffer.get(target);
        } catch (Throwable e) {
            fail("Should not throw: " + e.getClass().getSimpleName());
        }

        try {
            buffer.get((WritableBuffer) null);
            fail("Should throw NullPointerException");
        } catch (NullPointerException e) {
        }
    }

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

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

        int size = data1.length + data2.length + data3.length;

        buffer.append(data1).append(data2).append(data3);

        assertEquals(size, buffer.limit());

        ByteBuffer destination = ByteBuffer.allocate(1);
        WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination);

        for (int i = 0; i < size; i++) {
            assertEquals(buffer.position(), i);
            ReadableBuffer self = buffer.get(target);
            assertEquals(destination.get(0), buffer.get(i));
            assertSame(self, buffer);
            destination.rewind();
        }

        try {
            buffer.get(target);
        } catch (Throwable e) {
            fail("Should not throw: " + e.getClass().getSimpleName());
        }

        try {
            buffer.get((WritableBuffer) null);
            fail("Should throw NullPointerException");
        } catch (NullPointerException e) {
        }
    }

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

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

        ByteBuffer destination = ByteBuffer.allocate(data.length);
        WritableBuffer target = WritableBuffer.ByteBufferWrapper.wrap(destination);

        buffer.get(target);

        assertEquals(5, buffer.position());
        assertEquals(0, buffer.remaining());

        assertEquals(5, target.position());
        assertEquals(5, target.remaining());
    }

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

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

        for (int i = 0; i < buffer.capacity(); i++) {
            assertEquals(buffer.position(), i);
            assertEquals(buffer.get(i), buffer.get());
        }

        buffer.rewind();

        for (int i = 0; i < buffer.capacity(); i++) {
            assertEquals(buffer.position(), i);
            assertEquals(buffer.get(), buffer.get(i));
        }

        try {
            buffer.get(-1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(buffer.limit());
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }
    }

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

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

        for (int i = 0; i < buffer.capacity(); i++) {
            assertEquals(buffer.position(), i);
            assertEquals(buffer.get(), buffer.get(i));
        }

        try {
            buffer.get(-1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(buffer.limit());
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }
    }

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

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

        byte array[] = new byte[data.length];

        try {
            buffer.get(new byte[data.length + 1], 0, data.length + 1);
            fail("Should throw BufferUnderflowException");
        } catch (BufferUnderflowException e) {
        }

        assertEquals(buffer.position(), 0);

        try {
            buffer.get(array, -1, array.length);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        buffer.get(array, array.length, 0);

        try {
            buffer.get(array, array.length + 1, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        assertEquals(buffer.position(), 0);

        try {
            buffer.get(array, 2, -1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(array, 2, array.length);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get((byte[])null, -1, 0);
            fail("Should throw NullPointerException");
        } catch (NullPointerException e) {
        }

        try {
            buffer.get(array, 1, Integer.MAX_VALUE);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(array, Integer.MAX_VALUE, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        assertEquals(buffer.position(), 0);

        CompositeReadableBuffer self = buffer.get(array, 0, array.length);
        assertEquals(buffer.position(), buffer.capacity());
        assertContentEquals(buffer, array, 0, array.length);
        assertSame(self, buffer);
    }

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

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

        final int dataLength = data1.length + data2.length;

        buffer.append(data1).append(data2);

        assertEquals(dataLength, buffer.remaining());

        byte array[] = new byte[buffer.remaining()];

        try {
            buffer.get(new byte[dataLength + 1], 0, dataLength + 1);
            fail("Should throw BufferUnderflowException");
        } catch (BufferUnderflowException e) {
        }

        assertEquals(buffer.position(), 0);

        try {
            buffer.get(array, -1, array.length);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        buffer.get(array, array.length, 0);

        try {
            buffer.get(array, array.length + 1, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        assertEquals(buffer.position(), 0);

        try {
            buffer.get(array, 2, -1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(array, 2, array.length);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get((byte[])null, -1, 0);
            fail("Should throw NullPointerException");
        } catch (NullPointerException e) {
        }

        try {
            buffer.get(array, 1, Integer.MAX_VALUE);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        try {
            buffer.get(array, Integer.MAX_VALUE, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }

        assertEquals(buffer.position(), 0);

        CompositeReadableBuffer self = buffer.get(array, 0, array.length);
        assertEquals(buffer.position(), buffer.capacity());
        assertContentEquals(buffer, array, 0, array.length);
        assertSame(self, buffer);
    }

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

        buffer.append(float2bytes(3.14f));

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(3.14f, buffer.getFloat(), 0.1);

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

        try {
            buffer.getFloat();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

        buffer.append(double2bytes(6.11));

        assertEquals(8, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertEquals(6.11, buffer.getDouble(), 0.1);

        assertEquals(0, buffer.remaining());
        assertFalse(buffer.hasRemaining());
        assertEquals(8, buffer.position());

        try {
            buffer.getDouble();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

    //----- Test hasArray method ---------------------------------------------//

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

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

        assertTrue(buffer.hasArray());
        assertNotNull(buffer.array());
        assertSame(data1, buffer.array());
        assertEquals(0, buffer.arrayOffset());

        buffer.append(data2);

        assertFalse(buffer.hasArray());
        try {
            buffer.array();
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException e) {
        }
        try {
            buffer.arrayOffset();
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException e) {
        }

        byte[] result1 = new byte[data1.length];
        byte[] result2 = new byte[data1.length];

        buffer.get(result1);
        assertArrayEquals(data1, result1);
        assertFalse(buffer.hasArray());

        buffer.reclaimRead();

        assertTrue(buffer.hasArray());
        assertNotNull(buffer.array());
        assertSame(data2, buffer.array());
        assertEquals(0, buffer.arrayOffset());

        buffer.get(result2);
        assertArrayEquals(data2, result2);
        assertTrue(buffer.hasArray());

        buffer.reclaimRead();
        assertFalse(buffer.hasArray());

        try {
            buffer.array();
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException e) {
        }
        try {
            buffer.arrayOffset();
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException e) {
        }
    }

    //----- Test 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 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());

        buffer.position(source1.length);

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

        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(source1.length, buffer.position());

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

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

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

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

        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(source1.length + source2.length, buffer.position());

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

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

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

        buffer.append(source);

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        assertTrue(buffer.hasArray());
        assertSame(source, buffer.array());
        assertEquals(0, buffer.getArrays().size());

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

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

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

        buffer.append(source1);
        assertTrue(buffer.hasArray());
        assertSame(source1, buffer.array());
        assertEquals(-1, buffer.getCurrentIndex());

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

        byte[] source3 = new byte[] { 9, 10, 11, 12 };
        buffer.append(source3);
        assertFalse(buffer.hasArray());
        assertEquals(3, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
    }

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

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

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

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

    //----- Test buffer compaction handling ----------------------------------//

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

        try {
            buffer.reclaimRead();
        } catch (Throwable t) {
            fail("Should not fail to compact empty buffer");
        }

        CompositeReadableBuffer slice = buffer.slice();

        try {
            slice.reclaimRead();
        } catch (Throwable t) {
            fail("Should not fail to compact empty slice");
        }
    }

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

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

        buffer.append(source);

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());
        assertTrue(buffer.hasArray());
        assertSame(source, buffer.array());
        assertEquals(0, buffer.getArrays().size());

        // Should not have any affect on buffer that is not consumed
        buffer.reclaimRead();

        assertEquals(4, buffer.remaining());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());
        assertTrue(buffer.hasArray());
        assertSame(source, buffer.array());

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

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

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

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

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

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

        assertEquals(10, buffer.remaining());
        assertEquals(10, buffer.getArrays().size());
        assertFalse(buffer.hasArray());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        for (int i = 0; i < 10; ++i) {
            assertEquals(i, buffer.get());
            buffer.reclaimRead();
            assertEquals(0, buffer.position());
        }

        assertTrue(buffer.getArrays().isEmpty());
        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.remaining());
        assertEquals(0, buffer.position());
        assertEquals(0, buffer.getArrays().size());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

        assertEquals(10, buffer.remaining());
        assertFalse(buffer.hasArray());
        assertTrue(buffer.hasRemaining());
        assertEquals(0, buffer.position());

        for (int i = 0; i < 10; ++i) {
            assertEquals(i, buffer.get());
            buffer.reclaimRead();
        }

        assertTrue(buffer.getArrays().isEmpty());
        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.remaining());
        assertEquals(0, buffer.position());

        try {
            buffer.get();
            fail("Should not be able to read past end");
        } catch (BufferUnderflowException e) {}
    }

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

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

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

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

        buffer.position(5);
        buffer.mark();
        assertEquals(5, buffer.get());
        buffer.position(8);
        buffer.reset();
        assertEquals(5, buffer.position());
        buffer.mark();

        buffer.reclaimRead();
        buffer.position(buffer.limit());
        buffer.reset();
        assertEquals(5, buffer.get());

        assertFalse(buffer.getArrays().isEmpty());
    }

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

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

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

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

        buffer.position(4);
        buffer.reclaimRead();

        assertFalse(buffer.hasArray());
        assertEquals(2, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
        assertEquals(8, buffer.limit());
        assertEquals(8, buffer.capacity());

        buffer.position(4);
        buffer.reclaimRead();

        // TODO - Right now we hold off purging the array list until everything is consumed.
        assertTrue(buffer.hasArray());
        assertEquals(1, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
        assertEquals(4, buffer.limit());
        assertEquals(4, buffer.capacity());

        buffer.position(4);
        buffer.reclaimRead();

        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.getArrays().size());
        assertEquals(-1, buffer.getCurrentIndex());
        assertEquals(0, buffer.limit());
        assertEquals(0, buffer.capacity());
    }

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

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

        int size = source1.length + source2.length + source3.length + source4.length;

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

        assertFalse(buffer.hasArray());
        assertEquals(4, buffer.getArrays().size());
        assertEquals(0, buffer.getCurrentIndex());
        assertEquals(size, buffer.limit());
        assertEquals(size, buffer.capacity());

        buffer.position(buffer.limit());
        buffer.reclaimRead();

        assertFalse(buffer.hasArray());
        assertEquals(0, buffer.getArrays().size());
        assertEquals(-1, buffer.getCurrentIndex());
        assertEquals(0, buffer.limit());
        assertEquals(0, buffer.capacity());
    }

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

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

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

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

        buffer.position(4);
        buffer.reclaimRead();

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

        byte[] source3 = new byte[] { 8, 9, 10, 11 };

        buffer.append(source3);

        buffer.position(4);

        for (int i = 0; i < source3.length; ++i) {
            assertEquals(source3[i], buffer.get());
        }

        assertFalse(buffer.getArrays().isEmpty());
        buffer.reclaimRead();
        assertTrue(buffer.getArrays().isEmpty());
    }

    //----- Tests on Mark ----------------------------------------------------//

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

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

        // save state
        int oldPosition = buffer.position();
        int oldLimit = buffer.limit();

        assertEquals(0, oldPosition);
        assertEquals(10, oldLimit);

        CompositeReadableBuffer self = buffer.mark();
        assertSame(self, buffer);

        buffer.mark();
        buffer.position(buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), oldPosition);

        buffer.mark();
        buffer.position(buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), oldPosition);

        // restore state
        buffer.limit(oldLimit);
        buffer.position(oldPosition);
    }

    //----- Tests on Reset ---------------------------------------------------//

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

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

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException when not marked.");
        } catch (InvalidMarkException e) {
        }

        // save state
        int oldPosition = buffer.position();
        int oldLimit = buffer.limit();

        assertEquals(0, oldPosition);
        assertEquals(10, oldLimit);

        buffer.mark();
        buffer.position(buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), oldPosition);

        buffer.mark();
        buffer.position(buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), oldPosition);

        // Can call as mark is not cleared on reset.
        CompositeReadableBuffer self = buffer.reset();
        assertSame(self, buffer);
    }

    //----- Tests on Rewind --------------------------------------------------//

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

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

        // save state
        int oldPosition = buffer.position();
        int oldLimit = buffer.limit();

        assertEquals(0, oldPosition);
        assertEquals(10, oldLimit);

        CompositeReadableBuffer self = buffer.rewind();
        assertEquals(buffer.position(), 0);
        assertSame(self, buffer);

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }
    }

    //----- Tests on Flip ----------------------------------------------------//

    @Test
    public void testFlipWhenEmpty() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        CompositeReadableBuffer ret = buffer.flip();

        assertSame(ret, buffer);
        assertEquals(buffer.position(), 0);
        assertEquals(buffer.limit(), 0);
    }

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

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

        // save state
        int oldPosition = buffer.position();
        int oldLimit = buffer.limit();

        assertEquals(0, oldPosition);
        assertEquals(10, oldLimit);

        CompositeReadableBuffer ret = buffer.flip();
        assertSame(ret, buffer);
        assertEquals(buffer.position(), 0);
        assertEquals(buffer.limit(), oldPosition);

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }
    }

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

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

        // save state
        int oldPosition = buffer.position();
        int oldLimit = buffer.limit();

        assertEquals(0, oldPosition);
        assertEquals(10, oldLimit);

        CompositeReadableBuffer ret = buffer.flip();
        assertSame(ret, buffer);
        assertEquals(buffer.position(), 0);
        assertEquals(buffer.limit(), oldPosition);

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }
    }

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

        buffer.mark();
        buffer.position(1);
        buffer.limit(buffer.remaining() - 1);

        ReadableBuffer slice = buffer.slice();

        assertEquals(1, slice.get(0));
        slice.position(1);
        slice.mark();
        slice.flip();

        assertEquals(1, slice.get(0));
        assertEquals(1, slice.limit());

        try {
            slice.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }

        buffer.reset();
        assertEquals(0, buffer.position());
        assertEquals(buffer.remaining(), buffer.limit());
    }

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

        buffer.mark();
        buffer.position(5);

        ReadableBuffer slice = buffer.slice();

        assertEquals(5, slice.get(0));
        slice.position(1);
        slice.mark();
        slice.flip();

        assertEquals(5, slice.get(0));
        assertEquals(1, slice.limit());

        try {
            slice.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }

        buffer.reset();
        assertEquals(0, buffer.position());
        assertEquals(buffer.remaining(), buffer.limit());
    }

    //----- Tests on Clear --------------------------------------------------//

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

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

        assertEquals(0, buffer.position());
        assertEquals(10, buffer.limit());

        buffer.position(5);
        assertEquals(5, buffer.position());
        buffer.mark();

        CompositeReadableBuffer self = buffer.clear();
        assertEquals(0, buffer.position());
        assertEquals(10, buffer.limit());
        assertSame(self, buffer);

        try {
            buffer.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }
    }

    //----- Test various cases of Duplicate ----------------------------------//

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

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

        // duplicate's contents should be the same as buffer
        CompositeReadableBuffer duplicate = buffer.duplicate();
        assertNotSame(buffer, duplicate);
        assertEquals(buffer.capacity(), duplicate.capacity());
        assertEquals(buffer.position(), duplicate.position());
        assertEquals(buffer.limit(), duplicate.limit());
        assertContentEquals(buffer, duplicate);

        // duplicate's position, mark, and limit should be independent to buffer
        duplicate.reset();
        assertEquals(duplicate.position(), 0);
        duplicate.clear();
        assertEquals(buffer.position(), buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), 0);

        // One array buffer should share backing array
        assertTrue(buffer.hasArray());
        assertTrue(duplicate.hasArray());
        assertSame(buffer.array(), duplicate.array());
        assertTrue(buffer.getArrays().isEmpty());
        assertTrue(duplicate.getArrays().isEmpty());
        assertSame(buffer.getArrays(), duplicate.getArrays());  // Same Empty Buffer
    }

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

        CompositeReadableBuffer duplicate = buffer.duplicate();

        assertEquals(10, buffer.capacity());
        assertEquals(buffer.capacity(), duplicate.capacity());

        buffer.reclaimRead();
        assertEquals(10, buffer.capacity());
        assertEquals(buffer.capacity(), duplicate.capacity());

        duplicate.reclaimRead();
        assertEquals(10, buffer.capacity());
        assertEquals(buffer.capacity(), duplicate.capacity());
    }

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

        CompositeReadableBuffer duplicate = buffer.duplicate();

        assertEquals(10, buffer.capacity());
        assertEquals(buffer.capacity(), duplicate.capacity());

        duplicate.position(duplicate.limit());
        assertFalse(duplicate.hasRemaining());

        assertTrue(duplicate.hasArray());
        duplicate.reclaimRead();
        assertFalse(duplicate.hasArray());
        assertEquals(0, duplicate.capacity());

        // Buffer should be unaffected
        assertEquals(10, buffer.capacity());
        assertTrue(buffer.hasArray());
    }

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

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

        // duplicate's contents should be the same as buffer
        CompositeReadableBuffer duplicate = buffer.duplicate();
        assertNotSame(buffer, duplicate);
        assertEquals(buffer.capacity(), duplicate.capacity());
        assertEquals(buffer.position(), duplicate.position());
        assertEquals(buffer.limit(), duplicate.limit());
        assertContentEquals(buffer, duplicate);

        // duplicate's position, mark, and limit should be independent to buffer
        duplicate.reset();
        assertEquals(duplicate.position(), 0);
        duplicate.clear();
        assertEquals(buffer.position(), buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), 0);

        // One array buffer should share backing array
        assertFalse(buffer.hasArray());
        assertFalse(duplicate.hasArray());
        assertFalse(buffer.getArrays().isEmpty());
        assertFalse(duplicate.getArrays().isEmpty());
        assertNotSame(buffer.getArrays(), duplicate.getArrays());
    }

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

        CompositeReadableBuffer duplicate = buffer.duplicate();

        assertEquals(10, buffer.capacity());
        assertEquals(buffer.capacity(), duplicate.capacity());

        duplicate.position(duplicate.limit());
        assertFalse(duplicate.hasRemaining());

        assertFalse(duplicate.hasArray());
        duplicate.reclaimRead();
        assertFalse(duplicate.hasArray());
        assertEquals(0, duplicate.capacity());
        assertEquals(0, duplicate.getArrays().size());

        // Buffer should be unaffected
        assertEquals(10, buffer.capacity());
        assertFalse(buffer.hasArray());
        assertEquals(2, buffer.getArrays().size());
    }

    //----- Test various cases of Slice --------------------------------------//

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

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

        assertEquals(buffer.capacity(), data.length);
        buffer.position(1);
        buffer.limit(buffer.capacity() - 2);

        ReadableBuffer slice = buffer.slice();
        assertEquals(slice.position(), 0);
        assertEquals(slice.limit(), buffer.remaining());
        assertEquals(slice.capacity(), buffer.remaining());
        assertEquals(1, slice.get());

        try {
            slice.reset();
            fail("Should throw InvalidMarkException");
        } catch (InvalidMarkException e) {
        }
    }

    @Test
    public void testSliceOnEmptyBuffer() {
        CompositeReadableBuffer buffer = new CompositeReadableBuffer();
        CompositeReadableBuffer slice = buffer.slice();

        // Sliced contents should be the same as buffer
        assertNotSame(buffer, slice);
        assertEquals(buffer.capacity(), slice.capacity());
        assertEquals(buffer.position(), slice.position());
        assertEquals(buffer.limit(), slice.limit());
        assertContentEquals(buffer, slice);

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

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

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

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

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

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

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

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

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

        // Sliced contents should be the same as buffer
        CompositeReadableBuffer slice = buffer.slice();
        assertNotSame(buffer, slice);

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

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

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

        // Sliced contents should be the same as buffer
        CompositeReadableBuffer slice = buffer.slice();
        assertNotSame(buffer, slice);
        assertEquals(buffer.capacity(), slice.capacity());
        assertEquals(buffer.position(), slice.position());
        assertEquals(buffer.limit(), slice.limit());
        assertContentEquals(buffer, slice);

        // Sliced position, mark, and limit should be independent to buffer
        try {
            slice.reset();
            fail("Mark should be undefined in the slice and throw InvalidMarkException");
        } catch (InvalidMarkException e) {}

        assertEquals(slice.position(), 0);
        slice.clear();
        assertEquals(10, buffer.limit());
        buffer.reset();
        assertEquals(buffer.position(), 0);

        // One array buffer should share backing array
        assertTrue(buffer.hasArray());
        assertTrue(slice.hasArray());
        assertSame(buffer.array(), slice.array());
        assertTrue(buffer.getArrays().isEmpty());
        assertTrue(slice.getArrays().isEmpty());
        assertSame(buffer.getArrays(), slice.getArrays());  // Same Empty Buffer
    }

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

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

        // Sliced contents should be the same as buffer
        CompositeReadableBuffer slice = buffer.slice();
        assertNotSame(buffer, slice);
        assertEquals(10, buffer.capacity());
        assertEquals(5, slice.capacity());
        assertEquals(5, buffer.position());
        assertEquals(0, slice.position());
        assertEquals(10, buffer.limit());
        assertEquals(5, slice.limit());
        assertSpanEquals(buffer, slice);

        slice.position(1);
        assertEquals(6, slice.get());
        assertEquals(5, slice.get(0));

        try {
            slice.limit(6);
            fail("should throw IllegalArgumentException");
        } catch (IllegalArgumentException iae) {}

        try {
            slice.position(6);
            fail("should throw IllegalArgumentException");
        } catch (IllegalArgumentException iae) {}
    }

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

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

        // Sliced contents should be the same as buffer
        CompositeReadableBuffer slice = buffer.slice();
        assertNotSame(buffer, slice);
        assertEquals(10, buffer.capacity());
        assertEquals(5, slice.capacity());
        assertEquals(5, buffer.position());
        assertEquals(0, slice.position());
        assertEquals(10, buffer.limit());
        assertEquals(5, slice.limit());
        assertSpanEquals(buffer, slice);

        slice.position(1);
        assertEquals(6, slice.get());
        assertEquals(5, slice.get(0));

        try {
            slice.limit(6);
            fail("should throw IllegalArgumentException");
        } catch (IllegalArgumentException iae) {}

        try {
            slice.position(6);
            fail("should throw IllegalArgumentException");
        } catch (IllegalArgumentException iae) {}
    }

    //----- Test various cases of byteBuffer ---------------------------------//

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

        ByteBuffer byteBuffer = buffer.byteBuffer();

        assertNotNull(byteBuffer);
        assertEquals(0, byteBuffer.position());
        assertEquals(0, byteBuffer.limit());
        assertEquals(0, byteBuffer.capacity());

        // Our ByteBuffer results should be read-only and indicate no array.
        assertTrue(byteBuffer.isReadOnly());
        assertFalse(byteBuffer.hasArray());
    }

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

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

        ByteBuffer byteBuffer = buffer.byteBuffer();

        assertNotNull(byteBuffer);
        assertEquals(0, byteBuffer.position());
        assertEquals(10, byteBuffer.limit());
        assertEquals(10, byteBuffer.capacity());

        // Our ByteBuffer results should be read-only and indicate no array.
        assertTrue(byteBuffer.isReadOnly());
        assertFalse(byteBuffer.hasArray());

        for (int i = 0; i < 10; ++i) {
            assertEquals(buffer.get(i), byteBuffer.get(i));
        }
    }

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

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

        ByteBuffer byteBuffer = buffer.byteBuffer();

        assertNotNull(byteBuffer);
        assertEquals(0, byteBuffer.position());
        assertEquals(10, byteBuffer.limit());
        assertEquals(10, byteBuffer.capacity());

        // Our ByteBuffer results should be read-only and indicate no array.
        assertTrue(byteBuffer.isReadOnly());
        assertFalse(byteBuffer.hasArray());

        for (int i = 0; i < 10; ++i) {
            assertEquals(buffer.get(i), byteBuffer.get(i));
        }
    }

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

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

        buffer.position(3);
        buffer.limit(9);

        assertEquals(6, buffer.remaining());

        ByteBuffer byteBuffer = buffer.byteBuffer();

        assertNotNull(byteBuffer);
        assertEquals(0, byteBuffer.position());
        assertEquals(6, byteBuffer.limit());
        assertEquals(6, byteBuffer.capacity());

        // Our ByteBuffer results should be read-only and indicate no array.
        assertTrue(byteBuffer.isReadOnly());
        assertFalse(byteBuffer.hasArray());

        for (int i = 0; i < 6; ++i) {
            assertEquals(buffer.get(), byteBuffer.get());
        }
    }

    //----- Test readString ------------------------------------------//

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

        assertEquals("", buffer.readString(StandardCharsets.UTF_8.newDecoder()));
    }

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

        final String testString = "Test String to Decode!";
        byte[] encoded = testString.getBytes(StandardCharsets.UTF_8);

        buffer.append(encoded);

        assertEquals(testString, buffer.readString(StandardCharsets.UTF_8.newDecoder()));
    }

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

        final String testString = "Test String to Decode!";
        byte[] encoded = testString.getBytes(StandardCharsets.UTF_8);

        // Only read the first character
        buffer.append(encoded);
        buffer.limit(1);

        assertEquals("T", buffer.readString(StandardCharsets.UTF_8.newDecoder()));
    }

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

        final String testString = "Test String to Decode!!";
        byte[] encoded = testString.getBytes(StandardCharsets.UTF_8);

        byte[] first = new byte[encoded.length / 2];
        byte[] second = new byte[encoded.length - (encoded.length / 2)];

        System.arraycopy(encoded, 0, first, 0, first.length);
        System.arraycopy(encoded, first.length, second, 0, second.length);

        buffer.append(first).append(second);

        String result = buffer.readString(StandardCharsets.UTF_8.newDecoder());

        assertEquals(testString, result);
    }

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

        final String testString = "Test String to Decode!";
        byte[] encoded = testString.getBytes(StandardCharsets.UTF_8);

        byte[] first = new byte[encoded.length / 2];
        byte[] second = new byte[encoded.length - (encoded.length / 2)];

        System.arraycopy(encoded, 0, first, 0, first.length);
        System.arraycopy(encoded, first.length, second, 0, second.length);

        buffer.append(first).append(second);

        // Only read the first character
        buffer.limit(1);

        assertEquals("T", buffer.readString(StandardCharsets.UTF_8.newDecoder()));
    }

    //----- Tests for hashCode -----------------------------------------------//

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

        assertEquals(1, buffer.hashCode());

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

        buffer.append(data);

        assertTrue(buffer.hashCode() != 1);
        assertNotEquals(buffer.hashCode(), System.identityHashCode(buffer));
        assertEquals(buffer.hashCode(), buffer.hashCode());
    }

    @Test
    public void testHashCodeOnSameBackingBuffer() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer3 = new CompositeReadableBuffer();

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

        buffer1.append(data);
        buffer2.append(data);
        buffer3.append(data);

        assertEquals(buffer1.hashCode(), buffer2.hashCode());
        assertEquals(buffer2.hashCode(), buffer3.hashCode());
        assertEquals(buffer3.hashCode(), buffer1.hashCode());
    }

    @Test
    public void testHashCodeOnDifferentBackingBuffer() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1);
        buffer2.append(data2);

        assertNotEquals(buffer1.hashCode(), buffer2.hashCode());
    }

    @Test
    public void testHashCodeOnSplitBufferContentsNotSame() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1).append(data2);
        buffer2.append(data2).append(data1);

        assertNotEquals(buffer1.hashCode(), buffer2.hashCode());
    }

    @Test
    public void testHashCodeOnSplitBufferContentsSame() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1).append(data2);
        buffer2.append(data1).append(data2);

        assertEquals(buffer1.hashCode(), buffer2.hashCode());
    }

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

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

        ByteBuffer buffer2 = ByteBuffer.wrap(data);

        assertEquals(buffer1.hashCode(), buffer2.hashCode());
    }

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

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

        ByteBuffer buffer2 = ByteBuffer.wrap(data);

        ReadableBuffer slice1 = buffer1.position(1).slice();
        ByteBuffer slice2 = ((ByteBuffer) buffer2.position(1)).slice();

        assertEquals(slice1.hashCode(), slice2.hashCode());
    }

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

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

        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        buffer1.append(data1);
        buffer1.append(data2);

        ByteBuffer buffer2 = ByteBuffer.wrap(data);

        assertEquals(buffer1.hashCode(), buffer2.hashCode());
    }

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

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

        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        buffer1.append(data1);
        buffer1.append(data2);

        ByteBuffer buffer2 = ByteBuffer.wrap(data);

        ReadableBuffer slice1 = buffer1.position(1).limit(4).slice();
        ByteBuffer slice2 = ((ByteBuffer) buffer2.position(1).limit(4)).slice();

        assertEquals(slice1.hashCode(), slice2.hashCode());
    }

    //----- Tests for equals -------------------------------------------------//

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

        assertEquals(buffer, buffer);

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

        buffer.append(data);

        assertEquals(buffer, buffer);
    }

    @Test
    public void testEqualsOnSameBackingBuffer() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer3 = new CompositeReadableBuffer();

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

        buffer1.append(data);
        buffer2.append(data);
        buffer3.append(data);

        assertEquals(buffer1, buffer2);
        assertEquals(buffer2, buffer3);
        assertEquals(buffer3, buffer1);
    }

    @Test
    public void testEqualsOnDifferentBackingBuffer() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1);
        buffer2.append(data2);

        assertNotEquals(buffer1, buffer2);
    }

    @Test
    public void testEqualsWhenContentsInMultipleArraysNotSame() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1).append(data2);
        buffer2.append(data2).append(data1);

        assertNotEquals(buffer1, buffer2);
    }

    @Test
    public void testEqualsWhenContentsInMultipleArraysSame() throws CharacterCodingException {
        CompositeReadableBuffer buffer1 = new CompositeReadableBuffer();
        CompositeReadableBuffer buffer2 = new CompositeReadableBuffer();

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

        buffer1.append(data1).append(data2);
        buffer2.append(data1).append(data2);

        assertEquals(buffer1, buffer2);
    }

    //----- Utility Methods --------------------------------------------------//

    private void assertContentEquals(CompositeReadableBuffer buffer, byte array[], int offset, int length) {
        for (int i = 0; i < length; i++) {
            assertEquals(buffer.get(i), array[offset + i]);
        }
    }

    private void assertSpanEquals(ReadableBuffer source, ReadableBuffer other) {
        assertEquals(source.remaining(), other.remaining());
        for (int i = 0; i < source.remaining(); i++) {
            assertEquals(source.get(), other.get());
        }
    }

    private void assertContentEquals(ReadableBuffer source, ReadableBuffer other) {
        assertEquals(source.capacity(), other.capacity());
        for (int i = 0; i < source.capacity(); i++) {
            assertEquals(source.get(i), other.get(i));
        }
    }

    private byte[] int2bytes(int value) {
        byte bytes[] = new byte[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));
    }
}
