From 3281f723692b7b2416a0b360fdb825f2bdef7469 Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Thu, 29 Apr 2021 15:18:42 +0200 Subject: [PATCH 1/4] First draft of const buffers and how to have buffers as constants Currently only has a strawman implementation. --- src/main/java/io/netty/buffer/api/Buffer.java | 25 +++++++ .../io/netty/buffer/api/BufferAllocator.java | 33 ++++++++++ .../io/netty/buffer/api/MemoryManager.java | 3 - .../buffer/api/BufferBulkAccessTest.java | 13 ++++ .../netty/buffer/api/BufferReadOnlyTest.java | 30 ++++++++- .../netty/buffer/api/BufferTestSupport.java | 66 ++++++++++++------- 6 files changed, 144 insertions(+), 26 deletions(-) diff --git a/src/main/java/io/netty/buffer/api/Buffer.java b/src/main/java/io/netty/buffer/api/Buffer.java index 8043989..6e084dd 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 { /** @@ -308,6 +316,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..d6c34e3 100644 --- a/src/main/java/io/netty/buffer/api/BufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/BufferAllocator.java @@ -18,6 +18,7 @@ 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 +69,38 @@ 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 only "constants" in so far as they are {@linkplain Buffer#readOnly() read-only}. + * However, since all buffers are meant to behave the same, it is possible to make the returned buffers writeable + * again. Doing so will only impact the particular buffer instance, such that changing its contents will not impact + * any other buffer produced by the supplier. + *

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

+ * 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. Lastly, the read-only state could be changed, allowing the + * supposedly constant buffer to change its contents. 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) { + return () -> allocate(bytes.length).writeBytes(bytes).readOnly(true); + } + /** * 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. diff --git a/src/main/java/io/netty/buffer/api/MemoryManager.java b/src/main/java/io/netty/buffer/api/MemoryManager.java index ee0333e..7c864bd 100644 --- a/src/main/java/io/netty/buffer/api/MemoryManager.java +++ b/src/main/java/io/netty/buffer/api/MemoryManager.java @@ -15,9 +15,6 @@ */ 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 { diff --git a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java index 6a0d588..90e9bba 100644 --- a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java +++ b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java @@ -356,4 +356,17 @@ public class BufferBulkAccessTest extends BufferTestSupport { assertEquals(source, readableSlice); } } + + @ParameterizedTest + @MethodSource("allocators") + 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/BufferReadOnlyTest.java b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java index bce1846..4a7cce2 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.util.function.Supplier; + +import static java.nio.ByteOrder.BIG_ENDIAN; +import static java.nio.ByteOrder.LITTLE_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; @@ -136,5 +140,29 @@ public class BufferReadOnlyTest extends BufferTestSupport { } } } - // 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).readOnly(true)) { + assertThrows(IllegalStateException.class, () -> buf.writerOffset(4)); + } + } + + @Test + public void modifyingConstBufferDoesNotImpactSiblings() { + Supplier supplier = BufferAllocator.heap().constBufferSupplier(new byte[] {1, 2, 3, 4}); + try (Buffer a = supplier.get(); + Buffer b = supplier.get().order(LITTLE_ENDIAN)) { + a.order(BIG_ENDIAN).readOnly(false).setInt(0, 0xA1A2A3A4); + a.readerOffset(2); + assertThat(toByteArray(a)).containsExactly(0xA1, 0xA2, 0xA3, 0xA4); + assertThat(toByteArray(b)).containsExactly(1, 2, 3, 4); + assertThat(b.readerOffset()).isZero(); + assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); + assertThat(a.writerOffset()).isEqualTo(4); + assertThat(b.writerOffset()).isEqualTo(4); + } + } } diff --git a/src/test/java/io/netty/buffer/api/BufferTestSupport.java b/src/test/java/io/netty/buffer/api/BufferTestSupport.java index 7d38e43..38125f5 100644 --- a/src/test/java/io/netty/buffer/api/BufferTestSupport.java +++ b/src/test/java/io/netty/buffer/api/BufferTestSupport.java @@ -130,11 +130,23 @@ public abstract class BufferTestSupport { static List initialAllocators() { return List.of( new Fixture("heap", BufferAllocator::heap, HEAP), + new Fixture("constHeap", () -> constantBufferBasedAllocator(BufferAllocator.heap()), HEAP), + new Fixture("constDirect", () -> constantBufferBasedAllocator(BufferAllocator.direct()), + DIRECT, CLEANER), new Fixture("direct", BufferAllocator::direct, DIRECT, CLEANER), new Fixture("pooledHeap", BufferAllocator::pooledHeap, POOLED, HEAP), new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER)); } + private static BufferAllocator constantBufferBasedAllocator(BufferAllocator allocator) { + return size -> { + if (size < 0) { + throw new IllegalArgumentException(); + } + return allocator.constBufferSupplier(new byte[size]).get().readOnly(false).reset(); + }; + } + private static Stream fixtureCombinations() { List initFixtures = initialAllocators(); @@ -234,6 +246,37 @@ public abstract class BufferTestSupport { return buf; } + @Override + public void close() { + allocator.close(); + } + }; + }, COMPOSITE)); + builder.add(new Fixture(fixture + ".readOnly(true/false)", () -> { + var allocator = fixture.get(); + return new BufferAllocator() { + @Override + public Buffer allocate(int size) { + return allocator.allocate(size).readOnly(true).readOnly(false); + } + + @Override + public void close() { + allocator.close(); + } + }; + }, fixture.getProperties())); + builder.add(new Fixture(fixture + ".compose.readOnly(true/false)", () -> { + var allocator = fixture.get(); + return new BufferAllocator() { + @Override + public Buffer allocate(int size) { + try (Buffer buf = allocator.allocate(size)) { + CompositeBuffer composite = CompositeBuffer.compose(allocator, buf); + return composite.readOnly(true).readOnly(false); + } + } + @Override public void close() { allocator.close(); @@ -244,8 +287,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 +352,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; From d247ddeae35b51d70e0e431b8c2a61c728d2a140 Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Sun, 2 May 2021 17:07:58 +0200 Subject: [PATCH 2/4] Try speeding up the build some more The number of tests we run is increasing --- pom.xml | 1 + .../buffer/api/BufferBulkAccessTest.java | 54 - .../api/BufferByteOffsettedAccessorsTest.java | 341 +++ .../api/BufferCharOffsettedAccessorsTest.java | 190 ++ .../BufferDoubleOffsettedAccessorsTest.java | 172 ++ .../BufferFloatOffsettedAccessorsTest.java | 191 ++ .../api/BufferIntOffsettedAccessorsTest.java | 340 +++ .../api/BufferLongOffsettedAccessorsTest.java | 172 ++ .../BufferMediumOffsettedAccessorsTest.java | 360 +++ ...BufferPrimitiveOffsettedAccessorsTest.java | 1955 ----------------- .../BufferShortOffsettedAccessorsTest.java | 358 +++ .../api/BufferWriteBytesCombinationsTest.java | 81 + 12 files changed, 2206 insertions(+), 2009 deletions(-) create mode 100644 src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java delete mode 100644 src/test/java/io/netty/buffer/api/BufferPrimitiveOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java create mode 100644 src/test/java/io/netty/buffer/api/BufferWriteBytesCombinationsTest.java 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/test/java/io/netty/buffer/api/BufferBulkAccessTest.java b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java index 90e9bba..0469369 100644 --- a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java +++ b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java @@ -303,60 +303,6 @@ 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); - } - } - @ParameterizedTest @MethodSource("allocators") public void writeBytesMustWriteAllBytesFromByteArray(Fixture fixture) { 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..f0d1542 --- /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.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()); + } + } +} 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..dedb510 --- /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.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()); + } + } +} 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..47fd37f --- /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.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/BufferFloatOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java new file mode 100644 index 0000000..9fc6b2f --- /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.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()); + } + } +} 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..5a83cc1 --- /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.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()); + } + } +} 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..af67f8f --- /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.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()); + } + } +} 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..4b45f37 --- /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.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()); + } + } +} 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/BufferShortOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java new file mode 100644 index 0000000..7b6c691 --- /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.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()); + } + } +} 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); + } + } +} From 51cc1e7cf44a9170bf2bec3eabd065455c208b5f Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Mon, 3 May 2021 15:00:49 +0200 Subject: [PATCH 3/4] More efficient const buffer implementations The const buffers of the various implementations are now able to share the underlying memory. At least until they are forced not to. Const buffers will behave ust like normal buffers, except they start out as read-only. When they are made writable, or sliced, then they will allocate their own independent copy of the memory. That way, const buffers can have their contents changed, and behave just like normal buffers. The const-ness is a pure optimisation that should not have any externally observable behaviour. --- .../io/netty/buffer/api/BufferAllocator.java | 9 +- .../buffer/api/ManagedBufferAllocator.java | 18 ++- .../io/netty/buffer/api/MemoryManager.java | 2 +- .../buffer/api/SizeClassedMemoryPool.java | 8 + .../bytebuffer/ByteBufferMemoryManager.java | 12 +- .../buffer/api/bytebuffer/NioBuffer.java | 61 +++++++- .../io/netty/buffer/api/internal/ArcDrop.java | 7 + .../memseg/AbstractMemorySegmentManager.java | 10 +- .../api/memseg/HeapMemorySegmentManager.java | 5 - .../netty/buffer/api/memseg/MemSegBuffer.java | 74 ++++++++-- .../memseg/NativeMemorySegmentManager.java | 5 - .../netty/buffer/api/unsafe/UnsafeBuffer.java | 71 ++++++++- .../api/unsafe/UnsafeMemoryManager.java | 12 +- .../netty/buffer/api/BufferReadOnlyTest.java | 138 ++++++++++++++++-- .../netty/buffer/api/BufferTestSupport.java | 20 ++- .../java/io/netty/buffer/api/Fixture.java | 5 + 16 files changed, 386 insertions(+), 71 deletions(-) diff --git a/src/main/java/io/netty/buffer/api/BufferAllocator.java b/src/main/java/io/netty/buffer/api/BufferAllocator.java index d6c34e3..ba27595 100644 --- a/src/main/java/io/netty/buffer/api/BufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/BufferAllocator.java @@ -83,7 +83,10 @@ public interface BufferAllocator extends AutoCloseable { * any other buffer produced by the supplier. *

* 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. + * 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. Each buffer will then allocate + * their own independent copy of the data only when needed, such as when making the buffer writable, or when slicing + * the buffer. *

* 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 @@ -110,11 +113,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/ManagedBufferAllocator.java b/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java index 1295c71..315e296 100644 --- a/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java @@ -15,29 +15,37 @@ */ package io.netty.buffer.api; +import io.netty.buffer.api.internal.Statics; + import java.lang.ref.Cleaner; +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).readOnly(true); + return () -> manager.allocateCopyOnWritable(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 7c864bd..c65fde5 100644 --- a/src/main/java/io/netty/buffer/api/MemoryManager.java +++ b/src/main/java/io/netty/buffer/api/MemoryManager.java @@ -18,8 +18,8 @@ package io.netty.buffer.api; import java.lang.ref.Cleaner; public interface MemoryManager { - boolean isNative(); Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner); + Buffer allocateCopyOnWritable(Buffer ownedReadOnlyBuffer); 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..b13913c 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; @@ -54,6 +55,13 @@ class SizeClassedMemoryPool implements BufferAllocator, AllocatorControl, Drop constBufferSupplier(byte[] bytes) { + Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER); + constantBuffer.writeBytes(bytes).readOnly(true); + return () -> manager.allocateCopyOnWritable(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..997df48 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 allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { + assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); + NioBuffer buf = (NioBuffer) ownedReadOnlyBuffer; + 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..f86d09c 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) parent.unsafeGetDrop()).unwrap()))); + 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; @@ -159,6 +176,9 @@ class NioBuffer extends RcSupport implements Buffer, Readable @Override public Buffer readOnly(boolean readOnly) { + if (!readOnly) { + deconstify(); + } if (readOnly && wmem == rmem) { wmem = CLOSED_BUFFER; } else if (!readOnly && wmem != rmem) { @@ -180,6 +200,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable if (!isAccessible()) { throw new IllegalStateException("This buffer is closed: " + this + '.'); } + deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. ByteBuffer slice = rmem.slice(offset, length); ArcDrop drop = (ArcDrop) unsafeGetDrop(); drop.increment(); @@ -398,21 +419,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); } @@ -438,6 +466,9 @@ class NioBuffer extends RcSupport implements Buffer, Readable splitBuffer.order(order()); boolean readOnly = readOnly(); splitBuffer.readOnly(readOnly); + // 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 +585,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 +1085,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable throw bufferIsReadOnly(); } } + // @Override protected Owned prepareSend() { @@ -1060,6 +1093,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(); @@ -1071,6 +1105,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable copy.roff = roff; copy.woff = woff; copy.readOnly(readOnly); + copy.constBuffer = isConst; return copy; } }; @@ -1084,6 +1119,24 @@ class NioBuffer extends RcSupport implements Buffer, Readable woff = 0; } + /** + * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal + * buffer, in order to protect the const parent. + * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. + * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to + * guarantee that the contents of this buffer won't change. + */ + private void deconstify() { + if (constBuffer) { + ByteBuffer byteBuffer = (ByteBuffer) control.allocateUntethered(this, capacity()); + byteBuffer.put(rmem); + byteBuffer.order(rmem.order()); + Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); + unsafeSetDrop(drop); + attachNewBuffer(byteBuffer, drop); + } + } + @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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..bd5484f 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 allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { + assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); + MemSegBuffer buf = (MemSegBuffer) ownedReadOnlyBuffer; + 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..8e30c33 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) parent.unsafeGetDrop()).unwrap()))); + control = parent.control; + base = parent.base; + seg = parent.seg; + wseg = parent.wseg; + order = parent.order; + roff = parent.roff; + woff = parent.woff; + adaptor = null; // The adaptor must be independent, because we can de-constify. + constBuffer = true; + } + private static final class MakeInaccisbleOnDrop implements Drop { final Drop delegate; @@ -282,6 +299,9 @@ class MemSegBuffer extends RcSupport implements Buffer, Re @Override public Buffer readOnly(boolean readOnly) { + if (!readOnly) { + deconstify(); + } wseg = readOnly? CLOSED_SEGMENT : seg; return this; } @@ -299,9 +319,10 @@ class MemSegBuffer extends RcSupport implements Buffer, Re if (!isAccessible()) { throw new IllegalStateException("This buffer is closed: " + this + '.'); } + deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. var slice = seg.asSlice(offset, length); Drop drop = ArcDrop.acquire(unsafeGetDrop()); - return new MemSegBuffer(base, slice, drop, alloc) + return new MemSegBuffer(base, slice, drop, control) .writerOffset(length) .order(order()) .readOnly(readOnly()); @@ -518,32 +539,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 +590,15 @@ 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); + // 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 +1126,19 @@ 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); + copy.constBuffer = isConst; return copy; } }; @@ -1119,6 +1152,23 @@ class MemSegBuffer extends RcSupport implements Buffer, Re woff = 0; } + /** + * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal + * buffer, in order to protect the const parent. + * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. + * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to + * guarantee that the contents of this buffer won't change. + */ + private void deconstify() { + if (constBuffer) { + MemorySegment newSegment = (MemorySegment) control.allocateUntethered(this, capacity()); + newSegment.copyFrom(seg); + Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); + unsafeSetDrop(drop); + attachNewMemorySegment(newSegment, drop); + } + } + @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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..a73f22a 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) parent.unsafeGetDrop()).unwrap()))); + 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 + ']'; @@ -135,6 +153,9 @@ public class UnsafeBuffer extends RcSupport implements Buf @Override public Buffer readOnly(boolean readOnly) { + if (!readOnly) { + deconstify(); + } this.readOnly = readOnly; wsize = readOnly? CLOSED_SIZE : rsize; return this; @@ -151,6 +172,7 @@ public class UnsafeBuffer extends RcSupport implements Buf throw new IllegalArgumentException("Length cannot be negative: " + length + '.'); } checkGet(offset, length); + deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. ArcDrop drop = (ArcDrop) unsafeGetDrop(); drop.increment(); return new UnsafeBuffer(memory, baseOffset + offset, length, control, drop) @@ -436,24 +458,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); } @@ -478,6 +507,9 @@ public class UnsafeBuffer extends RcSupport implements Buf splitBuffer.order(order()); boolean readOnly = readOnly(); splitBuffer.readOnly(readOnly); + // 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 +660,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 +1222,7 @@ public class UnsafeBuffer extends RcSupport implements Buf } return this; } + // @Override protected Owned prepareSend() { @@ -1196,6 +1230,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; @@ -1209,6 +1244,7 @@ public class UnsafeBuffer extends RcSupport implements Buf copy.roff = roff; copy.woff = woff; copy.readOnly(readOnly); + copy.constBuffer = isConst; return copy; } }; @@ -1260,6 +1296,29 @@ public class UnsafeBuffer extends RcSupport implements Buf readOnly = false; } + /** + * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal + * buffer, in order to protect the const parent. + * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. + * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to + * guarantee that the contents of this buffer won't change. + */ + private void deconstify() { + if (constBuffer) { + UnsafeMemory newMemory = (UnsafeMemory) control.allocateUntethered(this, capacity()); + UnsafeMemory oldMemory = memory; + try { + PlatformDependent.copyMemory(base, address, newMemory.base, newMemory.address, newMemory.size); + Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); + unsafeSetDrop(drop); + attachNewMemory(newMemory, drop); + } finally { + Reference.reachabilityFence(newMemory); + Reference.reachabilityFence(oldMemory); + } + } + } + @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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..7699521 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 allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { + assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); + UnsafeBuffer buf = (UnsafeBuffer) ownedReadOnlyBuffer; + 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/BufferReadOnlyTest.java b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java index 4a7cce2..88a229e 100644 --- a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java +++ b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java @@ -19,6 +19,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.function.Supplier; import static java.nio.ByteOrder.BIG_ENDIAN; @@ -150,19 +152,129 @@ public class BufferReadOnlyTest extends BufferTestSupport { } } - @Test - public void modifyingConstBufferDoesNotImpactSiblings() { - Supplier supplier = BufferAllocator.heap().constBufferSupplier(new byte[] {1, 2, 3, 4}); - try (Buffer a = supplier.get(); - Buffer b = supplier.get().order(LITTLE_ENDIAN)) { - a.order(BIG_ENDIAN).readOnly(false).setInt(0, 0xA1A2A3A4); - a.readerOffset(2); - assertThat(toByteArray(a)).containsExactly(0xA1, 0xA2, 0xA3, 0xA4); - assertThat(toByteArray(b)).containsExactly(1, 2, 3, 4); - assertThat(b.readerOffset()).isZero(); - assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); - assertThat(a.writerOffset()).isEqualTo(4); - assertThat(b.writerOffset()).isEqualTo(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 modifyingConstBufferDoesNotImpactSiblings(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator()) { + Supplier supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}); + try (Buffer a = supplier.get().order(BIG_ENDIAN); + Buffer b = supplier.get().order(LITTLE_ENDIAN)) { + assertThat(a.order()).isEqualTo(BIG_ENDIAN); + assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); + a.readOnly(false); + a.setInt(0, 0xA1A2A3A4); + a.readerOffset(2); + assertThat(toByteArray(a)).containsExactly(0xA1, 0xA2, 0xA3, 0xA4); + assertThat(toByteArray(b)).containsExactly(1, 2, 3, 4); + assertThat(b.readerOffset()).isZero(); + assertThat(a.order()).isEqualTo(BIG_ENDIAN); + assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); + assertThat(a.writerOffset()).isEqualTo(4); + assertThat(b.writerOffset()).isEqualTo(4); + } + } + } + + @ParameterizedTest + @MethodSource("initialNoConstAllocators") + public void sliceOfConstBufferMustObserveChangesInParent(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer parent = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}).get(); + Buffer slice = parent.slice(0, 4)) { + parent.readOnly(false); + parent.setByte(0, (byte) 42); + assertThat(slice.getByte(0)).isEqualTo((byte) 42); + } + } + + @ParameterizedTest + @MethodSource("initialNoConstAllocators") + public void parentOfConstBufferSliceMustObserveChangesInSlice(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer parent = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}).get(); + Buffer slice = parent.slice(0, 4)) { + slice.readOnly(false); + slice.setByte(0, (byte) 42); + assertThat(parent.getByte(0)).isEqualTo((byte) 42); + } + } + + @ParameterizedTest + @MethodSource("initialNoConstAllocators") + public void splitsOfConstBuffersCanBecomeWritable(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer a = allocator.constBufferSupplier(new byte[16]).get(); + Buffer b = a.split(8)) { + assertTrue(a.readOnly()); + assertTrue(b.readOnly()); + assertThat(a.capacity()).isEqualTo(8); + assertThat(b.capacity()).isEqualTo(8); + a.readOnly(false); + b.readOnly(false); + a.setInt(0, 1); + b.setInt(0, 2); + assertEquals(1, a.getInt(0)); + assertEquals(2, b.getInt(0)); + } + } + + @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()) { + a.readShort(); + assertThrows(IllegalStateException.class, () -> a.compact()); // Can't compact read-only buffer. + a.readOnly(false).compact(); // Setting read-only to false will deconstify the buffer. + assertEquals(3, a.readByte()); + assertEquals(4, a.readByte()); + assertEquals(0, a.readableBytes()); + + assertEquals(1, b.readByte()); + assertEquals(2, b.readByte()); + assertEquals(3, b.readByte()); + assertEquals(4, b.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/BufferTestSupport.java b/src/test/java/io/netty/buffer/api/BufferTestSupport.java index 38125f5..f1ebad3 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,12 +130,16 @@ 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), - new Fixture("constHeap", () -> constantBufferBasedAllocator(BufferAllocator.heap()), HEAP), + new Fixture("constHeap", () -> constantBufferBasedAllocator(BufferAllocator.heap()), HEAP, CONST), new Fixture("constDirect", () -> constantBufferBasedAllocator(BufferAllocator.direct()), - DIRECT, CLEANER), + DIRECT, CONST, CLEANER), new Fixture("direct", BufferAllocator::direct, DIRECT, CLEANER), new Fixture("pooledHeap", BufferAllocator::pooledHeap, POOLED, HEAP), new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER)); @@ -147,7 +154,7 @@ public abstract class BufferTestSupport { }; } - private static Stream fixtureCombinations() { + static List initialFixturesForEachImplementation() { List initFixtures = initialAllocators(); // Multiply by all MemoryManagers. @@ -156,12 +163,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); 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, From 599c01b7623602243c24c9e04d6344b59dab32fe Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Wed, 5 May 2021 12:30:52 +0200 Subject: [PATCH 4/4] Make the buffer read-only state irreversible This greatly simplifies the semantics around the const buffers. When they can no longer be made writable, there is no longer any need for "deconstification". I decided to call the method "makeReadOnly" to distinguish it from "asReadOnly" that is seen in ByteBuf and ByteBuffer. The latter two return read-only _views_ of the buffer, while makeReadOnly changes the state of the buffer in-place. --- src/main/java/io/netty/buffer/api/Buffer.java | 6 +- .../io/netty/buffer/api/BufferAllocator.java | 19 +-- .../io/netty/buffer/api/CompositeBuffer.java | 6 +- .../buffer/api/ManagedBufferAllocator.java | 5 +- .../io/netty/buffer/api/MemoryManager.java | 2 +- .../buffer/api/SizeClassedMemoryPool.java | 6 +- .../bytebuffer/ByteBufferMemoryManager.java | 6 +- .../buffer/api/bytebuffer/NioBuffer.java | 49 +++----- .../memseg/AbstractMemorySegmentManager.java | 6 +- .../netty/buffer/api/memseg/MemSegBuffer.java | 46 +++---- .../netty/buffer/api/unsafe/UnsafeBuffer.java | 52 +++----- .../api/unsafe/UnsafeMemoryManager.java | 6 +- .../api/BufferByteOffsettedAccessorsTest.java | 18 +-- .../api/BufferCharOffsettedAccessorsTest.java | 10 +- .../api/BufferComponentIterationTest.java | 6 +- .../buffer/api/BufferCompositionTest.java | 12 +- .../BufferDoubleOffsettedAccessorsTest.java | 8 +- .../BufferFloatOffsettedAccessorsTest.java | 10 +- .../api/BufferIntOffsettedAccessorsTest.java | 18 +-- .../api/BufferLongOffsettedAccessorsTest.java | 8 +- .../BufferMediumOffsettedAccessorsTest.java | 20 ++-- .../BufferPrimitiveRelativeAccessorsTest.java | 22 ++-- .../netty/buffer/api/BufferReadOnlyTest.java | 112 +++++++----------- .../api/BufferReferenceCountingTest.java | 6 +- .../BufferShortOffsettedAccessorsTest.java | 20 ++-- .../netty/buffer/api/BufferTestSupport.java | 43 ------- .../ByteToMessageDecoderTest.java | 3 +- 27 files changed, 194 insertions(+), 331 deletions(-) diff --git a/src/main/java/io/netty/buffer/api/Buffer.java b/src/main/java/io/netty/buffer/api/Buffer.java index 6e084dd..e6187ca 100644 --- a/src/main/java/io/netty/buffer/api/Buffer.java +++ b/src/main/java/io/netty/buffer/api/Buffer.java @@ -226,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. diff --git a/src/main/java/io/netty/buffer/api/BufferAllocator.java b/src/main/java/io/netty/buffer/api/BufferAllocator.java index ba27595..0810145 100644 --- a/src/main/java/io/netty/buffer/api/BufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/BufferAllocator.java @@ -15,8 +15,6 @@ */ package io.netty.buffer.api; -import io.netty.buffer.api.internal.Statics; - import java.nio.ByteOrder; import java.util.function.Supplier; @@ -77,31 +75,26 @@ public interface BufferAllocator extends AutoCloseable { * 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 only "constants" in so far as they are {@linkplain Buffer#readOnly() read-only}. - * However, since all buffers are meant to behave the same, it is possible to make the returned buffers writeable - * again. Doing so will only impact the particular buffer instance, such that changing its contents will not impact - * any other buffer produced by the supplier. + * 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. Each buffer will then allocate - * their own independent copy of the data only when needed, such as when making the buffer writable, or when slicing - * the buffer. + * 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. Lastly, the read-only state could be changed, allowing the - * supposedly constant buffer to change its contents. The supplier-based API solves all of these problems, by - * enforcing that each usage get their own distinct buffer instance. + * 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) { - return () -> allocate(bytes.length).writeBytes(bytes).readOnly(true); + byte[] safeCopy = bytes.clone(); // Prevent modifying the bytes after creating the supplier. + return () -> allocate(bytes.length).writeBytes(safeCopy).makeReadOnly(); } /** 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 315e296..09ba957 100644 --- a/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java +++ b/src/main/java/io/netty/buffer/api/ManagedBufferAllocator.java @@ -17,7 +17,6 @@ package io.netty.buffer.api; import io.netty.buffer.api.internal.Statics; -import java.lang.ref.Cleaner; import java.util.function.Supplier; import static io.netty.buffer.api.internal.Statics.NO_OP_DROP; @@ -38,8 +37,8 @@ class ManagedBufferAllocator implements BufferAllocator, AllocatorControl { @Override public Supplier constBufferSupplier(byte[] bytes) { Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER); - constantBuffer.writeBytes(bytes).readOnly(true); - return () -> manager.allocateCopyOnWritable(constantBuffer); + constantBuffer.writeBytes(bytes).makeReadOnly(); + return () -> manager.allocateConstChild(constantBuffer); } @Override diff --git a/src/main/java/io/netty/buffer/api/MemoryManager.java b/src/main/java/io/netty/buffer/api/MemoryManager.java index c65fde5..0f2088d 100644 --- a/src/main/java/io/netty/buffer/api/MemoryManager.java +++ b/src/main/java/io/netty/buffer/api/MemoryManager.java @@ -19,7 +19,7 @@ import java.lang.ref.Cleaner; public interface MemoryManager { Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop drop, Cleaner cleaner); - Buffer allocateCopyOnWritable(Buffer ownedReadOnlyBuffer); + 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 b13913c..be6c8ea 100644 --- a/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java +++ b/src/main/java/io/netty/buffer/api/SizeClassedMemoryPool.java @@ -47,8 +47,6 @@ class SizeClassedMemoryPool implements BufferAllocator, AllocatorControl, Drop constBufferSupplier(byte[] bytes) { Buffer constantBuffer = manager.allocateShared(this, bytes.length, manager.drop(), Statics.CLEANER); - constantBuffer.writeBytes(bytes).readOnly(true); - return () -> manager.allocateCopyOnWritable(constantBuffer); + constantBuffer.writeBytes(bytes).makeReadOnly(); + return () -> manager.allocateConstChild(constantBuffer); } protected MemoryManager getMemoryManager() { 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 997df48..b9389ae 100644 --- a/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java +++ b/src/main/java/io/netty/buffer/api/bytebuffer/ByteBufferMemoryManager.java @@ -43,9 +43,9 @@ public class ByteBufferMemoryManager implements MemoryManager { } @Override - public Buffer allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { - assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); - NioBuffer buf = (NioBuffer) ownedReadOnlyBuffer; + public Buffer allocateConstChild(Buffer readOnlyConstParent) { + assert readOnlyConstParent.readOnly(); + NioBuffer buf = (NioBuffer) readOnlyConstParent; return new NioBuffer(buf); } 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 f86d09c..e96f2d0 100644 --- a/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java +++ b/src/main/java/io/netty/buffer/api/bytebuffer/NioBuffer.java @@ -61,7 +61,7 @@ class NioBuffer extends RcSupport implements Buffer, Readable * Constructor for {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffers}. */ NioBuffer(NioBuffer parent) { - super(new MakeInaccisbleOnDrop(new ArcDrop<>(((ArcDrop) parent.unsafeGetDrop()).unwrap()))); + 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. @@ -175,15 +175,8 @@ class NioBuffer extends RcSupport implements Buffer, Readable } @Override - public Buffer readOnly(boolean readOnly) { - if (!readOnly) { - deconstify(); - } - if (readOnly && wmem == rmem) { - wmem = CLOSED_BUFFER; - } else if (!readOnly && wmem != rmem) { - wmem = rmem; - } + public Buffer makeReadOnly() { + wmem = CLOSED_BUFFER; return this; } @@ -200,14 +193,16 @@ class NioBuffer extends RcSupport implements Buffer, Readable if (!isAccessible()) { throw new IllegalStateException("This buffer is closed: " + this + '.'); } - deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. 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 @@ -465,7 +460,9 @@ 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; @@ -1104,7 +1101,9 @@ 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; } @@ -1119,24 +1118,6 @@ class NioBuffer extends RcSupport implements Buffer, Readable woff = 0; } - /** - * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal - * buffer, in order to protect the const parent. - * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. - * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to - * guarantee that the contents of this buffer won't change. - */ - private void deconstify() { - if (constBuffer) { - ByteBuffer byteBuffer = (ByteBuffer) control.allocateUntethered(this, capacity()); - byteBuffer.put(rmem); - byteBuffer.order(rmem.order()); - Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); - unsafeSetDrop(drop); - attachNewBuffer(byteBuffer, drop); - } - } - @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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 bd5484f..6941143 100644 --- a/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java +++ b/src/main/java/io/netty/buffer/api/memseg/AbstractMemorySegmentManager.java @@ -34,9 +34,9 @@ public abstract class AbstractMemorySegmentManager implements MemoryManager { } @Override - public Buffer allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { - assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); - MemSegBuffer buf = (MemSegBuffer) ownedReadOnlyBuffer; + public Buffer allocateConstChild(Buffer readOnlyConstParent) { + assert readOnlyConstParent.readOnly(); + MemSegBuffer buf = (MemSegBuffer) readOnlyConstParent; return new MemSegBuffer(buf); } 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 8e30c33..b97a836 100644 --- a/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java +++ b/src/main/java/io/netty/buffer/api/memseg/MemSegBuffer.java @@ -106,7 +106,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re * Constructor for {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffers}. */ MemSegBuffer(MemSegBuffer parent) { - super(new MakeInaccisbleOnDrop(new ArcDrop<>(((ArcDrop) parent.unsafeGetDrop()).unwrap()))); + super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop())))); control = parent.control; base = parent.base; seg = parent.seg; @@ -114,7 +114,7 @@ class MemSegBuffer extends RcSupport implements Buffer, Re order = parent.order; roff = parent.roff; woff = parent.woff; - adaptor = null; // The adaptor must be independent, because we can de-constify. + adaptor = null; constBuffer = true; } @@ -298,11 +298,8 @@ class MemSegBuffer extends RcSupport implements Buffer, Re } @Override - public Buffer readOnly(boolean readOnly) { - if (!readOnly) { - deconstify(); - } - wseg = readOnly? CLOSED_SEGMENT : seg; + public Buffer makeReadOnly() { + wseg = CLOSED_SEGMENT; return this; } @@ -319,13 +316,15 @@ class MemSegBuffer extends RcSupport implements Buffer, Re if (!isAccessible()) { throw new IllegalStateException("This buffer is closed: " + this + '.'); } - deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. var slice = seg.asSlice(offset, length); Drop drop = ArcDrop.acquire(unsafeGetDrop()); - return new MemSegBuffer(base, slice, drop, control) + Buffer sliceBuffer = new MemSegBuffer(base, slice, drop, control) .writerOffset(length) - .order(order()) - .readOnly(readOnly()); + .order(order()); + if (readOnly()) { + sliceBuffer = sliceBuffer.makeReadOnly(); + } + return sliceBuffer; } @Override @@ -595,7 +594,9 @@ class MemSegBuffer extends RcSupport implements Buffer, Re 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; @@ -1137,7 +1138,9 @@ class MemSegBuffer extends RcSupport implements Buffer, Re copy.order = order; copy.roff = roff; copy.woff = woff; - copy.readOnly(readOnly); + if (readOnly) { + copy.makeReadOnly(); + } copy.constBuffer = isConst; return copy; } @@ -1152,23 +1155,6 @@ class MemSegBuffer extends RcSupport implements Buffer, Re woff = 0; } - /** - * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal - * buffer, in order to protect the const parent. - * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. - * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to - * guarantee that the contents of this buffer won't change. - */ - private void deconstify() { - if (constBuffer) { - MemorySegment newSegment = (MemorySegment) control.allocateUntethered(this, capacity()); - newSegment.copyFrom(seg); - Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); - unsafeSetDrop(drop); - attachNewMemorySegment(newSegment, drop); - } - } - @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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 a73f22a..e4b72aa 100644 --- a/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java +++ b/src/main/java/io/netty/buffer/api/unsafe/UnsafeBuffer.java @@ -70,7 +70,7 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re } UnsafeBuffer(UnsafeBuffer parent) { - super(new MakeInaccisbleOnDrop(new ArcDrop<>(((ArcDrop) parent.unsafeGetDrop()).unwrap()))); + super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop())))); control = parent.control; memory = parent.memory; base = parent.base; @@ -152,12 +152,9 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re } @Override - public Buffer readOnly(boolean readOnly) { - if (!readOnly) { - deconstify(); - } - this.readOnly = readOnly; - wsize = readOnly? CLOSED_SIZE : rsize; + public Buffer makeReadOnly() { + readOnly = true; + wsize = CLOSED_SIZE; return this; } @@ -172,13 +169,15 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re throw new IllegalArgumentException("Length cannot be negative: " + length + '.'); } checkGet(offset, length); - deconstify(); // Slice or parent could later be made writable, and if so, changes must be visible in both. 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 @@ -506,7 +505,9 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re 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; @@ -1243,7 +1244,9 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re copy.order(order); copy.roff = roff; copy.woff = woff; - copy.readOnly(readOnly); + if (readOnly) { + copy.makeReadOnly(); + } copy.constBuffer = isConst; return copy; } @@ -1296,29 +1299,6 @@ class UnsafeBuffer extends RcSupport implements Buffer, Re readOnly = false; } - /** - * If this buffer is a {@linkplain BufferAllocator#constBufferSupplier(byte[]) const buffer}, turn it into a normal - * buffer, in order to protect the const parent. - * A const buffer is sharing its memory with some parent, whose contents cannot be allowed to change. - * To ensure this, we must allocate our own memory and copy the contents, because we will soon not be able to - * guarantee that the contents of this buffer won't change. - */ - private void deconstify() { - if (constBuffer) { - UnsafeMemory newMemory = (UnsafeMemory) control.allocateUntethered(this, capacity()); - UnsafeMemory oldMemory = memory; - try { - PlatformDependent.copyMemory(base, address, newMemory.base, newMemory.address, newMemory.size); - Drop drop = ArcDrop.wrap(ArcDrop.unwrapAllArcs(unsafeGetDrop())); - unsafeSetDrop(drop); - attachNewMemory(newMemory, drop); - } finally { - Reference.reachabilityFence(newMemory); - Reference.reachabilityFence(oldMemory); - } - } - } - @Override public boolean isOwned() { return super.isOwned() && ((ArcDrop) unsafeGetDrop()).isOwned(); 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 7699521..97f794a 100644 --- a/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java +++ b/src/main/java/io/netty/buffer/api/unsafe/UnsafeMemoryManager.java @@ -57,9 +57,9 @@ public class UnsafeMemoryManager implements MemoryManager { } @Override - public Buffer allocateCopyOnWritable(Buffer ownedReadOnlyBuffer) { - assert ownedReadOnlyBuffer.isOwned() && ownedReadOnlyBuffer.readOnly(); - UnsafeBuffer buf = (UnsafeBuffer) ownedReadOnlyBuffer; + public Buffer allocateConstChild(Buffer readOnlyConstParent) { + assert readOnlyConstParent.readOnly(); + UnsafeBuffer buf = (UnsafeBuffer) readOnlyConstParent; return new UnsafeBuffer(buf); } diff --git a/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java index f0d1542..22d8c0e 100644 --- a/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferByteOffsettedAccessorsTest.java @@ -37,7 +37,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfByteReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getByte(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(-1)); } } @@ -83,7 +83,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { byte value = 0x01; buf.writeByte(value); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getByte(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(-1)); } } @@ -110,7 +110,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfByteReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getByte(0); + buf.makeReadOnly().getByte(0); } } @@ -119,7 +119,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getByte(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getByte(8)); } } @@ -137,7 +137,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedByte(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(-1)); } } @@ -193,7 +193,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { int value = 0x01; buf.writeUnsignedByte(value); - buf.readOnly(true).getUnsignedByte(1); + buf.makeReadOnly().getUnsignedByte(1); } } @@ -203,7 +203,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedByte(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(8)); } } @@ -230,7 +230,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedByteReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getUnsignedByte(0); + buf.makeReadOnly().getUnsignedByte(0); } } @@ -239,7 +239,7 @@ public class BufferByteOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedByteReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedByte(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedByte(8)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java index dedb510..2edac36 100644 --- a/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferCharOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferCharOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfCharReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getChar(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(-1)); } } @@ -91,7 +91,7 @@ public class BufferCharOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { char value = 0x0102; buf.writeChar(value); - buf.readOnly(true).getChar(1); + buf.makeReadOnly().getChar(1); } } @@ -100,7 +100,7 @@ public class BufferCharOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getChar(7)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(7)); } } @@ -127,7 +127,7 @@ public class BufferCharOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfCharReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getChar(0); + buf.makeReadOnly().getChar(0); } } @@ -136,7 +136,7 @@ public class BufferCharOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfCharReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getChar(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getChar(8)); } } 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 index 47fd37f..d002692 100644 --- a/src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferDoubleOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferDoubleOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfDoubleReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getDouble(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(-1)); } } @@ -82,7 +82,7 @@ public class BufferDoubleOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { double value = Double.longBitsToDouble(0x0102030405060708L); buf.writeDouble(value); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getDouble(1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(1)); } } @@ -109,7 +109,7 @@ public class BufferDoubleOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfDoubleReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getDouble(0); + buf.makeReadOnly().getDouble(0); } } @@ -118,7 +118,7 @@ public class BufferDoubleOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfDoubleReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getDouble(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getDouble(8)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java index 9fc6b2f..fce4902 100644 --- a/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferFloatOffsettedAccessorsTest.java @@ -37,7 +37,7 @@ public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfFloatReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getFloat(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(-1)); } } @@ -92,7 +92,7 @@ public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { float value = Float.intBitsToFloat(0x01020304); buf.writeFloat(value); - buf.readOnly(true).getFloat(1); + buf.makeReadOnly().getFloat(1); } } @@ -101,7 +101,7 @@ public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getFloat(5)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(5)); } } @@ -128,7 +128,7 @@ public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfFloatReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getFloat(0); + buf.makeReadOnly().getFloat(0); } } @@ -137,7 +137,7 @@ public class BufferFloatOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfFloatReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThan(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getFloat(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getFloat(8)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java index 5a83cc1..3e463b4 100644 --- a/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferIntOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfIntReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getInt(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(-1)); } } @@ -82,7 +82,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { int value = 0x01020304; buf.writeInt(value); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getInt(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(-1)); } } @@ -109,7 +109,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfIntReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getInt(0); + buf.makeReadOnly().getInt(0); } } @@ -118,7 +118,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getInt(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getInt(8)); } } @@ -136,7 +136,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedInt(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(-1)); } } @@ -192,7 +192,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { long value = 0x01020304; buf.writeUnsignedInt(value); - buf.readOnly(true).getUnsignedInt(1); + buf.makeReadOnly().getUnsignedInt(1); } } @@ -202,7 +202,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedInt(5)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(5)); } } @@ -229,7 +229,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedIntReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getUnsignedInt(0); + buf.makeReadOnly().getUnsignedInt(0); } } @@ -238,7 +238,7 @@ public class BufferIntOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedIntReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedInt(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedInt(8)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java index af67f8f..702795e 100644 --- a/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferLongOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferLongOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfLongReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getLong(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(-1)); } } @@ -82,7 +82,7 @@ public class BufferLongOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { long value = 0x0102030405060708L; buf.writeLong(value); - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getLong(1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(1)); } } @@ -109,7 +109,7 @@ public class BufferLongOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfLongReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getLong(0); + buf.makeReadOnly().getLong(0); } } @@ -118,7 +118,7 @@ public class BufferLongOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfLongReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getLong(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getLong(8)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java b/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java index 4b45f37..4be7196 100644 --- a/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferMediumOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfMediumReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getMedium(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(-1)); } } @@ -93,7 +93,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { int value = 0x010203; buf.writeMedium(value); - buf.readOnly(true).getMedium(1); + buf.makeReadOnly().getMedium(1); } } @@ -102,7 +102,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getMedium(6)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(6)); } } @@ -129,7 +129,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfMediumReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getMedium(0); + buf.makeReadOnly().getMedium(0); } } @@ -138,7 +138,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getMedium(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getMedium(8)); } } @@ -156,7 +156,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedMedium(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(-1)); } } @@ -212,7 +212,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { int value = 0x010203; buf.writeUnsignedMedium(value); - buf.readOnly(true).getUnsignedMedium(1); + buf.makeReadOnly().getUnsignedMedium(1); } } @@ -222,7 +222,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedMedium(6)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(6)); } } @@ -249,7 +249,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedMediumReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getUnsignedMedium(0); + buf.makeReadOnly().getUnsignedMedium(0); } } @@ -258,7 +258,7 @@ public class BufferMediumOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedMediumReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedMedium(8)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedMedium(8)); } } 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 88a229e..6ec8019 100644 --- a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java +++ b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java @@ -19,12 +19,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.function.Supplier; import static java.nio.ByteOrder.BIG_ENDIAN; -import static java.nio.ByteOrder.LITTLE_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; @@ -37,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); } @@ -48,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()); } @@ -56,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); } } @@ -76,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()); @@ -89,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()); @@ -104,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()); } } @@ -116,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()); } } @@ -126,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)); } } @@ -136,7 +134,7 @@ 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)); } @@ -147,7 +145,7 @@ public class BufferReadOnlyTest extends BufferTestSupport { @MethodSource("allocators") public void readOnlyBuffersCannotChangeWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); - Buffer buf = allocator.allocate(8).readOnly(true)) { + Buffer buf = allocator.allocate(8).makeReadOnly()) { assertThrows(IllegalStateException.class, () -> buf.writerOffset(4)); } } @@ -175,67 +173,30 @@ public class BufferReadOnlyTest extends BufferTestSupport { @ParameterizedTest @MethodSource("initialNoConstAllocators") - public void modifyingConstBufferDoesNotImpactSiblings(Fixture fixture) { + public void constBuffersCanBeSplit(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator()) { - Supplier supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}); - try (Buffer a = supplier.get().order(BIG_ENDIAN); - Buffer b = supplier.get().order(LITTLE_ENDIAN)) { - assertThat(a.order()).isEqualTo(BIG_ENDIAN); - assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); - a.readOnly(false); - a.setInt(0, 0xA1A2A3A4); - a.readerOffset(2); - assertThat(toByteArray(a)).containsExactly(0xA1, 0xA2, 0xA3, 0xA4); - assertThat(toByteArray(b)).containsExactly(1, 2, 3, 4); - assertThat(b.readerOffset()).isZero(); - assertThat(a.order()).isEqualTo(BIG_ENDIAN); - assertThat(b.order()).isEqualTo(LITTLE_ENDIAN); - assertThat(a.writerOffset()).isEqualTo(4); - assertThat(b.writerOffset()).isEqualTo(4); - } + Supplier supplier = allocator.constBufferSupplier(new byte[16]); + verifyConstBufferSplit(supplier); + // These shenanigans must not interfere with the parent const buffer. + verifyConstBufferSplit(supplier); } } - @ParameterizedTest - @MethodSource("initialNoConstAllocators") - public void sliceOfConstBufferMustObserveChangesInParent(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer parent = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}).get(); - Buffer slice = parent.slice(0, 4)) { - parent.readOnly(false); - parent.setByte(0, (byte) 42); - assertThat(slice.getByte(0)).isEqualTo((byte) 42); - } - } - - @ParameterizedTest - @MethodSource("initialNoConstAllocators") - public void parentOfConstBufferSliceMustObserveChangesInSlice(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer parent = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}).get(); - Buffer slice = parent.slice(0, 4)) { - slice.readOnly(false); - slice.setByte(0, (byte) 42); - assertThat(parent.getByte(0)).isEqualTo((byte) 42); - } - } - - @ParameterizedTest - @MethodSource("initialNoConstAllocators") - public void splitsOfConstBuffersCanBecomeWritable(Fixture fixture) { - try (BufferAllocator allocator = fixture.createAllocator(); - Buffer a = allocator.constBufferSupplier(new byte[16]).get(); + 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); - a.readOnly(false); - b.readOnly(false); - a.setInt(0, 1); - b.setInt(0, 2); - assertEquals(1, a.getInt(0)); - assertEquals(2, b.getInt(0)); + try (Buffer c = b.slice()) { + assertTrue(c.readOnly()); + assertFalse(c.isOwned()); + assertFalse(b.isOwned()); + assertThat(c.capacity()).isEqualTo(8); + } } } @@ -245,18 +206,25 @@ public class BufferReadOnlyTest extends BufferTestSupport { try (BufferAllocator allocator = fixture.createAllocator()) { Supplier supplier = allocator.constBufferSupplier(new byte[] {1, 2, 3, 4}); try (Buffer a = supplier.get(); - Buffer b = supplier.get()) { - a.readShort(); + 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. - a.readOnly(false).compact(); // Setting read-only to false will deconstify the buffer. assertEquals(3, a.readByte()); assertEquals(4, a.readByte()); - assertEquals(0, a.readableBytes()); 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()); } } } 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 index 7b6c691..657f6e2 100644 --- a/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java +++ b/src/test/java/io/netty/buffer/api/BufferShortOffsettedAccessorsTest.java @@ -36,7 +36,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfShortReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getShort(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(-1)); } } @@ -91,7 +91,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { short value = 0x0102; buf.writeShort(value); - buf.readOnly(true).getShort(1); + buf.makeReadOnly().getShort(1); } } @@ -100,7 +100,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetAndSizeIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getShort(7)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(7)); } } @@ -127,7 +127,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfShortReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getShort(0); + buf.makeReadOnly().getShort(0); } } @@ -136,7 +136,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getShort(7)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getShort(7)); } } @@ -154,7 +154,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckOnNegativeOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedShort(-1)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(-1)); } } @@ -210,7 +210,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { Buffer buf = allocator.allocate(8)) { int value = 0x0102; buf.writeUnsignedShort(value); - buf.readOnly(true).getUnsignedShort(1); + buf.makeReadOnly().getUnsignedShort(1); } } @@ -220,7 +220,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedShort(7)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(7)); } } @@ -247,7 +247,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedShortReadOnlyMustNotBoundsCheckWhenReadOffsetIsGreaterThanWriteOffset(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - buf.readOnly(true).getUnsignedShort(0); + buf.makeReadOnly().getUnsignedShort(0); } } @@ -256,7 +256,7 @@ public class BufferShortOffsettedAccessorsTest extends BufferTestSupport { void offsettedGetOfUnsignedShortReadOnlyMustBoundsCheckWhenReadOffsetIsGreaterThanCapacity(Fixture fixture) { try (BufferAllocator allocator = fixture.createAllocator(); Buffer buf = allocator.allocate(8)) { - assertThrows(IndexOutOfBoundsException.class, () -> buf.readOnly(true).getUnsignedShort(7)); + assertThrows(IndexOutOfBoundsException.class, () -> buf.makeReadOnly().getUnsignedShort(7)); } } diff --git a/src/test/java/io/netty/buffer/api/BufferTestSupport.java b/src/test/java/io/netty/buffer/api/BufferTestSupport.java index f1ebad3..b2c4c72 100644 --- a/src/test/java/io/netty/buffer/api/BufferTestSupport.java +++ b/src/test/java/io/netty/buffer/api/BufferTestSupport.java @@ -137,23 +137,11 @@ public abstract class BufferTestSupport { static List initialAllocators() { return List.of( new Fixture("heap", BufferAllocator::heap, HEAP), - new Fixture("constHeap", () -> constantBufferBasedAllocator(BufferAllocator.heap()), HEAP, CONST), - new Fixture("constDirect", () -> constantBufferBasedAllocator(BufferAllocator.direct()), - DIRECT, CONST, CLEANER), new Fixture("direct", BufferAllocator::direct, DIRECT, CLEANER), new Fixture("pooledHeap", BufferAllocator::pooledHeap, POOLED, HEAP), new Fixture("pooledDirect", BufferAllocator::pooledDirect, POOLED, DIRECT, CLEANER)); } - private static BufferAllocator constantBufferBasedAllocator(BufferAllocator allocator) { - return size -> { - if (size < 0) { - throw new IllegalArgumentException(); - } - return allocator.constBufferSupplier(new byte[size]).get().readOnly(false).reset(); - }; - } - static List initialFixturesForEachImplementation() { List initFixtures = initialAllocators(); @@ -258,37 +246,6 @@ public abstract class BufferTestSupport { return buf; } - @Override - public void close() { - allocator.close(); - } - }; - }, COMPOSITE)); - builder.add(new Fixture(fixture + ".readOnly(true/false)", () -> { - var allocator = fixture.get(); - return new BufferAllocator() { - @Override - public Buffer allocate(int size) { - return allocator.allocate(size).readOnly(true).readOnly(false); - } - - @Override - public void close() { - allocator.close(); - } - }; - }, fixture.getProperties())); - builder.add(new Fixture(fixture + ".compose.readOnly(true/false)", () -> { - var allocator = fixture.get(); - return new BufferAllocator() { - @Override - public Buffer allocate(int size) { - try (Buffer buf = allocator.allocate(size)) { - CompositeBuffer composite = CompositeBuffer.compose(allocator, buf); - return composite.readOnly(true).readOnly(false); - } - } - @Override public void close() { allocator.close(); 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()); }