netty5/buffer/src/test/java/io/netty5/buffer/AbstractByteBufTest.java

5029 lines
171 KiB
Java

/*
* Copyright 2012 The Netty Project
*
* The Netty Project 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:
*
* https://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 io.netty5.buffer;
import static io.netty5.buffer.Unpooled.LITTLE_ENDIAN;
import static io.netty5.buffer.Unpooled.buffer;
import static io.netty5.buffer.Unpooled.copiedBuffer;
import static io.netty5.buffer.Unpooled.directBuffer;
import static io.netty5.buffer.Unpooled.unreleasableBuffer;
import static io.netty5.buffer.Unpooled.wrappedBuffer;
import static io.netty5.util.internal.EmptyArrays.EMPTY_BYTES;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import io.netty5.util.ByteProcessor;
import io.netty5.util.CharsetUtil;
import io.netty5.util.IllegalReferenceCountException;
import io.netty5.util.internal.PlatformDependent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
/**
* An abstract test class for channel buffers
*/
public abstract class AbstractByteBufTest {
private static final int CAPACITY = 4096; // Must be even
private static final int BLOCK_SIZE = 128;
private static final int JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS = 100;
private long seed;
private Random random;
private ByteBuf buffer;
protected final ByteBuf newBuffer(int capacity) {
return newBuffer(capacity, Integer.MAX_VALUE);
}
protected abstract ByteBuf newBuffer(int capacity, int maxCapacity);
protected boolean discardReadBytesDoesNotMoveWritableBytes() {
return true;
}
@BeforeEach
public void init() {
buffer = newBuffer(CAPACITY);
seed = System.currentTimeMillis();
random = new Random(seed);
}
@AfterEach
public void dispose() {
if (buffer != null) {
assertThat(buffer.release(), is(true));
assertThat(buffer.refCnt(), is(0));
try {
buffer.release();
} catch (Exception e) {
// Ignore.
}
buffer = null;
}
}
@Test
public void comparableInterfaceNotViolated() {
assumeFalse(buffer.isReadOnly());
buffer.writerIndex(buffer.readerIndex());
assumeTrue(buffer.writableBytes() >= 4);
buffer.writeLong(0);
ByteBuf buffer2 = newBuffer(CAPACITY);
assumeFalse(buffer2.isReadOnly());
buffer2.writerIndex(buffer2.readerIndex());
// Write an unsigned integer that will cause buffer.getUnsignedInt() - buffer2.getUnsignedInt() to underflow the
// int type and wrap around on the negative side.
buffer2.writeLong(0xF0000000L);
assertTrue(buffer.compareTo(buffer2) < 0);
assertTrue(buffer2.compareTo(buffer) > 0);
buffer2.release();
}
@Test
public void initialState() {
assertEquals(CAPACITY, buffer.capacity());
assertEquals(0, buffer.readerIndex());
}
@Test
public void readerIndexBoundaryCheck1() {
try {
buffer.writerIndex(0);
} catch (IndexOutOfBoundsException e) {
fail();
}
assertThrows(IndexOutOfBoundsException.class, () -> buffer.readerIndex(-1));
}
@Test
public void readerIndexBoundaryCheck2() {
try {
buffer.writerIndex(buffer.capacity());
} catch (IndexOutOfBoundsException e) {
fail();
}
assertThrows(IndexOutOfBoundsException.class, () -> buffer.readerIndex(buffer.capacity() + 1));
}
@Test
public void readerIndexBoundaryCheck3() {
try {
buffer.writerIndex(CAPACITY / 2);
} catch (IndexOutOfBoundsException e) {
fail();
}
assertThrows(IndexOutOfBoundsException.class, () -> buffer.readerIndex(CAPACITY * 3 / 2));
}
@Test
public void readerIndexBoundaryCheck4() {
buffer.writerIndex(0);
buffer.readerIndex(0);
buffer.writerIndex(buffer.capacity());
buffer.readerIndex(buffer.capacity());
}
@Test
public void writerIndexBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.writerIndex(-1));
}
@Test
public void writerIndexBoundaryCheck2() {
try {
buffer.writerIndex(CAPACITY);
buffer.readerIndex(CAPACITY);
} catch (IndexOutOfBoundsException e) {
fail();
}
assertThrows(IndexOutOfBoundsException.class, () -> buffer.writerIndex(buffer.capacity() + 1));
}
@Test
public void writerIndexBoundaryCheck3() {
try {
buffer.writerIndex(CAPACITY);
buffer.readerIndex(CAPACITY / 2);
} catch (IndexOutOfBoundsException e) {
fail();
}
assertThrows(IndexOutOfBoundsException.class, () -> buffer.writerIndex(CAPACITY / 4));
}
@Test
public void writerIndexBoundaryCheck4() {
buffer.writerIndex(0);
buffer.readerIndex(0);
buffer.writerIndex(CAPACITY);
buffer.writeBytes(ByteBuffer.wrap(EMPTY_BYTES));
}
@Test
public void getBooleanBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBoolean(-1));
}
@Test
public void getBooleanBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBoolean(buffer.capacity()));
}
@Test
public void getByteBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getByte(-1));
}
@Test
public void getByteBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getByte(buffer.capacity()));
}
@Test
public void getShortBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getShort(-1));
}
@Test
public void getShortBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getShort(buffer.capacity() - 1));
}
@Test
public void getMediumBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getMedium(-1));
}
@Test
public void getMediumBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getMedium(buffer.capacity() - 2));
}
@Test
public void getIntBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getInt(-1));
}
@Test
public void getIntBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getInt(buffer.capacity() - 3));
}
@Test
public void getLongBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getLong(-1));
}
@Test
public void getLongBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getLong(buffer.capacity() - 7));
}
@Test
public void getByteArrayBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBytes(-1, EMPTY_BYTES));
}
@Test
public void getByteArrayBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBytes(-1, EMPTY_BYTES, 0, 0));
}
@Test
public void getByteArrayBoundaryCheck3() {
byte[] dst = new byte[4];
buffer.setInt(0, 0x01020304);
try {
buffer.getBytes(0, dst, -1, 4);
fail();
} catch (IndexOutOfBoundsException e) {
// Success
}
// No partial copy is expected.
assertEquals(0, dst[0]);
assertEquals(0, dst[1]);
assertEquals(0, dst[2]);
assertEquals(0, dst[3]);
}
@Test
public void getByteArrayBoundaryCheck4() {
byte[] dst = new byte[4];
buffer.setInt(0, 0x01020304);
try {
buffer.getBytes(0, dst, 1, 4);
fail();
} catch (IndexOutOfBoundsException e) {
// Success
}
// No partial copy is expected.
assertEquals(0, dst[0]);
assertEquals(0, dst[1]);
assertEquals(0, dst[2]);
assertEquals(0, dst[3]);
}
@Test
public void getByteBufferBoundaryCheck() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBytes(-1, ByteBuffer.allocate(0)));
}
@Test
public void copyBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.copy(-1, 0));
}
@Test
public void copyBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.copy(0, buffer.capacity() + 1));
}
@Test
public void copyBoundaryCheck3() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.copy(buffer.capacity() + 1, 0));
}
@Test
public void copyBoundaryCheck4() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.copy(buffer.capacity(), 1));
}
@Test
public void setIndexBoundaryCheck1() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.setIndex(-1, CAPACITY));
}
@Test
public void setIndexBoundaryCheck2() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.setIndex(CAPACITY / 2, CAPACITY / 4));
}
@Test
public void setIndexBoundaryCheck3() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.setIndex(0, CAPACITY + 1));
}
@Test
public void getByteBufferState() {
ByteBuffer dst = ByteBuffer.allocate(4);
dst.position(1);
dst.limit(3);
buffer.setByte(0, (byte) 1);
buffer.setByte(1, (byte) 2);
buffer.setByte(2, (byte) 3);
buffer.setByte(3, (byte) 4);
buffer.getBytes(1, dst);
assertEquals(3, dst.position());
assertEquals(3, dst.limit());
dst.clear();
assertEquals(0, dst.get(0));
assertEquals(2, dst.get(1));
assertEquals(3, dst.get(2));
assertEquals(0, dst.get(3));
}
@Test
public void getDirectByteBufferBoundaryCheck() {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBytes(-1, ByteBuffer.allocateDirect(0)));
}
@Test
public void getDirectByteBufferState() {
ByteBuffer dst = ByteBuffer.allocateDirect(4);
dst.position(1);
dst.limit(3);
buffer.setByte(0, (byte) 1);
buffer.setByte(1, (byte) 2);
buffer.setByte(2, (byte) 3);
buffer.setByte(3, (byte) 4);
buffer.getBytes(1, dst);
assertEquals(3, dst.position());
assertEquals(3, dst.limit());
dst.clear();
assertEquals(0, dst.get(0));
assertEquals(2, dst.get(1));
assertEquals(3, dst.get(2));
assertEquals(0, dst.get(3));
}
@Test
public void testRandomByteAccess() {
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
buffer.setByte(i, value);
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
assertEquals(value, buffer.getByte(i));
}
}
@Test
public void testRandomUnsignedByteAccess() {
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
buffer.setByte(i, value);
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i ++) {
int value = random.nextInt() & 0xFF;
assertEquals(value, buffer.getUnsignedByte(i));
}
}
@Test
public void testRandomShortAccess() {
testRandomShortAccess(true);
}
@Test
public void testRandomShortLEAccess() {
testRandomShortAccess(false);
}
private void testRandomShortAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 1; i += 2) {
short value = (short) random.nextInt();
if (testBigEndian) {
buffer.setShort(i, value);
} else {
buffer.setShortLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 1; i += 2) {
short value = (short) random.nextInt();
if (testBigEndian) {
assertEquals(value, buffer.getShort(i));
} else {
assertEquals(value, buffer.getShortLE(i));
}
}
}
@Test
public void testShortConsistentWithByteBuffer() {
testShortConsistentWithByteBuffer(true, true);
testShortConsistentWithByteBuffer(true, false);
testShortConsistentWithByteBuffer(false, true);
testShortConsistentWithByteBuffer(false, false);
}
private void testShortConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
: ByteBuffer.allocate(buffer.capacity());
if (!testBigEndian) {
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
short expected = (short) (random.nextInt() & 0xFFFF);
javaBuffer.putShort(expected);
final int bufferIndex = buffer.capacity() - 2;
if (testBigEndian) {
buffer.setShort(bufferIndex, expected);
} else {
buffer.setShortLE(bufferIndex, expected);
}
javaBuffer.flip();
short javaActual = javaBuffer.getShort();
assertEquals(expected, javaActual);
assertEquals(javaActual, testBigEndian ? buffer.getShort(bufferIndex)
: buffer.getShortLE(bufferIndex));
}
}
@Test
public void testRandomUnsignedShortAccess() {
testRandomUnsignedShortAccess(true);
}
@Test
public void testRandomUnsignedShortLEAccess() {
testRandomUnsignedShortAccess(false);
}
private void testRandomUnsignedShortAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 1; i += 2) {
short value = (short) random.nextInt();
if (testBigEndian) {
buffer.setShort(i, value);
} else {
buffer.setShortLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 1; i += 2) {
int value = random.nextInt() & 0xFFFF;
if (testBigEndian) {
assertEquals(value, buffer.getUnsignedShort(i));
} else {
assertEquals(value, buffer.getUnsignedShortLE(i));
}
}
}
@Test
public void testRandomMediumAccess() {
testRandomMediumAccess(true);
}
@Test
public void testRandomMediumLEAccess() {
testRandomMediumAccess(false);
}
private void testRandomMediumAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 2; i += 3) {
int value = random.nextInt();
if (testBigEndian) {
buffer.setMedium(i, value);
} else {
buffer.setMediumLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 2; i += 3) {
int value = random.nextInt() << 8 >> 8;
if (testBigEndian) {
assertEquals(value, buffer.getMedium(i));
} else {
assertEquals(value, buffer.getMediumLE(i));
}
}
}
@Test
public void testRandomUnsignedMediumAccess() {
testRandomUnsignedMediumAccess(true);
}
@Test
public void testRandomUnsignedMediumLEAccess() {
testRandomUnsignedMediumAccess(false);
}
private void testRandomUnsignedMediumAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 2; i += 3) {
int value = random.nextInt();
if (testBigEndian) {
buffer.setMedium(i, value);
} else {
buffer.setMediumLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 2; i += 3) {
int value = random.nextInt() & 0x00FFFFFF;
if (testBigEndian) {
assertEquals(value, buffer.getUnsignedMedium(i));
} else {
assertEquals(value, buffer.getUnsignedMediumLE(i));
}
}
}
@Test
public void testMediumConsistentWithByteBuffer() {
testMediumConsistentWithByteBuffer(true, true);
testMediumConsistentWithByteBuffer(true, false);
testMediumConsistentWithByteBuffer(false, true);
testMediumConsistentWithByteBuffer(false, false);
}
private void testMediumConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
: ByteBuffer.allocate(buffer.capacity());
if (!testBigEndian) {
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
int expected = random.nextInt() & 0x00FFFFFF;
javaBuffer.putInt(expected);
final int bufferIndex = buffer.capacity() - 3;
if (testBigEndian) {
buffer.setMedium(bufferIndex, expected);
} else {
buffer.setMediumLE(bufferIndex, expected);
}
javaBuffer.flip();
int javaActual = javaBuffer.getInt();
assertEquals(expected, javaActual);
assertEquals(javaActual, testBigEndian ? buffer.getUnsignedMedium(bufferIndex)
: buffer.getUnsignedMediumLE(bufferIndex));
}
}
@Test
public void testRandomIntAccess() {
testRandomIntAccess(true);
}
@Test
public void testRandomIntLEAccess() {
testRandomIntAccess(false);
}
private void testRandomIntAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
int value = random.nextInt();
if (testBigEndian) {
buffer.setInt(i, value);
} else {
buffer.setIntLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
int value = random.nextInt();
if (testBigEndian) {
assertEquals(value, buffer.getInt(i));
} else {
assertEquals(value, buffer.getIntLE(i));
}
}
}
@Test
public void testIntConsistentWithByteBuffer() {
testIntConsistentWithByteBuffer(true, true);
testIntConsistentWithByteBuffer(true, false);
testIntConsistentWithByteBuffer(false, true);
testIntConsistentWithByteBuffer(false, false);
}
private void testIntConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
: ByteBuffer.allocate(buffer.capacity());
if (!testBigEndian) {
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
int expected = random.nextInt();
javaBuffer.putInt(expected);
final int bufferIndex = buffer.capacity() - 4;
if (testBigEndian) {
buffer.setInt(bufferIndex, expected);
} else {
buffer.setIntLE(bufferIndex, expected);
}
javaBuffer.flip();
int javaActual = javaBuffer.getInt();
assertEquals(expected, javaActual);
assertEquals(javaActual, testBigEndian ? buffer.getInt(bufferIndex)
: buffer.getIntLE(bufferIndex));
}
}
@Test
public void testRandomUnsignedIntAccess() {
testRandomUnsignedIntAccess(true);
}
@Test
public void testRandomUnsignedIntLEAccess() {
testRandomUnsignedIntAccess(false);
}
private void testRandomUnsignedIntAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
int value = random.nextInt();
if (testBigEndian) {
buffer.setInt(i, value);
} else {
buffer.setIntLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
long value = random.nextInt() & 0xFFFFFFFFL;
if (testBigEndian) {
assertEquals(value, buffer.getUnsignedInt(i));
} else {
assertEquals(value, buffer.getUnsignedIntLE(i));
}
}
}
@Test
public void testRandomLongAccess() {
testRandomLongAccess(true);
}
@Test
public void testRandomLongLEAccess() {
testRandomLongAccess(false);
}
private void testRandomLongAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
long value = random.nextLong();
if (testBigEndian) {
buffer.setLong(i, value);
} else {
buffer.setLongLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
long value = random.nextLong();
if (testBigEndian) {
assertEquals(value, buffer.getLong(i));
} else {
assertEquals(value, buffer.getLongLE(i));
}
}
}
@Test
public void testLongConsistentWithByteBuffer() {
testLongConsistentWithByteBuffer(true, true);
testLongConsistentWithByteBuffer(true, false);
testLongConsistentWithByteBuffer(false, true);
testLongConsistentWithByteBuffer(false, false);
}
private void testLongConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
: ByteBuffer.allocate(buffer.capacity());
if (!testBigEndian) {
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
long expected = random.nextLong();
javaBuffer.putLong(expected);
final int bufferIndex = buffer.capacity() - 8;
if (testBigEndian) {
buffer.setLong(bufferIndex, expected);
} else {
buffer.setLongLE(bufferIndex, expected);
}
javaBuffer.flip();
long javaActual = javaBuffer.getLong();
assertEquals(expected, javaActual);
assertEquals(javaActual, testBigEndian ? buffer.getLong(bufferIndex)
: buffer.getLongLE(bufferIndex));
}
}
@Test
public void testRandomFloatAccess() {
testRandomFloatAccess(true);
}
@Test
public void testRandomFloatLEAccess() {
testRandomFloatAccess(false);
}
private void testRandomFloatAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
float value = random.nextFloat();
if (testBigEndian) {
buffer.setFloat(i, value);
} else {
buffer.setFloatLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
float expected = random.nextFloat();
float actual = testBigEndian? buffer.getFloat(i) : buffer.getFloatLE(i);
assertEquals(expected, actual, 0.01);
}
}
@Test
public void testRandomDoubleAccess() {
testRandomDoubleAccess(true);
}
@Test
public void testRandomDoubleLEAccess() {
testRandomDoubleAccess(false);
}
private void testRandomDoubleAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
double value = random.nextDouble();
if (testBigEndian) {
buffer.setDouble(i, value);
} else {
buffer.setDoubleLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
double expected = random.nextDouble();
double actual = testBigEndian? buffer.getDouble(i) : buffer.getDoubleLE(i);
assertEquals(expected, actual, 0.01);
}
}
@Test
public void testSetZero() {
buffer.clear();
while (buffer.isWritable()) {
buffer.writeByte((byte) 0xFF);
}
for (int i = 0; i < buffer.capacity();) {
int length = Math.min(buffer.capacity() - i, random.nextInt(32));
buffer.setZero(i, length);
i += length;
}
for (int i = 0; i < buffer.capacity(); i ++) {
assertEquals(0, buffer.getByte(i));
}
}
@Test
public void testSequentialByteAccess() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
buffer.writeByte(value);
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
assertEquals(value, buffer.readByte());
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialUnsignedByteAccess() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
buffer.writeByte(value);
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i ++) {
int value = random.nextInt() & 0xFF;
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
assertEquals(value, buffer.readUnsignedByte());
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialShortAccess() {
testSequentialShortAccess(true);
}
@Test
public void testSequentialShortLEAccess() {
testSequentialShortAccess(false);
}
private void testSequentialShortAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 2) {
short value = (short) random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeShort(value);
} else {
buffer.writeShortLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i += 2) {
short value = (short) random.nextInt();
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readShort());
} else {
assertEquals(value, buffer.readShortLE());
}
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialUnsignedShortAccess() {
testSequentialUnsignedShortAccess(true);
}
@Test
public void testSequentialUnsignedShortLEAccess() {
testSequentialUnsignedShortAccess(true);
}
private void testSequentialUnsignedShortAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 2) {
short value = (short) random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeShort(value);
} else {
buffer.writeShortLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i += 2) {
int value = random.nextInt() & 0xFFFF;
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readUnsignedShort());
} else {
assertEquals(value, buffer.readUnsignedShortLE());
}
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialMediumAccess() {
testSequentialMediumAccess(true);
}
@Test
public void testSequentialMediumLEAccess() {
testSequentialMediumAccess(false);
}
private void testSequentialMediumAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() / 3 * 3; i += 3) {
int value = random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeMedium(value);
} else {
buffer.writeMediumLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity() / 3 * 3, buffer.writerIndex());
assertEquals(buffer.capacity() % 3, buffer.writableBytes());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() / 3 * 3; i += 3) {
int value = random.nextInt() << 8 >> 8;
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readMedium());
} else {
assertEquals(value, buffer.readMediumLE());
}
}
assertEquals(buffer.capacity() / 3 * 3, buffer.readerIndex());
assertEquals(buffer.capacity() / 3 * 3, buffer.writerIndex());
assertEquals(0, buffer.readableBytes());
assertEquals(buffer.capacity() % 3, buffer.writableBytes());
}
@Test
public void testSequentialUnsignedMediumAccess() {
testSequentialUnsignedMediumAccess(true);
}
@Test
public void testSequentialUnsignedMediumLEAccess() {
testSequentialUnsignedMediumAccess(false);
}
private void testSequentialUnsignedMediumAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() / 3 * 3; i += 3) {
int value = random.nextInt() & 0x00FFFFFF;
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeMedium(value);
} else {
buffer.writeMediumLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity() / 3 * 3, buffer.writerIndex());
assertEquals(buffer.capacity() % 3, buffer.writableBytes());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() / 3 * 3; i += 3) {
int value = random.nextInt() & 0x00FFFFFF;
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readUnsignedMedium());
} else {
assertEquals(value, buffer.readUnsignedMediumLE());
}
}
assertEquals(buffer.capacity() / 3 * 3, buffer.readerIndex());
assertEquals(buffer.capacity() / 3 * 3, buffer.writerIndex());
assertEquals(0, buffer.readableBytes());
assertEquals(buffer.capacity() % 3, buffer.writableBytes());
}
@Test
public void testSequentialIntAccess() {
testSequentialIntAccess(true);
}
@Test
public void testSequentialIntLEAccess() {
testSequentialIntAccess(false);
}
private void testSequentialIntAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 4) {
int value = random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeInt(value);
} else {
buffer.writeIntLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i += 4) {
int value = random.nextInt();
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readInt());
} else {
assertEquals(value, buffer.readIntLE());
}
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialUnsignedIntAccess() {
testSequentialUnsignedIntAccess(true);
}
@Test
public void testSequentialUnsignedIntLEAccess() {
testSequentialUnsignedIntAccess(false);
}
private void testSequentialUnsignedIntAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 4) {
int value = random.nextInt();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeInt(value);
} else {
buffer.writeIntLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i += 4) {
long value = random.nextInt() & 0xFFFFFFFFL;
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readUnsignedInt());
} else {
assertEquals(value, buffer.readUnsignedIntLE());
}
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testSequentialLongAccess() {
testSequentialLongAccess(true);
}
@Test
public void testSequentialLongLEAccess() {
testSequentialLongAccess(false);
}
private void testSequentialLongAccess(boolean testBigEndian) {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 8) {
long value = random.nextLong();
assertEquals(i, buffer.writerIndex());
assertTrue(buffer.isWritable());
if (testBigEndian) {
buffer.writeLong(value);
} else {
buffer.writeLongLE(value);
}
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isWritable());
random.setSeed(seed);
for (int i = 0; i < buffer.capacity(); i += 8) {
long value = random.nextLong();
assertEquals(i, buffer.readerIndex());
assertTrue(buffer.isReadable());
if (testBigEndian) {
assertEquals(value, buffer.readLong());
} else {
assertEquals(value, buffer.readLongLE());
}
}
assertEquals(buffer.capacity(), buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
assertFalse(buffer.isReadable());
assertFalse(buffer.isWritable());
}
@Test
public void testByteArrayTransfer() {
byte[] value = new byte[BLOCK_SIZE * 2];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value);
buffer.setBytes(i, value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
}
random.setSeed(seed);
byte[] expectedValue = new byte[BLOCK_SIZE * 2];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue);
int valueOffset = random.nextInt(BLOCK_SIZE);
buffer.getBytes(i, value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue[j], value[j]);
}
}
}
@Test
public void testRandomByteArrayTransfer1() {
byte[] value = new byte[BLOCK_SIZE];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value);
buffer.setBytes(i, value);
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
buffer.getBytes(i, value);
for (int j = 0; j < BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value[j]);
}
}
}
@Test
public void testRandomByteArrayTransfer2() {
byte[] value = new byte[BLOCK_SIZE * 2];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value);
buffer.setBytes(i, value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
buffer.getBytes(i, value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value[j]);
}
}
}
@Test
public void testRandomHeapBufferTransfer1() {
byte[] valueContent = new byte[BLOCK_SIZE];
ByteBuf value = wrappedBuffer(valueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
value.setIndex(0, BLOCK_SIZE);
buffer.setBytes(i, value);
assertEquals(BLOCK_SIZE, value.readerIndex());
assertEquals(BLOCK_SIZE, value.writerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
value.clear();
buffer.getBytes(i, value);
assertEquals(0, value.readerIndex());
assertEquals(BLOCK_SIZE, value.writerIndex());
for (int j = 0; j < BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
}
}
@Test
public void testRandomHeapBufferTransfer2() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = wrappedBuffer(valueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
buffer.setBytes(i, value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
buffer.getBytes(i, value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
}
}
@Test
public void testRandomDirectBufferTransfer() {
byte[] tmp = new byte[BLOCK_SIZE * 2];
ByteBuf value = directBuffer(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(tmp);
value.setBytes(0, tmp, 0, value.capacity());
buffer.setBytes(i, value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
}
random.setSeed(seed);
ByteBuf expectedValue = directBuffer(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(tmp);
expectedValue.setBytes(0, tmp, 0, expectedValue.capacity());
int valueOffset = random.nextInt(BLOCK_SIZE);
buffer.getBytes(i, value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
}
value.release();
expectedValue.release();
}
@Test
public void testRandomByteBufferTransfer() {
ByteBuffer value = ByteBuffer.allocate(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value.array());
value.clear().position(random.nextInt(BLOCK_SIZE));
value.limit(value.position() + BLOCK_SIZE);
buffer.setBytes(i, value);
}
random.setSeed(seed);
ByteBuffer expectedValue = ByteBuffer.allocate(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue.array());
int valueOffset = random.nextInt(BLOCK_SIZE);
value.clear().position(valueOffset).limit(valueOffset + BLOCK_SIZE);
buffer.getBytes(i, value);
assertEquals(valueOffset + BLOCK_SIZE, value.position());
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.get(j), value.get(j));
}
}
}
@Test
public void testSequentialByteArrayTransfer1() {
byte[] value = new byte[BLOCK_SIZE];
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value);
}
random.setSeed(seed);
byte[] expectedValue = new byte[BLOCK_SIZE];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
buffer.readBytes(value);
for (int j = 0; j < BLOCK_SIZE; j ++) {
assertEquals(expectedValue[j], value[j]);
}
}
}
@Test
public void testSequentialByteArrayTransfer2() {
byte[] value = new byte[BLOCK_SIZE * 2];
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
int readerIndex = random.nextInt(BLOCK_SIZE);
buffer.writeBytes(value, readerIndex, BLOCK_SIZE);
}
random.setSeed(seed);
byte[] expectedValue = new byte[BLOCK_SIZE * 2];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue);
int valueOffset = random.nextInt(BLOCK_SIZE);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
buffer.readBytes(value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue[j], value[j]);
}
}
}
@Test
public void testSequentialHeapBufferTransfer1() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = wrappedBuffer(valueContent);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
assertEquals(0, value.readerIndex());
assertEquals(valueContent.length, value.writerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
buffer.readBytes(value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(0, value.readerIndex());
assertEquals(valueContent.length, value.writerIndex());
}
}
@Test
public void testSequentialHeapBufferTransfer2() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = wrappedBuffer(valueContent);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
int readerIndex = random.nextInt(BLOCK_SIZE);
value.readerIndex(readerIndex);
value.writerIndex(readerIndex + BLOCK_SIZE);
buffer.writeBytes(value);
assertEquals(readerIndex + BLOCK_SIZE, value.writerIndex());
assertEquals(value.writerIndex(), value.readerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
value.readerIndex(valueOffset);
value.writerIndex(valueOffset);
buffer.readBytes(value, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(valueOffset, value.readerIndex());
assertEquals(valueOffset + BLOCK_SIZE, value.writerIndex());
}
}
@Test
public void testSequentialDirectBufferTransfer1() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = directBuffer(BLOCK_SIZE * 2);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
value.setBytes(0, valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
assertEquals(0, value.readerIndex());
assertEquals(0, value.writerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
value.setBytes(0, valueContent);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
buffer.readBytes(value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(0, value.readerIndex());
assertEquals(0, value.writerIndex());
}
value.release();
expectedValue.release();
}
@Test
public void testSequentialDirectBufferTransfer2() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = directBuffer(BLOCK_SIZE * 2);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
value.setBytes(0, valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
int readerIndex = random.nextInt(BLOCK_SIZE);
value.readerIndex(0);
value.writerIndex(readerIndex + BLOCK_SIZE);
value.readerIndex(readerIndex);
buffer.writeBytes(value);
assertEquals(readerIndex + BLOCK_SIZE, value.writerIndex());
assertEquals(value.writerIndex(), value.readerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
value.setBytes(0, valueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
value.readerIndex(valueOffset);
value.writerIndex(valueOffset);
buffer.readBytes(value, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(valueOffset, value.readerIndex());
assertEquals(valueOffset + BLOCK_SIZE, value.writerIndex());
}
value.release();
expectedValue.release();
}
@Test
public void testSequentialByteBufferBackedHeapBufferTransfer1() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = wrappedBuffer(ByteBuffer.allocate(BLOCK_SIZE * 2));
value.writerIndex(0);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
value.setBytes(0, valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value, random.nextInt(BLOCK_SIZE), BLOCK_SIZE);
assertEquals(0, value.readerIndex());
assertEquals(0, value.writerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
value.setBytes(0, valueContent);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
buffer.readBytes(value, valueOffset, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(0, value.readerIndex());
assertEquals(0, value.writerIndex());
}
}
@Test
public void testSequentialByteBufferBackedHeapBufferTransfer2() {
byte[] valueContent = new byte[BLOCK_SIZE * 2];
ByteBuf value = wrappedBuffer(ByteBuffer.allocate(BLOCK_SIZE * 2));
value.writerIndex(0);
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(valueContent);
value.setBytes(0, valueContent);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
int readerIndex = random.nextInt(BLOCK_SIZE);
value.readerIndex(0);
value.writerIndex(readerIndex + BLOCK_SIZE);
value.readerIndex(readerIndex);
buffer.writeBytes(value);
assertEquals(readerIndex + BLOCK_SIZE, value.writerIndex());
assertEquals(value.writerIndex(), value.readerIndex());
}
random.setSeed(seed);
byte[] expectedValueContent = new byte[BLOCK_SIZE * 2];
ByteBuf expectedValue = wrappedBuffer(expectedValueContent);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValueContent);
value.setBytes(0, valueContent);
int valueOffset = random.nextInt(BLOCK_SIZE);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
value.readerIndex(valueOffset);
value.writerIndex(valueOffset);
buffer.readBytes(value, BLOCK_SIZE);
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.getByte(j), value.getByte(j));
}
assertEquals(valueOffset, value.readerIndex());
assertEquals(valueOffset + BLOCK_SIZE, value.writerIndex());
}
}
@Test
public void testSequentialByteBufferTransfer() {
buffer.writerIndex(0);
ByteBuffer value = ByteBuffer.allocate(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(value.array());
value.clear().position(random.nextInt(BLOCK_SIZE));
value.limit(value.position() + BLOCK_SIZE);
buffer.writeBytes(value);
}
random.setSeed(seed);
ByteBuffer expectedValue = ByteBuffer.allocate(BLOCK_SIZE * 2);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue.array());
int valueOffset = random.nextInt(BLOCK_SIZE);
value.clear().position(valueOffset).limit(valueOffset + BLOCK_SIZE);
buffer.readBytes(value);
assertEquals(valueOffset + BLOCK_SIZE, value.position());
for (int j = valueOffset; j < valueOffset + BLOCK_SIZE; j ++) {
assertEquals(expectedValue.get(j), value.get(j));
}
}
}
@Test
public void testSequentialCopiedBufferTransfer1() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
byte[] value = new byte[BLOCK_SIZE];
random.nextBytes(value);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value);
}
random.setSeed(seed);
byte[] expectedValue = new byte[BLOCK_SIZE];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
ByteBuf actualValue = buffer.readBytes(BLOCK_SIZE);
assertEquals(wrappedBuffer(expectedValue), actualValue);
// Make sure if it is a copied buffer.
actualValue.setByte(0, (byte) (actualValue.getByte(0) + 1));
assertFalse(buffer.getByte(i) == actualValue.getByte(0));
actualValue.release();
}
}
@Test
public void testSequentialSlice1() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
byte[] value = new byte[BLOCK_SIZE];
random.nextBytes(value);
assertEquals(0, buffer.readerIndex());
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(value);
}
random.setSeed(seed);
byte[] expectedValue = new byte[BLOCK_SIZE];
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
random.nextBytes(expectedValue);
assertEquals(i, buffer.readerIndex());
assertEquals(CAPACITY, buffer.writerIndex());
ByteBuf actualValue = buffer.readSlice(BLOCK_SIZE);
assertEquals(buffer.order(), actualValue.order());
assertEquals(wrappedBuffer(expectedValue), actualValue);
// Make sure if it is a sliced buffer.
actualValue.setByte(0, (byte) (actualValue.getByte(0) + 1));
assertEquals(buffer.getByte(i), actualValue.getByte(0));
}
}
@Test
public void testWriteZero() {
try {
buffer.writeZero(-1);
fail();
} catch (IllegalArgumentException e) {
// Expected
}
buffer.clear();
while (buffer.isWritable()) {
buffer.writeByte((byte) 0xFF);
}
buffer.clear();
for (int i = 0; i < buffer.capacity();) {
int length = Math.min(buffer.capacity() - i, random.nextInt(32));
buffer.writeZero(length);
i += length;
}
assertEquals(0, buffer.readerIndex());
assertEquals(buffer.capacity(), buffer.writerIndex());
for (int i = 0; i < buffer.capacity(); i ++) {
assertEquals(0, buffer.getByte(i));
}
}
@Test
public void testDiscardReadBytes() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i += 4) {
buffer.writeInt(i);
}
ByteBuf copy = copiedBuffer(buffer);
// Make sure there's no effect if called when readerIndex is 0.
buffer.readerIndex(CAPACITY / 4);
int readerIndex = buffer.readerIndex();
buffer.writerIndex(CAPACITY / 3);
int writerIndex = buffer.writerIndex();
buffer.readerIndex(0);
buffer.writerIndex(CAPACITY / 2);
buffer.discardReadBytes();
assertEquals(0, buffer.readerIndex());
assertEquals(CAPACITY / 2, buffer.writerIndex());
assertEquals(copy.slice(0, CAPACITY / 2), buffer.slice(0, CAPACITY / 2));
buffer.readerIndex(readerIndex);
assertEquals(CAPACITY / 4, buffer.readerIndex());
buffer.writerIndex(writerIndex);
assertEquals(CAPACITY / 3, buffer.writerIndex());
// Make sure bytes after writerIndex is not copied.
buffer.readerIndex(1);
buffer.writerIndex(CAPACITY / 2);
buffer.discardReadBytes();
assertEquals(0, buffer.readerIndex());
assertEquals(CAPACITY / 2 - 1, buffer.writerIndex());
assertEquals(copy.slice(1, CAPACITY / 2 - 1), buffer.slice(0, CAPACITY / 2 - 1));
if (discardReadBytesDoesNotMoveWritableBytes()) {
// If writable bytes were copied, the test should fail to avoid unnecessary memory bandwidth consumption.
assertFalse(copy.slice(CAPACITY / 2, CAPACITY / 2).equals(buffer.slice(CAPACITY / 2 - 1, CAPACITY / 2)));
} else {
assertEquals(copy.slice(CAPACITY / 2, CAPACITY / 2), buffer.slice(CAPACITY / 2 - 1, CAPACITY / 2));
}
copy.release();
}
/**
* The similar test case with {@link #testDiscardReadBytes()} but this one
* discards a large chunk at once.
*/
@Test
public void testDiscardReadBytes2() {
buffer.writerIndex(0);
for (int i = 0; i < buffer.capacity(); i ++) {
buffer.writeByte((byte) i);
}
ByteBuf copy = copiedBuffer(buffer);
// Discard the first (CAPACITY / 2 - 1) bytes.
buffer.setIndex(CAPACITY / 2 - 1, CAPACITY - 1);
buffer.discardReadBytes();
assertEquals(0, buffer.readerIndex());
assertEquals(CAPACITY / 2, buffer.writerIndex());
for (int i = 0; i < CAPACITY / 2; i ++) {
assertEquals(copy.slice(CAPACITY / 2 - 1 + i, CAPACITY / 2 - i), buffer.slice(i, CAPACITY / 2 - i));
}
copy.release();
}
@Test
public void testStreamTransfer1() throws Exception {
byte[] expected = new byte[buffer.capacity()];
random.nextBytes(expected);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
ByteArrayInputStream in = new ByteArrayInputStream(expected, i, BLOCK_SIZE);
assertEquals(BLOCK_SIZE, buffer.setBytes(i, in, BLOCK_SIZE));
assertEquals(-1, buffer.setBytes(i, in, 0));
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
buffer.getBytes(i, out, BLOCK_SIZE);
}
assertTrue(Arrays.equals(expected, out.toByteArray()));
}
@Test
public void testStreamTransfer2() throws Exception {
byte[] expected = new byte[buffer.capacity()];
random.nextBytes(expected);
buffer.clear();
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
ByteArrayInputStream in = new ByteArrayInputStream(expected, i, BLOCK_SIZE);
assertEquals(i, buffer.writerIndex());
buffer.writeBytes(in, BLOCK_SIZE);
assertEquals(i + BLOCK_SIZE, buffer.writerIndex());
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
assertEquals(i, buffer.readerIndex());
buffer.readBytes(out, BLOCK_SIZE);
assertEquals(i + BLOCK_SIZE, buffer.readerIndex());
}
assertTrue(Arrays.equals(expected, out.toByteArray()));
}
@Test
public void testCopy() {
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
buffer.setByte(i, value);
}
final int readerIndex = CAPACITY / 3;
final int writerIndex = CAPACITY * 2 / 3;
buffer.setIndex(readerIndex, writerIndex);
// Make sure all properties are copied.
ByteBuf copy = buffer.copy();
assertEquals(0, copy.readerIndex());
assertEquals(buffer.readableBytes(), copy.writerIndex());
assertEquals(buffer.readableBytes(), copy.capacity());
assertSame(buffer.order(), copy.order());
for (int i = 0; i < copy.capacity(); i ++) {
assertEquals(buffer.getByte(i + readerIndex), copy.getByte(i));
}
// Make sure the buffer content is independent from each other.
buffer.setByte(readerIndex, (byte) (buffer.getByte(readerIndex) + 1));
assertTrue(buffer.getByte(readerIndex) != copy.getByte(0));
copy.setByte(1, (byte) (copy.getByte(1) + 1));
assertTrue(buffer.getByte(readerIndex + 1) != copy.getByte(1));
copy.release();
}
@Test
public void testDuplicate() {
for (int i = 0; i < buffer.capacity(); i ++) {
byte value = (byte) random.nextInt();
buffer.setByte(i, value);
}
final int readerIndex = CAPACITY / 3;
final int writerIndex = CAPACITY * 2 / 3;
buffer.setIndex(readerIndex, writerIndex);
// Make sure all properties are copied.
ByteBuf duplicate = buffer.duplicate();
assertSame(buffer.order(), duplicate.order());
assertEquals(buffer.readableBytes(), duplicate.readableBytes());
assertEquals(0, buffer.compareTo(duplicate));
// Make sure the buffer content is shared.
buffer.setByte(readerIndex, (byte) (buffer.getByte(readerIndex) + 1));
assertEquals(buffer.getByte(readerIndex), duplicate.getByte(duplicate.readerIndex()));
duplicate.setByte(duplicate.readerIndex(), (byte) (duplicate.getByte(duplicate.readerIndex()) + 1));
assertEquals(buffer.getByte(readerIndex), duplicate.getByte(duplicate.readerIndex()));
}
@Test
public void testSliceEndianness() throws Exception {
assertEquals(buffer.order(), buffer.slice(0, buffer.capacity()).order());
assertEquals(buffer.order(), buffer.slice(0, buffer.capacity() - 1).order());
assertEquals(buffer.order(), buffer.slice(1, buffer.capacity() - 1).order());
assertEquals(buffer.order(), buffer.slice(1, buffer.capacity() - 2).order());
}
@Test
public void testSliceIndex() throws Exception {
assertEquals(0, buffer.slice(0, buffer.capacity()).readerIndex());
assertEquals(0, buffer.slice(0, buffer.capacity() - 1).readerIndex());
assertEquals(0, buffer.slice(1, buffer.capacity() - 1).readerIndex());
assertEquals(0, buffer.slice(1, buffer.capacity() - 2).readerIndex());
assertEquals(buffer.capacity(), buffer.slice(0, buffer.capacity()).writerIndex());
assertEquals(buffer.capacity() - 1, buffer.slice(0, buffer.capacity() - 1).writerIndex());
assertEquals(buffer.capacity() - 1, buffer.slice(1, buffer.capacity() - 1).writerIndex());
assertEquals(buffer.capacity() - 2, buffer.slice(1, buffer.capacity() - 2).writerIndex());
}
@Test
public void testRetainedSliceIndex() throws Exception {
ByteBuf retainedSlice = buffer.retainedSlice(0, buffer.capacity());
assertEquals(0, retainedSlice.readerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(0, buffer.capacity() - 1);
assertEquals(0, retainedSlice.readerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(1, buffer.capacity() - 1);
assertEquals(0, retainedSlice.readerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(1, buffer.capacity() - 2);
assertEquals(0, retainedSlice.readerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(0, buffer.capacity());
assertEquals(buffer.capacity(), retainedSlice.writerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(0, buffer.capacity() - 1);
assertEquals(buffer.capacity() - 1, retainedSlice.writerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(1, buffer.capacity() - 1);
assertEquals(buffer.capacity() - 1, retainedSlice.writerIndex());
retainedSlice.release();
retainedSlice = buffer.retainedSlice(1, buffer.capacity() - 2);
assertEquals(buffer.capacity() - 2, retainedSlice.writerIndex());
retainedSlice.release();
}
@Test
@SuppressWarnings("ObjectEqualsNull")
public void testEquals() {
assertFalse(buffer.equals(null));
assertFalse(buffer.equals(new Object()));
byte[] value = new byte[32];
buffer.setIndex(0, value.length);
random.nextBytes(value);
buffer.setBytes(0, value);
assertEquals(buffer, wrappedBuffer(value));
assertEquals(buffer, wrappedBuffer(value).order(LITTLE_ENDIAN));
value[0] ++;
assertFalse(buffer.equals(wrappedBuffer(value)));
assertFalse(buffer.equals(wrappedBuffer(value).order(LITTLE_ENDIAN)));
}
@Test
public void testCompareTo() {
try {
buffer.compareTo(null);
fail();
} catch (NullPointerException e) {
// Expected
}
// Fill the random stuff
byte[] value = new byte[32];
random.nextBytes(value);
// Prevent overflow / underflow
if (value[0] == 0) {
value[0] ++;
} else if (value[0] == -1) {
value[0] --;
}
buffer.setIndex(0, value.length);
buffer.setBytes(0, value);
assertEquals(0, buffer.compareTo(wrappedBuffer(value)));
assertEquals(0, buffer.compareTo(wrappedBuffer(value).order(LITTLE_ENDIAN)));
value[0] ++;
assertTrue(buffer.compareTo(wrappedBuffer(value)) < 0);
assertTrue(buffer.compareTo(wrappedBuffer(value).order(LITTLE_ENDIAN)) < 0);
value[0] -= 2;
assertTrue(buffer.compareTo(wrappedBuffer(value)) > 0);
assertTrue(buffer.compareTo(wrappedBuffer(value).order(LITTLE_ENDIAN)) > 0);
value[0] ++;
assertTrue(buffer.compareTo(wrappedBuffer(value, 0, 31)) > 0);
assertTrue(buffer.compareTo(wrappedBuffer(value, 0, 31).order(LITTLE_ENDIAN)) > 0);
assertTrue(buffer.slice(0, 31).compareTo(wrappedBuffer(value)) < 0);
assertTrue(buffer.slice(0, 31).compareTo(wrappedBuffer(value).order(LITTLE_ENDIAN)) < 0);
ByteBuf retainedSlice = buffer.retainedSlice(0, 31);
assertTrue(retainedSlice.compareTo(wrappedBuffer(value)) < 0);
retainedSlice.release();
retainedSlice = buffer.retainedSlice(0, 31);
assertTrue(retainedSlice.compareTo(wrappedBuffer(value).order(LITTLE_ENDIAN)) < 0);
retainedSlice.release();
}
@Test
public void testCompareTo2() {
byte[] bytes = {1, 2, 3, 4};
byte[] bytesReversed = {4, 3, 2, 1};
ByteBuf buf1 = newBuffer(4).clear().writeBytes(bytes).order(ByteOrder.LITTLE_ENDIAN);
ByteBuf buf2 = newBuffer(4).clear().writeBytes(bytesReversed).order(ByteOrder.LITTLE_ENDIAN);
ByteBuf buf3 = newBuffer(4).clear().writeBytes(bytes).order(ByteOrder.BIG_ENDIAN);
ByteBuf buf4 = newBuffer(4).clear().writeBytes(bytesReversed).order(ByteOrder.BIG_ENDIAN);
try {
assertEquals(buf1.compareTo(buf2), buf3.compareTo(buf4));
assertEquals(buf2.compareTo(buf1), buf4.compareTo(buf3));
assertEquals(buf1.compareTo(buf3), buf2.compareTo(buf4));
assertEquals(buf3.compareTo(buf1), buf4.compareTo(buf2));
} finally {
buf1.release();
buf2.release();
buf3.release();
buf4.release();
}
}
@Test
public void testToString() {
ByteBuf copied = copiedBuffer("Hello, World!", CharsetUtil.ISO_8859_1);
buffer.clear();
buffer.writeBytes(copied);
assertEquals("Hello, World!", buffer.toString(CharsetUtil.ISO_8859_1));
copied.release();
}
@Test
@Timeout(value = 10000, unit = TimeUnit.MILLISECONDS)
public void testToStringMultipleThreads() throws Throwable {
buffer.clear();
buffer.writeBytes("Hello, World!".getBytes(CharsetUtil.ISO_8859_1));
final AtomicInteger counter = new AtomicInteger(30000);
final AtomicReference<Throwable> errorRef = new AtomicReference<>();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(() -> {
try {
while (errorRef.get() == null && counter.decrementAndGet() > 0) {
assertEquals("Hello, World!", buffer.toString(CharsetUtil.ISO_8859_1));
}
} catch (Throwable cause) {
errorRef.compareAndSet(null, cause);
}
});
threads.add(thread);
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
Throwable error = errorRef.get();
if (error != null) {
throw error;
}
}
@Test
public void testSWARIndexOf() {
ByteBuf buffer = newBuffer(16);
buffer.clear();
// Ensure the buffer is completely zero'ed.
buffer.setZero(0, buffer.capacity());
buffer.writeByte((byte) 0); // 0
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0); // 7
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 0);
buffer.writeByte((byte) 1); // 11
buffer.writeByte((byte) 2);
buffer.writeByte((byte) 3);
buffer.writeByte((byte) 4);
buffer.writeByte((byte) 1);
assertEquals(11, buffer.indexOf(0, 12, (byte) 1));
assertEquals(12, buffer.indexOf(0, 16, (byte) 2));
assertEquals(-1, buffer.indexOf(0, 11, (byte) 1));
assertEquals(11, buffer.indexOf(0, 16, (byte) 1));
buffer.release();
}
@Test
public void testIndexOf() {
buffer.clear();
// Ensure the buffer is completely zero'ed.
buffer.setZero(0, buffer.capacity());
buffer.writeByte((byte) 1);
buffer.writeByte((byte) 2);
buffer.writeByte((byte) 3);
buffer.writeByte((byte) 2);
buffer.writeByte((byte) 1);
assertEquals(-1, buffer.indexOf(1, 4, (byte) 1));
assertEquals(-1, buffer.indexOf(4, 1, (byte) 1));
assertEquals(1, buffer.indexOf(1, 4, (byte) 2));
assertEquals(3, buffer.indexOf(4, 1, (byte) 2));
try {
buffer.indexOf(0, buffer.capacity() + 1, (byte) 0);
fail();
} catch (IndexOutOfBoundsException expected) {
// expected
}
try {
buffer.indexOf(buffer.capacity(), -1, (byte) 0);
fail();
} catch (IndexOutOfBoundsException expected) {
// expected
}
assertEquals(4, buffer.indexOf(buffer.capacity() + 1, 0, (byte) 1));
assertEquals(0, buffer.indexOf(-1, buffer.capacity(), (byte) 1));
}
@Test
public void testIndexOfReleaseBuffer() {
ByteBuf buffer = releasedBuffer();
if (buffer.capacity() != 0) {
try {
buffer.indexOf(0, 1, (byte) 1);
fail();
} catch (IllegalReferenceCountException expected) {
// expected
}
} else {
assertEquals(-1, buffer.indexOf(0, 1, (byte) 1));
}
}
@Test
public void testNioBuffer1() {
assumeTrue(buffer.nioBufferCount() == 1);
byte[] value = new byte[buffer.capacity()];
random.nextBytes(value);
buffer.clear();
buffer.writeBytes(value);
assertRemainingEquals(ByteBuffer.wrap(value), buffer.nioBuffer());
}
@Test
public void testToByteBuffer2() {
assumeTrue(buffer.nioBufferCount() == 1);
byte[] value = new byte[buffer.capacity()];
random.nextBytes(value);
buffer.clear();
buffer.writeBytes(value);
for (int i = 0; i < buffer.capacity() - BLOCK_SIZE + 1; i += BLOCK_SIZE) {
assertRemainingEquals(ByteBuffer.wrap(value, i, BLOCK_SIZE), buffer.nioBuffer(i, BLOCK_SIZE));
}
}
private static void assertRemainingEquals(ByteBuffer expected, ByteBuffer actual) {
int remaining = expected.remaining();
int remaining2 = actual.remaining();
assertEquals(remaining, remaining2);
byte[] array1 = new byte[remaining];
byte[] array2 = new byte[remaining2];
expected.get(array1);
actual.get(array2);
assertArrayEquals(array1, array2);
}
@Test
public void testToByteBuffer3() {
assumeTrue(buffer.nioBufferCount() == 1);
assertEquals(buffer.order(), buffer.nioBuffer().order());
}
@Test
public void testSkipBytes1() {
buffer.setIndex(CAPACITY / 4, CAPACITY / 2);
buffer.skipBytes(CAPACITY / 4);
assertEquals(CAPACITY / 4 * 2, buffer.readerIndex());
try {
buffer.skipBytes(CAPACITY / 4 + 1);
fail();
} catch (IndexOutOfBoundsException e) {
// Expected
}
// Should remain unchanged.
assertEquals(CAPACITY / 4 * 2, buffer.readerIndex());
}
@Test
public void testHashCode() {
ByteBuf elemA = buffer(15);
ByteBuf elemB = directBuffer(15);
elemA.writeBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 });
elemB.writeBytes(new byte[] { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9 });
Set<ByteBuf> set = new HashSet<>();
set.add(elemA);
set.add(elemB);
assertEquals(2, set.size());
ByteBuf elemACopy = elemA.copy();
assertTrue(set.contains(elemACopy));
ByteBuf elemBCopy = elemB.copy();
assertTrue(set.contains(elemBCopy));
buffer.clear();
buffer.writeBytes(elemA.duplicate());
assertTrue(set.remove(buffer));
assertFalse(set.contains(elemA));
assertEquals(1, set.size());
buffer.clear();
buffer.writeBytes(elemB.duplicate());
assertTrue(set.remove(buffer));
assertFalse(set.contains(elemB));
assertEquals(0, set.size());
elemA.release();
elemB.release();
elemACopy.release();
elemBCopy.release();
}
// Test case for https://github.com/netty/netty/issues/325
@Test
public void testDiscardAllReadBytes() {
buffer.writerIndex(buffer.capacity());
buffer.readerIndex(buffer.writerIndex());
buffer.discardReadBytes();
}
@Test
public void testForEachByte() {
buffer.clear();
for (int i = 0; i < CAPACITY; i ++) {
buffer.writeByte(i + 1);
}
final AtomicInteger lastIndex = new AtomicInteger();
buffer.setIndex(CAPACITY / 4, CAPACITY * 3 / 4);
assertThat(buffer.forEachByte(new ByteProcessor() {
int i = CAPACITY / 4;
@Override
public boolean process(byte value) {
assertThat(value, is((byte) (i + 1)));
lastIndex.set(i);
i ++;
return true;
}
}), is(-1));
assertThat(lastIndex.get(), is(CAPACITY * 3 / 4 - 1));
}
@Test
public void testForEachByteAbort() {
buffer.clear();
for (int i = 0; i < CAPACITY; i ++) {
buffer.writeByte(i + 1);
}
final int stop = CAPACITY / 2;
assertThat(buffer.forEachByte(CAPACITY / 3, CAPACITY / 3, new ByteProcessor() {
int i = CAPACITY / 3;
@Override
public boolean process(byte value) {
assertThat(value, is((byte) (i + 1)));
if (i == stop) {
return false;
}
i++;
return true;
}
}), is(stop));
}
@Test
public void testForEachByteDesc() {
buffer.clear();
for (int i = 0; i < CAPACITY; i ++) {
buffer.writeByte(i + 1);
}
final AtomicInteger lastIndex = new AtomicInteger();
assertThat(buffer.forEachByteDesc(CAPACITY / 4, CAPACITY * 2 / 4, new ByteProcessor() {
int i = CAPACITY * 3 / 4 - 1;
@Override
public boolean process(byte value) {
assertThat(value, is((byte) (i + 1)));
lastIndex.set(i);
i --;
return true;
}
}), is(-1));
assertThat(lastIndex.get(), is(CAPACITY / 4));
}
@Test
public void testInternalNioBuffer() {
testInternalNioBuffer(128);
testInternalNioBuffer(1024);
testInternalNioBuffer(4 * 1024);
testInternalNioBuffer(64 * 1024);
testInternalNioBuffer(32 * 1024 * 1024);
testInternalNioBuffer(64 * 1024 * 1024);
}
private void testInternalNioBuffer(int a) {
ByteBuf buffer = newBuffer(2);
ByteBuffer buf = buffer.internalNioBuffer(buffer.readerIndex(), 1);
assertEquals(1, buf.remaining());
byte[] data = new byte[a];
ThreadLocalRandom.current().nextBytes(data);
buffer.writeBytes(data);
buf = buffer.internalNioBuffer(buffer.readerIndex(), a);
assertEquals(a, buf.remaining());
for (int i = 0; i < a; i++) {
assertEquals(data[i], buf.get());
}
assertFalse(buf.hasRemaining());
buffer.release();
}
@Test
public void testDuplicateReadGatheringByteChannelMultipleThreads() throws Exception {
testReadGatheringByteChannelMultipleThreads(false);
}
@Test
public void testSliceReadGatheringByteChannelMultipleThreads() throws Exception {
testReadGatheringByteChannelMultipleThreads(true);
}
private void testReadGatheringByteChannelMultipleThreads(final boolean slice) throws Exception {
final byte[] bytes = new byte[8];
random.nextBytes(bytes);
final ByteBuf buffer = newBuffer(8);
buffer.writeBytes(bytes);
final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (latch.getCount() > 0) {
ByteBuf buf;
if (slice) {
buf = buffer.slice();
} else {
buf = buffer.duplicate();
}
TestGatheringByteChannel channel = new TestGatheringByteChannel();
while (buf.isReadable()) {
try {
buf.readBytes(channel, buf.readableBytes());
} catch (IOException e) {
// Never happens
return;
}
}
assertArrayEquals(bytes, channel.writtenBytes());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
}
}).start();
}
latch.await(10, TimeUnit.SECONDS);
barrier.await(5, TimeUnit.SECONDS);
buffer.release();
}
@Test
public void testDuplicateReadOutputStreamMultipleThreads() throws Exception {
testReadOutputStreamMultipleThreads(false);
}
@Test
public void testSliceReadOutputStreamMultipleThreads() throws Exception {
testReadOutputStreamMultipleThreads(true);
}
private void testReadOutputStreamMultipleThreads(final boolean slice) throws Exception {
final byte[] bytes = new byte[8];
random.nextBytes(bytes);
final ByteBuf buffer = newBuffer(8);
buffer.writeBytes(bytes);
final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (latch.getCount() > 0) {
ByteBuf buf;
if (slice) {
buf = buffer.slice();
} else {
buf = buffer.duplicate();
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
while (buf.isReadable()) {
try {
buf.readBytes(out, buf.readableBytes());
} catch (IOException e) {
// Never happens
return;
}
}
assertArrayEquals(bytes, out.toByteArray());
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
}
}).start();
}
latch.await(10, TimeUnit.SECONDS);
barrier.await(5, TimeUnit.SECONDS);
buffer.release();
}
@Test
public void testDuplicateBytesInArrayMultipleThreads() throws Exception {
testBytesInArrayMultipleThreads(false);
}
@Test
public void testSliceBytesInArrayMultipleThreads() throws Exception {
testBytesInArrayMultipleThreads(true);
}
private void testBytesInArrayMultipleThreads(final boolean slice) throws Exception {
final byte[] bytes = new byte[8];
random.nextBytes(bytes);
final ByteBuf buffer = newBuffer(8);
buffer.writeBytes(bytes);
final AtomicReference<Throwable> cause = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(60000);
final CyclicBarrier barrier = new CyclicBarrier(11);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (cause.get() == null && latch.getCount() > 0) {
ByteBuf buf;
if (slice) {
buf = buffer.slice();
} else {
buf = buffer.duplicate();
}
byte[] array = new byte[8];
buf.readBytes(array);
assertArrayEquals(bytes, array);
Arrays.fill(array, (byte) 0);
buf.getBytes(0, array);
assertArrayEquals(bytes, array);
latch.countDown();
}
try {
barrier.await();
} catch (Exception e) {
// ignore
}
}).start();
}
latch.await(10, TimeUnit.SECONDS);
barrier.await(5, TimeUnit.SECONDS);
assertNull(cause.get());
buffer.release();
}
@Test
public void readByteThrowsIndexOutOfBoundsException() {
final ByteBuf buffer = newBuffer(8);
try {
assertThrows(IndexOutOfBoundsException.class, () -> {
buffer.writeByte(0);
assertEquals((byte) 0, buffer.readByte());
buffer.readByte();
});
} finally {
buffer.release();
}
}
@Test
@SuppressWarnings("ForLoopThatDoesntUseLoopVariable")
public void testNioBufferExposeOnlyRegion() {
final ByteBuf buffer = newBuffer(8);
byte[] data = new byte[8];
random.nextBytes(data);
buffer.writeBytes(data);
ByteBuffer nioBuf = buffer.nioBuffer(1, data.length - 2);
assertEquals(0, nioBuf.position());
assertEquals(6, nioBuf.remaining());
for (int i = 1; nioBuf.hasRemaining(); i++) {
assertEquals(data[i], nioBuf.get());
}
buffer.release();
}
@Test
public void ensureWritableWithForceDoesNotThrow() {
ensureWritableDoesNotThrow(true);
}
@Test
public void ensureWritableWithOutForceDoesNotThrow() {
ensureWritableDoesNotThrow(false);
}
private void ensureWritableDoesNotThrow(boolean force) {
final ByteBuf buffer = newBuffer(8);
buffer.writerIndex(buffer.capacity());
buffer.ensureWritable(8, force);
buffer.release();
}
// See:
// - https://github.com/netty/netty/issues/2587
// - https://github.com/netty/netty/issues/2580
@Test
public void testLittleEndianWithExpand() {
ByteBuf buffer = newBuffer(0).order(LITTLE_ENDIAN);
buffer.writeInt(0x12345678);
assertEquals("78563412", ByteBufUtil.hexDump(buffer));
buffer.release();
}
private ByteBuf releasedBuffer() {
ByteBuf buffer = newBuffer(8);
// Clear the buffer so we are sure the reader and writer indices are 0.
// This is important as we may return a slice from newBuffer(...).
buffer.clear();
assertTrue(buffer.release());
return buffer;
}
@Test
public void testDiscardReadBytesAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().discardReadBytes());
}
@Test
public void testDiscardSomeReadBytesAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().discardSomeReadBytes());
}
@Test
public void testEnsureWritableAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().ensureWritable(16));
}
@Test
public void testGetBooleanAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBoolean(0));
}
@Test
public void testGetByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getByte(0));
}
@Test
public void testGetUnsignedByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedByte(0));
}
@Test
public void testGetShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getShort(0));
}
@Test
public void testGetShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getShortLE(0));
}
@Test
public void testGetUnsignedShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedShort(0));
}
@Test
public void testGetUnsignedShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedShortLE(0));
}
@Test
public void testGetMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getMedium(0));
}
@Test
public void testGetMediumLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getMediumLE(0));
}
@Test
public void testGetUnsignedMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedMedium(0));
}
@Test
public void testGetIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getInt(0));
}
@Test
public void testGetIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getIntLE(0));
}
@Test
public void testGetUnsignedIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedInt(0));
}
@Test
public void testGetUnsignedIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getUnsignedIntLE(0));
}
@Test
public void testGetLongAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getLong(0));
}
@Test
public void testGetLongLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getLongLE(0));
}
@Test
public void testGetCharAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getChar(0));
}
@Test
public void testGetFloatAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getFloat(0));
}
@Test
public void testGetFloatLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getFloatLE(0));
}
@Test
public void testGetDoubleAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getDouble(0));
}
@Test
public void testGetDoubleLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getDoubleLE(0));
}
@Test
public void testGetBytesAfterRelease() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, buffer));
} finally {
buffer.release();
}
}
@Test
public void testGetBytesAfterRelease2() {
ByteBuf buffer = buffer();
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, buffer, 1));
} finally {
buffer.release();
}
}
@Test
public void testGetBytesAfterRelease3() {
ByteBuf buffer = buffer();
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, buffer, 0, 1));
} finally {
buffer.release();
}
}
@Test
public void testGetBytesAfterRelease4() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, new byte[8]));
}
@Test
public void testGetBytesAfterRelease5() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, new byte[8], 0, 1));
}
@Test
public void testGetBytesAfterRelease6() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().getBytes(0, ByteBuffer.allocate(8)));
}
@Test
public void testGetBytesAfterRelease7() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().getBytes(0, new ByteArrayOutputStream(), 1));
}
@Test
public void testGetBytesAfterRelease8() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().getBytes(0, new DevNullGatheringByteChannel(), 1));
}
@Test
public void testSetBooleanAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBoolean(0, true));
}
@Test
public void testSetByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setByte(0, 1));
}
@Test
public void testSetShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setShort(0, 1));
}
@Test
public void testSetShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setShortLE(0, 1));
}
@Test
public void testSetMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setMedium(0, 1));
}
@Test
public void testSetMediumLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setMediumLE(0, 1));
}
@Test
public void testSetIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setInt(0, 1));
}
@Test
public void testSetIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setIntLE(0, 1));
}
@Test
public void testSetLongAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setLong(0, 1));
}
@Test
public void testSetLongLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setLongLE(0, 1));
}
@Test
public void testSetCharAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setChar(0, 1));
}
@Test
public void testSetFloatAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setFloat(0, 1));
}
@Test
public void testSetDoubleAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setDouble(0, 1));
}
@Test
public void testSetBytesAfterRelease() {
ByteBuf buffer = buffer();
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, buffer));
} finally {
buffer.release();
}
}
@Test
public void testSetBytesAfterRelease2() {
ByteBuf buffer = buffer();
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, buffer, 1));
} finally {
buffer.release();
}
}
@Test
public void testSetBytesAfterRelease3() {
ByteBuf buffer = buffer();
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, buffer, 0, 1));
} finally {
buffer.release();
}
}
@Test
public void testSetUsAsciiCharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testSetCharSequenceAfterRelease0(CharsetUtil.US_ASCII));
}
@Test
public void testSetIso88591CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testSetCharSequenceAfterRelease0(CharsetUtil.ISO_8859_1));
}
@Test
public void testSetUtf8CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testSetCharSequenceAfterRelease0(CharsetUtil.UTF_8));
}
@Test
public void testSetUtf16CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testSetCharSequenceAfterRelease0(CharsetUtil.UTF_16));
}
private void testSetCharSequenceAfterRelease0(Charset charset) {
releasedBuffer().setCharSequence(0, "x", charset);
}
@Test
public void testSetBytesAfterRelease4() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, new byte[8]));
}
@Test
public void testSetBytesAfterRelease5() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, new byte[8], 0, 1));
}
@Test
public void testSetBytesAfterRelease6() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setBytes(0, ByteBuffer.allocate(8)));
}
@Test
public void testSetBytesAfterRelease7() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().setBytes(0, new ByteArrayInputStream(new byte[8]), 1));
}
@Test
public void testSetBytesAfterRelease8() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().setBytes(0, new TestScatteringByteChannel(), 1));
}
@Test
public void testSetZeroAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().setZero(0, 1));
}
@Test
public void testReadBooleanAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBoolean());
}
@Test
public void testReadByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readByte());
}
@Test
public void testReadUnsignedByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedByte());
}
@Test
public void testReadShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readShort());
}
@Test
public void testReadShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readShortLE());
}
@Test
public void testReadUnsignedShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedShort());
}
@Test
public void testReadUnsignedShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedShortLE());
}
@Test
public void testReadMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readMedium());
}
@Test
public void testReadMediumLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readMediumLE());
}
@Test
public void testReadUnsignedMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedMedium());
}
@Test
public void testReadUnsignedMediumLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedMediumLE());
}
@Test
public void testReadIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readInt());
}
@Test
public void testReadIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readIntLE());
}
@Test
public void testReadUnsignedIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedInt());
}
@Test
public void testReadUnsignedIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readUnsignedIntLE());
}
@Test
public void testReadLongAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readLong());
}
@Test
public void testReadLongLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readLongLE());
}
@Test
public void testReadCharAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readChar());
}
@Test
public void testReadFloatAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readFloat());
}
@Test
public void testReadFloatLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readFloatLE());
}
@Test
public void testReadDoubleAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readDouble());
}
@Test
public void testReadDoubleLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readDoubleLE());
}
@Test
public void testReadBytesAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(1));
}
@Test
public void testReadBytesAfterRelease2() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(buffer));
} finally {
buffer.release();
}
}
@Test
public void testReadBytesAfterRelease3() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(buffer));
} finally {
buffer.release();
}
}
@Test
public void testReadBytesAfterRelease4() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(buffer, 0, 1));
} finally {
buffer.release();
}
}
@Test
public void testReadBytesAfterRelease5() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(new byte[8]));
}
@Test
public void testReadBytesAfterRelease6() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(new byte[8], 0, 1));
}
@Test
public void testReadBytesAfterRelease7() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().readBytes(ByteBuffer.allocate(8)));
}
@Test
public void testReadBytesAfterRelease8() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().readBytes(new ByteArrayOutputStream(), 1));
}
@Test
public void testReadBytesAfterRelease9() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().readBytes(new ByteArrayOutputStream(), 1));
}
@Test
public void testReadBytesAfterRelease10() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().readBytes(new DevNullGatheringByteChannel(), 1));
}
@Test
public void testWriteBooleanAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBoolean(true));
}
@Test
public void testWriteByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeByte(1));
}
@Test
public void testWriteShortAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeShort(1));
}
@Test
public void testWriteShortLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeShortLE(1));
}
@Test
public void testWriteMediumAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeMedium(1));
}
@Test
public void testWriteMediumLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeMediumLE(1));
}
@Test
public void testWriteIntAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeInt(1));
}
@Test
public void testWriteIntLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeIntLE(1));
}
@Test
public void testWriteLongAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeLong(1));
}
@Test
public void testWriteLongLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeLongLE(1));
}
@Test
public void testWriteCharAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeChar(1));
}
@Test
public void testWriteFloatAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeFloat(1));
}
@Test
public void testWriteFloatLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeFloatLE(1));
}
@Test
public void testWriteDoubleAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeDouble(1));
}
@Test
public void testWriteDoubleLEAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeDoubleLE(1));
}
@Test
public void testWriteBytesAfterRelease() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(buffer));
} finally {
buffer.release();
}
}
@Test
public void testWriteBytesAfterRelease2() {
ByteBuf buffer = copiedBuffer(new byte[8]);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(buffer, 1));
} finally {
buffer.release();
}
}
@Test
public void testWriteBytesAfterRelease3() {
ByteBuf buffer = buffer(8);
try {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(buffer, 0, 1));
} finally {
buffer.release();
}
}
@Test
public void testWriteBytesAfterRelease4() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(new byte[8]));
}
@Test
public void testWriteBytesAfterRelease5() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(new byte[8], 0 , 1));
}
@Test
public void testWriteBytesAfterRelease6() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeBytes(ByteBuffer.allocate(8)));
}
@Test
public void testWriteBytesAfterRelease7() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().writeBytes(new ByteArrayInputStream(new byte[8]), 1));
}
@Test
public void testWriteBytesAfterRelease8() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().writeBytes(new TestScatteringByteChannel(), 1));
}
@Test
public void testWriteZeroAfterRelease() throws IOException {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().writeZero(1));
}
@Test
public void testWriteUsAsciiCharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testWriteCharSequenceAfterRelease0(CharsetUtil.US_ASCII));
}
@Test
public void testWriteIso88591CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testWriteCharSequenceAfterRelease0(CharsetUtil.ISO_8859_1));
}
@Test
public void testWriteUtf8CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> testWriteCharSequenceAfterRelease0(CharsetUtil.UTF_8));
}
@Test
public void testWriteUtf16CharSequenceAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> testWriteCharSequenceAfterRelease0(CharsetUtil.UTF_16));
}
private void testWriteCharSequenceAfterRelease0(Charset charset) {
releasedBuffer().writeCharSequence("x", charset);
}
@Test
public void testForEachByteAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().forEachByte(new TestByteProcessor()));
}
@Test
public void testForEachByteAfterRelease1() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().forEachByte(0, 1, new TestByteProcessor()));
}
@Test
public void testForEachByteDescAfterRelease() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().forEachByteDesc(new TestByteProcessor()));
}
@Test
public void testForEachByteDescAfterRelease1() {
assertThrows(IllegalReferenceCountException.class,
() -> releasedBuffer().forEachByteDesc(0, 1, new TestByteProcessor()));
}
@Test
public void testCopyAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().copy());
}
@Test
public void testCopyAfterRelease1() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().copy());
}
@Test
public void testNioBufferAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().nioBuffer());
}
@Test
public void testNioBufferAfterRelease1() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().nioBuffer(0, 1));
}
@Test
public void testInternalNioBufferAfterRelease() {
testInternalNioBufferAfterRelease0(IllegalReferenceCountException.class);
}
protected void testInternalNioBufferAfterRelease0(final Class<? extends Throwable> expectedException) {
ByteBuf releasedBuffer = releasedBuffer();
assertThrows(expectedException, () -> releasedBuffer.internalNioBuffer(releasedBuffer.readerIndex(), 1));
}
@Test
public void testNioBuffersAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().nioBuffers());
}
@Test
public void testNioBuffersAfterRelease2() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().nioBuffers(0, 1));
}
@Test
public void testArrayAfterRelease() {
ByteBuf buf = releasedBuffer();
if (buf.hasArray()) {
try {
buf.array();
fail();
} catch (IllegalReferenceCountException e) {
// expected
}
}
}
@Test
public void testMemoryAddressAfterRelease() {
ByteBuf buf = releasedBuffer();
if (buf.hasMemoryAddress()) {
try {
buf.memoryAddress();
fail();
} catch (IllegalReferenceCountException e) {
// expected
}
}
}
@Test
public void testSliceAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().slice());
}
@Test
public void testSliceAfterRelease2() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().slice(0, 1));
}
private static void assertSliceFailAfterRelease(ByteBuf... bufs) {
for (ByteBuf buf : bufs) {
if (buf.refCnt() > 0) {
buf.release();
}
}
for (ByteBuf buf : bufs) {
try {
assertEquals(0, buf.refCnt());
buf.slice();
fail();
} catch (IllegalReferenceCountException ignored) {
// as expected
}
}
}
@Test
public void testSliceAfterReleaseRetainedSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
assertSliceFailAfterRelease(buf, buf2);
}
@Test
public void testSliceAfterReleaseRetainedSliceDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
ByteBuf buf3 = buf2.duplicate();
assertSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testSliceAfterReleaseRetainedSliceRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
ByteBuf buf3 = buf2.retainedDuplicate();
assertSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testSliceAfterReleaseRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
assertSliceFailAfterRelease(buf, buf2);
}
@Test
public void testSliceAfterReleaseRetainedDuplicateSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
ByteBuf buf3 = buf2.slice(0, 1);
assertSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testRetainedSliceAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().retainedSlice());
}
@Test
public void testRetainedSliceAfterRelease2() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().retainedSlice(0, 1));
}
private static void assertRetainedSliceFailAfterRelease(ByteBuf... bufs) {
for (ByteBuf buf : bufs) {
if (buf.refCnt() > 0) {
buf.release();
}
}
for (ByteBuf buf : bufs) {
try {
assertEquals(0, buf.refCnt());
buf.retainedSlice();
fail();
} catch (IllegalReferenceCountException ignored) {
// as expected
}
}
}
@Test
public void testRetainedSliceAfterReleaseRetainedSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
assertRetainedSliceFailAfterRelease(buf, buf2);
}
@Test
public void testRetainedSliceAfterReleaseRetainedSliceDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
ByteBuf buf3 = buf2.duplicate();
assertRetainedSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testRetainedSliceAfterReleaseRetainedSliceRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
ByteBuf buf3 = buf2.retainedDuplicate();
assertRetainedSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testRetainedSliceAfterReleaseRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
assertRetainedSliceFailAfterRelease(buf, buf2);
}
@Test
public void testRetainedSliceAfterReleaseRetainedDuplicateSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
ByteBuf buf3 = buf2.slice(0, 1);
assertRetainedSliceFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testDuplicateAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().duplicate());
}
@Test
public void testRetainedDuplicateAfterRelease() {
assertThrows(IllegalReferenceCountException.class, () -> releasedBuffer().retainedDuplicate());
}
private static void assertDuplicateFailAfterRelease(ByteBuf... bufs) {
for (ByteBuf buf : bufs) {
if (buf.refCnt() > 0) {
buf.release();
}
}
for (ByteBuf buf : bufs) {
try {
assertEquals(0, buf.refCnt());
buf.duplicate();
fail();
} catch (IllegalReferenceCountException ignored) {
// as expected
}
}
}
@Test
public void testDuplicateAfterReleaseRetainedSliceDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
ByteBuf buf3 = buf2.duplicate();
assertDuplicateFailAfterRelease(buf, buf2, buf3);
}
@Test
public void testDuplicateAfterReleaseRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
assertDuplicateFailAfterRelease(buf, buf2);
}
@Test
public void testDuplicateAfterReleaseRetainedDuplicateSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
ByteBuf buf3 = buf2.slice(0, 1);
assertDuplicateFailAfterRelease(buf, buf2, buf3);
}
private static void assertRetainedDuplicateFailAfterRelease(ByteBuf... bufs) {
for (ByteBuf buf : bufs) {
if (buf.refCnt() > 0) {
buf.release();
}
}
for (ByteBuf buf : bufs) {
try {
assertEquals(0, buf.refCnt());
buf.retainedDuplicate();
fail();
} catch (IllegalReferenceCountException ignored) {
// as expected
}
}
}
@Test
public void testRetainedDuplicateAfterReleaseRetainedDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedDuplicate();
assertRetainedDuplicateFailAfterRelease(buf, buf2);
}
@Test
public void testRetainedDuplicateAfterReleaseDuplicate() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.duplicate();
assertRetainedDuplicateFailAfterRelease(buf, buf2);
}
@Test
public void testRetainedDuplicateAfterReleaseRetainedSlice() {
ByteBuf buf = newBuffer(1);
ByteBuf buf2 = buf.retainedSlice(0, 1);
assertRetainedDuplicateFailAfterRelease(buf, buf2);
}
@Test
public void testSliceRelease() {
ByteBuf buf = newBuffer(8);
assertEquals(1, buf.refCnt());
assertTrue(buf.slice().release());
assertEquals(0, buf.refCnt());
}
@Test
public void testReadSliceOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testReadSliceOutOfBounds(false));
}
@Test
public void testReadRetainedSliceOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testReadSliceOutOfBounds(true));
}
private void testReadSliceOutOfBounds(boolean retainedSlice) {
ByteBuf buf = newBuffer(100);
try {
buf.writeZero(50);
if (retainedSlice) {
buf.readRetainedSlice(51);
} else {
buf.readSlice(51);
}
fail();
} finally {
buf.release();
}
}
@Test
public void testWriteUsAsciiCharSequenceExpand() {
testWriteCharSequenceExpand(CharsetUtil.US_ASCII);
}
@Test
public void testWriteUtf8CharSequenceExpand() {
testWriteCharSequenceExpand(CharsetUtil.UTF_8);
}
@Test
public void testWriteIso88591CharSequenceExpand() {
testWriteCharSequenceExpand(CharsetUtil.ISO_8859_1);
}
@Test
public void testWriteUtf16CharSequenceExpand() {
testWriteCharSequenceExpand(CharsetUtil.UTF_16);
}
private void testWriteCharSequenceExpand(Charset charset) {
ByteBuf buf = newBuffer(1);
try {
int writerIndex = buf.capacity() - 1;
buf.writerIndex(writerIndex);
int written = buf.writeCharSequence("AB", charset);
assertEquals(writerIndex, buf.writerIndex() - written);
} finally {
buf.release();
}
}
@Test
public void testSetUsAsciiCharSequenceNoExpand() {
assertThrows(IndexOutOfBoundsException.class, () -> testSetCharSequenceNoExpand(CharsetUtil.US_ASCII));
}
@Test
public void testSetUtf8CharSequenceNoExpand() {
assertThrows(IndexOutOfBoundsException.class, () -> testSetCharSequenceNoExpand(CharsetUtil.UTF_8));
}
@Test
public void testSetIso88591CharSequenceNoExpand() {
assertThrows(IndexOutOfBoundsException.class, () -> testSetCharSequenceNoExpand(CharsetUtil.ISO_8859_1));
}
@Test
public void testSetUtf16CharSequenceNoExpand() {
assertThrows(IndexOutOfBoundsException.class, () -> testSetCharSequenceNoExpand(CharsetUtil.UTF_16));
}
private void testSetCharSequenceNoExpand(Charset charset) {
ByteBuf buf = newBuffer(1);
try {
buf.setCharSequence(0, "AB", charset);
} finally {
buf.release();
}
}
@Test
public void testSetUsAsciiCharSequence() {
testSetGetCharSequence(CharsetUtil.US_ASCII);
}
@Test
public void testSetUtf8CharSequence() {
testSetGetCharSequence(CharsetUtil.UTF_8);
}
@Test
public void testSetIso88591CharSequence() {
testSetGetCharSequence(CharsetUtil.ISO_8859_1);
}
@Test
public void testSetUtf16CharSequence() {
testSetGetCharSequence(CharsetUtil.UTF_16);
}
private static final CharBuffer EXTENDED_ASCII_CHARS, ASCII_CHARS;
static {
char[] chars = new char[256];
for (char c = 0; c < chars.length; c++) {
chars[c] = c;
}
EXTENDED_ASCII_CHARS = CharBuffer.wrap(chars);
ASCII_CHARS = CharBuffer.wrap(chars, 0, 128);
}
private void testSetGetCharSequence(Charset charset) {
ByteBuf buf = newBuffer(1024);
CharBuffer sequence = CharsetUtil.US_ASCII.equals(charset)
? ASCII_CHARS : EXTENDED_ASCII_CHARS;
int bytes = buf.setCharSequence(1, sequence, charset);
assertEquals(sequence, CharBuffer.wrap(buf.getCharSequence(1, bytes, charset)));
buf.release();
}
@Test
public void testWriteReadUsAsciiCharSequence() {
testWriteReadCharSequence(CharsetUtil.US_ASCII);
}
@Test
public void testWriteReadUtf8CharSequence() {
testWriteReadCharSequence(CharsetUtil.UTF_8);
}
@Test
public void testWriteReadIso88591CharSequence() {
testWriteReadCharSequence(CharsetUtil.ISO_8859_1);
}
@Test
public void testWriteReadUtf16CharSequence() {
testWriteReadCharSequence(CharsetUtil.UTF_16);
}
private void testWriteReadCharSequence(Charset charset) {
ByteBuf buf = newBuffer(1024);
CharBuffer sequence = CharsetUtil.US_ASCII.equals(charset)
? ASCII_CHARS : EXTENDED_ASCII_CHARS;
buf.writerIndex(1);
int bytes = buf.writeCharSequence(sequence, charset);
buf.readerIndex(1);
assertEquals(sequence, CharBuffer.wrap(buf.readCharSequence(bytes, charset)));
buf.release();
}
@Test
public void testRetainedSliceIndexOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(true, true, true));
}
@Test
public void testRetainedSliceLengthOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(true, true, false));
}
@Test
public void testMixedSliceAIndexOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(true, false, true));
}
@Test
public void testMixedSliceALengthOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(true, false, false));
}
@Test
public void testMixedSliceBIndexOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(false, true, true));
}
@Test
public void testMixedSliceBLengthOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(false, true, false));
}
@Test
public void testSliceIndexOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(false, false, true));
}
@Test
public void testSliceLengthOutOfBounds() {
assertThrows(IndexOutOfBoundsException.class, () -> testSliceOutOfBounds(false, false, false));
}
@Test
public void testRetainedSliceAndRetainedDuplicateContentIsExpected() {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected1 = newBuffer(6).writerIndex(0);
ByteBuf expected2 = newBuffer(5).writerIndex(0);
ByteBuf expected3 = newBuffer(4).writerIndex(0);
ByteBuf expected4 = newBuffer(3).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected1.writeBytes(new byte[] {2, 3, 4, 5, 6, 7});
expected2.writeBytes(new byte[] {3, 4, 5, 6, 7});
expected3.writeBytes(new byte[] {4, 5, 6, 7});
expected4.writeBytes(new byte[] {5, 6, 7});
ByteBuf slice1 = buf.retainedSlice(buf.readerIndex() + 1, 6);
assertEquals(0, slice1.compareTo(expected1));
assertEquals(0, slice1.compareTo(buf.slice(buf.readerIndex() + 1, 6)));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
// Advance the reader index on the slice.
slice1.readByte();
ByteBuf dup1 = slice1.retainedDuplicate();
assertEquals(0, dup1.compareTo(expected2));
assertEquals(0, dup1.compareTo(slice1.duplicate()));
// Advance the reader index on dup1.
dup1.readByte();
ByteBuf dup2 = dup1.duplicate();
assertEquals(0, dup2.compareTo(expected3));
// Advance the reader index on dup2.
dup2.readByte();
ByteBuf slice2 = dup2.retainedSlice(dup2.readerIndex(), 3);
assertEquals(0, slice2.compareTo(expected4));
assertEquals(0, slice2.compareTo(dup2.slice(dup2.readerIndex(), 3)));
// Cleanup the expected buffers used for testing.
assertTrue(expected1.release());
assertTrue(expected2.release());
assertTrue(expected3.release());
assertTrue(expected4.release());
slice2.release();
dup2.release();
assertEquals(slice2.refCnt(), dup2.refCnt());
assertEquals(dup2.refCnt(), dup1.refCnt());
// The handler is now done with the original slice
assertTrue(slice1.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
assertEquals(0, dup1.refCnt());
assertEquals(0, dup2.refCnt());
}
@Test
public void testRetainedDuplicateAndRetainedSliceContentIsExpected() {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected1 = newBuffer(6).writerIndex(0);
ByteBuf expected2 = newBuffer(5).writerIndex(0);
ByteBuf expected3 = newBuffer(4).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected1.writeBytes(new byte[] {2, 3, 4, 5, 6, 7});
expected2.writeBytes(new byte[] {3, 4, 5, 6, 7});
expected3.writeBytes(new byte[] {5, 6, 7});
ByteBuf dup1 = buf.retainedDuplicate();
assertEquals(0, dup1.compareTo(buf));
assertEquals(0, dup1.compareTo(buf.slice()));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
// Advance the reader index on the dup.
dup1.readByte();
ByteBuf slice1 = dup1.retainedSlice(dup1.readerIndex(), 6);
assertEquals(0, slice1.compareTo(expected1));
assertEquals(0, slice1.compareTo(slice1.duplicate()));
// Advance the reader index on slice1.
slice1.readByte();
ByteBuf dup2 = slice1.duplicate();
assertEquals(0, dup2.compareTo(slice1));
// Advance the reader index on dup2.
dup2.readByte();
ByteBuf slice2 = dup2.retainedSlice(dup2.readerIndex() + 1, 3);
assertEquals(0, slice2.compareTo(expected3));
assertEquals(0, slice2.compareTo(dup2.slice(dup2.readerIndex() + 1, 3)));
// Cleanup the expected buffers used for testing.
assertTrue(expected1.release());
assertTrue(expected2.release());
assertTrue(expected3.release());
slice2.release();
slice1.release();
assertEquals(slice2.refCnt(), dup2.refCnt());
assertEquals(dup2.refCnt(), slice1.refCnt());
// The handler is now done with the original slice
assertTrue(dup1.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
assertEquals(0, dup1.refCnt());
assertEquals(0, dup2.refCnt());
}
@Test
public void testRetainedSliceContents() {
testSliceContents(true);
}
@Test
public void testMultipleLevelRetainedSlice1() {
testMultipleLevelRetainedSliceWithNonRetained(true, true);
}
@Test
public void testMultipleLevelRetainedSlice2() {
testMultipleLevelRetainedSliceWithNonRetained(true, false);
}
@Test
public void testMultipleLevelRetainedSlice3() {
testMultipleLevelRetainedSliceWithNonRetained(false, true);
}
@Test
public void testMultipleLevelRetainedSlice4() {
testMultipleLevelRetainedSliceWithNonRetained(false, false);
}
@Test
public void testRetainedSliceReleaseOriginal1() {
testSliceReleaseOriginal(true, true);
}
@Test
public void testRetainedSliceReleaseOriginal2() {
testSliceReleaseOriginal(true, false);
}
@Test
public void testRetainedSliceReleaseOriginal3() {
testSliceReleaseOriginal(false, true);
}
@Test
public void testRetainedSliceReleaseOriginal4() {
testSliceReleaseOriginal(false, false);
}
@Test
public void testRetainedDuplicateReleaseOriginal1() {
testDuplicateReleaseOriginal(true, true);
}
@Test
public void testRetainedDuplicateReleaseOriginal2() {
testDuplicateReleaseOriginal(true, false);
}
@Test
public void testRetainedDuplicateReleaseOriginal3() {
testDuplicateReleaseOriginal(false, true);
}
@Test
public void testRetainedDuplicateReleaseOriginal4() {
testDuplicateReleaseOriginal(false, false);
}
@Test
public void testMultipleRetainedSliceReleaseOriginal1() {
testMultipleRetainedSliceReleaseOriginal(true, true);
}
@Test
public void testMultipleRetainedSliceReleaseOriginal2() {
testMultipleRetainedSliceReleaseOriginal(true, false);
}
@Test
public void testMultipleRetainedSliceReleaseOriginal3() {
testMultipleRetainedSliceReleaseOriginal(false, true);
}
@Test
public void testMultipleRetainedSliceReleaseOriginal4() {
testMultipleRetainedSliceReleaseOriginal(false, false);
}
@Test
public void testMultipleRetainedDuplicateReleaseOriginal1() {
testMultipleRetainedDuplicateReleaseOriginal(true, true);
}
@Test
public void testMultipleRetainedDuplicateReleaseOriginal2() {
testMultipleRetainedDuplicateReleaseOriginal(true, false);
}
@Test
public void testMultipleRetainedDuplicateReleaseOriginal3() {
testMultipleRetainedDuplicateReleaseOriginal(false, true);
}
@Test
public void testMultipleRetainedDuplicateReleaseOriginal4() {
testMultipleRetainedDuplicateReleaseOriginal(false, false);
}
@Test
public void testSliceContents() {
testSliceContents(false);
}
@Test
public void testRetainedDuplicateContents() {
testDuplicateContents(true);
}
@Test
public void testDuplicateContents() {
testDuplicateContents(false);
}
@Test
public void testDuplicateCapacityChange() {
testDuplicateCapacityChange(false);
}
@Test
public void testRetainedDuplicateCapacityChange() {
testDuplicateCapacityChange(true);
}
@Test
public void testSliceCapacityChange() {
assertThrows(UnsupportedOperationException.class, () -> testSliceCapacityChange(false));
}
@Test
public void testRetainedSliceCapacityChange() {
assertThrows(UnsupportedOperationException.class, () -> testSliceCapacityChange(true));
}
@Test
public void testRetainedSliceUnreleasable1() {
testRetainedSliceUnreleasable(true, true);
}
@Test
public void testRetainedSliceUnreleasable2() {
testRetainedSliceUnreleasable(true, false);
}
@Test
public void testRetainedSliceUnreleasable3() {
testRetainedSliceUnreleasable(false, true);
}
@Test
public void testRetainedSliceUnreleasable4() {
testRetainedSliceUnreleasable(false, false);
}
@Test
public void testReadRetainedSliceUnreleasable1() {
testReadRetainedSliceUnreleasable(true, true);
}
@Test
public void testReadRetainedSliceUnreleasable2() {
testReadRetainedSliceUnreleasable(true, false);
}
@Test
public void testReadRetainedSliceUnreleasable3() {
testReadRetainedSliceUnreleasable(false, true);
}
@Test
public void testReadRetainedSliceUnreleasable4() {
testReadRetainedSliceUnreleasable(false, false);
}
@Test
public void testRetainedDuplicateUnreleasable1() {
testRetainedDuplicateUnreleasable(true, true);
}
@Test
public void testRetainedDuplicateUnreleasable2() {
testRetainedDuplicateUnreleasable(true, false);
}
@Test
public void testRetainedDuplicateUnreleasable3() {
testRetainedDuplicateUnreleasable(false, true);
}
@Test
public void testRetainedDuplicateUnreleasable4() {
testRetainedDuplicateUnreleasable(false, false);
}
private void testRetainedSliceUnreleasable(boolean initRetainedSlice, boolean finalRetainedSlice) {
ByteBuf buf = newBuffer(8);
ByteBuf buf1 = initRetainedSlice ? buf.retainedSlice() : buf.slice().retain();
ByteBuf buf2 = unreleasableBuffer(buf1);
ByteBuf buf3 = finalRetainedSlice ? buf2.retainedSlice() : buf2.slice().retain();
assertFalse(buf3.release());
assertFalse(buf2.release());
buf1.release();
assertTrue(buf.release());
assertEquals(0, buf1.refCnt());
assertEquals(0, buf.refCnt());
}
private void testReadRetainedSliceUnreleasable(boolean initRetainedSlice, boolean finalRetainedSlice) {
ByteBuf buf = newBuffer(8);
ByteBuf buf1 = initRetainedSlice ? buf.retainedSlice() : buf.slice().retain();
ByteBuf buf2 = unreleasableBuffer(buf1);
ByteBuf buf3 = finalRetainedSlice ? buf2.readRetainedSlice(buf2.readableBytes())
: buf2.readSlice(buf2.readableBytes()).retain();
assertFalse(buf3.release());
assertFalse(buf2.release());
buf1.release();
assertTrue(buf.release());
assertEquals(0, buf1.refCnt());
assertEquals(0, buf.refCnt());
}
private void testRetainedDuplicateUnreleasable(boolean initRetainedDuplicate, boolean finalRetainedDuplicate) {
ByteBuf buf = newBuffer(8);
ByteBuf buf1 = initRetainedDuplicate ? buf.retainedDuplicate() : buf.duplicate().retain();
ByteBuf buf2 = unreleasableBuffer(buf1);
ByteBuf buf3 = finalRetainedDuplicate ? buf2.retainedDuplicate() : buf2.duplicate().retain();
assertFalse(buf3.release());
assertFalse(buf2.release());
buf1.release();
assertTrue(buf.release());
assertEquals(0, buf1.refCnt());
assertEquals(0, buf.refCnt());
}
private void testDuplicateCapacityChange(boolean retainedDuplicate) {
ByteBuf buf = newBuffer(8);
ByteBuf dup = retainedDuplicate ? buf.retainedDuplicate() : buf.duplicate();
try {
dup.capacity(10);
assertEquals(buf.capacity(), dup.capacity());
dup.capacity(5);
assertEquals(buf.capacity(), dup.capacity());
} finally {
if (retainedDuplicate) {
dup.release();
}
buf.release();
}
}
private void testSliceCapacityChange(boolean retainedSlice) {
ByteBuf buf = newBuffer(8);
ByteBuf slice = retainedSlice ? buf.retainedSlice(buf.readerIndex() + 1, 3)
: buf.slice(buf.readerIndex() + 1, 3);
try {
slice.capacity(10);
} finally {
if (retainedSlice) {
slice.release();
}
buf.release();
}
}
private void testSliceOutOfBounds(boolean initRetainedSlice, boolean finalRetainedSlice, boolean indexOutOfBounds) {
ByteBuf buf = newBuffer(8);
ByteBuf slice = initRetainedSlice ? buf.retainedSlice(buf.readerIndex() + 1, 2)
: buf.slice(buf.readerIndex() + 1, 2);
try {
assertEquals(2, slice.capacity());
assertEquals(2, slice.maxCapacity());
final int index = indexOutOfBounds ? 3 : 0;
final int length = indexOutOfBounds ? 0 : 3;
if (finalRetainedSlice) {
// This is expected to fail ... so no need to release.
slice.retainedSlice(index, length);
} else {
slice.slice(index, length);
}
} finally {
if (initRetainedSlice) {
slice.release();
}
buf.release();
}
}
private void testSliceContents(boolean retainedSlice) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected = newBuffer(3).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected.writeBytes(new byte[] {4, 5, 6});
ByteBuf slice = retainedSlice ? buf.retainedSlice(buf.readerIndex() + 3, 3)
: buf.slice(buf.readerIndex() + 3, 3);
try {
assertEquals(0, slice.compareTo(expected));
assertEquals(0, slice.compareTo(slice.duplicate()));
ByteBuf b = slice.retainedDuplicate();
assertEquals(0, slice.compareTo(b));
b.release();
assertEquals(0, slice.compareTo(slice.slice(0, slice.capacity())));
} finally {
if (retainedSlice) {
slice.release();
}
buf.release();
expected.release();
}
}
private void testSliceReleaseOriginal(boolean retainedSlice1, boolean retainedSlice2) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected1 = newBuffer(3).writerIndex(0);
ByteBuf expected2 = newBuffer(2).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected1.writeBytes(new byte[] {6, 7, 8});
expected2.writeBytes(new byte[] {7, 8});
ByteBuf slice1 = retainedSlice1 ? buf.retainedSlice(buf.readerIndex() + 5, 3)
: buf.slice(buf.readerIndex() + 5, 3).retain();
assertEquals(0, slice1.compareTo(expected1));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
ByteBuf slice2 = retainedSlice2 ? slice1.retainedSlice(slice1.readerIndex() + 1, 2)
: slice1.slice(slice1.readerIndex() + 1, 2).retain();
assertEquals(0, slice2.compareTo(expected2));
// Cleanup the expected buffers used for testing.
assertTrue(expected1.release());
assertTrue(expected2.release());
// The handler created a slice of the slice and is now done with it.
slice2.release();
// The handler is now done with the original slice
assertTrue(slice1.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
}
private void testMultipleLevelRetainedSliceWithNonRetained(boolean doSlice1, boolean doSlice2) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected1 = newBuffer(6).writerIndex(0);
ByteBuf expected2 = newBuffer(4).writerIndex(0);
ByteBuf expected3 = newBuffer(2).writerIndex(0);
ByteBuf expected4SliceSlice = newBuffer(1).writerIndex(0);
ByteBuf expected4DupSlice = newBuffer(1).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected1.writeBytes(new byte[] {2, 3, 4, 5, 6, 7});
expected2.writeBytes(new byte[] {3, 4, 5, 6});
expected3.writeBytes(new byte[] {4, 5});
expected4SliceSlice.writeBytes(new byte[] {5});
expected4DupSlice.writeBytes(new byte[] {4});
ByteBuf slice1 = buf.retainedSlice(buf.readerIndex() + 1, 6);
assertEquals(0, slice1.compareTo(expected1));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
ByteBuf slice2 = slice1.retainedSlice(slice1.readerIndex() + 1, 4);
assertEquals(0, slice2.compareTo(expected2));
assertEquals(0, slice2.compareTo(slice2.duplicate()));
assertEquals(0, slice2.compareTo(slice2.slice()));
ByteBuf tmpBuf = slice2.retainedDuplicate();
assertEquals(0, slice2.compareTo(tmpBuf));
tmpBuf.release();
tmpBuf = slice2.retainedSlice();
assertEquals(0, slice2.compareTo(tmpBuf));
tmpBuf.release();
ByteBuf slice3 = doSlice1 ? slice2.slice(slice2.readerIndex() + 1, 2) : slice2.duplicate();
if (doSlice1) {
assertEquals(0, slice3.compareTo(expected3));
} else {
assertEquals(0, slice3.compareTo(expected2));
}
ByteBuf slice4 = doSlice2 ? slice3.slice(slice3.readerIndex() + 1, 1) : slice3.duplicate();
if (doSlice1 && doSlice2) {
assertEquals(0, slice4.compareTo(expected4SliceSlice));
} else if (doSlice2) {
assertEquals(0, slice4.compareTo(expected4DupSlice));
} else {
assertEquals(0, slice3.compareTo(slice4));
}
// Cleanup the expected buffers used for testing.
assertTrue(expected1.release());
assertTrue(expected2.release());
assertTrue(expected3.release());
assertTrue(expected4SliceSlice.release());
assertTrue(expected4DupSlice.release());
// Slice 4, 3, and 2 should effectively "share" a reference count.
slice4.release();
assertEquals(slice3.refCnt(), slice2.refCnt());
assertEquals(slice3.refCnt(), slice4.refCnt());
// Slice 1 should also release the original underlying buffer without throwing exceptions
assertTrue(slice1.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
assertEquals(0, slice3.refCnt());
}
private void testDuplicateReleaseOriginal(boolean retainedDuplicate1, boolean retainedDuplicate2) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected = newBuffer(8).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected.writeBytes(buf, buf.readerIndex(), buf.readableBytes());
ByteBuf dup1 = retainedDuplicate1 ? buf.retainedDuplicate()
: buf.duplicate().retain();
assertEquals(0, dup1.compareTo(expected));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
ByteBuf dup2 = retainedDuplicate2 ? dup1.retainedDuplicate()
: dup1.duplicate().retain();
assertEquals(0, dup2.compareTo(expected));
// Cleanup the expected buffers used for testing.
assertTrue(expected.release());
// The handler created a slice of the slice and is now done with it.
dup2.release();
// The handler is now done with the original slice
assertTrue(dup1.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, dup1.refCnt());
assertEquals(0, dup2.refCnt());
}
private void testMultipleRetainedSliceReleaseOriginal(boolean retainedSlice1, boolean retainedSlice2) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected1 = newBuffer(3).writerIndex(0);
ByteBuf expected2 = newBuffer(2).writerIndex(0);
ByteBuf expected3 = newBuffer(2).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected1.writeBytes(new byte[] {6, 7, 8});
expected2.writeBytes(new byte[] {7, 8});
expected3.writeBytes(new byte[] {6, 7});
ByteBuf slice1 = retainedSlice1 ? buf.retainedSlice(buf.readerIndex() + 5, 3)
: buf.slice(buf.readerIndex() + 5, 3).retain();
assertEquals(0, slice1.compareTo(expected1));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
ByteBuf slice2 = retainedSlice2 ? slice1.retainedSlice(slice1.readerIndex() + 1, 2)
: slice1.slice(slice1.readerIndex() + 1, 2).retain();
assertEquals(0, slice2.compareTo(expected2));
// The handler created a slice of the slice and is now done with it.
slice2.release();
ByteBuf slice3 = slice1.retainedSlice(slice1.readerIndex(), 2);
assertEquals(0, slice3.compareTo(expected3));
// The handler created another slice of the slice and is now done with it.
slice3.release();
// The handler is now done with the original slice
assertTrue(slice1.release());
// Cleanup the expected buffers used for testing.
assertTrue(expected1.release());
assertTrue(expected2.release());
assertTrue(expected3.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, slice1.refCnt());
assertEquals(0, slice2.refCnt());
assertEquals(0, slice3.refCnt());
}
private void testMultipleRetainedDuplicateReleaseOriginal(boolean retainedDuplicate1, boolean retainedDuplicate2) {
ByteBuf buf = newBuffer(8).writerIndex(0);
ByteBuf expected = newBuffer(8).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
expected.writeBytes(buf, buf.readerIndex(), buf.readableBytes());
ByteBuf dup1 = retainedDuplicate1 ? buf.retainedDuplicate()
: buf.duplicate().retain();
assertEquals(0, dup1.compareTo(expected));
// Simulate a handler that releases the original buffer, and propagates a slice.
buf.release();
ByteBuf dup2 = retainedDuplicate2 ? dup1.retainedDuplicate()
: dup1.duplicate().retain();
assertEquals(0, dup2.compareTo(expected));
assertEquals(0, dup2.compareTo(dup2.duplicate()));
assertEquals(0, dup2.compareTo(dup2.slice()));
ByteBuf tmpBuf = dup2.retainedDuplicate();
assertEquals(0, dup2.compareTo(tmpBuf));
tmpBuf.release();
tmpBuf = dup2.retainedSlice();
assertEquals(0, dup2.compareTo(tmpBuf));
tmpBuf.release();
// The handler created a slice of the slice and is now done with it.
dup2.release();
ByteBuf dup3 = dup1.retainedDuplicate();
assertEquals(0, dup3.compareTo(expected));
// The handler created another slice of the slice and is now done with it.
dup3.release();
// The handler is now done with the original slice
assertTrue(dup1.release());
// Cleanup the expected buffers used for testing.
assertTrue(expected.release());
// Reference counting may be shared, or may be independently tracked, but at this point all buffers should
// be deallocated and have a reference count of 0.
assertEquals(0, buf.refCnt());
assertEquals(0, dup1.refCnt());
assertEquals(0, dup2.refCnt());
assertEquals(0, dup3.refCnt());
}
private void testDuplicateContents(boolean retainedDuplicate) {
ByteBuf buf = newBuffer(8).writerIndex(0);
buf.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8});
ByteBuf dup = retainedDuplicate ? buf.retainedDuplicate() : buf.duplicate();
try {
assertEquals(0, dup.compareTo(buf));
assertEquals(0, dup.compareTo(dup.duplicate()));
ByteBuf b = dup.retainedDuplicate();
assertEquals(0, dup.compareTo(b));
b.release();
assertEquals(0, dup.compareTo(dup.slice(dup.readerIndex(), dup.readableBytes())));
} finally {
if (retainedDuplicate) {
dup.release();
}
buf.release();
}
}
@Test
public void testDuplicateRelease() {
ByteBuf buf = newBuffer(8);
assertEquals(1, buf.refCnt());
assertTrue(buf.duplicate().release());
assertEquals(0, buf.refCnt());
}
// Test-case trying to reproduce:
// https://github.com/netty/netty/issues/2843
@Test
public void testRefCnt() throws Exception {
testRefCnt0(false);
}
// Test-case trying to reproduce:
// https://github.com/netty/netty/issues/2843
@Test
public void testRefCnt2() throws Exception {
testRefCnt0(true);
}
@Test
public void testEmptyNioBuffers() throws Exception {
ByteBuf buffer = newBuffer(8);
buffer.clear();
assertFalse(buffer.isReadable());
ByteBuffer[] nioBuffers = buffer.nioBuffers();
assertEquals(1, nioBuffers.length);
assertFalse(nioBuffers[0].hasRemaining());
buffer.release();
}
@Test
public void testGetReadOnlyDirectDst() {
testGetReadOnlyDst(true);
}
@Test
public void testGetReadOnlyHeapDst() {
testGetReadOnlyDst(false);
}
private void testGetReadOnlyDst(boolean direct) {
byte[] bytes = { 'a', 'b', 'c', 'd' };
ByteBuf buffer = newBuffer(bytes.length);
buffer.writeBytes(bytes);
ByteBuffer dst = direct ? ByteBuffer.allocateDirect(bytes.length) : ByteBuffer.allocate(bytes.length);
ByteBuffer readOnlyDst = dst.asReadOnlyBuffer();
try {
buffer.getBytes(0, readOnlyDst);
fail();
} catch (ReadOnlyBufferException e) {
// expected
}
assertEquals(0, readOnlyDst.position());
buffer.release();
}
@Test
public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(file, "rw");
FileChannel channel = randomAccessFile.getChannel();
// channelPosition should never be changed
long channelPosition = channel.position();
byte[] bytes = {'a', 'b', 'c', 'd'};
int len = bytes.length;
ByteBuf buffer = newBuffer(len).writerIndex(0);
buffer.writeBytes(bytes);
int oldReaderIndex = buffer.readerIndex();
assertEquals(len, buffer.readBytes(channel, 10, len));
assertEquals(oldReaderIndex + len, buffer.readerIndex());
assertEquals(channelPosition, channel.position());
ByteBuf buffer2 = newBuffer(len).writerIndex(0);
int oldWriterIndex = buffer2.writerIndex();
assertEquals(len, buffer2.writeBytes(channel, 10, len));
assertEquals(channelPosition, channel.position());
assertEquals(oldWriterIndex + len, buffer2.writerIndex());
assertEquals('a', buffer2.getByte(0));
assertEquals('b', buffer2.getByte(1));
assertEquals('c', buffer2.getByte(2));
assertEquals('d', buffer2.getByte(3));
buffer.release();
buffer2.release();
} finally {
if (randomAccessFile != null) {
randomAccessFile.close();
}
file.delete();
}
}
@Test
public void testGetBytesAndSetBytesWithFileChannel() throws IOException {
File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(file, "rw");
FileChannel channel = randomAccessFile.getChannel();
// channelPosition should never be changed
long channelPosition = channel.position();
byte[] bytes = {'a', 'b', 'c', 'd'};
int len = bytes.length;
ByteBuf buffer = newBuffer(len).writerIndex(0);
buffer.writeBytes(bytes);
int oldReaderIndex = buffer.readerIndex();
assertEquals(len, buffer.getBytes(oldReaderIndex, channel, 10, len));
assertEquals(oldReaderIndex, buffer.readerIndex());
assertEquals(channelPosition, channel.position());
ByteBuf buffer2 = newBuffer(len).writerIndex(0);
int oldWriterIndex = buffer2.writerIndex();
assertEquals(buffer2.setBytes(oldWriterIndex, channel, 10, len), len);
assertEquals(channelPosition, channel.position());
assertEquals(oldWriterIndex, buffer2.writerIndex());
assertEquals('a', buffer2.getByte(oldWriterIndex));
assertEquals('b', buffer2.getByte(oldWriterIndex + 1));
assertEquals('c', buffer2.getByte(oldWriterIndex + 2));
assertEquals('d', buffer2.getByte(oldWriterIndex + 3));
buffer.release();
buffer2.release();
} finally {
if (randomAccessFile != null) {
randomAccessFile.close();
}
file.delete();
}
}
@Test
public void testReadBytes() {
ByteBuf buffer = newBuffer(8);
byte[] bytes = new byte[8];
buffer.writeBytes(bytes);
ByteBuf buffer2 = buffer.readBytes(4);
assertSame(buffer.alloc(), buffer2.alloc());
assertEquals(4, buffer.readerIndex());
assertTrue(buffer.release());
assertEquals(0, buffer.refCnt());
assertTrue(buffer2.release());
assertEquals(0, buffer2.refCnt());
}
@Test
public void testForEachByteDesc2() {
byte[] expected = {1, 2, 3, 4};
ByteBuf buf = newBuffer(expected.length);
try {
buf.writeBytes(expected);
final byte[] bytes = new byte[expected.length];
int i = buf.forEachByteDesc(new ByteProcessor() {
private int index = bytes.length - 1;
@Override
public boolean process(byte value) {
bytes[index--] = value;
return true;
}
});
assertEquals(-1, i);
assertArrayEquals(expected, bytes);
} finally {
buf.release();
}
}
@Test
public void testForEachByte2() {
byte[] expected = {1, 2, 3, 4};
ByteBuf buf = newBuffer(expected.length);
try {
buf.writeBytes(expected);
final byte[] bytes = new byte[expected.length];
int i = buf.forEachByte(new ByteProcessor() {
private int index;
@Override
public boolean process(byte value) {
bytes[index++] = value;
return true;
}
});
assertEquals(-1, i);
assertArrayEquals(expected, bytes);
} finally {
buf.release();
}
}
@Test
public void testGetBytesByteBuffer() {
byte[] bytes = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
// Ensure destination buffer is bigger then what is in the ByteBuf.
ByteBuffer nioBuffer = ByteBuffer.allocate(bytes.length + 1);
ByteBuf buffer = newBuffer(bytes.length);
try {
buffer.writeBytes(bytes);
assertThrows(IndexOutOfBoundsException.class, () -> buffer.getBytes(buffer.readerIndex(), nioBuffer));
} finally {
buffer.release();
}
}
private void testRefCnt0(final boolean parameter) throws Exception {
for (int i = 0; i < 10; i++) {
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch innerLatch = new CountDownLatch(1);
final ByteBuf buffer = newBuffer(4);
assertEquals(1, buffer.refCnt());
final AtomicInteger cnt = new AtomicInteger(Integer.MAX_VALUE);
Thread t1 = new Thread(() -> {
boolean released;
if (parameter) {
released = buffer.release(buffer.refCnt());
} else {
released = buffer.release();
}
assertTrue(released);
Thread t2 = new Thread(() -> {
cnt.set(buffer.refCnt());
latch.countDown();
});
t2.start();
try {
// Keep Thread alive a bit so the ThreadLocal caches are not freed
innerLatch.await();
} catch (InterruptedException ignore) {
// ignore
}
});
t1.start();
latch.await();
assertEquals(0, cnt.get());
innerLatch.countDown();
}
}
static final class TestGatheringByteChannel implements GatheringByteChannel {
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
private final WritableByteChannel channel = Channels.newChannel(out);
private final int limit;
TestGatheringByteChannel(int limit) {
this.limit = limit;
}
TestGatheringByteChannel() {
this(Integer.MAX_VALUE);
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
long written = 0;
for (; offset < length; offset++) {
written += write(srcs[offset]);
if (written >= limit) {
break;
}
}
return written;
}
@Override
public long write(ByteBuffer[] srcs) throws IOException {
return write(srcs, 0, srcs.length);
}
@Override
public int write(ByteBuffer src) throws IOException {
int oldLimit = src.limit();
if (limit < src.remaining()) {
src.limit(src.position() + limit);
}
int w = channel.write(src);
src.limit(oldLimit);
return w;
}
@Override
public boolean isOpen() {
return channel.isOpen();
}
@Override
public void close() throws IOException {
channel.close();
}
public byte[] writtenBytes() {
return out.toByteArray();
}
}
private static final class DevNullGatheringByteChannel implements GatheringByteChannel {
@Override
public long write(ByteBuffer[] srcs, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
public long write(ByteBuffer[] srcs) {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src) {
throw new UnsupportedOperationException();
}
@Override
public boolean isOpen() {
return false;
}
@Override
public void close() {
throw new UnsupportedOperationException();
}
}
private static final class TestScatteringByteChannel implements ScatteringByteChannel {
@Override
public long read(ByteBuffer[] dsts, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
public long read(ByteBuffer[] dsts) {
throw new UnsupportedOperationException();
}
@Override
public int read(ByteBuffer dst) {
throw new UnsupportedOperationException();
}
@Override
public boolean isOpen() {
return false;
}
@Override
public void close() {
throw new UnsupportedOperationException();
}
}
private static final class TestByteProcessor implements ByteProcessor {
@Override
public boolean process(byte value) {
return true;
}
}
@Test
public void testCapacityEnforceMaxCapacity() {
ByteBuf buffer = newBuffer(3, 13);
assertEquals(13, buffer.maxCapacity());
assertEquals(3, buffer.capacity());
try {
assertThrows(IllegalArgumentException.class, () -> buffer.capacity(14));
} finally {
buffer.release();
}
}
@Test
public void testCapacityNegative() {
ByteBuf buffer = newBuffer(3, 13);
assertEquals(13, buffer.maxCapacity());
assertEquals(3, buffer.capacity());
try {
assertThrows(IllegalArgumentException.class, () -> buffer.capacity(-1));
} finally {
buffer.release();
}
}
@Test
public void testCapacityDecrease() {
ByteBuf buffer = newBuffer(3, 13);
assertEquals(13, buffer.maxCapacity());
assertEquals(3, buffer.capacity());
try {
buffer.capacity(2);
assertEquals(2, buffer.capacity());
assertEquals(13, buffer.maxCapacity());
} finally {
buffer.release();
}
}
@Test
public void testCapacityIncrease() {
ByteBuf buffer = newBuffer(3, 13);
assertEquals(13, buffer.maxCapacity());
assertEquals(3, buffer.capacity());
try {
buffer.capacity(4);
assertEquals(4, buffer.capacity());
assertEquals(13, buffer.maxCapacity());
} finally {
buffer.release();
}
}
@Test
public void testReaderIndexLargerThanWriterIndex() {
String content1 = "hello";
String content2 = "world";
int length = content1.length() + content2.length();
ByteBuf buffer = newBuffer(length);
buffer.setIndex(0, 0);
buffer.writeCharSequence(content1, CharsetUtil.US_ASCII);
buffer.skipBytes(content1.length());
buffer.writeCharSequence(content2, CharsetUtil.US_ASCII);
buffer.skipBytes(content2.length());
assertTrue(buffer.readerIndex() <= buffer.writerIndex());
try {
assertThrows(IndexOutOfBoundsException.class, () -> buffer.readerIndex(buffer.writerIndex() + 1));
} finally {
buffer.release();
}
}
@Test
public void testMaxFastWritableBytes() {
ByteBuf buffer = newBuffer(150, 500).writerIndex(100);
assertEquals(50, buffer.writableBytes());
assertEquals(150, buffer.capacity());
assertEquals(500, buffer.maxCapacity());
assertEquals(400, buffer.maxWritableBytes());
// Default implementation has fast writable == writable
assertEquals(50, buffer.maxFastWritableBytes());
buffer.release();
}
@Test
public void testEnsureWritableIntegerOverflow() {
ByteBuf buffer = newBuffer(CAPACITY);
buffer.writerIndex(buffer.readerIndex());
buffer.writeByte(1);
try {
buffer.ensureWritable(Integer.MAX_VALUE);
fail();
} catch (IndexOutOfBoundsException e) {
// expected
} finally {
buffer.release();
}
}
@Test
public void testEndiannessIndexOf() {
buffer.clear();
final int v = 0x02030201;
buffer.writeIntLE(v);
buffer.writeByte(0x01);
assertEquals(-1, buffer.indexOf(1, 4, (byte) 1));
assertEquals(-1, buffer.indexOf(4, 1, (byte) 1));
assertEquals(1, buffer.indexOf(1, 4, (byte) 2));
assertEquals(3, buffer.indexOf(4, 1, (byte) 2));
}
@Test
public void explicitLittleEndianReadMethodsMustAlwaysUseLittleEndianByteOrder() {
buffer.clear();
buffer.writeBytes(new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08});
assertEquals(0x0201, buffer.readShortLE());
buffer.readerIndex(0);
assertEquals(0x0201, buffer.readUnsignedShortLE());
buffer.readerIndex(0);
assertEquals(0x030201, buffer.readMediumLE());
buffer.readerIndex(0);
assertEquals(0x030201, buffer.readUnsignedMediumLE());
buffer.readerIndex(0);
assertEquals(0x04030201, buffer.readIntLE());
buffer.readerIndex(0);
assertEquals(0x04030201, buffer.readUnsignedIntLE());
buffer.readerIndex(0);
assertEquals(0x04030201, Float.floatToRawIntBits(buffer.readFloatLE()));
buffer.readerIndex(0);
assertEquals(0x0807060504030201L, buffer.readLongLE());
buffer.readerIndex(0);
assertEquals(0x0807060504030201L, Double.doubleToRawLongBits(buffer.readDoubleLE()));
buffer.readerIndex(0);
}
@Test
public void explicitLittleEndianWriteMethodsMustAlwaysUseLittleEndianByteOrder() {
buffer.clear();
buffer.writeShortLE(0x0102);
assertEquals(0x0102, buffer.readShortLE());
buffer.clear();
buffer.writeMediumLE(0x010203);
assertEquals(0x010203, buffer.readMediumLE());
buffer.clear();
buffer.writeIntLE(0x01020304);
assertEquals(0x01020304, buffer.readIntLE());
buffer.clear();
buffer.writeFloatLE(Float.intBitsToFloat(0x01020304));
assertEquals(0x01020304, Float.floatToRawIntBits(buffer.readFloatLE()));
buffer.clear();
buffer.writeLongLE(0x0102030405060708L);
assertEquals(0x0102030405060708L, buffer.readLongLE());
buffer.clear();
buffer.writeDoubleLE(Double.longBitsToDouble(0x0102030405060708L));
assertEquals(0x0102030405060708L, Double.doubleToRawLongBits(buffer.readDoubleLE()));
}
}