Author: orudyy
Date: Wed Oct  5 15:39:15 2016
New Revision: 1763459

URL: http://svn.apache.org/viewvc?rev=1763459&view=rev
Log:
QPID-6803: Re-inplement QpidByteBuffer slice, duplicate and view operations

Removed:
    
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBufferImpl.java
    
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/SlicedQpidByteBuffer.java
    
qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/SlicedQpidByteBufferTest.java
Modified:
    
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBuffer.java
    
qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/QpidByteBufferTest.java

Modified: 
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBuffer.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBuffer.java?rev=1763459&r1=1763458&r2=1763459&view=diff
==============================================================================
--- 
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBuffer.java
 (original)
+++ 
qpid/java/trunk/common/src/main/java/org/apache/qpid/bytebuffer/QpidByteBuffer.java
 Wed Oct  5 15:39:15 2016
@@ -45,7 +45,7 @@ import javax.net.ssl.SSLException;
 
 import org.apache.qpid.streams.CompositeInputStream;
 
-public abstract class QpidByteBuffer
+public class QpidByteBuffer
 {
     private static final AtomicIntegerFieldUpdater<QpidByteBuffer>
             DISPOSED_UPDATER = AtomicIntegerFieldUpdater.newUpdater(
@@ -56,15 +56,25 @@ public abstract class QpidByteBuffer
     private volatile static BufferPool _bufferPool;
     private volatile static int _pooledBufferSize;
     private volatile static ByteBuffer _zeroed;
+    private final int _offset;
+
     final ByteBufferRef _ref;
     volatile ByteBuffer _buffer;
     @SuppressWarnings("unused")
     private volatile int _disposed;
 
-    QpidByteBuffer(ByteBufferRef ref, ByteBuffer buffer)
+
+    QpidByteBuffer(ByteBufferRef ref)
+    {
+        this(ref, ref.getBuffer(), 0);
+    }
+
+    private QpidByteBuffer(ByteBufferRef ref, ByteBuffer buffer, int offset)
     {
         _ref = ref;
         _buffer = buffer;
+        _offset = offset;
+        _ref.incrementRef();
     }
 
     public final boolean isDirect()
@@ -160,11 +170,23 @@ public abstract class QpidByteBuffer
         return _buffer.hasRemaining();
     }
 
-    public abstract QpidByteBuffer putInt(int index, int value);
+    public QpidByteBuffer putInt(final int index, final int value)
+    {
+        _buffer.putInt(index, value);
+        return this;
+    }
 
-    public abstract QpidByteBuffer putShort(int index, short value);
+    public QpidByteBuffer putShort(final int index, final short value)
+    {
+        _buffer.putShort(index, value);
+        return this;
+    }
 
-    public abstract QpidByteBuffer putChar(int index, char value);
+    public QpidByteBuffer putChar(final int index, final char value)
+    {
+        _buffer.putChar(index, value);
+        return this;
+    }
 
     public final QpidByteBuffer put(final byte b)
     {
@@ -172,9 +194,16 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract QpidByteBuffer put(int index, byte b);
+    public QpidByteBuffer put(final int index, final byte b)
+    {
+        _buffer.put(index, b);
+        return this;
+    }
 
-    public abstract short getShort(int index);
+    public short getShort(final int index)
+    {
+        return _buffer.getShort(index);
+    }
 
     public final QpidByteBuffer mark()
     {
@@ -187,9 +216,16 @@ public abstract class QpidByteBuffer
         return _buffer.getLong();
     }
 
-    public abstract QpidByteBuffer putFloat(int index, float value);
+    public QpidByteBuffer putFloat(final int index, final float value)
+    {
+        _buffer.putFloat(index, value);
+        return this;
+    }
 
-    public abstract double getDouble(int index);
+    public double getDouble(final int index)
+    {
+        return _buffer.getDouble(index);
+    }
 
     public final boolean hasArray()
     {
@@ -213,7 +249,10 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract byte[] array();
+    public byte[] array()
+    {
+        return _buffer.array();
+    }
 
     public final QpidByteBuffer putShort(final short value)
     {
@@ -221,7 +260,10 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract int getInt(int index);
+    public int getInt(final int index)
+    {
+        return _buffer.getInt(index);
+    }
 
     public final int remaining()
     {
@@ -287,13 +329,29 @@ public abstract class QpidByteBuffer
         put(source.getUnderlyingBuffer().duplicate());
     }
 
-    public abstract QpidByteBuffer rewind();
+    public QpidByteBuffer rewind()
+    {
+        _buffer.rewind();
+        return this;
+    }
 
-    public abstract QpidByteBuffer clear();
+    public QpidByteBuffer clear()
+    {
+        _buffer.clear();
+        return this;
+    }
 
-    public abstract QpidByteBuffer putLong(int index, long value);
+    public QpidByteBuffer putLong(final int index, final long value)
+    {
+        _buffer.putLong(index, value);
+        return this;
+    }
 
-    public abstract QpidByteBuffer compact();
+    public QpidByteBuffer compact()
+    {
+        _buffer.compact();
+        return this;
+    }
 
     public final QpidByteBuffer putDouble(final double value)
     {
@@ -301,11 +359,22 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract int limit();
+    public int limit()
+    {
+        return _buffer.limit();
+    }
 
-    public abstract QpidByteBuffer reset();
+    public QpidByteBuffer reset()
+    {
+        _buffer.reset();
+        return this;
+    }
 
-    public abstract QpidByteBuffer flip();
+    public QpidByteBuffer flip()
+    {
+        _buffer.flip();
+        return this;
+    }
 
     public final short getShort()
     {
@@ -318,9 +387,34 @@ public abstract class QpidByteBuffer
         return _buffer.getFloat();
     }
 
-    public abstract QpidByteBuffer limit(int newLimit);
+    public QpidByteBuffer limit(final int newLimit)
+    {
+        _buffer.limit(newLimit);
+        return this;
+    }
+
+    /**
+     * Method does not respect mark.
+     *
+     * @return QpidByteBuffer
+     */
+    public QpidByteBuffer duplicate()
+    {
+        ByteBuffer buffer = _ref.getBuffer();
+        if (!(_ref instanceof PooledByteBufferRef))
+        {
+            buffer = buffer.duplicate();
+        }
+
+        buffer.position(_offset );
+        buffer.limit(_offset + _buffer.capacity());
 
-    public abstract QpidByteBuffer duplicate();
+        buffer = buffer.slice();
+
+        buffer.limit(_buffer.limit());
+        buffer.position(_buffer.position());
+        return new QpidByteBuffer(_ref, buffer, _offset);
+    }
 
     public final QpidByteBuffer put(final byte[] src, final int offset, final 
int length)
     {
@@ -328,18 +422,30 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract long getLong(int index);
+    public long getLong(final int index)
+    {
+        return _buffer.getLong(index);
+    }
 
-    public abstract int capacity();
+    public int capacity()
+    {
+        return _buffer.capacity();
+    }
 
-    public abstract char getChar(int index);
+    public char getChar(final int index)
+    {
+        return _buffer.getChar(index);
+    }
 
     public final byte get()
     {
         return _buffer.get();
     }
 
-    public abstract byte get(int index);
+    public byte get(final int index)
+    {
+        return _buffer.get(index);
+    }
 
     public final QpidByteBuffer get(final byte[] dst)
     {
@@ -362,9 +468,16 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract QpidByteBuffer position(int newPosition);
+    public QpidByteBuffer position(final int newPosition)
+    {
+        _buffer.position(newPosition);
+        return this;
+    }
 
-    public abstract int arrayOffset();
+    public int arrayOffset()
+    {
+        return _buffer.arrayOffset();
+    }
 
     public final char getChar()
     {
@@ -382,17 +495,50 @@ public abstract class QpidByteBuffer
         return this;
     }
 
-    public abstract float getFloat(int index);
+    public float getFloat(final int index)
+    {
+        return _buffer.getFloat(index);
+    }
+
+    public QpidByteBuffer slice()
+    {
+        return view(0, _buffer.remaining());
+    }
+
+    public QpidByteBuffer view(int offset, int length)
+    {
+        ByteBuffer buffer = _ref.getBuffer();
+        if (!(_ref instanceof PooledByteBufferRef))
+        {
+            buffer = buffer.duplicate();
+        }
+
+        int newRemaining = Math.min(_buffer.remaining() - offset, length);
 
-    public abstract QpidByteBuffer slice();
+        int newPosition = _offset + _buffer.position() + offset;
+        buffer.limit(newPosition + newRemaining);
+        buffer.position(newPosition);
 
-    public abstract QpidByteBuffer view(int offset, int length);
+        buffer = buffer.slice();
 
-    public abstract int position();
+        return new QpidByteBuffer(_ref, buffer, newPosition);
+    }
 
-    public abstract QpidByteBuffer putDouble(int index, double value);
+    public int position()
+    {
+        return _buffer.position();
+    }
 
-    abstract ByteBuffer getUnderlyingBuffer();
+    public QpidByteBuffer putDouble(final int index, final double value)
+    {
+        _buffer.putDouble(index, value);
+        return this;
+    }
+
+    ByteBuffer getUnderlyingBuffer()
+    {
+        return _buffer;
+    }
 
     public static QpidByteBuffer allocate(boolean direct, int size)
     {
@@ -401,7 +547,7 @@ public abstract class QpidByteBuffer
 
     public static QpidByteBuffer allocate(int size)
     {
-        return new QpidByteBufferImpl(new 
NonPooledByteBufferRef(ByteBuffer.allocate(size)));
+        return new QpidByteBuffer(new 
NonPooledByteBufferRef(ByteBuffer.allocate(size)));
     }
 
     public static QpidByteBuffer allocateDirect(int size)
@@ -447,7 +593,7 @@ public abstract class QpidByteBuffer
         {
             ref = new NonPooledByteBufferRef(ByteBuffer.allocateDirect(size));
         }
-        return new QpidByteBufferImpl(ref);
+        return new QpidByteBuffer(ref);
     }
 
     public static Collection<QpidByteBuffer> allocateDirectCollection(int size)
@@ -596,7 +742,7 @@ public abstract class QpidByteBuffer
 
     public static QpidByteBuffer wrap(final ByteBuffer wrap)
     {
-        return new QpidByteBufferImpl(new NonPooledByteBufferRef(wrap));
+        return new QpidByteBuffer(new NonPooledByteBufferRef(wrap));
     }
 
     public static QpidByteBuffer wrap(final byte[] data)

Modified: 
qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/QpidByteBufferTest.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/QpidByteBufferTest.java?rev=1763459&r1=1763458&r2=1763459&view=diff
==============================================================================
--- 
qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/QpidByteBufferTest.java
 (original)
+++ 
qpid/java/trunk/common/src/test/java/org/apache/qpid/bytebuffer/QpidByteBufferTest.java
 Wed Oct  5 15:39:15 2016
@@ -20,27 +20,710 @@
 
 package org.apache.qpid.bytebuffer;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 
+import com.google.common.io.ByteStreams;
 import org.junit.Assert;
+import org.mockito.internal.util.Primitives;
 
 import org.apache.qpid.test.utils.QpidTestCase;
 import org.apache.qpid.util.ByteBufferUtils;
 
 public class QpidByteBufferTest extends QpidTestCase
 {
+    private static final int BUFFER_SIZE = 10;
+    private static final int POOL_SIZE = 20;
 
-    public static final int BUFFER_SIZE = 10;
-    public static final int POOL_SIZE = 20;
+
+    private QpidByteBuffer _slicedBuffer;
+    private QpidByteBuffer _parent;
 
     @Override
     protected void setUp() throws Exception
     {
         super.setUp();
         QpidByteBuffer.initialisePool(BUFFER_SIZE, POOL_SIZE);
+        _parent = QpidByteBuffer.allocateDirect(BUFFER_SIZE);
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+        _parent.dispose();
+        if (_slicedBuffer != null)
+        {
+            _slicedBuffer.dispose();
+        }
+    }
+
+    public void testPutGetByIndex() throws Exception
+    {
+        testPutGetByIndex(double.class, 1.0);
+        testPutGetByIndex(float.class, 1.0f);
+        testPutGetByIndex(long.class, 1L);
+        testPutGetByIndex(int.class, 1);
+        testPutGetByIndex(char.class, 'A');
+        testPutGetByIndex(short.class, (short)1);
+        testPutGetByIndex(byte.class, (byte)1);
+    }
+
+    public void testPutGet() throws Exception
+    {
+        testPutGet(double.class, false, 1.0);
+        testPutGet(float.class, false, 1.0f);
+        testPutGet(long.class, false, 1L);
+        testPutGet(int.class, false, 1);
+        testPutGet(char.class, false, 'A');
+        testPutGet(short.class, false, (short)1);
+        testPutGet(byte.class, false, (byte)1);
+
+        testPutGet(int.class, true, 1L);
+        testPutGet(short.class, true, 1);
+        testPutGet(byte.class, true, (short)1);
+    }
+
+    public void testMarkReset() throws Exception
+    {
+        _slicedBuffer = createSlice();
+
+        _slicedBuffer.mark();
+        _slicedBuffer.position(_slicedBuffer.position() + 1);
+        assertEquals("Unexpected position after move", 1, 
_slicedBuffer.position());
+
+        _slicedBuffer.reset();
+        assertEquals("Unexpected position after reset", 0, 
_slicedBuffer.position());
+    }
+
+    public void testPosition() throws Exception
+    {
+        _slicedBuffer = createSlice();
+
+        assertEquals("Unexpected position for new slice", 0, 
_slicedBuffer.position());
+
+        _slicedBuffer.position(1);
+        assertEquals("Unexpected position after advance", 1, 
_slicedBuffer.position());
+
+        final int oldLimit = _slicedBuffer.limit();
+        _slicedBuffer.limit(oldLimit - 1);
+        try
+        {
+            _slicedBuffer.position(oldLimit);
+            fail("Exception not thrown");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+    }
+
+    public void testBulkPutGet() throws Exception
+    {
+        _slicedBuffer = createSlice();
+
+        final byte[] source = getTestBytes(_slicedBuffer.remaining());
+
+        QpidByteBuffer rv = _slicedBuffer.put(source, 0, source.length);
+        assertEquals("Unexpected builder return value", _slicedBuffer, rv);
+
+        _slicedBuffer.flip();
+        byte[] target = new byte[_slicedBuffer.remaining()];
+        rv = _slicedBuffer.get(target, 0, target.length);
+        assertEquals("Unexpected builder return value", _slicedBuffer, rv);
+
+        Assert.assertArrayEquals("Unexpected bulk put/get result", source, 
target);
+
+
+        _slicedBuffer.clear();
+        _slicedBuffer.position(1);
+
+        try
+        {
+            _slicedBuffer.put(source, 0, source.length);
+            fail("Exception not thrown");
+        }
+        catch (BufferOverflowException e)
+        {
+            // pass
+        }
+
+        assertEquals("Position should be unchanged after failed put", 1, 
_slicedBuffer.position());
+
+        try
+        {
+            _slicedBuffer.get(target, 0, target.length);
+            fail("Exception not thrown");
+        }
+        catch (BufferUnderflowException e)
+        {
+            // pass
+        }
+
+        assertEquals("Position should be unchanged after failed get", 1, 
_slicedBuffer.position());
+
+
+    }
+
+    public void testByteBufferPutGet()
+    {
+        _slicedBuffer = createSlice();
+        final byte[] source = getTestBytes(_slicedBuffer.remaining());
+
+        ByteBuffer sourceByteBuffer = ByteBuffer.wrap(source);
+
+        QpidByteBuffer rv = _slicedBuffer.put(sourceByteBuffer);
+        assertEquals("Unexpected builder return value", _slicedBuffer, rv);
+
+        assertEquals("Unexpected position", _slicedBuffer.capacity(), 
_slicedBuffer.position());
+        assertEquals("Unexpected remaining", 0, _slicedBuffer.remaining());
+
+        assertEquals("Unexpected remaining in source ByteBuffer", 0, 
sourceByteBuffer.remaining());
+
+        _slicedBuffer.flip();
+
+        ByteBuffer destinationByteBuffer =  ByteBuffer.allocate(source.length);
+        _slicedBuffer.get(destinationByteBuffer);
+
+
+        assertEquals("Unexpected remaining", 0, _slicedBuffer.remaining());
+
+        assertEquals("Unexpected remaining in destination ByteBuffer", 0, 
destinationByteBuffer.remaining());
+        assertEquals("Unexpected position in destination ByteBuffer", 
source.length, destinationByteBuffer.position());
+
+        Assert.assertArrayEquals("Unexpected ByteBuffer put/get result", 
source, destinationByteBuffer.array());
+
+        _slicedBuffer.clear();
+        _slicedBuffer.position(1);
+
+        sourceByteBuffer.clear();
+        try
+        {
+            _slicedBuffer.put(sourceByteBuffer);
+            fail("Exception should be thrown");
+        }
+        catch(BufferOverflowException e)
+        {
+            // pass
+        }
+
+        assertEquals("Position should not be changed after failed put", 1, 
_slicedBuffer.position());
+        assertEquals("Source position should not changed after failed put", 
source.length, sourceByteBuffer.remaining());
+
+        _slicedBuffer.clear();
+        destinationByteBuffer.position(1);
+
+        try
+        {
+            _slicedBuffer.get(destinationByteBuffer);
+            fail("Exception should be thrown");
+        }
+        catch(BufferUnderflowException e )
+        {
+            // pass
+        }
+    }
+
+    public void testQpidByteBufferPutGet()
+    {
+        _slicedBuffer = createSlice();
+        final byte[] source = getTestBytes(_slicedBuffer.remaining());
+
+        QpidByteBuffer sourceQpidByteBuffer = QpidByteBuffer.wrap(source);
+
+        QpidByteBuffer rv = _slicedBuffer.put(sourceQpidByteBuffer);
+        assertEquals("Unexpected builder return value", _slicedBuffer, rv);
+
+        assertEquals("Unexpected position", _slicedBuffer.capacity(), 
_slicedBuffer.position());
+        assertEquals("Unexpected remaining", 0, _slicedBuffer.remaining());
+
+        assertEquals("Unexpected remaining in source QpidByteBuffer", 0, 
sourceQpidByteBuffer.remaining());
+
+        _slicedBuffer.flip();
+
+        ByteBuffer destinationByteBuffer =  ByteBuffer.allocate(source.length);
+        _slicedBuffer.get(destinationByteBuffer);
+
+        assertEquals("Unexpected remaining", 0, _slicedBuffer.remaining());
+
+        assertEquals("Unexpected remaining in destination ByteBuffer", 0, 
destinationByteBuffer.remaining());
+        assertEquals("Unexpected position in destination ByteBuffer", 
source.length, destinationByteBuffer.position());
+
+        Assert.assertArrayEquals("Unexpected ByteBuffer put/get result", 
source, destinationByteBuffer.array());
+
+        _slicedBuffer.clear();
+        _slicedBuffer.position(1);
+
+        sourceQpidByteBuffer.clear();
+        try
+        {
+            _slicedBuffer.put(sourceQpidByteBuffer);
+            fail("Exception should be thrown");
+        }
+        catch(BufferOverflowException e)
+        {
+            // pass
+        }
+
+        assertEquals("Position should not be changed after failed put", 1, 
_slicedBuffer.position());
+        assertEquals("Source position should not changed after failed put", 
source.length, sourceQpidByteBuffer.remaining());
+    }
+
+    public void testDuplicate()
+    {
+        _slicedBuffer = createSlice();
+        _slicedBuffer.position(1);
+        int originalLimit = _slicedBuffer.limit();
+        _slicedBuffer.limit(originalLimit - 1);
+
+        QpidByteBuffer duplicate = _slicedBuffer.duplicate();
+        try
+        {
+            assertEquals("Unexpected position", _slicedBuffer.position(), 
duplicate.position() );
+            assertEquals("Unexpected limit", _slicedBuffer.limit(), 
duplicate.limit() );
+            assertEquals("Unexpected capacity", _slicedBuffer.capacity(), 
duplicate.capacity() );
+
+            duplicate.position(2);
+            duplicate.limit(originalLimit - 2);
+
+            assertEquals("Unexpected position in the original", 1, 
_slicedBuffer.position());
+            assertEquals("Unexpected limit in the original", originalLimit -1, 
_slicedBuffer.limit());
+        }
+        finally
+        {
+            duplicate.dispose();
+        }
+    }
+
+    public void testCopyToByteBuffer()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+        _slicedBuffer.flip();
+
+        int originalRemaining = _slicedBuffer.remaining();
+        ByteBuffer destination =  ByteBuffer.allocate(source.length);
+        _slicedBuffer.copyTo(destination);
+
+        assertEquals("Unexpected remaining in original QBB", 
originalRemaining, _slicedBuffer.remaining());
+        assertEquals("Unexpected remaining in destination", 0, 
destination.remaining());
+
+        Assert.assertArrayEquals("Unexpected copyTo result", source, 
destination.array());
+    }
+
+    public void testCopyToArray()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+        _slicedBuffer.flip();
+
+        int originalRemaining = _slicedBuffer.remaining();
+        byte[] destination = new byte[source.length];
+        _slicedBuffer.copyTo(destination);
+
+        assertEquals("Unexpected remaining in original QBB", 
originalRemaining, _slicedBuffer.remaining());
+
+        Assert.assertArrayEquals("Unexpected copyTo result", source, 
destination);
+    }
+
+    public void testPutCopyOf()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+
+        QpidByteBuffer sourceQpidByteBuffer =  QpidByteBuffer.wrap(source);
+        _slicedBuffer.putCopyOf(sourceQpidByteBuffer);
+
+        assertEquals("Copied buffer should not be changed", source.length, 
sourceQpidByteBuffer.remaining());
+        assertEquals("Buffer should be full", 0, _slicedBuffer.remaining());
+        _slicedBuffer.flip();
+
+        byte[] destination = new byte[source.length];
+        _slicedBuffer.get(destination);
+
+        Assert.assertArrayEquals("Unexpected putCopyOf result", source, 
destination);
+    }
+
+    public void testCompact()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+
+        _slicedBuffer.position(1);
+        _slicedBuffer.limit(_slicedBuffer.limit() - 1);
+
+        int remaining =  _slicedBuffer.remaining();
+        _slicedBuffer.compact();
+
+        assertEquals("Unexpected position", remaining, 
_slicedBuffer.position());
+        assertEquals("Unexpected limit", _slicedBuffer.capacity(), 
_slicedBuffer.limit());
+
+        _slicedBuffer.flip();
+
+
+        byte[] destination =  new byte[_slicedBuffer.remaining()];
+        _slicedBuffer.get(destination);
+
+        byte[] expected =  new byte[source.length - 2];
+        System.arraycopy(source, 1, expected, 0, expected.length);
+
+        Assert.assertArrayEquals("Unexpected compact result", expected, 
destination);
+    }
+
+    public void testSliceOfSlice()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+
+        _slicedBuffer.position(1);
+        _slicedBuffer.limit(_slicedBuffer.limit() - 1);
+
+        int remaining = _slicedBuffer.remaining();
+        QpidByteBuffer newSlice = _slicedBuffer.slice();
+        try
+        {
+            assertEquals("Unexpected position in original", 1, 
_slicedBuffer.position());
+            assertEquals("Unexpected limit in original", source.length - 1, 
_slicedBuffer.limit());
+            assertEquals("Unexpected position", 0, newSlice.position());
+            assertEquals("Unexpected limit", remaining, newSlice.limit());
+            assertEquals("Unexpected capacity", remaining, 
newSlice.capacity());
+
+            byte[] destination =  new byte[newSlice.remaining()];
+            newSlice.get(destination);
+
+            byte[] expected =  new byte[source.length - 2];
+            System.arraycopy(source, 1, expected, 0, expected.length);
+            Assert.assertArrayEquals("Unexpected slice result", expected, 
destination);
+        }
+        finally
+        {
+            newSlice.dispose();
+        }
+    }
+
+    public void testViewOfSlice()
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+
+        _slicedBuffer.position(1);
+        _slicedBuffer.limit(_slicedBuffer.limit() - 1);
+
+        QpidByteBuffer view = _slicedBuffer.view(0, _slicedBuffer.remaining());
+        try
+        {
+            assertEquals("Unexpected position in original", 1, 
_slicedBuffer.position());
+            assertEquals("Unexpected limit in original", source.length - 1, 
_slicedBuffer.limit());
+
+            assertEquals("Unexpected position", 0, view.position());
+            assertEquals("Unexpected limit", _slicedBuffer.remaining(), 
view.limit());
+            assertEquals("Unexpected capacity", _slicedBuffer.remaining(), 
view.capacity());
+
+            byte[] destination =  new byte[view.remaining()];
+            view.get(destination);
+
+            byte[] expected =  new byte[source.length - 2];
+            System.arraycopy(source, 1, expected, 0, expected.length);
+            Assert.assertArrayEquals("Unexpected view result", expected, 
destination);
+        }
+        finally
+        {
+            view.dispose();
+        }
+
+        view = _slicedBuffer.view(1, _slicedBuffer.remaining() - 2);
+        try
+        {
+            assertEquals("Unexpected position in original", 1, 
_slicedBuffer.position());
+            assertEquals("Unexpected limit in original", source.length - 1, 
_slicedBuffer.limit());
+
+            assertEquals("Unexpected position", 0, view.position());
+            assertEquals("Unexpected limit", _slicedBuffer.remaining() - 2, 
view.limit());
+            assertEquals("Unexpected capacity", _slicedBuffer.remaining() - 2, 
view.capacity());
+
+            byte[] destination =  new byte[view.remaining()];
+            view.get(destination);
+
+            byte[] expected =  new byte[source.length - 4];
+            System.arraycopy(source, 2, expected, 0, expected.length);
+            Assert.assertArrayEquals("Unexpected view result", expected, 
destination);
+        }
+        finally
+        {
+            view.dispose();
+        }
+    }
+
+    public void testAsInputStream() throws Exception
+    {
+        _slicedBuffer = createSlice();
+        byte[] source = getTestBytes(_slicedBuffer.remaining());
+        _slicedBuffer.put(source);
+
+        _slicedBuffer.position(1);
+        _slicedBuffer.limit(_slicedBuffer.limit() - 1);
+
+        ByteArrayOutputStream destination = new ByteArrayOutputStream();
+        try(InputStream is = _slicedBuffer.asInputStream())
+        {
+            ByteStreams.copy(is, destination);
+        }
+
+        byte[] expected =  new byte[source.length - 2];
+        System.arraycopy(source, 1, expected, 0, expected.length);
+        Assert.assertArrayEquals("Unexpected view result", expected, 
destination.toByteArray());
+    }
+
+    public void testAsByteBuffer() throws Exception
+    {
+        _slicedBuffer = createSlice();
+
+        _slicedBuffer.position(1);
+        _slicedBuffer.limit(_slicedBuffer.limit() - 1);
+
+        _slicedBuffer.mark();
+        int remaining = _slicedBuffer.remaining();
+        byte[] source = getTestBytes(remaining);
+        _slicedBuffer.put(source);
+        _slicedBuffer.reset();
+
+        ByteBuffer buffer = _slicedBuffer.asByteBuffer();
+        assertEquals("Unexpected remaining", remaining, buffer.remaining());
+
+        byte[] target = new byte[remaining];
+        buffer.get(target);
+        Assert.assertArrayEquals("Unexpected asByteBuffer result", source, 
target);
+    }
+
+    public void testDecode()
+    {
+        _slicedBuffer = createSlice();
+        final String input = "ABC";
+        _slicedBuffer.put(input.getBytes());
+        _slicedBuffer.flip();
+
+        final CharBuffer charBuffer = 
_slicedBuffer.decode(StandardCharsets.US_ASCII);
+        final char[] destination = new char[charBuffer.remaining()];
+        charBuffer.get(destination);
+        Assert.assertArrayEquals("Unexpected char buffer", 
input.toCharArray(), destination);
+    }
+
+    private byte[] getTestBytes(final int length)
+    {
+        final byte[] source = new byte[length];
+        for (int i = 0; i < source.length; i++)
+        {
+            source[i] = (byte) ('A' + i);
+        }
+        return source;
+    }
+
+    private QpidByteBuffer createSlice()
+    {
+        _parent.position(1);
+        _parent.limit(_parent.capacity() - 1);
+
+        return _parent.slice();
+    }
+
+    private void testPutGet(final Class<?> primitiveTargetClass, final boolean 
unsigned, final Object value) throws Exception
+    {
+        int size = sizeof(primitiveTargetClass);
+
+        _parent.position(1);
+        _parent.limit(size + 1);
+
+        _slicedBuffer = _parent.slice();
+        _parent.limit(_parent.capacity());
+
+        assertEquals("Unexpected position ", 0, _slicedBuffer.position());
+        assertEquals("Unexpected limit ", size, _slicedBuffer.limit());
+        assertEquals("Unexpected capacity ", size, _slicedBuffer.capacity());
+
+        String methodSuffix = getMethodSuffix(primitiveTargetClass, unsigned);
+        Method put = _slicedBuffer.getClass().getMethod("put" + methodSuffix, 
Primitives.primitiveTypeOf(value.getClass()));
+        Method get = _slicedBuffer.getClass().getMethod("get" + methodSuffix);
+
+
+        _slicedBuffer.mark();
+        QpidByteBuffer rv = (QpidByteBuffer) put.invoke(_slicedBuffer, value);
+        assertEquals("Unexpected builder return value for type " + 
methodSuffix, _slicedBuffer, rv);
+
+        assertEquals("Unexpected position for type " + methodSuffix, size, 
_slicedBuffer.position());
+
+        try
+        {
+            invokeMethod(put, value);
+            fail("BufferOverflowException should be thrown for put with 
insufficient room for " + methodSuffix);
+        }
+        catch (BufferOverflowException e)
+        {
+            // pass
+        }
+
+        _slicedBuffer.reset();
+
+        assertEquals("Unexpected position after reset", 0, 
_slicedBuffer.position());
+
+        Object retrievedValue = get.invoke(_slicedBuffer);
+        assertEquals("Unexpected value retrieved from get method for " + 
methodSuffix, value, retrievedValue);
+        try
+        {
+            invokeMethod(get);
+            fail("BufferUnderflowException not thrown for get with 
insufficient room for " + methodSuffix);
+        }
+        catch (BufferUnderflowException ite)
+        {
+            // pass
+        }
+    }
+
+    private void testPutGetByIndex(final Class<?> primitiveTargetClass, Object 
value) throws Exception
+    {
+        int size = sizeof(primitiveTargetClass);
+
+        _parent.position(1);
+        _parent.limit(size + 1);
+
+        _slicedBuffer = _parent.slice();
+        _parent.limit(_parent.capacity());
+
+        String methodSuffix = getMethodSuffix(primitiveTargetClass, false);
+        Method put = _slicedBuffer.getClass().getMethod("put" + methodSuffix, 
int.class, primitiveTargetClass);
+        Method get = _slicedBuffer.getClass().getMethod("get" + methodSuffix, 
int.class);
+
+        QpidByteBuffer rv = (QpidByteBuffer) put.invoke(_slicedBuffer, 0, 
value);
+        assertEquals("Unexpected builder return value for type " + 
methodSuffix, _slicedBuffer, rv);
+
+        Object retrievedValue = get.invoke(_slicedBuffer, 0);
+        assertEquals("Unexpected value retrieved from index get method for " + 
methodSuffix, value, retrievedValue);
+
+        try
+        {
+            invokeMethod(put, 1, value);
+            fail("IndexOutOfBoundsException not thrown for  indexed " + 
methodSuffix + " put");
+        }
+        catch (IndexOutOfBoundsException ite)
+        {
+            // pass
+        }
+
+        try
+        {
+            invokeMethod(put, -1, value);
+            fail("IndexOutOfBoundsException not thrown for indexed " + 
methodSuffix + " put with negative index");
+        }
+        catch (IndexOutOfBoundsException ite)
+        {
+            // pass
+        }
+
+        try
+        {
+            invokeMethod(get, 1);
+            fail("IndexOutOfBoundsException not thrown for indexed " + 
methodSuffix + " get");
+        }
+        catch (IndexOutOfBoundsException ite)
+        {
+            // pass
+        }
+
+        try
+        {
+            invokeMethod(get, -1);
+            fail("IndexOutOfBoundsException not thrown for indexed " + 
methodSuffix + " get with negative index");
+        }
+        catch (IndexOutOfBoundsException ite)
+        {
+            // pass
+        }
+    }
+
+    private void invokeMethod(final Method method, final Object... value)
+            throws Exception
+    {
+        try
+        {
+            method.invoke(_slicedBuffer, value);
+        }
+        catch (InvocationTargetException e)
+        {
+            Throwable cause = e.getCause();
+            if (cause instanceof Exception)
+            {
+                throw (Exception)cause;
+            }
+            fail(String.format("Unexpected throwable on method %s invocation: 
%s", method.getName(), cause));
+        }
+    }
+
+
+    private String getMethodSuffix(final Class<?> target, final boolean 
unsigned)
+    {
+        StringBuilder name = new StringBuilder();
+        if (unsigned)
+        {
+            name.append("Unsigned");
+        }
+        if ((!target.isAssignableFrom(byte.class) || unsigned))
+        {
+            String simpleName = target.getSimpleName();
+            name.append(simpleName.substring(0, 
1).toUpperCase()).append(simpleName.substring(1));
+        }
+
+        return name.toString();
+    }
+
+    private int sizeof(final Class<?> type)
+    {
+        if (type.isAssignableFrom(double.class))
+        {
+            return 8;
+        }
+        else if (type.isAssignableFrom(float.class))
+        {
+            return 4;
+        }
+        else if (type.isAssignableFrom(long.class))
+        {
+            return 8;
+        }
+        else if (type.isAssignableFrom(int.class))
+        {
+            return 4;
+        }
+        else if (type.isAssignableFrom(short.class))
+        {
+            return 2;
+        }
+        else if (type.isAssignableFrom(char.class))
+        {
+            return 2;
+        }
+        else if (type.isAssignableFrom(byte.class))
+        {
+            return 1;
+        }
+        else
+        {
+            throw new UnsupportedOperationException("Unexpected type " + type);
+        }
     }
 
     public void testPooledBufferIsZeroedLoan() throws Exception
@@ -158,38 +841,25 @@ public class QpidByteBufferTest extends
         QpidByteBuffer directSlice = directBuffer.slice();
 
         assertTrue("Direct slice should be direct too", 
directSlice.isDirect());
-        assertTrue("Direct slice should be special", directSlice instanceof 
SlicedQpidByteBuffer);
         assertEquals("Unexpected capacity", 3, directSlice.capacity());
         assertEquals("Unexpected limit", 3, directSlice.limit());
         assertEquals("Unexpected position", 0, directSlice.position());
 
         directBuffer.dispose();
         directSlice.dispose();
-
-        final QpidByteBuffer heapBuffer = QpidByteBuffer.allocate(false, 6);
-        final QpidByteBuffer heapSlice = heapBuffer.slice();
-        assertFalse("Heap slice should not be special", heapSlice instanceof 
SlicedQpidByteBuffer);
-        heapBuffer.dispose();
-        heapSlice.dispose();
     }
 
     public void testView() throws Exception
     {
-        doTestView(true);
-        doTestView(false);
-    }
-
-    private void doTestView(final boolean direct)
-    {
         byte[] content = "ABCDEF".getBytes();
-        QpidByteBuffer buffer = QpidByteBuffer.allocate(direct, 
content.length);
+        QpidByteBuffer buffer = QpidByteBuffer.allocate(true, content.length);
         buffer.put(content);
         buffer.position(2);
         buffer.limit(5);
 
         QpidByteBuffer view = buffer.view(0, buffer.remaining());
 
-        assertEquals("Unexpected view direct", direct, view.isDirect());
+        assertTrue("Unexpected view direct", view.isDirect());
 
         assertEquals("Unexpected capacity", 3, view.capacity());
         assertEquals("Unexpected limit", 3, view.limit());




---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to