From 8525cafdea953ab9941c4e26cb3e011d86248c27 Mon Sep 17 00:00:00 2001 From: Tomasz Kowalczewski Date: Mon, 31 Mar 2025 18:58:40 +0200 Subject: [PATCH 1/3] Downgraded to Java 8. Java 11 is still required to build and run test due to Mockito dependency. --- README.md | 6 +- pom.xml | 8 +-- .../org/voltdb/meshmonitor/ConsoleLogger.java | 4 +- .../GitPropertiesVersionProvider.java | 6 +- .../voltdb/meshmonitor/HistogramLogger.java | 4 +- .../meshmonitor/MeshMonitorTimings.java | 58 +++++++++++++++++-- .../org/voltdb/meshmonitor/ServerManager.java | 5 +- .../meshmonitor/cli/MeshMonitorCommand.java | 19 +++--- .../GitPropertiesVersionProviderTest.java | 42 +++++--------- .../meshmonitor/e2e/ContainerTestBase.java | 15 +++-- .../ByteBufferReadableByteChannel.java | 5 +- .../testutils/FakeWritableByteChannel.java | 4 +- .../testutils/FileChannelUtils.java | 11 ++++ 13 files changed, 121 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 4bd9d95..5f5e767 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ using [GraalVM Community Edition](https://github.com/graalvm/graalvm-ce-builds/r dependencies and can be run as is. A pure Java version in jar form (meshmonitor.jar) is also available. The Java version should work on -any platform with Java 17 or later installed (although it has only been tested on Linux). +any platform with Java 8 or later installed (although it has only been tested on Linux). # Using Meshmonitor @@ -230,11 +230,11 @@ Use the following command to run meshmonitor from the jar file: java -jar meshmonitor.jar ``` -It requires at least Java 17 to run. +Java 8 is enough run it but Java 11 is required to build and execute tests. ## Building -Java SDK is required to build and test the Meshmonitor. Version 17 or above. +Java SDK is required to build and test the Meshmonitor. Version 11 or above. Maven is used as a build system but does not need to be installed locally. The `mvnw` script (or `mvnw.cmd` on Windows) is used to bootstrap the build diff --git a/pom.xml b/pom.xml index 6d20272..f1ecfd3 100644 --- a/pom.xml +++ b/pom.xml @@ -21,11 +21,11 @@ UTF-8 UTF-8 - 17 - 17 + 8 + 8 - 17 - 17 + 11 + 11 meshmonitor org.voltdb.meshmonitor.cli.MeshMonitorCommand diff --git a/src/main/java/org/voltdb/meshmonitor/ConsoleLogger.java b/src/main/java/org/voltdb/meshmonitor/ConsoleLogger.java index ab6407d..563a1f6 100644 --- a/src/main/java/org/voltdb/meshmonitor/ConsoleLogger.java +++ b/src/main/java/org/voltdb/meshmonitor/ConsoleLogger.java @@ -69,14 +69,14 @@ private void log(String hostAddress, LogLevel logLevel, String message, Object.. String colourfulDateTime = CommandLine.Help.Ansi.AUTO.string(String.format("@|%s %s|@", logLevel, dateTime)); String colourfulHostAddress = CommandLine.Help.Ansi.AUTO.string(String.format("@|%s [%15s]|@", logLevel, hostAddress)); - out.println(colourfulDateTime + " " + colourfulHostAddress + " " + message.formatted(args)); + out.println(colourfulDateTime + " " + colourfulHostAddress + " " + String.format(message, args)); } public void debug(InetSocketAddress socketAddress, String format, Object... args) { String hostAddress = socketAddress.getAddress().getHostAddress(); if (enableDebugLogging) { - log(hostAddress, LogLevel.INFO, format.formatted(args)); + log(hostAddress, LogLevel.INFO, String.format(format, args)); } } diff --git a/src/main/java/org/voltdb/meshmonitor/GitPropertiesVersionProvider.java b/src/main/java/org/voltdb/meshmonitor/GitPropertiesVersionProvider.java index c116697..9ee8f52 100644 --- a/src/main/java/org/voltdb/meshmonitor/GitPropertiesVersionProvider.java +++ b/src/main/java/org/voltdb/meshmonitor/GitPropertiesVersionProvider.java @@ -59,15 +59,15 @@ public String getSimpleVersion() { String maybeCommitId = Objects.toString(properties.get(GIT_COMMIT_ID_PROPERTY), ""); StringBuilder version = new StringBuilder(); - if (!maybeTags.isBlank()) { + if (!maybeTags.trim().isEmpty()) { version.append(maybeTags); - } else if (!maybeCommitId.isBlank()) { + } else if (!maybeCommitId.trim().isEmpty()) { version.append(maybeCommitId); } else { version.append(VERSION_UNKNOWN); } - if (!maybeBuildTime.isBlank()) { + if (!maybeBuildTime.trim().isEmpty()) { version.append(" built on ").append(maybeBuildTime); } diff --git a/src/main/java/org/voltdb/meshmonitor/HistogramLogger.java b/src/main/java/org/voltdb/meshmonitor/HistogramLogger.java index 7f6f1f8..4d255f4 100644 --- a/src/main/java/org/voltdb/meshmonitor/HistogramLogger.java +++ b/src/main/java/org/voltdb/meshmonitor/HistogramLogger.java @@ -53,11 +53,11 @@ private String format(Histogram deltaHistogram, long minHiccupSizeMicroseconds) private String getFormatWithColours(double value, double minHiccupSize) { if (value > 999.9) { - String formatted = "%4.1fs".formatted(value / 1000.0); + String formatted = String.format("%4.1fs", value / 1000.0); return CommandLine.Help.Ansi.AUTO.string("@|bold,red " + formatted + "|@"); } - String formatted = "%5.1f".formatted(value); + String formatted = String.format("%5.1f", value); if (value > minHiccupSize) { return CommandLine.Help.Ansi.AUTO.string("@|bold,yellow " + formatted + "|@"); } diff --git a/src/main/java/org/voltdb/meshmonitor/MeshMonitorTimings.java b/src/main/java/org/voltdb/meshmonitor/MeshMonitorTimings.java index 317d757..98ca9f2 100644 --- a/src/main/java/org/voltdb/meshmonitor/MeshMonitorTimings.java +++ b/src/main/java/org/voltdb/meshmonitor/MeshMonitorTimings.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Volt Active Data Inc. + * Copyright (C) 2024-2025 Volt Active Data Inc. * * Use of this source code is governed by an MIT * license that can be found in the LICENSE file or at @@ -9,13 +9,24 @@ import org.HdrHistogram.SynchronizedHistogram; -public record MeshMonitorTimings( - HistogramWithDelta receiveHistogram, - HistogramWithDelta sendHistogram, - HistogramWithDelta deltaHistogram) { +import java.util.Objects; + +public final class MeshMonitorTimings { public static final int NUMBER_OF_SIGNIFICANT_VALUE_DIGITS = 3; public static final long HIGHEST_TRACKABLE_VALUE = 24 * 60 * 60 * 1000 * 1000L; + private final HistogramWithDelta receiveHistogram; + private final HistogramWithDelta sendHistogram; + private final HistogramWithDelta deltaHistogram; + + public MeshMonitorTimings( + HistogramWithDelta receiveHistogram, + HistogramWithDelta sendHistogram, + HistogramWithDelta deltaHistogram) { + this.receiveHistogram = receiveHistogram; + this.sendHistogram = sendHistogram; + this.deltaHistogram = deltaHistogram; + } public void pingReceived(long now, long lastReceiveTime, long timestampFromRemoteHost, long pingInterval) { long valueToRecord = now - lastReceiveTime; @@ -41,4 +52,41 @@ public static MeshMonitorTimings createDefault(ConsoleLogger logger) { new HistogramWithDelta(logger, "delta", defaultHistogram()) ); } + + public HistogramWithDelta receiveHistogram() { + return receiveHistogram; + } + + public HistogramWithDelta sendHistogram() { + return sendHistogram; + } + + public HistogramWithDelta deltaHistogram() { + return deltaHistogram; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) + return false; + MeshMonitorTimings that = (MeshMonitorTimings) obj; + return Objects.equals(this.receiveHistogram, that.receiveHistogram) && + Objects.equals(this.sendHistogram, that.sendHistogram) && + Objects.equals(this.deltaHistogram, that.deltaHistogram); + } + + @Override + public int hashCode() { + return Objects.hash(receiveHistogram, sendHistogram, deltaHistogram); + } + + @Override + public String toString() { + return "MeshMonitorTimings[" + + "receiveHistogram=" + receiveHistogram + ", " + + "sendHistogram=" + sendHistogram + ", " + + "deltaHistogram=" + deltaHistogram + ']'; + } + } diff --git a/src/main/java/org/voltdb/meshmonitor/ServerManager.java b/src/main/java/org/voltdb/meshmonitor/ServerManager.java index 35dad6e..6ccc4b2 100644 --- a/src/main/java/org/voltdb/meshmonitor/ServerManager.java +++ b/src/main/java/org/voltdb/meshmonitor/ServerManager.java @@ -12,6 +12,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public class ServerManager { @@ -30,14 +31,14 @@ public ServerManager(ConsoleLogger consoleLogger, MonitorFactory monitorFactory, public synchronized List getMonitors() { return monitors.stream() .filter(Monitor::isRunning) - .toList(); + .collect(Collectors.toList()); } public synchronized List getConnections() { return monitors.stream() .filter(Monitor::isRunning) .map(Monitor::getRemoteId) - .toList(); + .collect(Collectors.toList()); } public synchronized boolean createNewMonitorIfNotAlreadyPresent(SocketChannel channel, MeshMonitor meshMonitor, InetSocketAddress remoteId) { diff --git a/src/main/java/org/voltdb/meshmonitor/cli/MeshMonitorCommand.java b/src/main/java/org/voltdb/meshmonitor/cli/MeshMonitorCommand.java index 8c8eb68..db8287c 100644 --- a/src/main/java/org/voltdb/meshmonitor/cli/MeshMonitorCommand.java +++ b/src/main/java/org/voltdb/meshmonitor/cli/MeshMonitorCommand.java @@ -121,14 +121,17 @@ public Integer call() { System.out.println( CommandLine.Help.Ansi.AUTO.string( - """ - @|green __ ___ __ _ __ \s - / |/ /__ _____/ /_ ____ ___ ____ ____ (_) /_____ _____ - / /|_/ / _ \\/ ___/ __ \\/ __ `__ \\/ __ \\/ __ \\/ / __/ __ \\/ ___/ - / / / / __(__ ) / / / / / / / / /_/ / / / / / /_/ /_/ / / \s - /_/ /_/\\___/____/_/ /_/_/ /_/ /_/\\____/_/ /_/_/\\__/\\____/_/ \s - |@ %s - """.formatted(new GitPropertiesVersionProvider().getSimpleVersion()))); + String.format( + "@|green __ ___ __ _ __ \n" + + " / |/ /__ _____/ /_ ____ ___ ____ ____ (_) /_____ _____\n" + + " / /|_/ / _ \\/ ___/ __ \\/ __ `__ \\/ __ \\/ __ \\/ / __/ __ \\/ ___/\n" + + " / / / / __(__ ) / / / / / / / / /_/ / / / / / /_/ /_/ / / \n" + + " /_/ /_/\\___/____/_/ /_/_/ /_/ /_/\\____/_/ /_/_/\\__/\\____/_/ \n" + + " |@ %s\n", + new GitPropertiesVersionProvider().getSimpleVersion() + ) + ) + ); ConsoleLogger consoleLogger = new ConsoleLogger(spec.commandLine().getOut(), enableDebugLogging); ServerManager serverManager = new ServerManager(consoleLogger, Monitor::new, Duration.ofMillis(pingIntervalMilliseconds)); diff --git a/src/test/java/org/voltdb/meshmonitor/GitPropertiesVersionProviderTest.java b/src/test/java/org/voltdb/meshmonitor/GitPropertiesVersionProviderTest.java index fe7080d..265b226 100644 --- a/src/test/java/org/voltdb/meshmonitor/GitPropertiesVersionProviderTest.java +++ b/src/test/java/org/voltdb/meshmonitor/GitPropertiesVersionProviderTest.java @@ -22,48 +22,36 @@ public class GitPropertiesVersionProviderTest { static Stream variousPropertiesContents() { return Stream.of( Arguments.of( - """ - git.tags=v1.0 - git.build.time=2024-01-01 - git.commit.id.abbrev=abc123 - """, + "git.tags=v1.0\n" + + "git.build.time=2024-01-01\n" + + "git.commit.id.abbrev=abc123\n", "version v1.0 built on 2024-01-01" ), Arguments.of( - """ - git.tags= - git.build.time=2024-01-01 - git.commit.id.abbrev=abc123 - """, + "git.tags=\n" + + "git.build.time=2024-01-01\n" + + "git.commit.id.abbrev=abc123\n", "version abc123 built on 2024-01-01" ), Arguments.of( - """ - git.tags= - git.build.time=2024-01-01 - git.commit.id.abbrev= - """, + "git.tags=\n" + + "git.build.time=2024-01-01\n" + + "git.commit.id.abbrev=\n", "version unknown built on 2024-01-01" ), Arguments.of( - """ - git.tags= - git.build.time= - git.commit.id.abbrev= - """, + "git.tags=\n" + + "git.build.time=\n" + + "git.commit.id.abbrev=\n", "version unknown" ), Arguments.of( - """ - git.build.time=2024-01-01 - git.commit.id.abbrev=abc123 - """, + "git.build.time=2024-01-01\n" + + "git.commit.id.abbrev=abc123\n", "version abc123 built on 2024-01-01" ), Arguments.of( - """ - git.build.time=2024-01-01 - """, + "git.build.time=2024-01-01\n", "version unknown built on 2024-01-01" ), Arguments.of( diff --git a/src/test/java/org/voltdb/meshmonitor/e2e/ContainerTestBase.java b/src/test/java/org/voltdb/meshmonitor/e2e/ContainerTestBase.java index c642445..9bbe9b2 100644 --- a/src/test/java/org/voltdb/meshmonitor/e2e/ContainerTestBase.java +++ b/src/test/java/org/voltdb/meshmonitor/e2e/ContainerTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Volt Active Data Inc. + * Copyright (C) 2024-2025 Volt Active Data Inc. * * Use of this source code is governed by an MIT * license that can be found in the LICENSE file or at @@ -35,13 +35,12 @@ public class ContainerTestBase { private static final ImageFromDockerfile IMAGE_WITH_JAR = new ImageFromDockerfile() .withFileFromFile("/home/meshmonitor", new File(".").getAbsoluteFile().getParentFile()) - .withFileFromString("/home/meshmonitor/meshmonitor", """ - #!/bin/bash - - java --enable-preview \\ - -cp "/home/meshmonitor/target/meshmonitor-1.0.0-jar-with-dependencies.jar" \\ - org.voltdb.meshmonitor.cli.MeshMonitorCommand -i 1 "$@" - """) + .withFileFromString("/home/meshmonitor/meshmonitor", + "#!/bin/bash\n" + + "java \\\n" + + " -cp \"/home/meshmonitor/target/meshmonitor-1.0.0-jar-with-dependencies.jar\" \\\n" + + " org.voltdb.meshmonitor.cli.MeshMonitorCommand -i 1 \"$@\"\n" + ) .withDockerfileFromBuilder(builder -> builder .from("ghcr.io/graalvm/graalvm-community:21.0.1-ol9-20231024") diff --git a/src/test/java/org/voltdb/meshmonitor/testutils/ByteBufferReadableByteChannel.java b/src/test/java/org/voltdb/meshmonitor/testutils/ByteBufferReadableByteChannel.java index 1a7c27c..5b9c856 100644 --- a/src/test/java/org/voltdb/meshmonitor/testutils/ByteBufferReadableByteChannel.java +++ b/src/test/java/org/voltdb/meshmonitor/testutils/ByteBufferReadableByteChannel.java @@ -10,6 +10,8 @@ import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; +import static org.voltdb.meshmonitor.testutils.FileChannelUtils.byteBufferAbsolutePut; + public class ByteBufferReadableByteChannel implements ReadableByteChannel { private final ByteBuffer data; @@ -21,7 +23,8 @@ public class ByteBufferReadableByteChannel implements ReadableByteChannel { @Override public int read(ByteBuffer dst) { int remaining = dst.remaining(); - dst.put(dst.position(), data, data.position(), remaining); + + byteBufferAbsolutePut(dst, dst.position(), data, data.position(), remaining); dst.position(dst.position() + remaining); data.position(data.position() + remaining); diff --git a/src/test/java/org/voltdb/meshmonitor/testutils/FakeWritableByteChannel.java b/src/test/java/org/voltdb/meshmonitor/testutils/FakeWritableByteChannel.java index 5c593ee..b8f657d 100644 --- a/src/test/java/org/voltdb/meshmonitor/testutils/FakeWritableByteChannel.java +++ b/src/test/java/org/voltdb/meshmonitor/testutils/FakeWritableByteChannel.java @@ -10,6 +10,8 @@ import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; +import static org.voltdb.meshmonitor.testutils.FileChannelUtils.byteBufferAbsolutePut; + public class FakeWritableByteChannel implements WritableByteChannel { private final boolean isSlow; @@ -30,7 +32,7 @@ public int write(ByteBuffer src) { toBeWritten = 1; } - dataWritten.put(dataWritten.position(), src, src.position(), toBeWritten); + byteBufferAbsolutePut(dataWritten, dataWritten.position(), src, src.position(), toBeWritten); dataWritten.position(dataWritten.position() + toBeWritten); src.position(src.position() + toBeWritten); diff --git a/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java index 3a31fbf..204ff54 100644 --- a/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java +++ b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java @@ -18,4 +18,15 @@ public static FakeWritableByteChannel newWritableChannel(boolean isSlowConnectio public static ByteBufferReadableByteChannel newReadableChannel(ByteBuffer data) { return new ByteBufferReadableByteChannel(data); } + + /** + * It simulates put method that is available since Java 16: + *

+ * public ByteBuffer put(int index, ByteBuffer src, int offset, int length); + */ + public static void byteBufferAbsolutePut(ByteBuffer dst, int index, ByteBuffer src, int offset, int length) { + for (int i = offset, j = index; i < offset + length; i++, j++) { + dst.put(j, src.get(i)); + } + } } From 1bdf108d1a6545a8436f12491a68996397001d48 Mon Sep 17 00:00:00 2001 From: Tomasz Kowalczewski Date: Mon, 31 Mar 2025 19:48:50 +0200 Subject: [PATCH 2/3] Added tests for byteBufferAbsolutePut shim. --- .../testutils/FileChannelUtils.java | 11 +- .../testutils/FileChannelUtilsTest.java | 173 ++++++++++++++++++ 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtilsTest.java diff --git a/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java index 204ff54..7faef37 100644 --- a/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java +++ b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtils.java @@ -20,11 +20,20 @@ public static ByteBufferReadableByteChannel newReadableChannel(ByteBuffer data) } /** - * It simulates put method that is available since Java 16: + * It simulates put method that is available only since Java 16: *

* public ByteBuffer put(int index, ByteBuffer src, int offset, int length); */ public static void byteBufferAbsolutePut(ByteBuffer dst, int index, ByteBuffer src, int offset, int length) { + if ((index < 0) || (offset < 0) || (length < 0) || + (index > dst.limit() - length) || + (offset > src.limit() - length)) { + throw new IndexOutOfBoundsException( + String.format("dst.limit()=%d, index=%d, src.limit()=%d, offset=%d, length=%d", + dst.limit(), index, src.limit(), offset, length) + ); + } + for (int i = offset, j = index; i < offset + length; i++, j++) { dst.put(j, src.get(i)); } diff --git a/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtilsTest.java b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtilsTest.java new file mode 100644 index 0000000..e6aa781 --- /dev/null +++ b/src/test/java/org/voltdb/meshmonitor/testutils/FileChannelUtilsTest.java @@ -0,0 +1,173 @@ +package org.voltdb.meshmonitor.testutils; + +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.nio.ReadOnlyBufferException; +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +public class FileChannelUtilsTest { + + private byte[] createTestData(int size) { + byte[] data = new byte[size]; + for (int i = 0; i < size; i++) { + data[i] = (byte) (i % 128); + } + return data; + } + + @Test + public void testSimplePutHeap() { + // Give + byte[] srcData = createTestData(10); + byte[] dstData = new byte[10]; + Arrays.fill(dstData, (byte) -1); + + ByteBuffer src = ByteBuffer.wrap(srcData); + ByteBuffer dst = ByteBuffer.wrap(dstData); + + int srcPos = src.position(); + int dstPos = dst.position(); + + // When + // Copy 5 bytes from src[1..5] to dst[2..6] + FileChannelUtils.byteBufferAbsolutePut(dst, 2, src, 1, 5); + + // Then + byte[] expectedDst = {-1, -1, 1, 2, 3, 4, 5, -1, -1, -1}; + assertThat(expectedDst).containsExactly(dst.array()); + + // Verify positions unchanged + assertEquals(srcPos, src.position()); + assertEquals(dstPos, dst.position()); + } + + @Test + public void testSimplePutDirect() { + // Given + byte[] srcData = createTestData(10); + byte[] dstData = new byte[10]; + Arrays.fill(dstData, (byte) -1); + + ByteBuffer src = ByteBuffer.allocateDirect(10); + src.put(srcData).flip(); + + ByteBuffer dst = ByteBuffer.allocateDirect(10); + dst.put(dstData).clear(); + + // When + // Copy 5 bytes from src[1..5] to dst[2..6] + FileChannelUtils.byteBufferAbsolutePut(dst, 2, src, 1, 5); + + // Then + byte[] actualDst = new byte[10]; + dst.get(actualDst); + + byte[] expectedDst = {-1, -1, 1, 2, 3, 4, 5, -1, -1, -1}; + assertThat(expectedDst).containsExactly(actualDst); + } + + @Test + public void testPutToSelfNoOverlap() { + // Given + byte[] data = createTestData(10); + ByteBuffer buf = ByteBuffer.wrap(data); + int pos = buf.position(); + + // When + // Copy bytes 0,1,2 (src offset=0, len=3) to indices 5,6,7 (dst index=5) + FileChannelUtils.byteBufferAbsolutePut(buf, 5, buf, 0, 3); + + // Then + byte[] expected = {0, 1, 2, 3, 4, 0, 1, 2, 8, 9}; + assertThat(expected).containsExactly(buf.array()); + assertEquals(pos, buf.position()); + } + + @Test + public void testPutZeroLength() { + // Given + byte[] srcData = createTestData(5); + byte[] dstData = new byte[5]; + byte[] originalDstData = Arrays.copyOf(dstData, dstData.length); + + ByteBuffer src = ByteBuffer.wrap(srcData); + ByteBuffer dst = ByteBuffer.wrap(dstData); + int srcPos = src.position(); + int dstPos = dst.position(); + + // When + FileChannelUtils.byteBufferAbsolutePut(dst, 1, src, 1, 0); // Length is 0 + + // Then + assertThat(originalDstData).containsExactly(dst.array()); // Destination unchanged + assertEquals(srcPos, src.position()); + assertEquals(dstPos, dst.position()); + } + + @Test(expected = ReadOnlyBufferException.class) + public void testPutToReadOnlyBuffer() { + // Given + byte[] srcData = createTestData(5); + byte[] dstData = new byte[5]; + + ByteBuffer src = ByteBuffer.wrap(srcData); + ByteBuffer dst = ByteBuffer.wrap(dstData).asReadOnlyBuffer(); + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, 0, src, 0, 5); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testPutNegativeIndex() { + // Given + ByteBuffer src = ByteBuffer.allocate(5); + ByteBuffer dst = ByteBuffer.allocate(5); + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, -1, src, 0, 1); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testPutNegativeOffset() { + // Given + ByteBuffer src = ByteBuffer.allocate(5); + ByteBuffer dst = ByteBuffer.allocate(5); + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, 0, src, -1, 1); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testPutNegativeLength() { + // Given + ByteBuffer src = ByteBuffer.allocate(5); + ByteBuffer dst = ByteBuffer.allocate(5); + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, 0, src, 0, -1); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testPutIndexOverflow() { + // Given + ByteBuffer src = ByteBuffer.allocate(5); + ByteBuffer dst = ByteBuffer.allocate(5); // limit = 5 + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, 3, src, 0, 3); // index=3, length=3 -> needs dst[3..5], requires limit >= 6 + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testPutOffsetOverflow() { + // Given + ByteBuffer src = ByteBuffer.allocate(5); // limit = 5 + ByteBuffer dst = ByteBuffer.allocate(5); + + // When & Then + FileChannelUtils.byteBufferAbsolutePut(dst, 0, src, 3, 3); // offset=3, length=3 -> needs src[3..5], requires limit >= 6 + } +} From 0bcfc288a669c2fef6c870e4f5e0c328e955d1c0 Mon Sep 17 00:00:00 2001 From: Tomasz Kowalczewski Date: Mon, 31 Mar 2025 22:38:07 +0200 Subject: [PATCH 3/3] Typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f5e767..39a3e41 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ Use the following command to run meshmonitor from the jar file: java -jar meshmonitor.jar ``` -Java 8 is enough run it but Java 11 is required to build and execute tests. +Java 8 is enough to run it but Java 11 is required to build and execute tests. ## Building