diff --git a/pom.xml b/pom.xml index 65bace2..5240097 100644 --- a/pom.xml +++ b/pom.xml @@ -176,6 +176,7 @@ 600 false + 1C nosample diff --git a/src/main/java/io/netty/buffer/api/Buffer.java b/src/main/java/io/netty/buffer/api/Buffer.java index 8043989..e6187ca 100644 --- a/src/main/java/io/netty/buffer/api/Buffer.java +++ b/src/main/java/io/netty/buffer/api/Buffer.java @@ -128,6 +128,14 @@ import java.nio.ByteOrder; * 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 * further processing, as split buffer regions, once their data has been received in its entirety. + * + *

Buffers as constants

+ * + * 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, BufferAccessors { /** @@ -218,11 +226,13 @@ public interface Buffer extends Rc, BufferAccessors { 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. */ - Buffer readOnly(boolean readOnly); + Buffer makeReadOnly(); /** * Query if this buffer is read-only or not. @@ -308,6 +318,23 @@ public interface Buffer extends Rc, BufferAccessors { 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 * buffer to their initial values. diff --git a/src/main/java/io/netty/buffer/api/BufferAllocator.java b/src/main/java/io/netty/buffer/api/BufferAllocator.java index 1cd0fe8..0810145 100644 --- a/src/main/java/io/netty/buffer/api/BufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/BufferAllocator.java @@ -15,9 +15,8 @@ */ package io.netty.buffer.api; -import io.netty.buffer.api.internal.Statics; - import java.nio.ByteOrder; +import java.util.function.Supplier; /** * Interface for {@link Buffer} allocators. @@ -68,6 +67,36 @@ public interface BufferAllocator extends AutoCloseable { 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. + *

+ * 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. + *

+ * The buffers produced are "constants", in the sense that they are {@linkplain Buffer#readOnly() read-only}. + *

+ * 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. + *

+ * 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 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 * used after this method has been called on it. @@ -77,11 +106,11 @@ public interface BufferAllocator extends AutoCloseable { } static BufferAllocator heap() { - return new ManagedBufferAllocator(MemoryManagers.getManagers().getHeapMemoryManager(), Statics.CLEANER); + return new ManagedBufferAllocator(MemoryManagers.getManagers().getHeapMemoryManager()); } static BufferAllocator direct() { - return new ManagedBufferAllocator(MemoryManagers.getManagers().getNativeMemoryManager(), Statics.CLEANER); + return new ManagedBufferAllocator(MemoryManagers.getManagers().getNativeMemoryManager()); } static BufferAllocator pooledHeap() { diff --git a/src/main/java/io/netty/buffer/api/CompositeBuffer.java b/src/main/java/io/netty/buffer/api/CompositeBuffer.java index 7e98415..2b45ada 100644 --- a/src/main/java/io/netty/buffer/api/CompositeBuffer.java +++ b/src/main/java/io/netty/buffer/api/CompositeBuffer.java @@ -444,11 +444,11 @@ public final class CompositeBuffer extends RcSupport im } @Override - public CompositeBuffer readOnly(boolean readOnly) { + public CompositeBuffer makeReadOnly() { for (Buffer buf : bufs) { - buf.readOnly(readOnly); + buf.makeReadOnly(); } - this.readOnly = readOnly; + readOnly = true; return this; } diff --git a/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java b/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java index 1295c71..09ba957 100644 --- a/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java @@ -15,29 +15,36 @@ */ 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; class ManagedBufferAllocator implements BufferAllocator, AllocatorControl { private final MemoryManager manager; - private final Cleaner cleaner; - ManagedBufferAllocator(MemoryManager manager, Cleaner cleaner) { + ManagedBufferAllocator(MemoryManager manager) { this.manager = manager; - this.cleaner = cleaner; } @Override public Buffer allocate(int size) { BufferAllocator.checkSize(size); - return manager.allocateShared(this, size, manager.drop(), cleaner); + return manager.allocateShared(this, size, manager.drop(), Statics.CLEANER); + } + + @Override + public Supplier constBufferSupplier(byte[] bytes) { + Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER); + constantBuffer.writeBytes(bytes).makeReadOnly(); + return () -> manager.allocateConstChild(constantBuffer); } @Override public Object allocateUntethered(Buffer originator, int 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); } diff --git a/src/main/java/io/netty/buffer/api/MemoryManager.java b/src/main/java/io/netty/buffer/api/MemoryManager.java index ee0333e..0f2088d 100644 --- a/src/main/java/io/netty/buffer/api/MemoryManager.java +++ b/src/main/java/io/netty/buffer/api/MemoryManager.java @@ -15,14 +15,11 @@ */ package io.netty.buffer.api; -import io.netty.buffer.api.memseg.HeapMemorySegmentManager; -import io.netty.buffer.api.memseg.NativeMemorySegmentManager; - import java.lang.ref.Cleaner; public interface MemoryManager { - boolean isNative(); Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner); + Buffer allocateConstChild(Buffer readOnlyConstParent); Drop drop(); Object unwrapRecoverableMemory(Buffer buf); int capacityOfRecoverableMemory(Object memory); diff --git a/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java b/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java index 4ec5f73..be6c8ea 100644 --- a/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java +++ b/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java @@ -22,6 +22,7 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.function.Supplier; import static io.netty.buffer.api.internal.Statics.NO_OP_DROP; import static java.lang.invoke.MethodHandles.lookup; @@ -46,14 +47,19 @@ class SizeClassedMemoryPool implements BufferAllocator, AllocatorControl, Drop 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() { return manager; } diff --git a/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java b/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java index 676de27..b9389ae 100644 --- a/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java +++ b/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java @@ -34,11 +34,6 @@ public class ByteBufferMemoryManager implements MemoryManager { this.direct = direct; } - @Override - public boolean isNative() { - return direct; - } - @Override public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner) { int capacity = Math.toIntExact(size); @@ -47,6 +42,13 @@ public class ByteBufferMemoryManager implements MemoryManager { 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 public Drop drop() { return Statics.NO_OP_DROP; diff --git a/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java b/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java index 68310b6..e96f2d0 100644 --- a/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java +++ b/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java @@ -47,6 +47,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable private int roff; private int woff; + private boolean constBuffer; NioBuffer(ByteBuffer base, ByteBuffer memory, AllocatorControl control, Drop drop) { super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop))); @@ -56,6 +57,22 @@ class NioBuffer extends RcSupport implements Buffer, Readable 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 { final Drop delegate; @@ -158,12 +175,8 @@ class NioBuffer extends RcSupport implements Buffer, Readable } @Override - public Buffer readOnly(boolean readOnly) { - if (readOnly && wmem == rmem) { - wmem = CLOSED_BUFFER; - } else if (!readOnly && wmem != rmem) { - wmem = rmem; - } + public Buffer makeReadOnly() { + wmem = CLOSED_BUFFER; return this; } @@ -183,10 +196,13 @@ class NioBuffer extends RcSupport implements Buffer, Readable ByteBuffer slice = rmem.slice(offset, length); ArcDrop drop = (ArcDrop) unsafeGetDrop(); drop.increment(); - return new NioBuffer(base, slice, control, drop) + Buffer sliceBuffer = new NioBuffer(base, slice, control, drop) .writerOffset(length) - .order(order()) - .readOnly(readOnly()); + .order(order()); + if (readOnly()) { + sliceBuffer = sliceBuffer.makeReadOnly(); + } + return sliceBuffer; } @Override @@ -398,21 +414,28 @@ class NioBuffer extends RcSupport implements Buffer, Readable // Copy contents. copyInto(0, buffer, 0, capacity()); - // Release old memory: + // Release the old memory and install the new: + Drop drop = disconnectDrop(); + attachNewBuffer(buffer, drop); + } + + private Drop disconnectDrop() { var drop = (Drop) unsafeGetDrop(); int roff = this.roff; int woff = this.woff; drop.drop(this); - while (drop instanceof ArcDrop) { - drop = ((ArcDrop) drop).unwrap(); - } + drop = ArcDrop.unwrapAllArcs(drop); unsafeSetDrop(new ArcDrop<>(drop)); this.roff = roff; this.woff = woff; + return drop; + } + private void attachNewBuffer(ByteBuffer buffer, Drop drop) { base = buffer; rmem = buffer; wmem = buffer; + constBuffer = false; drop.attach(this); } @@ -437,7 +460,12 @@ class NioBuffer extends RcSupport implements Buffer, Readable splitBuffer.roff = Math.min(roff, splitOffset); splitBuffer.order(order()); 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); if (!readOnly) { wmem = rmem; @@ -554,6 +582,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable return processor.process(initialIndex, this)? 1 : -1; } + // @Override public byte readByte() { checkRead(roff, Byte.BYTES); @@ -1053,6 +1082,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable throw bufferIsReadOnly(); } } + // @Override protected Owned prepareSend() { @@ -1060,6 +1090,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable var roff = this.roff; var woff = this.woff; var readOnly = readOnly(); + var isConst = constBuffer; ByteBuffer base = this.base; ByteBuffer rmem = this.rmem; makeInaccessible(); @@ -1070,7 +1101,10 @@ class NioBuffer extends RcSupport implements Buffer, Readable copy.order(order); copy.roff = roff; copy.woff = woff; - copy.readOnly(readOnly); + if (readOnly) { + copy.makeReadOnly(); + } + copy.constBuffer = isConst; return copy; } }; diff --git a/src/main/java/io/netty/buffer/api/internal/ArcDrop.java b/src/main/java/io/netty/buffer/api/internal/ArcDrop.java index 87fe945..3f98b68 100644 --- a/src/main/java/io/netty/buffer/api/internal/ArcDrop.java +++ b/src/main/java/io/netty/buffer/api/internal/ArcDrop.java @@ -46,6 +46,13 @@ public final class ArcDrop implements Drop { return new ArcDrop(drop); } + public static Drop unwrapAllArcs(Drop drop) { + while (drop instanceof ArcDrop) { + drop = ((ArcDrop) drop).unwrap(); + } + return drop; + } + public static Drop acquire(Drop drop) { if (drop.getClass() == ArcDrop.class) { ((ArcDrop) drop).increment(); diff --git a/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java b/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java index 4c2f62a..6941143 100644 --- a/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java +++ b/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java @@ -27,15 +27,19 @@ import java.lang.ref.Cleaner; import static io.netty.buffer.api.internal.Statics.convert; public abstract class AbstractMemorySegmentManager implements MemoryManager { - @Override - public abstract boolean isNative(); - @Override public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner) { var segment = createSegment(size, cleaner); 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); @Override diff --git a/src/main/java/io/netty/buffer/api/memseg/HeapMemorySegmentManager.java b/src/main/java/io/netty/buffer/api/memseg/HeapMemorySegmentManager.java index 47d6bad..5b7a095 100644 --- a/src/main/java/io/netty/buffer/api/memseg/HeapMemorySegmentManager.java +++ b/src/main/java/io/netty/buffer/api/memseg/HeapMemorySegmentManager.java @@ -20,11 +20,6 @@ import jdk.incubator.foreign.MemorySegment; import java.lang.ref.Cleaner; public class HeapMemorySegmentManager extends AbstractMemorySegmentManager { - @Override - public boolean isNative() { - return false; - } - @Override protected MemorySegment createSegment(long size, Cleaner cleaner) { return MemorySegment.ofArray(new byte[Math.toIntExact(size)]); diff --git a/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java b/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java index 65dbcba..b97a836 100644 --- a/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java +++ b/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java @@ -84,23 +84,40 @@ class MemSegBuffer extends RcSupport implements Buffer, Re }; } - private final AllocatorControl alloc; + private final AllocatorControl control; private MemorySegment base; private MemorySegment seg; private MemorySegment wseg; private ByteOrder order; private int roff; private int woff; + private boolean constBuffer; - MemSegBuffer(MemorySegment base, MemorySegment view, Drop drop, AllocatorControl alloc) { + MemSegBuffer(MemorySegment base, MemorySegment view, Drop drop, AllocatorControl control) { super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop))); - this.alloc = alloc; + this.control = control; this.base = base; seg = view; wseg = view; 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 { final Drop delegate; @@ -281,8 +298,8 @@ class MemSegBuffer extends RcSupport implements Buffer, Re } @Override - public Buffer readOnly(boolean readOnly) { - wseg = readOnly? CLOSED_SEGMENT : seg; + public Buffer makeReadOnly() { + wseg = CLOSED_SEGMENT; return this; } @@ -301,10 +318,13 @@ class MemSegBuffer extends RcSupport implements Buffer, Re } var slice = seg.asSlice(offset, length); Drop drop = ArcDrop.acquire(unsafeGetDrop()); - return new MemSegBuffer(base, slice, drop, alloc) + Buffer sliceBuffer = new MemSegBuffer(base, slice, drop, control) .writerOffset(length) - .order(order()) - .readOnly(readOnly()); + .order(order()); + if (readOnly()) { + sliceBuffer = sliceBuffer.makeReadOnly(); + } + return sliceBuffer; } @Override @@ -518,32 +538,39 @@ class MemSegBuffer extends RcSupport implements Buffer, Re // Allocate a bigger buffer. long newSize = capacity() + (long) Math.max(size - writableBytes(), minimumGrowth); BufferAllocator.checkSize(newSize); - MemorySegment newSegment = (MemorySegment) alloc.allocateUntethered(this, (int) newSize); + MemorySegment newSegment = (MemorySegment) control.allocateUntethered(this, (int) newSize); // Copy contents. newSegment.copyFrom(seg); - // Release old memory segment: + // Release the old memory segment and install the new one: + Drop drop = disconnectDrop(); + attachNewMemorySegment(newSegment, drop); + } + + private Drop disconnectDrop() { var drop = unsafeGetDrop(); if (drop instanceof ArcDrop) { // Disconnect from the current arc drop, since we'll get our own fresh memory segment. int roff = this.roff; int woff = this.woff; drop.drop(this); - while (drop instanceof ArcDrop) { - drop = ((ArcDrop) drop).unwrap(); - } + drop = ArcDrop.unwrapAllArcs(drop); unsafeSetDrop(new ArcDrop<>(drop)); this.roff = roff; this.woff = woff; } else { // TODO would we ever get here? - alloc.recoverMemory(recoverableMemory()); + control.recoverMemory(recoverableMemory()); } + return drop; + } + private void attachNewMemorySegment(MemorySegment newSegment, Drop drop) { base = newSegment; seg = newSegment; wseg = newSegment; + constBuffer = false; drop.attach(this); } @@ -562,12 +589,17 @@ class MemSegBuffer extends RcSupport implements Buffer, Re var drop = (ArcDrop) unsafeGetDrop(); unsafeSetDrop(new ArcDrop<>(drop)); 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.roff = Math.min(roff, splitOffset); splitBuffer.order(order); 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); if (!readOnly) { wseg = seg; @@ -1095,17 +1127,21 @@ class MemSegBuffer extends RcSupport implements Buffer, Re var roff = this.roff; var woff = this.woff; var readOnly = readOnly(); + var isConst = constBuffer; MemorySegment transferSegment = seg; MemorySegment base = this.base; makeInaccessible(); return new Owned() { @Override public MemSegBuffer transferOwnership(Drop drop) { - MemSegBuffer copy = new MemSegBuffer(base, transferSegment, drop, alloc); + MemSegBuffer copy = new MemSegBuffer(base, transferSegment, drop, control); copy.order = order; copy.roff = roff; copy.woff = woff; - copy.readOnly(readOnly); + if (readOnly) { + copy.makeReadOnly(); + } + copy.constBuffer = isConst; return copy; } }; diff --git a/src/main/java/io/netty/buffer/api/memseg/NativeMemorySegmentManager.java b/src/main/java/io/netty/buffer/api/memseg/NativeMemorySegmentManager.java index 1575ff6..c71d1bf 100644 --- a/src/main/java/io/netty/buffer/api/memseg/NativeMemorySegmentManager.java +++ b/src/main/java/io/netty/buffer/api/memseg/NativeMemorySegmentManager.java @@ -52,11 +52,6 @@ public class NativeMemorySegmentManager extends AbstractMemorySegmentManager { } } - @Override - public boolean isNative() { - return true; - } - @Override protected MemorySegment createSegment(long size, Cleaner cleaner) { final ResourceScope scope = cleaner == null ? newSharedScope() : newSharedScope(cleaner); diff --git a/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java b/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java index 784857a..e4b72aa 100644 --- a/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java +++ b/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java @@ -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.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER; -public class UnsafeBuffer extends RcSupport implements Buffer, ReadableComponent, +class UnsafeBuffer extends RcSupport implements Buffer, ReadableComponent, WritableComponent { private static final int CLOSED_SIZE = -1; private static final boolean ACCESS_UNALIGNED = PlatformDependent.isUnaligned(); @@ -54,8 +54,9 @@ public class UnsafeBuffer extends RcSupport implements Buf private boolean readOnly; private int roff; 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 drop) { super(new MakeInaccisbleOnDrop(ArcDrop.wrap(drop))); this.memory = memory; @@ -68,6 +69,23 @@ public class UnsafeBuffer extends RcSupport implements Buf 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 public String toString() { return "Buffer[roff:" + roff + ", woff:" + woff + ", cap:" + rsize + ']'; @@ -134,9 +152,9 @@ public class UnsafeBuffer extends RcSupport implements Buf } @Override - public Buffer readOnly(boolean readOnly) { - this.readOnly = readOnly; - wsize = readOnly? CLOSED_SIZE : rsize; + public Buffer makeReadOnly() { + readOnly = true; + wsize = CLOSED_SIZE; return this; } @@ -153,10 +171,13 @@ public class UnsafeBuffer extends RcSupport implements Buf checkGet(offset, length); ArcDrop drop = (ArcDrop) unsafeGetDrop(); drop.increment(); - return new UnsafeBuffer(memory, baseOffset + offset, length, control, drop) + Buffer sliceBuffer = new UnsafeBuffer(memory, baseOffset + offset, length, control, drop) .writerOffset(length) - .order(order) - .readOnly(readOnly); + .order(order); + if (readOnly) { + sliceBuffer = sliceBuffer.makeReadOnly(); + } + return sliceBuffer; } @Override @@ -436,24 +457,31 @@ public class UnsafeBuffer extends RcSupport implements Buf Reference.reachabilityFence(memory); } - // Release old memory: + // Release the old memory, and install the new memory: + Drop drop = disconnectDrop(); + attachNewMemory(memory, drop); + } + + private Drop disconnectDrop() { var drop = (Drop) unsafeGetDrop(); int roff = this.roff; int woff = this.woff; drop.drop(this); - while (drop instanceof ArcDrop) { - drop = ((ArcDrop) drop).unwrap(); - } + drop = ArcDrop.unwrapAllArcs(drop); unsafeSetDrop(new ArcDrop<>(drop)); this.roff = roff; this.woff = woff; + return drop; + } + private void attachNewMemory(UnsafeMemory memory, Drop drop) { this.memory = memory; base = memory.base; baseOffset = 0; address = memory.address; rsize = memory.size; wsize = memory.size; + constBuffer = false; drop.attach(this); } @@ -477,7 +505,12 @@ public class UnsafeBuffer extends RcSupport implements Buf splitBuffer.roff = Math.min(roff, splitOffset); splitBuffer.order(order()); 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; baseOffset += splitOffset; address += splitOffset; @@ -628,6 +661,7 @@ public class UnsafeBuffer extends RcSupport implements Buf return processor.process(initialIndex, this)? 1 : -1; } + // @Override public byte readByte() { checkRead(roff, Byte.BYTES); @@ -1189,6 +1223,7 @@ public class UnsafeBuffer extends RcSupport implements Buf } return this; } + // @Override protected Owned prepareSend() { @@ -1196,6 +1231,7 @@ public class UnsafeBuffer extends RcSupport implements Buf var roff = this.roff; var woff = this.woff; var readOnly = readOnly(); + var isConst = constBuffer; UnsafeMemory memory = this.memory; AllocatorControl control = this.control; long baseOffset = this.baseOffset; @@ -1208,7 +1244,10 @@ public class UnsafeBuffer extends RcSupport implements Buf copy.order(order); copy.roff = roff; copy.woff = woff; - copy.readOnly(readOnly); + if (readOnly) { + copy.makeReadOnly(); + } + copy.constBuffer = isConst; return copy; } }; diff --git a/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java b/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java index 3379f53..97f794a 100644 --- a/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java +++ b/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java @@ -33,11 +33,6 @@ public class UnsafeMemoryManager implements MemoryManager { this.offheap = offheap; } - @Override - public boolean isNative() { - return offheap; - } - @Override public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner) { final Object base; @@ -61,6 +56,13 @@ public class UnsafeMemoryManager implements MemoryManager { 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 public Drop drop() { // We cannot reliably drop unsafe memory. We have to rely on the cleaner to do that. diff --git a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java index 6a0d588..0469369 100644 --- a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java +++ b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java @@ -303,57 +303,16 @@ public class BufferBulkAccessTest extends BufferTestSupport { } } - private static final Memoize OTHER_FIXTURES = new Memoize( - () -> 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); + public void writeBytesMustWriteAllBytesFromByteArray(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer buffer = allocator.allocate(8)) { + buffer.writeByte((byte) 1); + buffer.writeBytes(new byte[] {2, 3, 4, 5, 6, 7}); + assertThat(buffer.writerOffset()).isEqualTo(7); + assertThat(buffer.readerOffset()).isZero(); + assertThat(toByteArray(buffer)).containsExactly(1, 2, 3, 4, 5, 6, 7, 0); } } } diff --git a/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java new file mode 100644 index 0000000..22d8c0e --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java new file mode 100644 index 0000000..2edac36 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java b/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java index 030e9f2..a6db788 100644 --- a/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java +++ b/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java @@ -103,8 +103,8 @@ public class BufferComponentIterationTest extends BufferTestSupport { try (BufferAllocator allocator = fixture.createAllocator(); Buffer bufBERW = allocator.allocate(8).order(BIG_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 bufLERO = allocator.allocate(8).order(LITTLE_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).makeReadOnly()) { verifyForEachReadableSingleComponent(fixture, bufBERW); verifyForEachReadableSingleComponent(fixture, bufLERW); verifyForEachReadableSingleComponent(fixture, bufBERO); @@ -361,7 +361,7 @@ public class BufferComponentIterationTest extends BufferTestSupport { @MethodSource("allocators") public void forEachWritableOnReadOnlyBufferMustThrow(Fixture fixture) { 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)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferCompositionTest.java b/src/test/java/io/netty/buffer/api/BufferCompositionTest.java index 2768674..1c9c1b3 100644 --- a/src/test/java/io/netty/buffer/api/BufferCompositionTest.java +++ b/src/test/java/io/netty/buffer/api/BufferCompositionTest.java @@ -316,7 +316,7 @@ public class BufferCompositionTest extends BufferTestSupport { public void emptyCompositeBufferMustAllowExtendingWithReadOnlyBuffer() { try (BufferAllocator allocator = BufferAllocator.heap()) { try (CompositeBuffer composite = CompositeBuffer.compose(allocator)) { - try (Buffer b = allocator.allocate(8).readOnly(true)) { + try (Buffer b = allocator.allocate(8).makeReadOnly()) { composite.extendWith(b); assertTrue(composite.readOnly()); } @@ -425,8 +425,8 @@ public class BufferCompositionTest extends BufferTestSupport { @Test public void composingReadOnlyBuffersMustCreateReadOnlyCompositeBuffer() { try (BufferAllocator allocator = BufferAllocator.heap(); - Buffer a = allocator.allocate(4).readOnly(true); - Buffer b = allocator.allocate(4).readOnly(true); + Buffer a = allocator.allocate(4).makeReadOnly(); + Buffer b = allocator.allocate(4).makeReadOnly(); Buffer composite = CompositeBuffer.compose(allocator, a, b)) { assertTrue(composite.readOnly()); verifyWriteInaccessible(composite); @@ -436,7 +436,7 @@ public class BufferCompositionTest extends BufferTestSupport { @Test public void composingReadOnlyAndWritableBuffersMustThrow() { try (BufferAllocator allocator = BufferAllocator.heap(); - Buffer a = allocator.allocate(8).readOnly(true); + Buffer a = allocator.allocate(8).makeReadOnly(); Buffer b = allocator.allocate(8)) { assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b)); assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, b, a)); @@ -452,7 +452,7 @@ public class BufferCompositionTest extends BufferTestSupport { try (Buffer a = allocator.allocate(8)) { 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)); } } @@ -462,7 +462,7 @@ public class BufferCompositionTest extends BufferTestSupport { public void compositeReadOnlyBufferCannotBeExtendedWithWritableBuffer() { try (BufferAllocator allocator = BufferAllocator.heap()) { CompositeBuffer composite; - try (Buffer a = allocator.allocate(8).readOnly(true)) { + try (Buffer a = allocator.allocate(8).makeReadOnly()) { composite = CompositeBuffer.compose(allocator, a); } try (composite; Buffer b = allocator.allocate(8)) { diff --git a/src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java new file mode 100644 index 0000000..d002692 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java new file mode 100644 index 0000000..fce4902 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java new file mode 100644 index 0000000..3e463b4 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java new file mode 100644 index 0000000..702795e --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java new file mode 100644 index 0000000..4be7196 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferPrimitiveOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferPrimitiveOffsettedAccessorsTest.java deleted file mode 100644 index fbbf4b4..0000000 --- a/src/test/java/io/netty/buffer/api/BufferPrimitiveOffsettedAccessorsTest.java +++ /dev/null @@ -1,1955 +0,0 @@ -/* - * 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 BufferPrimitiveOffsettedAccessorsTest 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.readOnly(true).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.readOnly(true).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.readOnly(true).getByte(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).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.readOnly(true).getUnsignedByte(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity( - Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getUnsignedByte(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).getChar(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getChar(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).getShort(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getShort(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).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.readOnly(true).getUnsignedShort(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity( - Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getUnsignedShort(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).getMedium(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getMedium(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).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.readOnly(true).getUnsignedMedium(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity( - Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getUnsignedMedium(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).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.readOnly(true).getInt(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).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.readOnly(true).getUnsignedInt(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity( - Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getUnsignedInt(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).getFloat(1); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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.readOnly(true).getFloat(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThan(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).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.readOnly(true).getLong(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfLongReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } - - @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.readOnly(true).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.readOnly(true).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.readOnly(true).getDouble(0); - } - } - - @ParameterizedTest - @MethodSource("allocators") - void offsettedGetOfDoubleReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).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()); - } - } -} diff --git a/src/test/java/io/netty/buffer/api/BufferPrimitiveRelativeAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferPrimitiveRelativeAccessorsTest.java index 05f7582..6959a50 100644 --- a/src/test/java/io/netty/buffer/api/BufferPrimitiveRelativeAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferPrimitiveRelativeAccessorsTest.java @@ -137,7 +137,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(0, buf.readableBytes()); assertEquals(7, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedByte()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedByte()); assertEquals(0, buf.readableBytes()); } } @@ -275,7 +275,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(1, buf.readableBytes()); assertEquals(6, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readChar()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readChar()); assertEquals(1, buf.readableBytes()); } } @@ -378,7 +378,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(1, buf.readableBytes()); assertEquals(6, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readShort()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readShort()); assertEquals(1, buf.readableBytes()); } } @@ -446,7 +446,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(1, buf.readableBytes()); assertEquals(6, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedShort()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedShort()); assertEquals(1, buf.readableBytes()); } } @@ -584,7 +584,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(2, buf.readableBytes()); assertEquals(5, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readMedium()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readMedium()); assertEquals(2, buf.readableBytes()); } } @@ -652,7 +652,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(2, buf.readableBytes()); assertEquals(5, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedMedium()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedMedium()); assertEquals(2, buf.readableBytes()); } } @@ -790,7 +790,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(3, buf.readableBytes()); assertEquals(4, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readInt()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readInt()); assertEquals(3, buf.readableBytes()); } } @@ -858,7 +858,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(3, buf.readableBytes()); assertEquals(4, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readUnsignedInt()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readUnsignedInt()); assertEquals(3, buf.readableBytes()); } } @@ -996,7 +996,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(3, buf.readableBytes()); assertEquals(4, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readFloat()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readFloat()); assertEquals(3, buf.readableBytes()); } } @@ -1099,7 +1099,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(7, buf.readableBytes()); assertEquals(0, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readLong()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readLong()); assertEquals(7, buf.readableBytes()); } } @@ -1202,7 +1202,7 @@ public class BufferPrimitiveRelativeAccessorsTest extends BufferTestSupport { buf.readerOffset(1); assertEquals(7, buf.readableBytes()); assertEquals(0, buf.writableBytes()); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).readDouble()); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().readDouble()); assertEquals(7, buf.readableBytes()); } } diff --git a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java index bce1846..6ec8019 100644 --- a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java +++ b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java @@ -19,6 +19,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; 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.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -31,7 +35,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void readOnlyBufferMustPreventWriteAccess(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - var b = buf.readOnly(true); + var b = buf.makeReadOnly(); assertThat(b).isSameAs(buf); verifyWriteInaccessible(buf); } @@ -42,7 +46,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void closedBuffersAreNotReadOnly(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator()) { Buffer buf = allocator.allocate(8); - buf.readOnly(true); + buf.makeReadOnly(); buf.close(); assertFalse(buf.readOnly()); } @@ -50,18 +54,18 @@ public class BufferReadOnlyTest extends BufferTestSupport { @ParameterizedTest @MethodSource("allocators") - public void readOnlyBufferMustBecomeWritableAgainAfterTogglingReadOnlyOff(Fixture fixture) { + public void readOnlyBufferMustMustStayReadOnlyAfterRepeatedToggles(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { assertFalse(buf.readOnly()); - buf.readOnly(true); + buf.makeReadOnly(); assertTrue(buf.readOnly()); verifyWriteInaccessible(buf); - buf.readOnly(false); - assertFalse(buf.readOnly()); + buf.makeReadOnly(); + assertTrue(buf.readOnly()); - verifyWriteAccessible(buf); + verifyWriteInaccessible(buf); } } @@ -70,7 +74,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void readOnlyBufferMustRemainReadOnlyAfterSend(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true); + buf.makeReadOnly(); var send = buf.send(); try (Buffer receive = send.receive()) { assertTrue(receive.readOnly()); @@ -83,7 +87,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void readOnlyBufferMustRemainReadOnlyAfterSendForEmptyCompositeBuffer() { try (BufferAllocator allocator = BufferAllocator.heap(); Buffer buf = CompositeBuffer.compose(allocator)) { - buf.readOnly(true); + buf.makeReadOnly(); var send = buf.send(); try (Buffer receive = send.receive()) { assertTrue(receive.readOnly()); @@ -98,7 +102,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { for (int i = 0; i < 1000; i++) { try (Buffer buf = allocator.allocate(8)) { assertFalse(buf.readOnly()); - buf.readOnly(true); + buf.makeReadOnly(); assertTrue(buf.readOnly()); } } @@ -110,7 +114,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void compactOnReadOnlyBufferMustThrow(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true); + buf.makeReadOnly(); assertThrows(IllegalStateException.class, () -> buf.compact()); } } @@ -120,7 +124,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void ensureWritableOnReadOnlyBufferMustThrow(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true); + buf.makeReadOnly(); assertThrows(IllegalStateException.class, () -> buf.ensureWritable(1)); } } @@ -130,11 +134,115 @@ public class BufferReadOnlyTest extends BufferTestSupport { public void copyIntoOnReadOnlyBufferMustThrow(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer dest = allocator.allocate(8)) { - dest.readOnly(true); + dest.makeReadOnly(); try (Buffer src = allocator.allocate(8)) { 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 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 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 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 supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}); + try (Buffer buffer = supplier.get()) { + Send send = buffer.send(); + var future = executor.submit(() -> { + try (Buffer receive = send.receive()) { + return receive.order(BIG_ENDIAN).readInt(); + } + }); + assertEquals(0x01020304, future.get()); + } + } + } } diff --git a/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java b/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java index 4f365eb..010abd3 100644 --- a/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java +++ b/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java @@ -694,7 +694,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport { public void acquireOfReadOnlyBufferMustBeReadOnly(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true); + buf.makeReadOnly(); try (Buffer acquire = buf.acquire()) { assertTrue(acquire.readOnly()); } @@ -707,7 +707,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { buf.writeLong(0x0102030405060708L); - buf.readOnly(true); + buf.makeReadOnly(); try (Buffer slice = buf.slice()) { assertTrue(slice.readOnly()); } @@ -720,7 +720,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(16)) { buf.writeLong(0x0102030405060708L); - buf.readOnly(true); + buf.makeReadOnly(); try (Buffer split = buf.split()) { assertTrue(split.readOnly()); assertTrue(buf.readOnly()); diff --git a/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java new file mode 100644 index 0000000..657f6e2 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java @@ -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()); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/BufferTestSupport.java b/src/test/java/io/netty/buffer/api/BufferTestSupport.java index 7d38e43..b2c4c72 100644 --- a/src/test/java/io/netty/buffer/api/BufferTestSupport.java +++ b/src/test/java/io/netty/buffer/api/BufferTestSupport.java @@ -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.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.HEAP; 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 static ExecutorService executor; + private static final Memoize INITIAL_NO_CONST = new Memoize<>( + () -> initialFixturesForEachImplementation().stream().filter(f -> !f.isConst()).toArray(Fixture[]::new)); private static final Memoize ALL_COMBINATIONS = new Memoize<>( () -> fixtureCombinations().toArray(Fixture[]::new)); private static final Memoize ALL_ALLOCATORS = new Memoize<>( @@ -127,6 +130,10 @@ public abstract class BufferTestSupport { return POOLED_DIRECT_ALLOCS.get(); } + static Fixture[] initialNoConstAllocators() { + return INITIAL_NO_CONST.get(); + } + static List initialAllocators() { return List.of( new Fixture("heap", BufferAllocator::heap, HEAP), @@ -135,7 +142,7 @@ public abstract class BufferTestSupport { new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER)); } - private static Stream fixtureCombinations() { + static List initialFixturesForEachImplementation() { List initFixtures = initialAllocators(); // Multiply by all MemoryManagers. @@ -144,12 +151,17 @@ public abstract class BufferTestSupport { loadableManagers.add(provider.get()); }); initFixtures = initFixtures.stream().flatMap(f -> { - Stream.Builder builder = Stream.builder(); + Builder builder = Stream.builder(); for (MemoryManagers managers : loadableManagers) { builder.add(new Fixture(f + "/" + managers, () -> using(managers, f), f.getProperties())); } return builder.build(); }).toList(); + return initFixtures; + } + + private static Stream fixtureCombinations() { + List initFixtures = initialFixturesForEachImplementation(); Builder builder = Stream.builder(); initFixtures.forEach(builder); @@ -244,8 +256,7 @@ public abstract class BufferTestSupport { var stream = builder.build(); return stream.flatMap(BufferTestSupport::injectSplits) - .flatMap(BufferTestSupport::injectSlices) - .flatMap(BufferTestSupport::injectReadOnlyToggling); + .flatMap(BufferTestSupport::injectSlices); } private static Stream injectSplits(Fixture f) { @@ -310,26 +321,6 @@ public abstract class BufferTestSupport { return builder.build(); } - private static Stream injectReadOnlyToggling(Fixture f) { - Builder 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) { props = Arrays.copyOf(props, props.length + 1); props[props.length - 1] = prop; diff --git a/src/test/java/io/netty/buffer/api/BufferWriteBytesCombinationsTest.java b/src/test/java/io/netty/buffer/api/BufferWriteBytesCombinationsTest.java new file mode 100644 index 0000000..0d10e96 --- /dev/null +++ b/src/test/java/io/netty/buffer/api/BufferWriteBytesCombinationsTest.java @@ -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 OTHER_FIXTURES = new Memoize( + () -> 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); + } + } +} diff --git a/src/test/java/io/netty/buffer/api/Fixture.java b/src/test/java/io/netty/buffer/api/Fixture.java index 9bd800c..8d0a677 100644 --- a/src/test/java/io/netty/buffer/api/Fixture.java +++ b/src/test/java/io/netty/buffer/api/Fixture.java @@ -72,9 +72,14 @@ public final class Fixture implements Supplier { return properties.contains(Properties.SLICE); } + public boolean isConst() { + return properties.contains(Properties.CONST); + } + public enum Properties { HEAP, DIRECT, + CONST, COMPOSITE, CLEANER, POOLED, diff --git a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java index 42016b7..cbf3684 100644 --- a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java +++ b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java @@ -17,7 +17,6 @@ package io.netty.buffer.api.examples.bytetomessagedecoder; import io.netty.buffer.api.Buffer; import io.netty.buffer.api.BufferAllocator; -import io.netty.buffer.api.CompositeBuffer; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.embedded.EmbeddedChannel; @@ -334,7 +333,7 @@ public class ByteToMessageDecoderTest { @Override 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.finish()); }