commit
928f0bbb14
1
pom.xml
1
pom.xml
@ -176,6 +176,7 @@
|
|||||||
<forkedProcessExitTimeoutInSeconds>600</forkedProcessExitTimeoutInSeconds>
|
<forkedProcessExitTimeoutInSeconds>600</forkedProcessExitTimeoutInSeconds>
|
||||||
<!-- Not reusing forks lets us be more frugal with memory. We have a lot of tests, and they need a lot of metadata -->
|
<!-- Not reusing forks lets us be more frugal with memory. We have a lot of tests, and they need a lot of metadata -->
|
||||||
<reuseForks>false</reuseForks>
|
<reuseForks>false</reuseForks>
|
||||||
|
<forkCount>1C</forkCount>
|
||||||
<systemProperties>
|
<systemProperties>
|
||||||
<sample>nosample</sample>
|
<sample>nosample</sample>
|
||||||
</systemProperties>
|
</systemProperties>
|
||||||
|
@ -128,6 +128,14 @@ import java.nio.ByteOrder;
|
|||||||
* perhaps unknown, piece of code, and relinquish your ownership of that buffer region in the process.
|
* perhaps unknown, piece of code, and relinquish your ownership of that buffer region in the process.
|
||||||
* Examples include aggregating messages into an accumulator buffer, and sending messages down the pipeline for
|
* Examples include aggregating messages into an accumulator buffer, and sending messages down the pipeline for
|
||||||
* further processing, as split buffer regions, once their data has been received in its entirety.
|
* further processing, as split buffer regions, once their data has been received in its entirety.
|
||||||
|
*
|
||||||
|
* <h3>Buffers as constants</h3>
|
||||||
|
*
|
||||||
|
* Sometimes, the same bit of data will be processed or transmitted over and over again. In such cases, it can be
|
||||||
|
* tempting to allocate and fill a buffer once, and then reuse it.
|
||||||
|
* Such reuse must be done carefully, however, to avoid a number of bugs.
|
||||||
|
* The {@link BufferAllocator} has a {@link BufferAllocator#constBufferSupplier(byte[])} method that solves this, and
|
||||||
|
* prevents these bugs from occurring.
|
||||||
*/
|
*/
|
||||||
public interface Buffer extends Rc<Buffer>, BufferAccessors {
|
public interface Buffer extends Rc<Buffer>, BufferAccessors {
|
||||||
/**
|
/**
|
||||||
@ -218,11 +226,13 @@ public interface Buffer extends Rc<Buffer>, BufferAccessors {
|
|||||||
long nativeAddress();
|
long nativeAddress();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the read-only state of this buffer.
|
* Make this buffer read-only. This is irreversible.
|
||||||
|
* Unless a writable slice has previously been obtained from this buffer, there will no longer be any way to modify
|
||||||
|
* the data contained in this buffer.
|
||||||
*
|
*
|
||||||
* @return this buffer.
|
* @return this buffer.
|
||||||
*/
|
*/
|
||||||
Buffer readOnly(boolean readOnly);
|
Buffer makeReadOnly();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query if this buffer is read-only or not.
|
* Query if this buffer is read-only or not.
|
||||||
@ -308,6 +318,23 @@ public interface Buffer extends Rc<Buffer>, BufferAccessors {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write into this buffer, all the bytes from the given byte array.
|
||||||
|
* This updates the {@linkplain #writerOffset() write offset} of this buffer by the length of the array.
|
||||||
|
*
|
||||||
|
* @param source The byte array to read from.
|
||||||
|
* @return This buffer.
|
||||||
|
*/
|
||||||
|
default Buffer writeBytes(byte[] source) {
|
||||||
|
int size = source.length;
|
||||||
|
int woff = writerOffset();
|
||||||
|
writerOffset(woff + size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
setByte(woff + i, source[i]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the {@linkplain #readerOffset() read offset} and the {@linkplain #writerOffset() write offset} on this
|
* Resets the {@linkplain #readerOffset() read offset} and the {@linkplain #writerOffset() write offset} on this
|
||||||
* buffer to their initial values.
|
* buffer to their initial values.
|
||||||
|
@ -15,9 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer.api;
|
package io.netty.buffer.api;
|
||||||
|
|
||||||
import io.netty.buffer.api.internal.Statics;
|
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for {@link Buffer} allocators.
|
* Interface for {@link Buffer} allocators.
|
||||||
@ -68,6 +67,36 @@ public interface BufferAllocator extends AutoCloseable {
|
|||||||
return allocate(size).order(order);
|
return allocate(size).order(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a supplier of "constant" {@linkplain Buffer Buffers} from this allocator, that all have the given
|
||||||
|
* byte contents. The buffer has the same capacity as the byte array length, and its write offset is placed at the
|
||||||
|
* end, and its read offset is at the beginning, such that the entire buffer contents are readable.
|
||||||
|
* <p>
|
||||||
|
* The buffers produced by the supplier will have {@linkplain Buffer#isOwned() ownership}, and closing them will
|
||||||
|
* make them {@linkplain Buffer#isAccessible() inaccessible}, just like a normally allocated buffer.
|
||||||
|
* <p>
|
||||||
|
* The buffers produced are "constants", in the sense that they are {@linkplain Buffer#readOnly() read-only}.
|
||||||
|
* <p>
|
||||||
|
* It can generally be expected, but is not guaranteed, that the returned supplier is more resource efficient than
|
||||||
|
* allocating and copying memory with other available APIs. In such optimised implementations, the underlying memory
|
||||||
|
* baking the buffers will be shared among all the buffers produced by the supplier.
|
||||||
|
* <p>
|
||||||
|
* The primary use case for this API, is when you need to repeatedly produce buffers with the same contents, and
|
||||||
|
* you perhaps wish to keep a {@code static final} field with these contents. This use case has previously been
|
||||||
|
* solved by allocating a read-only buffer with the given contents, and then slicing or duplicating it on every use.
|
||||||
|
* This approach had several problems. For instance, if you forget to slice, the offsets of the buffer can change
|
||||||
|
* in unexpected ways, since the same buffer instance is shared and accessed from many places. The buffer could also
|
||||||
|
* be deallocated, making the data inaccessible. The supplier-based API solves all of these problems, by enforcing
|
||||||
|
* that each usage get their own distinct buffer instance.
|
||||||
|
*
|
||||||
|
* @param bytes The byte contents of the buffers produced by the returned supplier.
|
||||||
|
* @return A supplier of read-only buffers with the given contents.
|
||||||
|
*/
|
||||||
|
default Supplier<Buffer> constBufferSupplier(byte[] bytes) {
|
||||||
|
byte[] safeCopy = bytes.clone(); // Prevent modifying the bytes after creating the supplier.
|
||||||
|
return () -> allocate(bytes.length).writeBytes(safeCopy).makeReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close this allocator, freeing all of its internal resources. It is not specified if the allocator can still be
|
* Close this allocator, freeing all of its internal resources. It is not specified if the allocator can still be
|
||||||
* used after this method has been called on it.
|
* used after this method has been called on it.
|
||||||
@ -77,11 +106,11 @@ public interface BufferAllocator extends AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BufferAllocator heap() {
|
static BufferAllocator heap() {
|
||||||
return new ManagedBufferAllocator(MemoryManagers.getManagers().getHeapMemoryManager(), Statics.CLEANER);
|
return new ManagedBufferAllocator(MemoryManagers.getManagers().getHeapMemoryManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferAllocator direct() {
|
static BufferAllocator direct() {
|
||||||
return new ManagedBufferAllocator(MemoryManagers.getManagers().getNativeMemoryManager(), Statics.CLEANER);
|
return new ManagedBufferAllocator(MemoryManagers.getManagers().getNativeMemoryManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferAllocator pooledHeap() {
|
static BufferAllocator pooledHeap() {
|
||||||
|
@ -444,11 +444,11 @@ public final class CompositeBuffer extends RcSupport<Buffer, CompositeBuffer> im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeBuffer readOnly(boolean readOnly) {
|
public CompositeBuffer makeReadOnly() {
|
||||||
for (Buffer buf : bufs) {
|
for (Buffer buf : bufs) {
|
||||||
buf.readOnly(readOnly);
|
buf.makeReadOnly();
|
||||||
}
|
}
|
||||||
this.readOnly = readOnly;
|
readOnly = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,29 +15,36 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer.api;
|
package io.netty.buffer.api;
|
||||||
|
|
||||||
import java.lang.ref.Cleaner;
|
import io.netty.buffer.api.internal.Statics;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static io.netty.buffer.api.internal.Statics.NO_OP_DROP;
|
import static io.netty.buffer.api.internal.Statics.NO_OP_DROP;
|
||||||
|
|
||||||
class ManagedBufferAllocator implements BufferAllocator, AllocatorControl {
|
class ManagedBufferAllocator implements BufferAllocator, AllocatorControl {
|
||||||
private final MemoryManager manager;
|
private final MemoryManager manager;
|
||||||
private final Cleaner cleaner;
|
|
||||||
|
|
||||||
ManagedBufferAllocator(MemoryManager manager, Cleaner cleaner) {
|
ManagedBufferAllocator(MemoryManager manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.cleaner = cleaner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer allocate(int size) {
|
public Buffer allocate(int size) {
|
||||||
BufferAllocator.checkSize(size);
|
BufferAllocator.checkSize(size);
|
||||||
return manager.allocateShared(this, size, manager.drop(), cleaner);
|
return manager.allocateShared(this, size, manager.drop(), Statics.CLEANER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<Buffer> constBufferSupplier(byte[] bytes) {
|
||||||
|
Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER);
|
||||||
|
constantBuffer.writeBytes(bytes).makeReadOnly();
|
||||||
|
return () -> manager.allocateConstChild(constantBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object allocateUntethered(Buffer originator, int size) {
|
public Object allocateUntethered(Buffer originator, int size) {
|
||||||
BufferAllocator.checkSize(size);
|
BufferAllocator.checkSize(size);
|
||||||
var buf = manager.allocateShared(this, size, NO_OP_DROP, cleaner);
|
var buf = manager.allocateShared(this, size, NO_OP_DROP, Statics.CLEANER);
|
||||||
return manager.unwrapRecoverableMemory(buf);
|
return manager.unwrapRecoverableMemory(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,14 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer.api;
|
package io.netty.buffer.api;
|
||||||
|
|
||||||
import io.netty.buffer.api.memseg.HeapMemorySegmentManager;
|
|
||||||
import io.netty.buffer.api.memseg.NativeMemorySegmentManager;
|
|
||||||
|
|
||||||
import java.lang.ref.Cleaner;
|
import java.lang.ref.Cleaner;
|
||||||
|
|
||||||
public interface MemoryManager {
|
public interface MemoryManager {
|
||||||
boolean isNative();
|
|
||||||
Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner);
|
Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner);
|
||||||
|
Buffer allocateConstChild(Buffer readOnlyConstParent);
|
||||||
Drop<Buffer> drop();
|
Drop<Buffer> drop();
|
||||||
Object unwrapRecoverableMemory(Buffer buf);
|
Object unwrapRecoverableMemory(Buffer buf);
|
||||||
int capacityOfRecoverableMemory(Object memory);
|
int capacityOfRecoverableMemory(Object memory);
|
||||||
|
@ -22,6 +22,7 @@ import java.nio.ByteOrder;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static io.netty.buffer.api.internal.Statics.NO_OP_DROP;
|
import static io.netty.buffer.api.internal.Statics.NO_OP_DROP;
|
||||||
import static java.lang.invoke.MethodHandles.lookup;
|
import static java.lang.invoke.MethodHandles.lookup;
|
||||||
@ -46,14 +47,19 @@ class SizeClassedMemoryPool implements BufferAllocator, AllocatorControl, Drop<B
|
|||||||
Object memory = sizeClassPool.poll();
|
Object memory = sizeClassPool.poll();
|
||||||
if (memory != null) {
|
if (memory != null) {
|
||||||
return recoverMemoryIntoBuffer(memory)
|
return recoverMemoryIntoBuffer(memory)
|
||||||
.reset()
|
|
||||||
.readOnly(false)
|
|
||||||
.fill((byte) 0)
|
.fill((byte) 0)
|
||||||
.order(ByteOrder.nativeOrder());
|
.order(ByteOrder.nativeOrder());
|
||||||
}
|
}
|
||||||
return createBuf(size, getDrop());
|
return createBuf(size, getDrop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<Buffer> constBufferSupplier(byte[] bytes) {
|
||||||
|
Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER);
|
||||||
|
constantBuffer.writeBytes(bytes).makeReadOnly();
|
||||||
|
return () -> manager.allocateConstChild(constantBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
protected MemoryManager getMemoryManager() {
|
protected MemoryManager getMemoryManager() {
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,6 @@ public class ByteBufferMemoryManager implements MemoryManager {
|
|||||||
this.direct = direct;
|
this.direct = direct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNative() {
|
|
||||||
return direct;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
||||||
int capacity = Math.toIntExact(size);
|
int capacity = Math.toIntExact(size);
|
||||||
@ -47,6 +42,13 @@ public class ByteBufferMemoryManager implements MemoryManager {
|
|||||||
return new NioBuffer(buffer, buffer, allocatorControl, convert(drop));
|
return new NioBuffer(buffer, buffer, allocatorControl, convert(drop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Buffer allocateConstChild(Buffer readOnlyConstParent) {
|
||||||
|
assert readOnlyConstParent.readOnly();
|
||||||
|
NioBuffer buf = (NioBuffer) readOnlyConstParent;
|
||||||
|
return new NioBuffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Drop<Buffer> drop() {
|
public Drop<Buffer> drop() {
|
||||||
return Statics.NO_OP_DROP;
|
return Statics.NO_OP_DROP;
|
||||||
|
@ -47,6 +47,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
|
|
||||||
private int roff;
|
private int roff;
|
||||||
private int woff;
|
private int woff;
|
||||||
|
private boolean constBuffer;
|
||||||
|
|
||||||
NioBuffer(ByteBuffer base, ByteBuffer memory, AllocatorControl control, Drop<NioBuffer> drop) {
|
NioBuffer(ByteBuffer base, ByteBuffer memory, AllocatorControl control, Drop<NioBuffer> drop) {
|
||||||
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
||||||
@ -56,6 +57,22 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
this.control = control;
|
this.control = control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffers}.
|
||||||
|
*/
|
||||||
|
NioBuffer(NioBuffer parent) {
|
||||||
|
super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop()))));
|
||||||
|
control = parent.control;
|
||||||
|
base = parent.base;
|
||||||
|
rmem = parent.rmem.slice(0, parent.rmem.capacity()); // Need to slice to get independent byte orders.
|
||||||
|
assert parent.wmem == CLOSED_BUFFER;
|
||||||
|
wmem = CLOSED_BUFFER;
|
||||||
|
roff = parent.roff;
|
||||||
|
woff = parent.woff;
|
||||||
|
order(parent.order());
|
||||||
|
constBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final class MakeInaccisbleOnDrop implements Drop<NioBuffer> {
|
private static final class MakeInaccisbleOnDrop implements Drop<NioBuffer> {
|
||||||
final Drop<NioBuffer> delegate;
|
final Drop<NioBuffer> delegate;
|
||||||
|
|
||||||
@ -158,12 +175,8 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer readOnly(boolean readOnly) {
|
public Buffer makeReadOnly() {
|
||||||
if (readOnly && wmem == rmem) {
|
|
||||||
wmem = CLOSED_BUFFER;
|
wmem = CLOSED_BUFFER;
|
||||||
} else if (!readOnly && wmem != rmem) {
|
|
||||||
wmem = rmem;
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,10 +196,13 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
ByteBuffer slice = rmem.slice(offset, length);
|
ByteBuffer slice = rmem.slice(offset, length);
|
||||||
ArcDrop<NioBuffer> drop = (ArcDrop<NioBuffer>) unsafeGetDrop();
|
ArcDrop<NioBuffer> drop = (ArcDrop<NioBuffer>) unsafeGetDrop();
|
||||||
drop.increment();
|
drop.increment();
|
||||||
return new NioBuffer(base, slice, control, drop)
|
Buffer sliceBuffer = new NioBuffer(base, slice, control, drop)
|
||||||
.writerOffset(length)
|
.writerOffset(length)
|
||||||
.order(order())
|
.order(order());
|
||||||
.readOnly(readOnly());
|
if (readOnly()) {
|
||||||
|
sliceBuffer = sliceBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
return sliceBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -398,21 +414,28 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
// Copy contents.
|
// Copy contents.
|
||||||
copyInto(0, buffer, 0, capacity());
|
copyInto(0, buffer, 0, capacity());
|
||||||
|
|
||||||
// Release old memory:
|
// Release the old memory and install the new:
|
||||||
|
Drop<NioBuffer> drop = disconnectDrop();
|
||||||
|
attachNewBuffer(buffer, drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drop<NioBuffer> disconnectDrop() {
|
||||||
var drop = (Drop<NioBuffer>) unsafeGetDrop();
|
var drop = (Drop<NioBuffer>) unsafeGetDrop();
|
||||||
int roff = this.roff;
|
int roff = this.roff;
|
||||||
int woff = this.woff;
|
int woff = this.woff;
|
||||||
drop.drop(this);
|
drop.drop(this);
|
||||||
while (drop instanceof ArcDrop) {
|
drop = ArcDrop.unwrapAllArcs(drop);
|
||||||
drop = ((ArcDrop<NioBuffer>) drop).unwrap();
|
|
||||||
}
|
|
||||||
unsafeSetDrop(new ArcDrop<>(drop));
|
unsafeSetDrop(new ArcDrop<>(drop));
|
||||||
this.roff = roff;
|
this.roff = roff;
|
||||||
this.woff = woff;
|
this.woff = woff;
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachNewBuffer(ByteBuffer buffer, Drop<NioBuffer> drop) {
|
||||||
base = buffer;
|
base = buffer;
|
||||||
rmem = buffer;
|
rmem = buffer;
|
||||||
wmem = buffer;
|
wmem = buffer;
|
||||||
|
constBuffer = false;
|
||||||
drop.attach(this);
|
drop.attach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +460,12 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
splitBuffer.roff = Math.min(roff, splitOffset);
|
splitBuffer.roff = Math.min(roff, splitOffset);
|
||||||
splitBuffer.order(order());
|
splitBuffer.order(order());
|
||||||
boolean readOnly = readOnly();
|
boolean readOnly = readOnly();
|
||||||
splitBuffer.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
splitBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
// Note that split, unlike slice, does not deconstify, because data changes in either buffer are not visible
|
||||||
|
// in the other. The split buffers can later deconstify independently if needed.
|
||||||
|
splitBuffer.constBuffer = constBuffer;
|
||||||
rmem = rmem.slice(splitOffset, rmem.capacity() - splitOffset);
|
rmem = rmem.slice(splitOffset, rmem.capacity() - splitOffset);
|
||||||
if (!readOnly) {
|
if (!readOnly) {
|
||||||
wmem = rmem;
|
wmem = rmem;
|
||||||
@ -554,6 +582,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
return processor.process(initialIndex, this)? 1 : -1;
|
return processor.process(initialIndex, this)? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Primitive accessors implementation.">
|
||||||
@Override
|
@Override
|
||||||
public byte readByte() {
|
public byte readByte() {
|
||||||
checkRead(roff, Byte.BYTES);
|
checkRead(roff, Byte.BYTES);
|
||||||
@ -1053,6 +1082,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
throw bufferIsReadOnly();
|
throw bufferIsReadOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// </editor-fold>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Owned<NioBuffer> prepareSend() {
|
protected Owned<NioBuffer> prepareSend() {
|
||||||
@ -1060,6 +1090,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
var roff = this.roff;
|
var roff = this.roff;
|
||||||
var woff = this.woff;
|
var woff = this.woff;
|
||||||
var readOnly = readOnly();
|
var readOnly = readOnly();
|
||||||
|
var isConst = constBuffer;
|
||||||
ByteBuffer base = this.base;
|
ByteBuffer base = this.base;
|
||||||
ByteBuffer rmem = this.rmem;
|
ByteBuffer rmem = this.rmem;
|
||||||
makeInaccessible();
|
makeInaccessible();
|
||||||
@ -1070,7 +1101,10 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
|||||||
copy.order(order);
|
copy.order(order);
|
||||||
copy.roff = roff;
|
copy.roff = roff;
|
||||||
copy.woff = woff;
|
copy.woff = woff;
|
||||||
copy.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
copy.makeReadOnly();
|
||||||
|
}
|
||||||
|
copy.constBuffer = isConst;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,13 @@ public final class ArcDrop<T> implements Drop<T> {
|
|||||||
return new ArcDrop<X>(drop);
|
return new ArcDrop<X>(drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <X> Drop<X> unwrapAllArcs(Drop<X> drop) {
|
||||||
|
while (drop instanceof ArcDrop) {
|
||||||
|
drop = ((ArcDrop<X>) drop).unwrap();
|
||||||
|
}
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
|
||||||
public static <X> Drop<X> acquire(Drop<X> drop) {
|
public static <X> Drop<X> acquire(Drop<X> drop) {
|
||||||
if (drop.getClass() == ArcDrop.class) {
|
if (drop.getClass() == ArcDrop.class) {
|
||||||
((ArcDrop<X>) drop).increment();
|
((ArcDrop<X>) drop).increment();
|
||||||
|
@ -27,15 +27,19 @@ import java.lang.ref.Cleaner;
|
|||||||
import static io.netty.buffer.api.internal.Statics.convert;
|
import static io.netty.buffer.api.internal.Statics.convert;
|
||||||
|
|
||||||
public abstract class AbstractMemorySegmentManager implements MemoryManager {
|
public abstract class AbstractMemorySegmentManager implements MemoryManager {
|
||||||
@Override
|
|
||||||
public abstract boolean isNative();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
||||||
var segment = createSegment(size, cleaner);
|
var segment = createSegment(size, cleaner);
|
||||||
return new MemSegBuffer(segment, segment, convert(drop), allocatorControl);
|
return new MemSegBuffer(segment, segment, convert(drop), allocatorControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Buffer allocateConstChild(Buffer readOnlyConstParent) {
|
||||||
|
assert readOnlyConstParent.readOnly();
|
||||||
|
MemSegBuffer buf = (MemSegBuffer) readOnlyConstParent;
|
||||||
|
return new MemSegBuffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract MemorySegment createSegment(long size, Cleaner cleaner);
|
protected abstract MemorySegment createSegment(long size, Cleaner cleaner);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,11 +20,6 @@ import jdk.incubator.foreign.MemorySegment;
|
|||||||
import java.lang.ref.Cleaner;
|
import java.lang.ref.Cleaner;
|
||||||
|
|
||||||
public class HeapMemorySegmentManager extends AbstractMemorySegmentManager {
|
public class HeapMemorySegmentManager extends AbstractMemorySegmentManager {
|
||||||
@Override
|
|
||||||
public boolean isNative() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
||||||
return MemorySegment.ofArray(new byte[Math.toIntExact(size)]);
|
return MemorySegment.ofArray(new byte[Math.toIntExact(size)]);
|
||||||
|
@ -84,23 +84,40 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AllocatorControl alloc;
|
private final AllocatorControl control;
|
||||||
private MemorySegment base;
|
private MemorySegment base;
|
||||||
private MemorySegment seg;
|
private MemorySegment seg;
|
||||||
private MemorySegment wseg;
|
private MemorySegment wseg;
|
||||||
private ByteOrder order;
|
private ByteOrder order;
|
||||||
private int roff;
|
private int roff;
|
||||||
private int woff;
|
private int woff;
|
||||||
|
private boolean constBuffer;
|
||||||
|
|
||||||
MemSegBuffer(MemorySegment base, MemorySegment view, Drop<MemSegBuffer> drop, AllocatorControl alloc) {
|
MemSegBuffer(MemorySegment base, MemorySegment view, Drop<MemSegBuffer> drop, AllocatorControl control) {
|
||||||
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
||||||
this.alloc = alloc;
|
this.control = control;
|
||||||
this.base = base;
|
this.base = base;
|
||||||
seg = view;
|
seg = view;
|
||||||
wseg = view;
|
wseg = view;
|
||||||
order = ByteOrder.nativeOrder();
|
order = ByteOrder.nativeOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffers}.
|
||||||
|
*/
|
||||||
|
MemSegBuffer(MemSegBuffer parent) {
|
||||||
|
super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop()))));
|
||||||
|
control = parent.control;
|
||||||
|
base = parent.base;
|
||||||
|
seg = parent.seg;
|
||||||
|
wseg = parent.wseg;
|
||||||
|
order = parent.order;
|
||||||
|
roff = parent.roff;
|
||||||
|
woff = parent.woff;
|
||||||
|
adaptor = null;
|
||||||
|
constBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
private static final class MakeInaccisbleOnDrop implements Drop<MemSegBuffer> {
|
private static final class MakeInaccisbleOnDrop implements Drop<MemSegBuffer> {
|
||||||
final Drop<MemSegBuffer> delegate;
|
final Drop<MemSegBuffer> delegate;
|
||||||
|
|
||||||
@ -281,8 +298,8 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer readOnly(boolean readOnly) {
|
public Buffer makeReadOnly() {
|
||||||
wseg = readOnly? CLOSED_SEGMENT : seg;
|
wseg = CLOSED_SEGMENT;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,10 +318,13 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
}
|
}
|
||||||
var slice = seg.asSlice(offset, length);
|
var slice = seg.asSlice(offset, length);
|
||||||
Drop<MemSegBuffer> drop = ArcDrop.acquire(unsafeGetDrop());
|
Drop<MemSegBuffer> drop = ArcDrop.acquire(unsafeGetDrop());
|
||||||
return new MemSegBuffer(base, slice, drop, alloc)
|
Buffer sliceBuffer = new MemSegBuffer(base, slice, drop, control)
|
||||||
.writerOffset(length)
|
.writerOffset(length)
|
||||||
.order(order())
|
.order(order());
|
||||||
.readOnly(readOnly());
|
if (readOnly()) {
|
||||||
|
sliceBuffer = sliceBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
return sliceBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -518,32 +538,39 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
// Allocate a bigger buffer.
|
// Allocate a bigger buffer.
|
||||||
long newSize = capacity() + (long) Math.max(size - writableBytes(), minimumGrowth);
|
long newSize = capacity() + (long) Math.max(size - writableBytes(), minimumGrowth);
|
||||||
BufferAllocator.checkSize(newSize);
|
BufferAllocator.checkSize(newSize);
|
||||||
MemorySegment newSegment = (MemorySegment) alloc.allocateUntethered(this, (int) newSize);
|
MemorySegment newSegment = (MemorySegment) control.allocateUntethered(this, (int) newSize);
|
||||||
|
|
||||||
// Copy contents.
|
// Copy contents.
|
||||||
newSegment.copyFrom(seg);
|
newSegment.copyFrom(seg);
|
||||||
|
|
||||||
// Release old memory segment:
|
// Release the old memory segment and install the new one:
|
||||||
|
Drop<MemSegBuffer> drop = disconnectDrop();
|
||||||
|
attachNewMemorySegment(newSegment, drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drop<MemSegBuffer> disconnectDrop() {
|
||||||
var drop = unsafeGetDrop();
|
var drop = unsafeGetDrop();
|
||||||
if (drop instanceof ArcDrop) {
|
if (drop instanceof ArcDrop) {
|
||||||
// Disconnect from the current arc drop, since we'll get our own fresh memory segment.
|
// Disconnect from the current arc drop, since we'll get our own fresh memory segment.
|
||||||
int roff = this.roff;
|
int roff = this.roff;
|
||||||
int woff = this.woff;
|
int woff = this.woff;
|
||||||
drop.drop(this);
|
drop.drop(this);
|
||||||
while (drop instanceof ArcDrop) {
|
drop = ArcDrop.unwrapAllArcs(drop);
|
||||||
drop = ((ArcDrop<MemSegBuffer>) drop).unwrap();
|
|
||||||
}
|
|
||||||
unsafeSetDrop(new ArcDrop<>(drop));
|
unsafeSetDrop(new ArcDrop<>(drop));
|
||||||
this.roff = roff;
|
this.roff = roff;
|
||||||
this.woff = woff;
|
this.woff = woff;
|
||||||
} else {
|
} else {
|
||||||
// TODO would we ever get here?
|
// TODO would we ever get here?
|
||||||
alloc.recoverMemory(recoverableMemory());
|
control.recoverMemory(recoverableMemory());
|
||||||
|
}
|
||||||
|
return drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void attachNewMemorySegment(MemorySegment newSegment, Drop<MemSegBuffer> drop) {
|
||||||
base = newSegment;
|
base = newSegment;
|
||||||
seg = newSegment;
|
seg = newSegment;
|
||||||
wseg = newSegment;
|
wseg = newSegment;
|
||||||
|
constBuffer = false;
|
||||||
drop.attach(this);
|
drop.attach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,12 +589,17 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
var drop = (ArcDrop<MemSegBuffer>) unsafeGetDrop();
|
var drop = (ArcDrop<MemSegBuffer>) unsafeGetDrop();
|
||||||
unsafeSetDrop(new ArcDrop<>(drop));
|
unsafeSetDrop(new ArcDrop<>(drop));
|
||||||
var splitSegment = seg.asSlice(0, splitOffset);
|
var splitSegment = seg.asSlice(0, splitOffset);
|
||||||
var splitBuffer = new MemSegBuffer(base, splitSegment, new ArcDrop<>(drop.increment()), alloc);
|
var splitBuffer = new MemSegBuffer(base, splitSegment, new ArcDrop<>(drop.increment()), control);
|
||||||
splitBuffer.woff = Math.min(woff, splitOffset);
|
splitBuffer.woff = Math.min(woff, splitOffset);
|
||||||
splitBuffer.roff = Math.min(roff, splitOffset);
|
splitBuffer.roff = Math.min(roff, splitOffset);
|
||||||
splitBuffer.order(order);
|
splitBuffer.order(order);
|
||||||
boolean readOnly = readOnly();
|
boolean readOnly = readOnly();
|
||||||
splitBuffer.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
splitBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
// Note that split, unlike slice, does not deconstify, because data changes in either buffer are not visible
|
||||||
|
// in the other. The split buffers can later deconstify independently if needed.
|
||||||
|
splitBuffer.constBuffer = constBuffer;
|
||||||
seg = seg.asSlice(splitOffset, seg.byteSize() - splitOffset);
|
seg = seg.asSlice(splitOffset, seg.byteSize() - splitOffset);
|
||||||
if (!readOnly) {
|
if (!readOnly) {
|
||||||
wseg = seg;
|
wseg = seg;
|
||||||
@ -1095,17 +1127,21 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
|||||||
var roff = this.roff;
|
var roff = this.roff;
|
||||||
var woff = this.woff;
|
var woff = this.woff;
|
||||||
var readOnly = readOnly();
|
var readOnly = readOnly();
|
||||||
|
var isConst = constBuffer;
|
||||||
MemorySegment transferSegment = seg;
|
MemorySegment transferSegment = seg;
|
||||||
MemorySegment base = this.base;
|
MemorySegment base = this.base;
|
||||||
makeInaccessible();
|
makeInaccessible();
|
||||||
return new Owned<MemSegBuffer>() {
|
return new Owned<MemSegBuffer>() {
|
||||||
@Override
|
@Override
|
||||||
public MemSegBuffer transferOwnership(Drop<MemSegBuffer> drop) {
|
public MemSegBuffer transferOwnership(Drop<MemSegBuffer> drop) {
|
||||||
MemSegBuffer copy = new MemSegBuffer(base, transferSegment, drop, alloc);
|
MemSegBuffer copy = new MemSegBuffer(base, transferSegment, drop, control);
|
||||||
copy.order = order;
|
copy.order = order;
|
||||||
copy.roff = roff;
|
copy.roff = roff;
|
||||||
copy.woff = woff;
|
copy.woff = woff;
|
||||||
copy.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
copy.makeReadOnly();
|
||||||
|
}
|
||||||
|
copy.constBuffer = isConst;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -52,11 +52,6 @@ public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNative() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
protected MemorySegment createSegment(long size, Cleaner cleaner) {
|
||||||
final ResourceScope scope = cleaner == null ? newSharedScope() : newSharedScope(cleaner);
|
final ResourceScope scope = cleaner == null ? newSharedScope() : newSharedScope(cleaner);
|
||||||
|
@ -38,7 +38,7 @@ import static io.netty.buffer.api.internal.Statics.bufferIsClosed;
|
|||||||
import static io.netty.buffer.api.internal.Statics.bufferIsReadOnly;
|
import static io.netty.buffer.api.internal.Statics.bufferIsReadOnly;
|
||||||
import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
|
import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
|
||||||
|
|
||||||
public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buffer, ReadableComponent,
|
class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buffer, ReadableComponent,
|
||||||
WritableComponent {
|
WritableComponent {
|
||||||
private static final int CLOSED_SIZE = -1;
|
private static final int CLOSED_SIZE = -1;
|
||||||
private static final boolean ACCESS_UNALIGNED = PlatformDependent.isUnaligned();
|
private static final boolean ACCESS_UNALIGNED = PlatformDependent.isUnaligned();
|
||||||
@ -54,8 +54,9 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
private boolean readOnly;
|
private boolean readOnly;
|
||||||
private int roff;
|
private int roff;
|
||||||
private int woff;
|
private int woff;
|
||||||
|
private boolean constBuffer;
|
||||||
|
|
||||||
public UnsafeBuffer(UnsafeMemory memory, long offset, int size, AllocatorControl allocatorControl,
|
UnsafeBuffer(UnsafeMemory memory, long offset, int size, AllocatorControl allocatorControl,
|
||||||
Drop<UnsafeBuffer> drop) {
|
Drop<UnsafeBuffer> drop) {
|
||||||
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop)));
|
||||||
this.memory = memory;
|
this.memory = memory;
|
||||||
@ -68,6 +69,23 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
order = ByteOrder.nativeOrder();
|
order = ByteOrder.nativeOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnsafeBuffer(UnsafeBuffer parent) {
|
||||||
|
super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop()))));
|
||||||
|
control = parent.control;
|
||||||
|
memory = parent.memory;
|
||||||
|
base = parent.base;
|
||||||
|
baseOffset = parent.baseOffset;
|
||||||
|
address = parent.address;
|
||||||
|
rsize = parent.rsize;
|
||||||
|
wsize = parent.wsize;
|
||||||
|
order = parent.order;
|
||||||
|
flipBytes = parent.flipBytes;
|
||||||
|
readOnly = parent.readOnly;
|
||||||
|
roff = parent.roff;
|
||||||
|
woff = parent.woff;
|
||||||
|
constBuffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Buffer[roff:" + roff + ", woff:" + woff + ", cap:" + rsize + ']';
|
return "Buffer[roff:" + roff + ", woff:" + woff + ", cap:" + rsize + ']';
|
||||||
@ -134,9 +152,9 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer readOnly(boolean readOnly) {
|
public Buffer makeReadOnly() {
|
||||||
this.readOnly = readOnly;
|
readOnly = true;
|
||||||
wsize = readOnly? CLOSED_SIZE : rsize;
|
wsize = CLOSED_SIZE;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,10 +171,13 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
checkGet(offset, length);
|
checkGet(offset, length);
|
||||||
ArcDrop<UnsafeBuffer> drop = (ArcDrop<UnsafeBuffer>) unsafeGetDrop();
|
ArcDrop<UnsafeBuffer> drop = (ArcDrop<UnsafeBuffer>) unsafeGetDrop();
|
||||||
drop.increment();
|
drop.increment();
|
||||||
return new UnsafeBuffer(memory, baseOffset + offset, length, control, drop)
|
Buffer sliceBuffer = new UnsafeBuffer(memory, baseOffset + offset, length, control, drop)
|
||||||
.writerOffset(length)
|
.writerOffset(length)
|
||||||
.order(order)
|
.order(order);
|
||||||
.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
sliceBuffer = sliceBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
return sliceBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -436,24 +457,31 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
Reference.reachabilityFence(memory);
|
Reference.reachabilityFence(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release old memory:
|
// Release the old memory, and install the new memory:
|
||||||
|
Drop<UnsafeBuffer> drop = disconnectDrop();
|
||||||
|
attachNewMemory(memory, drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drop<UnsafeBuffer> disconnectDrop() {
|
||||||
var drop = (Drop<UnsafeBuffer>) unsafeGetDrop();
|
var drop = (Drop<UnsafeBuffer>) unsafeGetDrop();
|
||||||
int roff = this.roff;
|
int roff = this.roff;
|
||||||
int woff = this.woff;
|
int woff = this.woff;
|
||||||
drop.drop(this);
|
drop.drop(this);
|
||||||
while (drop instanceof ArcDrop) {
|
drop = ArcDrop.unwrapAllArcs(drop);
|
||||||
drop = ((ArcDrop<UnsafeBuffer>) drop).unwrap();
|
|
||||||
}
|
|
||||||
unsafeSetDrop(new ArcDrop<>(drop));
|
unsafeSetDrop(new ArcDrop<>(drop));
|
||||||
this.roff = roff;
|
this.roff = roff;
|
||||||
this.woff = woff;
|
this.woff = woff;
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachNewMemory(UnsafeMemory memory, Drop<UnsafeBuffer> drop) {
|
||||||
this.memory = memory;
|
this.memory = memory;
|
||||||
base = memory.base;
|
base = memory.base;
|
||||||
baseOffset = 0;
|
baseOffset = 0;
|
||||||
address = memory.address;
|
address = memory.address;
|
||||||
rsize = memory.size;
|
rsize = memory.size;
|
||||||
wsize = memory.size;
|
wsize = memory.size;
|
||||||
|
constBuffer = false;
|
||||||
drop.attach(this);
|
drop.attach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +505,12 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
splitBuffer.roff = Math.min(roff, splitOffset);
|
splitBuffer.roff = Math.min(roff, splitOffset);
|
||||||
splitBuffer.order(order());
|
splitBuffer.order(order());
|
||||||
boolean readOnly = readOnly();
|
boolean readOnly = readOnly();
|
||||||
splitBuffer.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
splitBuffer.makeReadOnly();
|
||||||
|
}
|
||||||
|
// Note that split, unlike slice, does not deconstify, because data changes in either buffer are not visible
|
||||||
|
// in the other. The split buffers can later deconstify independently if needed.
|
||||||
|
splitBuffer.constBuffer = constBuffer;
|
||||||
rsize -= splitOffset;
|
rsize -= splitOffset;
|
||||||
baseOffset += splitOffset;
|
baseOffset += splitOffset;
|
||||||
address += splitOffset;
|
address += splitOffset;
|
||||||
@ -628,6 +661,7 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
return processor.process(initialIndex, this)? 1 : -1;
|
return processor.process(initialIndex, this)? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Primitive accessors implementation.">
|
||||||
@Override
|
@Override
|
||||||
public byte readByte() {
|
public byte readByte() {
|
||||||
checkRead(roff, Byte.BYTES);
|
checkRead(roff, Byte.BYTES);
|
||||||
@ -1189,6 +1223,7 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
// </editor-fold>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Owned<UnsafeBuffer> prepareSend() {
|
protected Owned<UnsafeBuffer> prepareSend() {
|
||||||
@ -1196,6 +1231,7 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
var roff = this.roff;
|
var roff = this.roff;
|
||||||
var woff = this.woff;
|
var woff = this.woff;
|
||||||
var readOnly = readOnly();
|
var readOnly = readOnly();
|
||||||
|
var isConst = constBuffer;
|
||||||
UnsafeMemory memory = this.memory;
|
UnsafeMemory memory = this.memory;
|
||||||
AllocatorControl control = this.control;
|
AllocatorControl control = this.control;
|
||||||
long baseOffset = this.baseOffset;
|
long baseOffset = this.baseOffset;
|
||||||
@ -1208,7 +1244,10 @@ public class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buf
|
|||||||
copy.order(order);
|
copy.order(order);
|
||||||
copy.roff = roff;
|
copy.roff = roff;
|
||||||
copy.woff = woff;
|
copy.woff = woff;
|
||||||
copy.readOnly(readOnly);
|
if (readOnly) {
|
||||||
|
copy.makeReadOnly();
|
||||||
|
}
|
||||||
|
copy.constBuffer = isConst;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -33,11 +33,6 @@ public class UnsafeMemoryManager implements MemoryManager {
|
|||||||
this.offheap = offheap;
|
this.offheap = offheap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNative() {
|
|
||||||
return offheap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
||||||
final Object base;
|
final Object base;
|
||||||
@ -61,6 +56,13 @@ public class UnsafeMemoryManager implements MemoryManager {
|
|||||||
return new UnsafeBuffer(memory, 0, size32, allocatorControl, convert(drop));
|
return new UnsafeBuffer(memory, 0, size32, allocatorControl, convert(drop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Buffer allocateConstChild(Buffer readOnlyConstParent) {
|
||||||
|
assert readOnlyConstParent.readOnly();
|
||||||
|
UnsafeBuffer buf = (UnsafeBuffer) readOnlyConstParent;
|
||||||
|
return new UnsafeBuffer(buf);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Drop<Buffer> drop() {
|
public Drop<Buffer> drop() {
|
||||||
// We cannot reliably drop unsafe memory. We have to rely on the cleaner to do that.
|
// We cannot reliably drop unsafe memory. We have to rely on the cleaner to do that.
|
||||||
|
@ -303,57 +303,16 @@ public class BufferBulkAccessTest extends BufferTestSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Memoize<Fixture[]> OTHER_FIXTURES = new Memoize<Fixture[]>(
|
|
||||||
() -> Arrays.stream(allocators()).filter(filterOfTheDay(10)).toArray(Fixture[]::new));
|
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("allocators")
|
@MethodSource("allocators")
|
||||||
public void writeBytesMustTransferDataAndUpdateOffsets(Fixture fixture) {
|
public void writeBytesMustWriteAllBytesFromByteArray(Fixture fixture) {
|
||||||
try (BufferAllocator alloc1 = fixture.createAllocator()) {
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
// Only test 10% of available combinations. Otherwise, this takes too long.
|
Buffer buffer = allocator.allocate(8)) {
|
||||||
Fixture[] allocators = OTHER_FIXTURES.get();
|
buffer.writeByte((byte) 1);
|
||||||
Arrays.stream(allocators).parallel().forEach(otherFixture -> {
|
buffer.writeBytes(new byte[] {2, 3, 4, 5, 6, 7});
|
||||||
try (BufferAllocator alloc2 = otherFixture.createAllocator();
|
assertThat(buffer.writerOffset()).isEqualTo(7);
|
||||||
Buffer target = alloc1.allocate(37);
|
assertThat(buffer.readerOffset()).isZero();
|
||||||
Buffer source = alloc2.allocate(35)) {
|
assertThat(toByteArray(buffer)).containsExactly(1, 2, 3, 4, 5, 6, 7, 0);
|
||||||
// BE to BE
|
|
||||||
target.order(BIG_ENDIAN);
|
|
||||||
source.order(BIG_ENDIAN);
|
|
||||||
verifyWriteBytes(target, source);
|
|
||||||
|
|
||||||
// LE to BE
|
|
||||||
target.fill((byte) 0).reset().order(BIG_ENDIAN);
|
|
||||||
source.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
|
||||||
verifyWriteBytes(target, source);
|
|
||||||
|
|
||||||
// BE to LE
|
|
||||||
target.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
|
||||||
source.fill((byte) 0).reset().order(BIG_ENDIAN);
|
|
||||||
verifyWriteBytes(target, source);
|
|
||||||
|
|
||||||
// LE to LE
|
|
||||||
target.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
|
||||||
source.fill((byte) 0).reset().order(BIG_ENDIAN);
|
|
||||||
verifyWriteBytes(target, source);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.addSuppressed(new RuntimeException("other fixture was: " + otherFixture));
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void verifyWriteBytes(Buffer target, Buffer source) {
|
|
||||||
for (int i = 0; i < 35; i++) {
|
|
||||||
source.writeByte((byte) (i + 1));
|
|
||||||
}
|
|
||||||
target.writeBytes(source);
|
|
||||||
assertThat(target.readerOffset()).isZero();
|
|
||||||
assertThat(target.writerOffset()).isEqualTo(35);
|
|
||||||
assertThat(source.readerOffset()).isEqualTo(35);
|
|
||||||
assertThat(source.writerOffset()).isEqualTo(35);
|
|
||||||
try (Buffer readableSlice = target.slice()) {
|
|
||||||
assertEquals(source, readableSlice);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferByteOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
byte value = 0x01;
|
||||||
|
buf.writeByte(value);
|
||||||
|
assertEquals(value, buf.getByte(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
byte value = 0x01;
|
||||||
|
buf.writeByte(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x10, buf.getByte(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
byte value = 0x01;
|
||||||
|
buf.writeByte(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
byte value = 0x01;
|
||||||
|
buf.writeByte(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01;
|
||||||
|
buf.writeUnsignedByte(value);
|
||||||
|
assertEquals(value, buf.getUnsignedByte(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x01;
|
||||||
|
buf.writeUnsignedByte(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x10, buf.getUnsignedByte(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01;
|
||||||
|
buf.writeUnsignedByte(value);
|
||||||
|
buf.getUnsignedByte(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01;
|
||||||
|
buf.writeUnsignedByte(value);
|
||||||
|
buf.makeReadOnly().getUnsignedByte(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getUnsignedByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getUnsignedByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfByteMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
byte value = 0x01;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setByte(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfByteMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
byte value = 0x01;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setByte(8, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfByteMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
byte value = 0x01;
|
||||||
|
buf.setByte(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedByteMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x01;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedByte(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedByteMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x01;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedByte(8, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedByteMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x01;
|
||||||
|
buf.setUnsignedByte(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferCharOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getChar(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
char value = 0x0102;
|
||||||
|
buf.writeChar(value);
|
||||||
|
assertEquals(value, buf.getChar(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
char value = 0x0102;
|
||||||
|
buf.writeChar(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x1002, buf.getChar(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
char value = 0x0102;
|
||||||
|
buf.writeChar(value);
|
||||||
|
buf.getChar(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getChar(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
char value = 0x0102;
|
||||||
|
buf.writeChar(value);
|
||||||
|
buf.makeReadOnly().getChar(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getChar(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getChar(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getChar(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfCharMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
char value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setChar(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfCharMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
char value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setChar(7, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfCharMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
char value = 0x0102;
|
||||||
|
buf.setChar(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -103,8 +103,8 @@ public class BufferComponentIterationTest extends BufferTestSupport {
|
|||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer bufBERW = allocator.allocate(8).order(BIG_ENDIAN).writeLong(value);
|
Buffer bufBERW = allocator.allocate(8).order(BIG_ENDIAN).writeLong(value);
|
||||||
Buffer bufLERW = allocator.allocate(8).order(LITTLE_ENDIAN).writeLong(value);
|
Buffer bufLERW = allocator.allocate(8).order(LITTLE_ENDIAN).writeLong(value);
|
||||||
Buffer bufBERO = allocator.allocate(8).order(BIG_ENDIAN).writeLong(value).readOnly(true);
|
Buffer bufBERO = allocator.allocate(8).order(BIG_ENDIAN).writeLong(value).makeReadOnly();
|
||||||
Buffer bufLERO = allocator.allocate(8).order(LITTLE_ENDIAN).writeLong(value).readOnly(true)) {
|
Buffer bufLERO = allocator.allocate(8).order(LITTLE_ENDIAN).writeLong(value).makeReadOnly()) {
|
||||||
verifyForEachReadableSingleComponent(fixture, bufBERW);
|
verifyForEachReadableSingleComponent(fixture, bufBERW);
|
||||||
verifyForEachReadableSingleComponent(fixture, bufLERW);
|
verifyForEachReadableSingleComponent(fixture, bufLERW);
|
||||||
verifyForEachReadableSingleComponent(fixture, bufBERO);
|
verifyForEachReadableSingleComponent(fixture, bufBERO);
|
||||||
@ -361,7 +361,7 @@ public class BufferComponentIterationTest extends BufferTestSupport {
|
|||||||
@MethodSource("allocators")
|
@MethodSource("allocators")
|
||||||
public void forEachWritableOnReadOnlyBufferMustThrow(Fixture fixture) {
|
public void forEachWritableOnReadOnlyBufferMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8).readOnly(true)) {
|
Buffer buf = allocator.allocate(8).makeReadOnly()) {
|
||||||
assertThrows(IllegalStateException.class, () -> buf.forEachWritable(0, (index, component) -> true));
|
assertThrows(IllegalStateException.class, () -> buf.forEachWritable(0, (index, component) -> true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ public class BufferCompositionTest extends BufferTestSupport {
|
|||||||
public void emptyCompositeBufferMustAllowExtendingWithReadOnlyBuffer() {
|
public void emptyCompositeBufferMustAllowExtendingWithReadOnlyBuffer() {
|
||||||
try (BufferAllocator allocator = BufferAllocator.heap()) {
|
try (BufferAllocator allocator = BufferAllocator.heap()) {
|
||||||
try (CompositeBuffer composite = CompositeBuffer.compose(allocator)) {
|
try (CompositeBuffer composite = CompositeBuffer.compose(allocator)) {
|
||||||
try (Buffer b = allocator.allocate(8).readOnly(true)) {
|
try (Buffer b = allocator.allocate(8).makeReadOnly()) {
|
||||||
composite.extendWith(b);
|
composite.extendWith(b);
|
||||||
assertTrue(composite.readOnly());
|
assertTrue(composite.readOnly());
|
||||||
}
|
}
|
||||||
@ -425,8 +425,8 @@ public class BufferCompositionTest extends BufferTestSupport {
|
|||||||
@Test
|
@Test
|
||||||
public void composingReadOnlyBuffersMustCreateReadOnlyCompositeBuffer() {
|
public void composingReadOnlyBuffersMustCreateReadOnlyCompositeBuffer() {
|
||||||
try (BufferAllocator allocator = BufferAllocator.heap();
|
try (BufferAllocator allocator = BufferAllocator.heap();
|
||||||
Buffer a = allocator.allocate(4).readOnly(true);
|
Buffer a = allocator.allocate(4).makeReadOnly();
|
||||||
Buffer b = allocator.allocate(4).readOnly(true);
|
Buffer b = allocator.allocate(4).makeReadOnly();
|
||||||
Buffer composite = CompositeBuffer.compose(allocator, a, b)) {
|
Buffer composite = CompositeBuffer.compose(allocator, a, b)) {
|
||||||
assertTrue(composite.readOnly());
|
assertTrue(composite.readOnly());
|
||||||
verifyWriteInaccessible(composite);
|
verifyWriteInaccessible(composite);
|
||||||
@ -436,7 +436,7 @@ public class BufferCompositionTest extends BufferTestSupport {
|
|||||||
@Test
|
@Test
|
||||||
public void composingReadOnlyAndWritableBuffersMustThrow() {
|
public void composingReadOnlyAndWritableBuffersMustThrow() {
|
||||||
try (BufferAllocator allocator = BufferAllocator.heap();
|
try (BufferAllocator allocator = BufferAllocator.heap();
|
||||||
Buffer a = allocator.allocate(8).readOnly(true);
|
Buffer a = allocator.allocate(8).makeReadOnly();
|
||||||
Buffer b = allocator.allocate(8)) {
|
Buffer b = allocator.allocate(8)) {
|
||||||
assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b));
|
assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b));
|
||||||
assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, b, a));
|
assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, b, a));
|
||||||
@ -452,7 +452,7 @@ public class BufferCompositionTest extends BufferTestSupport {
|
|||||||
try (Buffer a = allocator.allocate(8)) {
|
try (Buffer a = allocator.allocate(8)) {
|
||||||
composite = CompositeBuffer.compose(allocator, a);
|
composite = CompositeBuffer.compose(allocator, a);
|
||||||
}
|
}
|
||||||
try (composite; Buffer b = allocator.allocate(8).readOnly(true)) {
|
try (composite; Buffer b = allocator.allocate(8).makeReadOnly()) {
|
||||||
assertThrows(IllegalArgumentException.class, () -> composite.extendWith(b));
|
assertThrows(IllegalArgumentException.class, () -> composite.extendWith(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,7 +462,7 @@ public class BufferCompositionTest extends BufferTestSupport {
|
|||||||
public void compositeReadOnlyBufferCannotBeExtendedWithWritableBuffer() {
|
public void compositeReadOnlyBufferCannotBeExtendedWithWritableBuffer() {
|
||||||
try (BufferAllocator allocator = BufferAllocator.heap()) {
|
try (BufferAllocator allocator = BufferAllocator.heap()) {
|
||||||
CompositeBuffer composite;
|
CompositeBuffer composite;
|
||||||
try (Buffer a = allocator.allocate(8).readOnly(true)) {
|
try (Buffer a = allocator.allocate(8).makeReadOnly()) {
|
||||||
composite = CompositeBuffer.compose(allocator, a);
|
composite = CompositeBuffer.compose(allocator, a);
|
||||||
}
|
}
|
||||||
try (composite; Buffer b = allocator.allocate(8)) {
|
try (composite; Buffer b = allocator.allocate(8)) {
|
||||||
|
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferDoubleOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getDouble(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
buf.writeDouble(value);
|
||||||
|
assertEquals(value, buf.getDouble(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
buf.writeDouble(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(Double.longBitsToDouble(0x1002030405060708L), buf.getDouble(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
buf.writeDouble(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getDouble(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
buf.writeDouble(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getDouble(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getDouble(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getDouble(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfDoubleReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfDoubleMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setDouble(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfDoubleMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setDouble(1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfDoubleMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
double value = Double.longBitsToDouble(0x0102030405060708L);
|
||||||
|
buf.setDouble(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x04, buf.readByte());
|
||||||
|
assertEquals((byte) 0x05, buf.readByte());
|
||||||
|
assertEquals((byte) 0x06, buf.readByte());
|
||||||
|
assertEquals((byte) 0x07, buf.readByte());
|
||||||
|
assertEquals((byte) 0x08, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getFloat(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
buf.writeFloat(value);
|
||||||
|
assertEquals(value, buf.getFloat(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
buf.writeFloat(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(Float.intBitsToFloat(0x10020304), buf.getFloat(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
buf.writeFloat(value);
|
||||||
|
buf.getFloat(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getFloat(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
buf.writeFloat(value);
|
||||||
|
buf.makeReadOnly().getFloat(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getFloat(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getFloat(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getFloat(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThan(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfFloatMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setFloat(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfFloatMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setFloat(5, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfFloatMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
float value = Float.intBitsToFloat(0x01020304);
|
||||||
|
buf.setFloat(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x04, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferIntOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01020304;
|
||||||
|
buf.writeInt(value);
|
||||||
|
assertEquals(value, buf.getInt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x01020304;
|
||||||
|
buf.writeInt(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x10020304, buf.getInt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01020304;
|
||||||
|
buf.writeInt(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x01020304;
|
||||||
|
buf.writeInt(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getInt(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x01020304;
|
||||||
|
buf.writeUnsignedInt(value);
|
||||||
|
assertEquals(value, buf.getUnsignedInt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
long value = 0x01020304;
|
||||||
|
buf.writeUnsignedInt(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x10020304, buf.getUnsignedInt(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x01020304;
|
||||||
|
buf.writeUnsignedInt(value);
|
||||||
|
buf.getUnsignedInt(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedInt(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x01020304;
|
||||||
|
buf.writeUnsignedInt(value);
|
||||||
|
buf.makeReadOnly().getUnsignedInt(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getUnsignedInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedInt(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getUnsignedInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfIntMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x01020304;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setInt(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfIntMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x01020304;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setInt(5, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfIntMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x01020304;
|
||||||
|
buf.setInt(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x04, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedIntMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
long value = 0x01020304;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedInt(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedIntMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
long value = 0x01020304;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedInt(5, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedIntMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
long value = 0x01020304;
|
||||||
|
buf.setUnsignedInt(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x04, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferLongOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getLong(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
buf.writeLong(value);
|
||||||
|
assertEquals(value, buf.getLong(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
buf.writeLong(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x1002030405060708L, buf.getLong(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
buf.writeLong(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getLong(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
buf.writeLong(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getLong(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getLong(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getLong(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfLongReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfLongMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setLong(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfLongMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setLong(1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfLongMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
long value = 0x0102030405060708L;
|
||||||
|
buf.setLong(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x04, buf.readByte());
|
||||||
|
assertEquals((byte) 0x05, buf.readByte());
|
||||||
|
assertEquals((byte) 0x06, buf.readByte());
|
||||||
|
assertEquals((byte) 0x07, buf.readByte());
|
||||||
|
assertEquals((byte) 0x08, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getMedium(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeMedium(value);
|
||||||
|
assertEquals(value, buf.getMedium(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeMedium(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x100203, buf.getMedium(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeMedium(value);
|
||||||
|
buf.getMedium(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeMedium(value);
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getMedium(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeMedium(value);
|
||||||
|
buf.makeReadOnly().getMedium(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getMedium(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getMedium(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getMedium(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedMedium(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeUnsignedMedium(value);
|
||||||
|
assertEquals(value, buf.getUnsignedMedium(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeUnsignedMedium(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x100203, buf.getUnsignedMedium(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeUnsignedMedium(value);
|
||||||
|
buf.getUnsignedMedium(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedMedium(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.writeUnsignedMedium(value);
|
||||||
|
buf.makeReadOnly().getUnsignedMedium(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getUnsignedMedium(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedMedium(6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getUnsignedMedium(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfMediumMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x010203;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setMedium(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfMediumMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x010203;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setMedium(6, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfMediumMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.setMedium(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedMediumMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x010203;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedMedium(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedMediumMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x010203;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedMedium(6, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedMediumMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x010203;
|
||||||
|
buf.setUnsignedMedium(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x03, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -137,7 +137,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(0, buf.readableBytes());
|
assertEquals(0, buf.readableBytes());
|
||||||
assertEquals(7, buf.writableBytes());
|
assertEquals(7, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedByte());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedByte());
|
||||||
assertEquals(0, buf.readableBytes());
|
assertEquals(0, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
assertEquals(6, buf.writableBytes());
|
assertEquals(6, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readChar());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readChar());
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
assertEquals(6, buf.writableBytes());
|
assertEquals(6, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readShort());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readShort());
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,7 +446,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
assertEquals(6, buf.writableBytes());
|
assertEquals(6, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedShort());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedShort());
|
||||||
assertEquals(1, buf.readableBytes());
|
assertEquals(1, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,7 +584,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(2, buf.readableBytes());
|
assertEquals(2, buf.readableBytes());
|
||||||
assertEquals(5, buf.writableBytes());
|
assertEquals(5, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readMedium());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readMedium());
|
||||||
assertEquals(2, buf.readableBytes());
|
assertEquals(2, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -652,7 +652,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(2, buf.readableBytes());
|
assertEquals(2, buf.readableBytes());
|
||||||
assertEquals(5, buf.writableBytes());
|
assertEquals(5, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedMedium());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedMedium());
|
||||||
assertEquals(2, buf.readableBytes());
|
assertEquals(2, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -790,7 +790,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
assertEquals(4, buf.writableBytes());
|
assertEquals(4, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readInt());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readInt());
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -858,7 +858,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
assertEquals(4, buf.writableBytes());
|
assertEquals(4, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedInt());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedInt());
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -996,7 +996,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
assertEquals(4, buf.writableBytes());
|
assertEquals(4, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readFloat());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readFloat());
|
||||||
assertEquals(3, buf.readableBytes());
|
assertEquals(3, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1099,7 +1099,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(7, buf.readableBytes());
|
assertEquals(7, buf.readableBytes());
|
||||||
assertEquals(0, buf.writableBytes());
|
assertEquals(0, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readLong());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readLong());
|
||||||
assertEquals(7, buf.readableBytes());
|
assertEquals(7, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1202,7 +1202,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport {
|
|||||||
buf.readerOffset(1);
|
buf.readerOffset(1);
|
||||||
assertEquals(7, buf.readableBytes());
|
assertEquals(7, buf.readableBytes());
|
||||||
assertEquals(0, buf.writableBytes());
|
assertEquals(0, buf.writableBytes());
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readDouble());
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readDouble());
|
||||||
assertEquals(7, buf.readableBytes());
|
assertEquals(7, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
@ -31,7 +35,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void readOnlyBufferMustPreventWriteAccess(Fixture fixture) {
|
public void readOnlyBufferMustPreventWriteAccess(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
var b = buf.readOnly(true);
|
var b = buf.makeReadOnly();
|
||||||
assertThat(b).isSameAs(buf);
|
assertThat(b).isSameAs(buf);
|
||||||
verifyWriteInaccessible(buf);
|
verifyWriteInaccessible(buf);
|
||||||
}
|
}
|
||||||
@ -42,7 +46,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void closedBuffersAreNotReadOnly(Fixture fixture) {
|
public void closedBuffersAreNotReadOnly(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator()) {
|
try (BufferAllocator allocator = fixture.createAllocator()) {
|
||||||
Buffer buf = allocator.allocate(8);
|
Buffer buf = allocator.allocate(8);
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
buf.close();
|
buf.close();
|
||||||
assertFalse(buf.readOnly());
|
assertFalse(buf.readOnly());
|
||||||
}
|
}
|
||||||
@ -50,18 +54,18 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("allocators")
|
@MethodSource("allocators")
|
||||||
public void readOnlyBufferMustBecomeWritableAgainAfterTogglingReadOnlyOff(Fixture fixture) {
|
public void readOnlyBufferMustMustStayReadOnlyAfterRepeatedToggles(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
assertFalse(buf.readOnly());
|
assertFalse(buf.readOnly());
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
assertTrue(buf.readOnly());
|
assertTrue(buf.readOnly());
|
||||||
verifyWriteInaccessible(buf);
|
verifyWriteInaccessible(buf);
|
||||||
|
|
||||||
buf.readOnly(false);
|
buf.makeReadOnly();
|
||||||
assertFalse(buf.readOnly());
|
assertTrue(buf.readOnly());
|
||||||
|
|
||||||
verifyWriteAccessible(buf);
|
verifyWriteInaccessible(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +74,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void readOnlyBufferMustRemainReadOnlyAfterSend(Fixture fixture) {
|
public void readOnlyBufferMustRemainReadOnlyAfterSend(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
var send = buf.send();
|
var send = buf.send();
|
||||||
try (Buffer receive = send.receive()) {
|
try (Buffer receive = send.receive()) {
|
||||||
assertTrue(receive.readOnly());
|
assertTrue(receive.readOnly());
|
||||||
@ -83,7 +87,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void readOnlyBufferMustRemainReadOnlyAfterSendForEmptyCompositeBuffer() {
|
public void readOnlyBufferMustRemainReadOnlyAfterSendForEmptyCompositeBuffer() {
|
||||||
try (BufferAllocator allocator = BufferAllocator.heap();
|
try (BufferAllocator allocator = BufferAllocator.heap();
|
||||||
Buffer buf = CompositeBuffer.compose(allocator)) {
|
Buffer buf = CompositeBuffer.compose(allocator)) {
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
var send = buf.send();
|
var send = buf.send();
|
||||||
try (Buffer receive = send.receive()) {
|
try (Buffer receive = send.receive()) {
|
||||||
assertTrue(receive.readOnly());
|
assertTrue(receive.readOnly());
|
||||||
@ -98,7 +102,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
try (Buffer buf = allocator.allocate(8)) {
|
try (Buffer buf = allocator.allocate(8)) {
|
||||||
assertFalse(buf.readOnly());
|
assertFalse(buf.readOnly());
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
assertTrue(buf.readOnly());
|
assertTrue(buf.readOnly());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +114,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void compactOnReadOnlyBufferMustThrow(Fixture fixture) {
|
public void compactOnReadOnlyBufferMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
assertThrows(IllegalStateException.class, () -> buf.compact());
|
assertThrows(IllegalStateException.class, () -> buf.compact());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +124,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void ensureWritableOnReadOnlyBufferMustThrow(Fixture fixture) {
|
public void ensureWritableOnReadOnlyBufferMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
assertThrows(IllegalStateException.class, () -> buf.ensureWritable(1));
|
assertThrows(IllegalStateException.class, () -> buf.ensureWritable(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,11 +134,115 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
public void copyIntoOnReadOnlyBufferMustThrow(Fixture fixture) {
|
public void copyIntoOnReadOnlyBufferMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer dest = allocator.allocate(8)) {
|
Buffer dest = allocator.allocate(8)) {
|
||||||
dest.readOnly(true);
|
dest.makeReadOnly();
|
||||||
try (Buffer src = allocator.allocate(8)) {
|
try (Buffer src = allocator.allocate(8)) {
|
||||||
assertThrows(IllegalStateException.class, () -> src.copyInto(0, dest, 0, 1));
|
assertThrows(IllegalStateException.class, () -> src.copyInto(0, dest, 0, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// todo read only buffer must have zero writable bytes
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
public void readOnlyBuffersCannotChangeWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8).makeReadOnly()) {
|
||||||
|
assertThrows(IllegalStateException.class, () -> buf.writerOffset(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("initialNoConstAllocators")
|
||||||
|
public void constBufferInitialState(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}).get()) {
|
||||||
|
assertTrue(buf.readOnly());
|
||||||
|
assertThat(buf.order()).isEqualTo(ByteOrder.nativeOrder());
|
||||||
|
assertThat(buf.readerOffset()).isZero();
|
||||||
|
assertThat(buf.capacity()).isEqualTo(4);
|
||||||
|
assertThat(buf.writerOffset()).isEqualTo(4);
|
||||||
|
assertTrue(buf.isOwned());
|
||||||
|
assertTrue(buf.isAccessible());
|
||||||
|
assertThat(buf.countComponents()).isOne();
|
||||||
|
assertThat(buf.countBorrows()).isZero();
|
||||||
|
assertEquals((byte) 1, buf.readByte());
|
||||||
|
assertEquals((byte) 2, buf.readByte());
|
||||||
|
assertEquals((byte) 3, buf.readByte());
|
||||||
|
assertEquals((byte) 4, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("initialNoConstAllocators")
|
||||||
|
public void constBuffersCanBeSplit(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator()) {
|
||||||
|
Supplier<Buffer> supplier = allocator.constBufferSupplier(new byte[16]);
|
||||||
|
verifyConstBufferSplit(supplier);
|
||||||
|
// These shenanigans must not interfere with the parent const buffer.
|
||||||
|
verifyConstBufferSplit(supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void verifyConstBufferSplit(Supplier<Buffer> supplier) {
|
||||||
|
try (Buffer a = supplier.get();
|
||||||
|
Buffer b = a.split(8)) {
|
||||||
|
assertTrue(a.readOnly());
|
||||||
|
assertTrue(b.readOnly());
|
||||||
|
assertTrue(a.isOwned());
|
||||||
|
assertTrue(b.isOwned());
|
||||||
|
assertThat(a.capacity()).isEqualTo(8);
|
||||||
|
assertThat(b.capacity()).isEqualTo(8);
|
||||||
|
try (Buffer c = b.slice()) {
|
||||||
|
assertTrue(c.readOnly());
|
||||||
|
assertFalse(c.isOwned());
|
||||||
|
assertFalse(b.isOwned());
|
||||||
|
assertThat(c.capacity()).isEqualTo(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("initialNoConstAllocators")
|
||||||
|
public void compactOnConstBufferMustNotImpactSiblings(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator()) {
|
||||||
|
Supplier<Buffer> supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4});
|
||||||
|
try (Buffer a = supplier.get();
|
||||||
|
Buffer b = supplier.get();
|
||||||
|
Buffer c = a.slice()) {
|
||||||
|
assertEquals(1, a.readByte());
|
||||||
|
assertEquals(2, a.readByte());
|
||||||
|
assertThrows(IllegalStateException.class, () -> a.compact()); // Can't compact read-only buffer.
|
||||||
|
assertEquals(3, a.readByte());
|
||||||
|
assertEquals(4, a.readByte());
|
||||||
|
|
||||||
|
assertEquals(1, b.readByte());
|
||||||
|
assertEquals(2, b.readByte());
|
||||||
|
assertThrows(IllegalStateException.class, () -> b.compact()); // Can't compact read-only buffer.
|
||||||
|
assertEquals(3, b.readByte());
|
||||||
|
assertEquals(4, b.readByte());
|
||||||
|
|
||||||
|
assertEquals(1, c.readByte());
|
||||||
|
assertEquals(2, c.readByte());
|
||||||
|
assertThrows(IllegalStateException.class, () -> c.compact()); // Can't compact read-only buffer.
|
||||||
|
assertEquals(3, c.readByte());
|
||||||
|
assertEquals(4, c.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("initialNoConstAllocators")
|
||||||
|
public void constBuffersMustBeSendable(Fixture fixture) throws Exception {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator()) {
|
||||||
|
Supplier<Buffer> supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4});
|
||||||
|
try (Buffer buffer = supplier.get()) {
|
||||||
|
Send<Buffer> send = buffer.send();
|
||||||
|
var future = executor.submit(() -> {
|
||||||
|
try (Buffer receive = send.receive()) {
|
||||||
|
return receive.order(BIG_ENDIAN).readInt();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(0x01020304, future.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,7 +694,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
public void acquireOfReadOnlyBufferMustBeReadOnly(Fixture fixture) {
|
public void acquireOfReadOnlyBufferMustBeReadOnly(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
try (Buffer acquire = buf.acquire()) {
|
try (Buffer acquire = buf.acquire()) {
|
||||||
assertTrue(acquire.readOnly());
|
assertTrue(acquire.readOnly());
|
||||||
}
|
}
|
||||||
@ -707,7 +707,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.writeLong(0x0102030405060708L);
|
buf.writeLong(0x0102030405060708L);
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
try (Buffer slice = buf.slice()) {
|
try (Buffer slice = buf.slice()) {
|
||||||
assertTrue(slice.readOnly());
|
assertTrue(slice.readOnly());
|
||||||
}
|
}
|
||||||
@ -720,7 +720,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(16)) {
|
Buffer buf = allocator.allocate(16)) {
|
||||||
buf.writeLong(0x0102030405060708L);
|
buf.writeLong(0x0102030405060708L);
|
||||||
buf.readOnly(true);
|
buf.makeReadOnly();
|
||||||
try (Buffer split = buf.split()) {
|
try (Buffer split = buf.split()) {
|
||||||
assertTrue(split.readOnly());
|
assertTrue(split.readOnly());
|
||||||
assertTrue(buf.readOnly());
|
assertTrue(buf.readOnly());
|
||||||
|
@ -0,0 +1,358 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class BufferShortOffsettedAccessorsTest extends BufferTestSupport {
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getShort(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
short value = 0x0102;
|
||||||
|
buf.writeShort(value);
|
||||||
|
assertEquals(value, buf.getShort(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
short value = 0x0102;
|
||||||
|
buf.writeShort(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x1002, buf.getShort(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
short value = 0x0102;
|
||||||
|
buf.writeShort(value);
|
||||||
|
buf.getShort(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
short value = 0x0102;
|
||||||
|
buf.writeShort(value);
|
||||||
|
buf.makeReadOnly().getShort(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getShort(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getShort(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedShort(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustNotBoundsCheckWhenReadOffsetAndSizeIsEqualToWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x0102;
|
||||||
|
buf.writeUnsignedShort(value);
|
||||||
|
assertEquals(value, buf.getUnsignedShort(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustReadWithDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x0102;
|
||||||
|
buf.writeUnsignedShort(value);
|
||||||
|
buf.setByte(0, (byte) 0x10);
|
||||||
|
assertEquals(0x1002, buf.getUnsignedShort(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x0102;
|
||||||
|
buf.writeUnsignedShort(value);
|
||||||
|
buf.getUnsignedShort(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortReadOnlyMustNotBoundsCheckWhenReadOffsetAndSizeIsGreaterThanWriteOffset(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
int value = 0x0102;
|
||||||
|
buf.writeUnsignedShort(value);
|
||||||
|
buf.makeReadOnly().getUnsignedShort(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(
|
||||||
|
Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.getUnsignedShort(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.getUnsignedShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.makeReadOnly().getUnsignedShort(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfShortMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
short value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setShort(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfShortMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
short value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setShort(7, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfShortMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
short value = 0x0102;
|
||||||
|
buf.setShort(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedShortMustBoundsCheckWhenWriteOffsetIsNegative(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedShort(-1, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedShortMustBoundsCheckWhenWriteOffsetAndSizeIsBeyondCapacity(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
assertEquals(Long.BYTES, buf.capacity());
|
||||||
|
int value = 0x0102;
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.setUnsignedShort(7, value));
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
// Verify contents are unchanged.
|
||||||
|
assertEquals(0, buf.readLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
void offsettedSetOfUnsignedShortMustHaveDefaultEndianByteOrder(Fixture fixture) {
|
||||||
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
|
Buffer buf = allocator.allocate(8)) {
|
||||||
|
buf.order(BIG_ENDIAN);
|
||||||
|
int value = 0x0102;
|
||||||
|
buf.setUnsignedShort(0, value);
|
||||||
|
buf.writerOffset(Long.BYTES);
|
||||||
|
assertEquals((byte) 0x01, buf.readByte());
|
||||||
|
assertEquals((byte) 0x02, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
assertEquals((byte) 0x00, buf.readByte());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -40,6 +40,7 @@ import java.util.stream.Stream.Builder;
|
|||||||
|
|
||||||
import static io.netty.buffer.api.Fixture.Properties.CLEANER;
|
import static io.netty.buffer.api.Fixture.Properties.CLEANER;
|
||||||
import static io.netty.buffer.api.Fixture.Properties.COMPOSITE;
|
import static io.netty.buffer.api.Fixture.Properties.COMPOSITE;
|
||||||
|
import static io.netty.buffer.api.Fixture.Properties.CONST;
|
||||||
import static io.netty.buffer.api.Fixture.Properties.DIRECT;
|
import static io.netty.buffer.api.Fixture.Properties.DIRECT;
|
||||||
import static io.netty.buffer.api.Fixture.Properties.HEAP;
|
import static io.netty.buffer.api.Fixture.Properties.HEAP;
|
||||||
import static io.netty.buffer.api.Fixture.Properties.POOLED;
|
import static io.netty.buffer.api.Fixture.Properties.POOLED;
|
||||||
@ -55,6 +56,8 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||||||
public abstract class BufferTestSupport {
|
public abstract class BufferTestSupport {
|
||||||
public static ExecutorService executor;
|
public static ExecutorService executor;
|
||||||
|
|
||||||
|
private static final Memoize<Fixture[]> INITIAL_NO_CONST = new Memoize<>(
|
||||||
|
() -> initialFixturesForEachImplementation().stream().filter(f -> !f.isConst()).toArray(Fixture[]::new));
|
||||||
private static final Memoize<Fixture[]> ALL_COMBINATIONS = new Memoize<>(
|
private static final Memoize<Fixture[]> ALL_COMBINATIONS = new Memoize<>(
|
||||||
() -> fixtureCombinations().toArray(Fixture[]::new));
|
() -> fixtureCombinations().toArray(Fixture[]::new));
|
||||||
private static final Memoize<Fixture[]> ALL_ALLOCATORS = new Memoize<>(
|
private static final Memoize<Fixture[]> ALL_ALLOCATORS = new Memoize<>(
|
||||||
@ -127,6 +130,10 @@ public abstract class BufferTestSupport {
|
|||||||
return POOLED_DIRECT_ALLOCS.get();
|
return POOLED_DIRECT_ALLOCS.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Fixture[] initialNoConstAllocators() {
|
||||||
|
return INITIAL_NO_CONST.get();
|
||||||
|
}
|
||||||
|
|
||||||
static List<Fixture> initialAllocators() {
|
static List<Fixture> initialAllocators() {
|
||||||
return List.of(
|
return List.of(
|
||||||
new Fixture("heap", BufferAllocator::heap, HEAP),
|
new Fixture("heap", BufferAllocator::heap, HEAP),
|
||||||
@ -135,7 +142,7 @@ public abstract class BufferTestSupport {
|
|||||||
new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER));
|
new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Fixture> fixtureCombinations() {
|
static List<Fixture> initialFixturesForEachImplementation() {
|
||||||
List<Fixture> initFixtures = initialAllocators();
|
List<Fixture> initFixtures = initialAllocators();
|
||||||
|
|
||||||
// Multiply by all MemoryManagers.
|
// Multiply by all MemoryManagers.
|
||||||
@ -144,12 +151,17 @@ public abstract class BufferTestSupport {
|
|||||||
loadableManagers.add(provider.get());
|
loadableManagers.add(provider.get());
|
||||||
});
|
});
|
||||||
initFixtures = initFixtures.stream().flatMap(f -> {
|
initFixtures = initFixtures.stream().flatMap(f -> {
|
||||||
Stream.Builder<Fixture> builder = Stream.builder();
|
Builder<Fixture> builder = Stream.builder();
|
||||||
for (MemoryManagers managers : loadableManagers) {
|
for (MemoryManagers managers : loadableManagers) {
|
||||||
builder.add(new Fixture(f + "/" + managers, () -> using(managers, f), f.getProperties()));
|
builder.add(new Fixture(f + "/" + managers, () -> using(managers, f), f.getProperties()));
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}).toList();
|
}).toList();
|
||||||
|
return initFixtures;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Fixture> fixtureCombinations() {
|
||||||
|
List<Fixture> initFixtures = initialFixturesForEachImplementation();
|
||||||
|
|
||||||
Builder<Fixture> builder = Stream.builder();
|
Builder<Fixture> builder = Stream.builder();
|
||||||
initFixtures.forEach(builder);
|
initFixtures.forEach(builder);
|
||||||
@ -244,8 +256,7 @@ public abstract class BufferTestSupport {
|
|||||||
|
|
||||||
var stream = builder.build();
|
var stream = builder.build();
|
||||||
return stream.flatMap(BufferTestSupport::injectSplits)
|
return stream.flatMap(BufferTestSupport::injectSplits)
|
||||||
.flatMap(BufferTestSupport::injectSlices)
|
.flatMap(BufferTestSupport::injectSlices);
|
||||||
.flatMap(BufferTestSupport::injectReadOnlyToggling);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Fixture> injectSplits(Fixture f) {
|
private static Stream<Fixture> injectSplits(Fixture f) {
|
||||||
@ -310,26 +321,6 @@ public abstract class BufferTestSupport {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Fixture> injectReadOnlyToggling(Fixture f) {
|
|
||||||
Builder<Fixture> builder = Stream.builder();
|
|
||||||
builder.add(f);
|
|
||||||
builder.add(new Fixture(f + ".readOnly(true/false)", () -> {
|
|
||||||
var allocatorBase = f.get();
|
|
||||||
return new BufferAllocator() {
|
|
||||||
@Override
|
|
||||||
public Buffer allocate(int size) {
|
|
||||||
return allocatorBase.allocate(size).readOnly(true).readOnly(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
allocatorBase.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, f.getProperties()));
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties[] concat(Properties[] props, Properties prop) {
|
private static Properties[] concat(Properties[] props, Properties prop) {
|
||||||
props = Arrays.copyOf(props, props.length + 1);
|
props = Arrays.copyOf(props, props.length + 1);
|
||||||
props[props.length - 1] = prop;
|
props[props.length - 1] = prop;
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.netty.buffer.api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
import static java.nio.ByteOrder.LITTLE_ENDIAN;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class BufferWriteBytesCombinationsTest extends BufferTestSupport {
|
||||||
|
private static final Memoize<Fixture[]> OTHER_FIXTURES = new Memoize<Fixture[]>(
|
||||||
|
() -> Arrays.stream(allocators()).filter(filterOfTheDay(10)).toArray(Fixture[]::new));
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("allocators")
|
||||||
|
public void writeBytesMustTransferDataAndUpdateOffsets(Fixture fixture) {
|
||||||
|
try (BufferAllocator alloc1 = fixture.createAllocator()) {
|
||||||
|
// Only test 10% of available combinations. Otherwise, this takes too long.
|
||||||
|
Fixture[] allocators = OTHER_FIXTURES.get();
|
||||||
|
Arrays.stream(allocators).parallel().forEach(otherFixture -> {
|
||||||
|
try (BufferAllocator alloc2 = otherFixture.createAllocator();
|
||||||
|
Buffer target = alloc1.allocate(37);
|
||||||
|
Buffer source = alloc2.allocate(35)) {
|
||||||
|
// BE to BE
|
||||||
|
target.order(BIG_ENDIAN);
|
||||||
|
source.order(BIG_ENDIAN);
|
||||||
|
verifyWriteBytes(target, source);
|
||||||
|
|
||||||
|
// LE to BE
|
||||||
|
target.fill((byte) 0).reset().order(BIG_ENDIAN);
|
||||||
|
source.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
||||||
|
verifyWriteBytes(target, source);
|
||||||
|
|
||||||
|
// BE to LE
|
||||||
|
target.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
||||||
|
source.fill((byte) 0).reset().order(BIG_ENDIAN);
|
||||||
|
verifyWriteBytes(target, source);
|
||||||
|
|
||||||
|
// LE to LE
|
||||||
|
target.fill((byte) 0).reset().order(LITTLE_ENDIAN);
|
||||||
|
source.fill((byte) 0).reset().order(BIG_ENDIAN);
|
||||||
|
verifyWriteBytes(target, source);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.addSuppressed(new RuntimeException("other fixture was: " + otherFixture));
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void verifyWriteBytes(Buffer target, Buffer source) {
|
||||||
|
for (int i = 0; i < 35; i++) {
|
||||||
|
source.writeByte((byte) (i + 1));
|
||||||
|
}
|
||||||
|
target.writeBytes(source);
|
||||||
|
assertThat(target.readerOffset()).isZero();
|
||||||
|
assertThat(target.writerOffset()).isEqualTo(35);
|
||||||
|
assertThat(source.readerOffset()).isEqualTo(35);
|
||||||
|
assertThat(source.writerOffset()).isEqualTo(35);
|
||||||
|
try (Buffer readableSlice = target.slice()) {
|
||||||
|
assertEquals(source, readableSlice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -72,9 +72,14 @@ public final class Fixture implements Supplier<BufferAllocator> {
|
|||||||
return properties.contains(Properties.SLICE);
|
return properties.contains(Properties.SLICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isConst() {
|
||||||
|
return properties.contains(Properties.CONST);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Properties {
|
public enum Properties {
|
||||||
HEAP,
|
HEAP,
|
||||||
DIRECT,
|
DIRECT,
|
||||||
|
CONST,
|
||||||
COMPOSITE,
|
COMPOSITE,
|
||||||
CLEANER,
|
CLEANER,
|
||||||
POOLED,
|
POOLED,
|
||||||
|
@ -17,7 +17,6 @@ package io.netty.buffer.api.examples.bytetomessagedecoder;
|
|||||||
|
|
||||||
import io.netty.buffer.api.Buffer;
|
import io.netty.buffer.api.Buffer;
|
||||||
import io.netty.buffer.api.BufferAllocator;
|
import io.netty.buffer.api.BufferAllocator;
|
||||||
import io.netty.buffer.api.CompositeBuffer;
|
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
@ -334,7 +333,7 @@ public class ByteToMessageDecoderTest {
|
|||||||
@Override
|
@Override
|
||||||
protected void decode(ChannelHandlerContext ctx, Buffer in) { }
|
protected void decode(ChannelHandlerContext ctx, Buffer in) { }
|
||||||
});
|
});
|
||||||
assertFalse(channel.writeInbound(heap().allocate(8).writeByte((byte) 1).readOnly(true)));
|
assertFalse(channel.writeInbound(heap().allocate(8).writeByte((byte) 1).makeReadOnly()));
|
||||||
assertFalse(channel.writeInbound(heap().allocate(1).writeByte((byte) 2)));
|
assertFalse(channel.writeInbound(heap().allocate(1).writeByte((byte) 2)));
|
||||||
assertFalse(channel.finish());
|
assertFalse(channel.finish());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user