2020-08-28 14:02:51 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2020 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:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
2020-07-24 19:38:48 +02:00
|
|
|
package io.netty.buffer.b2;
|
|
|
|
|
2020-08-28 12:17:41 +02:00
|
|
|
import org.junit.After;
|
2020-08-17 16:09:38 +02:00
|
|
|
import org.junit.AssumptionViolatedException;
|
2020-08-28 12:17:41 +02:00
|
|
|
import org.junit.Before;
|
2020-07-24 19:38:48 +02:00
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.concurrent.Future;
|
|
|
|
import java.util.concurrent.SynchronousQueue;
|
|
|
|
|
|
|
|
import static org.hamcrest.Matchers.*;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
|
2020-07-29 10:30:03 +02:00
|
|
|
public abstract class BBufTest {
|
2020-07-24 19:38:48 +02:00
|
|
|
protected abstract Allocator createAllocator();
|
|
|
|
|
2020-08-28 12:17:41 +02:00
|
|
|
private Allocator allocator;
|
|
|
|
private Buf buf;
|
|
|
|
|
|
|
|
@Before
|
|
|
|
public void setUp() {
|
|
|
|
allocator = createAllocator();
|
|
|
|
buf = allocator.allocate(8);
|
|
|
|
}
|
|
|
|
|
|
|
|
@After
|
|
|
|
public void tearDown() {
|
|
|
|
buf.close();
|
|
|
|
allocator.close();
|
|
|
|
}
|
|
|
|
|
2020-07-24 19:38:48 +02:00
|
|
|
@Test
|
|
|
|
public void allocateAndAccessingBuffer() {
|
2020-08-28 12:17:41 +02:00
|
|
|
buf.writeByte((byte) 1);
|
|
|
|
buf.writeByte((byte) 2);
|
|
|
|
try (Buf inner = buf.acquire()) {
|
|
|
|
inner.writeByte((byte) 3);
|
|
|
|
inner.writeByte((byte) 4);
|
|
|
|
inner.writeByte((byte) 5);
|
|
|
|
inner.writeByte((byte) 6);
|
|
|
|
inner.writeByte((byte) 7);
|
|
|
|
inner.writeByte((byte) 8);
|
|
|
|
try {
|
|
|
|
inner.writeByte((byte) 9);
|
|
|
|
fail("Expected to be out of bounds.");
|
|
|
|
} catch (RuntimeException re) {
|
|
|
|
assertThat(re.getMessage(), containsString("bound"));
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
|
|
|
try {
|
2020-08-28 12:17:41 +02:00
|
|
|
buf.writeByte((byte) 9);
|
2020-07-24 19:38:48 +02:00
|
|
|
fail("Expected to be out of bounds.");
|
|
|
|
} catch (RuntimeException re) {
|
|
|
|
assertThat(re.getMessage(), containsString("bound"));
|
|
|
|
}
|
|
|
|
}
|
2020-08-28 12:17:41 +02:00
|
|
|
assertEquals((byte) 1, buf.readByte());
|
|
|
|
assertEquals((byte) 2, buf.readByte());
|
|
|
|
assertEquals((byte) 3, buf.readByte());
|
|
|
|
assertEquals((byte) 4, buf.readByte());
|
|
|
|
assertEquals((byte) 5, buf.readByte());
|
|
|
|
assertEquals((byte) 6, buf.readByte());
|
|
|
|
assertEquals((byte) 7, buf.readByte());
|
|
|
|
assertEquals((byte) 8, buf.readByte());
|
|
|
|
try {
|
|
|
|
assertEquals((byte) 9, buf.readByte());
|
|
|
|
fail("Expected to be out of bounds.");
|
|
|
|
} catch (RuntimeException re) {
|
|
|
|
assertThat(re.getMessage(), containsString("bound"));
|
|
|
|
}
|
|
|
|
assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}, buf.copy());
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void allocateAndSendToThread() throws Exception {
|
2020-08-28 12:17:41 +02:00
|
|
|
ArrayBlockingQueue<Send<Buf>> queue = new ArrayBlockingQueue<>(10);
|
|
|
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
Future<Byte> future = executor.submit(() -> {
|
|
|
|
try (Buf byteBuf = queue.take().receive()) {
|
|
|
|
return byteBuf.readByte();
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
2020-08-28 12:17:41 +02:00
|
|
|
});
|
|
|
|
executor.shutdown();
|
2020-07-24 19:38:48 +02:00
|
|
|
|
2020-08-28 12:17:41 +02:00
|
|
|
try (Buf buf = allocator.allocate(8)) {
|
|
|
|
buf.writeByte((byte) 42);
|
|
|
|
assertTrue(queue.offer(buf.send()));
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
2020-08-28 12:17:41 +02:00
|
|
|
|
|
|
|
assertEquals((byte) 42, future.get().byteValue());
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void allocateAndSendToThreadViaSyncQueue() throws Exception {
|
2020-08-28 12:17:41 +02:00
|
|
|
SynchronousQueue<Send<Buf>> queue = new SynchronousQueue<>();
|
|
|
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
Future<Byte> future = executor.submit(() -> {
|
|
|
|
try (Buf byteBuf = queue.take().receive()) {
|
|
|
|
return byteBuf.readByte();
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
2020-08-28 12:17:41 +02:00
|
|
|
});
|
|
|
|
executor.shutdown();
|
2020-07-24 19:38:48 +02:00
|
|
|
|
2020-08-28 12:17:41 +02:00
|
|
|
try (Buf buf = allocator.allocate(8)) {
|
|
|
|
assertSame(buf, buf.writeByte((byte) 42));
|
|
|
|
queue.put(buf.send());
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
2020-08-28 12:17:41 +02:00
|
|
|
|
|
|
|
assertEquals((byte) 42, future.get().byteValue());
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
2020-08-17 16:09:38 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void mustThrowWhenAllocatingZeroSizedBuffer() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
allocator.allocate(0);
|
|
|
|
fail("Expected to throw an IllegalArgumentException.");
|
|
|
|
} catch (IllegalArgumentException ignore) {
|
2020-08-17 16:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void mustThrowWhenAllocatingNegativeSizedBuffer() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
allocator.allocate(-1);
|
|
|
|
fail("Expected to throw an IllegalArgumentException.");
|
|
|
|
} catch (IllegalArgumentException ignore) {
|
2020-08-17 16:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void mustThrowWhenAllocatingOverSizedBuffer() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
allocator.allocate(Integer.MAX_VALUE);
|
|
|
|
fail("Expected to throw an IllegalArgumentException.");
|
|
|
|
} catch (IllegalArgumentException ignore) {
|
2020-08-17 16:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void mustAllowAllocatingMaxArraySizedBuffer() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
allocator.allocate(Integer.MAX_VALUE - 8).close();
|
|
|
|
} catch (OutOfMemoryError oome) {
|
|
|
|
// Mark test as ignored if this happens.
|
|
|
|
throw new AssumptionViolatedException("JVM does not have enough memory for this test.", oome);
|
2020-08-17 16:09:38 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-24 16:03:02 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void setReaderIndexMustThrowOnNegativeIndex() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
buf.readerIndex(-1);
|
|
|
|
fail("Expected an exception to be thrown.");
|
|
|
|
} catch (IndexOutOfBoundsException e) {
|
|
|
|
// Good.
|
2020-08-24 16:03:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void setReaderIndexMustThrowOnOversizedIndex() {
|
2020-08-28 12:17:41 +02:00
|
|
|
try {
|
|
|
|
buf.readerIndex(8);
|
|
|
|
fail("Expected an exception to be thrown.");
|
|
|
|
} catch (IndexOutOfBoundsException e) {
|
|
|
|
// Good.
|
2020-08-24 16:03:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void setReaderIndexMustNotThrowWithinBounds() {
|
2020-08-28 12:17:41 +02:00
|
|
|
assertSame(buf, buf.readerIndex(0));
|
|
|
|
assertSame(buf, buf.readerIndex(7));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void capacityMustBeAllocatedSize() {
|
|
|
|
assertEquals(8, buf.capacity());
|
|
|
|
try (Buf b = allocator.allocate(13)) {
|
|
|
|
assertEquals(13, b.capacity());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void readerWriterIndexUpdates() {
|
|
|
|
try (Buf buf = allocator.allocate(42)) {
|
|
|
|
assertEquals(0, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writerIndex(1));
|
|
|
|
assertEquals(1, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeByte((byte) 7));
|
|
|
|
assertEquals(2, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeShort((short) 3003));
|
|
|
|
assertEquals(4, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeInt(0x5A55_BA55));
|
|
|
|
assertEquals(8, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeLong(0x123456789ABCDEF0L));
|
|
|
|
assertEquals(16, buf.writerIndex());
|
|
|
|
assertEquals(26, buf.writableBytes());
|
|
|
|
assertEquals(16, buf.readableBytes());
|
|
|
|
|
|
|
|
assertEquals(0, buf.readerIndex());
|
|
|
|
assertSame(buf, buf.readerIndex(1));
|
|
|
|
assertEquals(1, buf.readerIndex());
|
|
|
|
assertEquals((byte) 7, buf.readByte());
|
|
|
|
assertEquals(2, buf.readerIndex());
|
|
|
|
assertEquals((short) 3003, buf.readShort());
|
|
|
|
assertEquals(4, buf.readerIndex());
|
|
|
|
assertEquals(0x5A55_BA55, buf.readInt());
|
|
|
|
assertEquals(8, buf.readerIndex());
|
|
|
|
assertEquals(0x123456789ABCDEF0L, buf.readLong());
|
|
|
|
assertEquals(16, buf.readerIndex());
|
|
|
|
assertEquals(0, buf.readableBytes());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void fill() {
|
|
|
|
try (Buf buf = allocator.allocate(16)) {
|
|
|
|
assertSame(buf, buf.fill((byte) 0xA5));
|
|
|
|
assertEquals(0xA5A5A5A5_A5A5A5A5L, buf.readLong());
|
|
|
|
assertEquals(0xA5A5A5A5_A5A5A5A5L, buf.readLong());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void readAndWriteAtOffset() {
|
|
|
|
try (Buf buf = allocator.allocate(16)) {
|
|
|
|
buf.fill((byte) 0xA5);
|
|
|
|
assertSame(buf, buf.writeLong(3, 0xBEEF_CA4E_1234_5678L));
|
|
|
|
assertEquals(0xBEEF_CA4E_1234_5678L, buf.readLong(3));
|
|
|
|
assertEquals(0, buf.readerIndex());
|
|
|
|
assertEquals(0, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeInt(3, 0x1234_5678));
|
|
|
|
assertEquals(0x1234_5678, buf.readInt(3));
|
|
|
|
assertEquals(0, buf.readerIndex());
|
|
|
|
assertEquals(0, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeShort(3, (short) 0x5678));
|
|
|
|
assertEquals((short) 0x5678, buf.readShort(3));
|
|
|
|
assertEquals(0, buf.readerIndex());
|
|
|
|
assertEquals(0, buf.writerIndex());
|
|
|
|
assertSame(buf, buf.writeByte(3, (byte) 0x78));
|
|
|
|
assertEquals((byte) 0x78, buf.readByte(3));
|
|
|
|
assertEquals(0, buf.readerIndex());
|
|
|
|
assertEquals(0, buf.writerIndex());
|
2020-08-24 16:03:02 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-24 19:38:48 +02:00
|
|
|
}
|
|
|
|
|