blob: 0bbbfd4a0967c14e5c9c3ee7bd2330d85abd146c [file] [log] [blame]
/*
* 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.server.bytebuffer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
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.InvalidMarkException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import com.google.common.io.ByteStreams;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.internal.util.Primitives;
import org.apache.qpid.test.utils.UnitTestBase;
public class QpidByteBufferTest extends UnitTestBase
{
private static final int BUFFER_FRAGMENT_SIZE = 5;
private static final int BUFFER_SIZE = 10;
private static final int POOL_SIZE = 20;
private static final double SPARSITY_FRACTION = 0.5;
private QpidByteBuffer _slicedBuffer;
private QpidByteBuffer _parent;
@Before
public void setUp() throws Exception
{
QpidByteBuffer.deinitialisePool();
QpidByteBuffer.initialisePool(BUFFER_FRAGMENT_SIZE, POOL_SIZE, SPARSITY_FRACTION);
_parent = QpidByteBuffer.allocateDirect(BUFFER_SIZE);
}
@After
public void tearDown() throws Exception
{
try
{
}
finally
{
if (_parent != null)
{
_parent.dispose();
}
if (_slicedBuffer != null)
{
_slicedBuffer.dispose();
}
QpidByteBuffer.deinitialisePool();
}
}
@Test
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);
}
@Test
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);
}
@Test
public void testMarkReset() throws Exception
{
_slicedBuffer = createSlice();
_slicedBuffer.mark();
_slicedBuffer.position(_slicedBuffer.position() + 1);
assertEquals("Unexpected position after move", (long) 1, (long) _slicedBuffer.position());
_slicedBuffer.reset();
assertEquals("Unexpected position after reset", (long) 0, (long) _slicedBuffer.position());
}
@Test
public void testMarkResetAcrossFragmentBoundary() throws Exception
{
for (int i = 0; i < BUFFER_SIZE; ++i)
{
_parent.put((byte) i);
}
_parent.flip();
_parent.mark();
for (int i = 0; i < BUFFER_FRAGMENT_SIZE + 2; ++i)
{
assertEquals("Unexpected value", (long) i, (long) _parent.get());
}
_parent.reset();
for (int i = 0; i < BUFFER_SIZE; ++i)
{
assertEquals("Unexpected value", (long) i, (long) _parent.get());
}
}
@Test
public void testPosition() throws Exception
{
_slicedBuffer = createSlice();
assertEquals("Unexpected position for new slice", (long) 0, (long) _slicedBuffer.position());
_slicedBuffer.position(1);
assertEquals("Unexpected position after advance", (long) 1, (long) _slicedBuffer.position());
final int oldLimit = _slicedBuffer.limit();
_slicedBuffer.limit(oldLimit - 1);
try
{
_slicedBuffer.position(oldLimit);
fail("Exception not thrown");
}
catch (IllegalArgumentException e)
{
// pass
}
}
@Test
public void testSettingPositionBackwardsResetsMark()
{
_parent.position(8);
_parent.mark();
_parent.position(7);
try
{
_parent.reset();
fail("Expected exception not thrown");
}
catch (InvalidMarkException e)
{
// pass
}
}
@Test
public void testSettingPositionForwardDoeNotResetMark()
{
final int originalPosition = 3;
_parent.position(originalPosition);
_parent.mark();
_parent.position(9);
_parent.reset();
assertEquals("Unexpected position", (long) originalPosition, (long) _parent.position());
}
@Test
public void testRewind() throws Exception
{
final int expectedLimit = 7;
_parent.position(1);
_parent.limit(expectedLimit);
_parent.mark();
_parent.position(3);
_parent.rewind();
assertEquals("Unexpected position", (long) 0, (long) _parent.position());
assertEquals("Unexpected limit", (long) expectedLimit, (long) _parent.limit());
try
{
_parent.reset();
fail("Expected exception not thrown");
}
catch (InvalidMarkException e)
{
// pass
}
}
@Test
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", (long) 1, (long) _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", (long) 1, (long) _slicedBuffer.position());
}
@Test
public void testPutQpidByteBufferMultipleIntoMultiple() throws Exception
{
_slicedBuffer = createSlice();
final byte[] source = getTestBytes(_slicedBuffer.remaining());
_slicedBuffer.put(source);
_slicedBuffer.flip();
try( QpidByteBuffer other = QpidByteBuffer.allocateDirect(BUFFER_SIZE))
{
other.put(_slicedBuffer);
other.flip();
byte[] target = new byte[other.remaining()];
other.get(target);
Assert.assertArrayEquals("Unexpected put QpidByteBuffer result", source, target);
}
}
@Test
public void testPutQpidByteBufferMultipleIntoSingle() throws Exception
{
_slicedBuffer = createSlice();
final byte[] source = getTestBytes(_slicedBuffer.remaining());
_slicedBuffer.put(source);
_slicedBuffer.flip();
try( QpidByteBuffer other = QpidByteBuffer.wrap(new byte[source.length]))
{
other.put(_slicedBuffer);
other.flip();
byte[] target = new byte[other.remaining()];
other.get(target);
Assert.assertArrayEquals("Unexpected put QpidByteBuffer result", source, target);
}
}
@Test
public void testPutQpidByteBufferSingleIntoMultiple() throws Exception
{
_slicedBuffer = createSlice();
final byte[] source = getTestBytes(_slicedBuffer.remaining());
try( QpidByteBuffer other = QpidByteBuffer.wrap(source))
{
_slicedBuffer.put(other);
_slicedBuffer.flip();
byte[] target = new byte[_slicedBuffer.remaining()];
_slicedBuffer.get(target);
Assert.assertArrayEquals("Unexpected put QpidByteBuffer result", source, target);
}
}
@Test
public void testPutByteBuffer() throws Exception
{
final byte[] source = getTestBytes(_parent.remaining() - 1);
ByteBuffer src = ByteBuffer.wrap(source);
_parent.put(src);
_parent.flip();
byte[] target = new byte[_parent.remaining()];
_parent.get(target);
Assert.assertArrayEquals("Unexpected but ByteBuffer result", source, target);
}
@Test
public void testDuplicate()
{
_slicedBuffer = createSlice();
_slicedBuffer.position(1);
int originalLimit = _slicedBuffer.limit();
_slicedBuffer.limit(originalLimit - 1);
try (QpidByteBuffer duplicate = _slicedBuffer.duplicate())
{
assertEquals("Unexpected position", (long) _slicedBuffer.position(), (long) duplicate.position());
assertEquals("Unexpected limit", (long) _slicedBuffer.limit(), (long) duplicate.limit());
assertEquals("Unexpected capacity", (long) _slicedBuffer.capacity(), (long) duplicate.capacity());
duplicate.position(2);
duplicate.limit(originalLimit - 2);
assertEquals("Unexpected position in the original", (long) 1, (long) _slicedBuffer.position());
assertEquals("Unexpected limit in the original",
(long) (originalLimit - 1),
(long) _slicedBuffer.limit());
}
}
@Test
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",
(long) originalRemaining,
(long) _slicedBuffer.remaining());
assertEquals("Unexpected remaining in destination", (long) 0, (long) destination.remaining());
Assert.assertArrayEquals("Unexpected copyTo result", source, destination.array());
}
@Test
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",
(long) originalRemaining,
(long) _slicedBuffer.remaining());
Assert.assertArrayEquals("Unexpected copyTo result", source, destination);
}
@Test
public void testPutCopyOfSingleIntoMultiple()
{
_slicedBuffer = createSlice();
byte[] source = getTestBytes(_slicedBuffer.remaining());
QpidByteBuffer sourceQpidByteBuffer = QpidByteBuffer.wrap(source);
_slicedBuffer.putCopyOf(sourceQpidByteBuffer);
assertEquals("Copied buffer should not be changed",
(long) source.length,
(long) sourceQpidByteBuffer.remaining());
assertEquals("Buffer should be full", (long) 0, (long) _slicedBuffer.remaining());
_slicedBuffer.flip();
byte[] destination = new byte[source.length];
_slicedBuffer.get(destination);
Assert.assertArrayEquals("Unexpected putCopyOf result", source, destination);
}
@Test
public void testPutCopyOfMultipleIntoSingle()
{
_slicedBuffer = createSlice();
byte[] source = getTestBytes(_slicedBuffer.remaining());
_slicedBuffer.put(source);
_slicedBuffer.flip();
try (QpidByteBuffer target = QpidByteBuffer.wrap(new byte[source.length + 1]))
{
target.putCopyOf(_slicedBuffer);
assertEquals("Copied buffer should not be changed",
(long) source.length,
(long) _slicedBuffer.remaining());
assertEquals("Unexpected remaining", (long) 1, (long) target.remaining());
target.flip();
byte[] destination = new byte[source.length];
target.get(destination);
Assert.assertArrayEquals("Unexpected putCopyOf result", source, destination);
}
}
@Test
public void testPutCopyOfMultipleIntoMultiple()
{
_slicedBuffer = createSlice();
byte[] source = getTestBytes(_slicedBuffer.remaining());
_slicedBuffer.put(source);
_slicedBuffer.flip();
try (QpidByteBuffer target = QpidByteBuffer.allocateDirect(BUFFER_SIZE))
{
target.putCopyOf(_slicedBuffer);
assertEquals("Copied buffer should not be changed",
(long) source.length,
(long) _slicedBuffer.remaining());
assertEquals("Unexpected remaining", (long) 2, (long) target.remaining());
target.flip();
byte[] destination = new byte[source.length];
target.get(destination);
Assert.assertArrayEquals("Unexpected putCopyOf result", source, destination);
}
}
@Test
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", (long) remaining, (long) _slicedBuffer.position());
assertEquals("Unexpected limit", (long) _slicedBuffer.capacity(), (long) _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);
}
@Test
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();
try (QpidByteBuffer newSlice = _slicedBuffer.slice())
{
assertEquals("Unexpected position in original", (long) 1, (long) _slicedBuffer.position());
assertEquals("Unexpected limit in original",
(long) (source.length - 1),
(long) _slicedBuffer.limit());
assertEquals("Unexpected position", (long) 0, (long) newSlice.position());
assertEquals("Unexpected limit", (long) remaining, (long) newSlice.limit());
assertEquals("Unexpected capacity", (long) remaining, (long) 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);
}
}
@Test
public void testViewOfSlice()
{
_slicedBuffer = createSlice();
byte[] source = getTestBytes(_slicedBuffer.remaining());
_slicedBuffer.put(source);
_slicedBuffer.position(1);
_slicedBuffer.limit(_slicedBuffer.limit() - 1);
try (QpidByteBuffer view = _slicedBuffer.view(0, _slicedBuffer.remaining()))
{
assertEquals("Unexpected position in original", (long) 1, (long) _slicedBuffer.position());
assertEquals("Unexpected limit in original",
(long) (source.length - 1),
(long) _slicedBuffer.limit());
assertEquals("Unexpected position", (long) 0, (long) view.position());
assertEquals("Unexpected limit", (long) _slicedBuffer.remaining(), (long) view.limit());
assertEquals("Unexpected capacity", (long) _slicedBuffer.remaining(), (long) 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);
}
try (QpidByteBuffer view = _slicedBuffer.view(1, _slicedBuffer.remaining() - 2))
{
assertEquals("Unexpected position in original", (long) 1, (long) _slicedBuffer.position());
assertEquals("Unexpected limit in original",
(long) (source.length - 1),
(long) _slicedBuffer.limit());
assertEquals("Unexpected position", (long) 0, (long) view.position());
assertEquals("Unexpected limit", (long) (_slicedBuffer.remaining() - 2), (long) view.limit());
assertEquals("Unexpected capacity", (long) (_slicedBuffer.remaining() - 2), (long) 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);
}
}
@Test
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());
}
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 ", (long) 0, (long) _slicedBuffer.position());
assertEquals("Unexpected limit ", (long) size, (long) _slicedBuffer.limit());
assertEquals("Unexpected capacity ", (long) size, (long) _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,
(long) size,
(long) _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", (long) 0, (long) _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
}
_slicedBuffer.dispose();
_slicedBuffer = null;
}
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
}
_slicedBuffer.dispose();
_slicedBuffer = null;
}
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);
}
}
@Test
public void testPooledBufferIsZeroedLoan() throws Exception
{
try (QpidByteBuffer buffer = QpidByteBuffer.allocateDirect(BUFFER_SIZE))
{
buffer.put((byte) 0xFF);
}
try (QpidByteBuffer buffer = QpidByteBuffer.allocateDirect(BUFFER_SIZE))
{
buffer.limit(1);
assertEquals("Pooled QpidByteBuffer is not zeroed.", (long) (byte) 0x0, (long) buffer.get());
}
}
@Test
public void testAllocateDirectOfSameSize() throws Exception
{
int bufferSize = BUFFER_SIZE;
try (QpidByteBuffer buffer = QpidByteBuffer.allocateDirect(bufferSize))
{
assertEquals("Unexpected buffer size", (long) bufferSize, (long) buffer.capacity());
assertEquals("Unexpected position on newly created buffer", (long) 0, (long) buffer.position());
assertEquals("Unexpected limit on newly created buffer", (long) bufferSize, (long) buffer.limit());
}
}
@Test
public void testAllocateDirectOfSmallerSize() throws Exception
{
int bufferSize = BUFFER_SIZE - 1;
try (QpidByteBuffer buffer = QpidByteBuffer.allocateDirect(bufferSize))
{
assertEquals("Unexpected buffer size", (long) bufferSize, (long) buffer.capacity());
assertEquals("Unexpected position on newly created buffer", (long) 0, (long) buffer.position());
assertEquals("Unexpected limit on newly created buffer", (long) bufferSize, (long) buffer.limit());
}
}
@Test
public void testAllocateDirectOfLargerSize() throws Exception
{
int bufferSize = BUFFER_SIZE + 1;
try (QpidByteBuffer buffer = QpidByteBuffer.allocateDirect(bufferSize))
{
assertEquals("Unexpected buffer size", (long) bufferSize, (long) buffer.capacity());
assertEquals("Unexpected position on newly created buffer", (long) 0, (long) buffer.position());
assertEquals("Unexpected limit on newly created buffer", (long) bufferSize, (long) buffer.limit());
}
}
@Test
public void testAllocateDirectWithNegativeSize() throws Exception
{
try
{
QpidByteBuffer.allocateDirect(-1);
fail("It is not legal to create buffer with negative size.");
}
catch (IllegalArgumentException e)
{
// pass
}
}
@Test
public void testSettingUpPoolTwice() throws Exception
{
try
{
QpidByteBuffer.initialisePool(BUFFER_SIZE + 1, POOL_SIZE + 1, SPARSITY_FRACTION);
fail("It is not legal to initialize buffer twice with different settings.");
}
catch (IllegalStateException e)
{
// pass
}
}
@Test
public void testDeflateInflateDirect() throws Exception
{
byte[] input = "aaabbbcccddddeeeffff".getBytes();
try (QpidByteBuffer inputBuf = QpidByteBuffer.allocateDirect(input.length))
{
inputBuf.put(input);
inputBuf.flip();
assertEquals((long) input.length, (long) inputBuf.remaining());
doDeflateInflate(input, inputBuf, true);
}
}
@Test
public void testDeflateInflateHeap() throws Exception
{
byte[] input = "aaabbbcccddddeeeffff".getBytes();
try (QpidByteBuffer buffer = QpidByteBuffer.wrap(input))
{
doDeflateInflate(input, buffer, false);
}
}
@Test
public void testInflatingUncompressedBytes_ThrowsZipException() throws Exception
{
byte[] input = "not_a_compressed_stream".getBytes();
try (QpidByteBuffer original = QpidByteBuffer.wrap(input))
{
QpidByteBuffer.inflate(original);
fail("Exception not thrown");
}
catch(java.util.zip.ZipException ze)
{
// PASS
}
}
@Test
public void testSlice() throws Exception
{
try (QpidByteBuffer directBuffer = QpidByteBuffer.allocate(true, 6))
{
directBuffer.position(2);
directBuffer.limit(5);
try (QpidByteBuffer directSlice = directBuffer.slice())
{
assertTrue("Direct slice should be direct too", directSlice.isDirect());
assertEquals("Unexpected capacity", (long) 3, (long) directSlice.capacity());
assertEquals("Unexpected limit", (long) 3, (long) directSlice.limit());
assertEquals("Unexpected position", (long) 0, (long) directSlice.position());
}
}
}
@Test
public void testView() throws Exception
{
byte[] content = "ABCDEF".getBytes();
try (QpidByteBuffer buffer = QpidByteBuffer.allocate(true, content.length))
{
buffer.put(content);
buffer.position(2);
buffer.limit(5);
try (QpidByteBuffer view = buffer.view(0, buffer.remaining()))
{
assertTrue("Unexpected view direct", view.isDirect());
assertEquals("Unexpected capacity", (long) 3, (long) view.capacity());
assertEquals("Unexpected limit", (long) 3, (long) view.limit());
assertEquals("Unexpected position", (long) 0, (long) view.position());
final byte[] destination = new byte[view.remaining()];
view.get(destination);
Assert.assertArrayEquals("CDE".getBytes(), destination);
}
try (QpidByteBuffer viewWithOffset = buffer.view(1, 1))
{
final byte[] destination = new byte[viewWithOffset.remaining()];
viewWithOffset.get(destination);
Assert.assertArrayEquals("D".getBytes(), destination);
}
}
}
@Test
public void testSparsity()
{
assertFalse("Unexpected sparsity after creation", _parent.isSparse());
QpidByteBuffer child = _parent.view(0, 8);
QpidByteBuffer grandChild = child.view(0, 2);
assertFalse("Unexpected sparsity after child creation", _parent.isSparse());
_parent.dispose();
_parent = null;
assertFalse("Unexpected sparsity after parent disposal", child.isSparse());
child.dispose();
assertTrue("Buffer should be sparse", grandChild.isSparse());
grandChild.dispose();
}
@Test
public void testAsQpidByteBuffers() throws IOException
{
byte[] dataForTwoBufs = "01234567890".getBytes(StandardCharsets.US_ASCII);
try (QpidByteBuffer qpidByteBuffer = QpidByteBuffer.asQpidByteBuffer(new ByteArrayInputStream(dataForTwoBufs)))
{
assertEquals("Unexpected remaining in buf", (long) 11, (long) qpidByteBuffer.remaining());
}
try (QpidByteBuffer bufsForEmptyBytes = QpidByteBuffer.asQpidByteBuffer(new ByteArrayInputStream(new byte[]{})))
{
assertEquals("Unexpected remaining in buf for empty buffer",
(long) 0,
(long) bufsForEmptyBytes.remaining());
}
}
@Test
public void testConcatenate() throws Exception
{
try (QpidByteBuffer buffer1 = QpidByteBuffer.allocateDirect(10);
QpidByteBuffer buffer2 = QpidByteBuffer.allocateDirect(10))
{
final short buffer1Value = (short) (1 << 15);
buffer1.putShort(buffer1Value);
buffer1.flip();
final char buffer2Value = 'x';
buffer2.putChar(2, buffer2Value);
buffer2.position(4);
buffer2.flip();
try (QpidByteBuffer concatenate = QpidByteBuffer.concatenate(buffer1, buffer2))
{
assertEquals("Unexpected capacity", (long) 6, (long) concatenate.capacity());
assertEquals("Unexpected position", (long) 0, (long) concatenate.position());
assertEquals("Unexpected limit", (long) 6, (long) concatenate.limit());
assertEquals("Unexpected value 1", (long) buffer1Value, (long) concatenate.getShort());
assertEquals("Unexpected value 2", (long) buffer2Value, (long) concatenate.getChar(4));
}
}
}
private void doDeflateInflate(byte[] input,
QpidByteBuffer inputBuf,
boolean direct) throws IOException
{
try (QpidByteBuffer deflatedBuf = QpidByteBuffer.deflate(inputBuf))
{
assertNotNull(deflatedBuf);
try (QpidByteBuffer inflatedBuf = QpidByteBuffer.inflate(deflatedBuf))
{
assertNotNull(inflatedBuf);
int inflatedBytesCount = inflatedBuf.remaining();
byte[] inflatedBytes = new byte[inflatedBytesCount];
inflatedBuf.get(inflatedBytes);
byte[] expectedBytes = Arrays.copyOfRange(input, 0, inflatedBytes.length);
Assert.assertArrayEquals("Inflated buf has unexpected content", expectedBytes, inflatedBytes);
assertEquals("Unexpected number of inflated bytes",
(long) input.length,
(long) inflatedBytesCount);
}
}
}
}