From dbb7e97cd05f3cce4b36084ae4858ce537736c84 Mon Sep 17 00:00:00 2001 From: Jacob G Date: Sat, 25 May 2019 12:10:34 -0400 Subject: [PATCH] Fixed potential bug; added another unit test. --- README.md | 4 ++-- pom.xml | 2 +- src/main/java/simplenet/Client.java | 28 ++++++++++++++++++---------- src/test/java/ReadTest.java | 25 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c03fb8e..3826118 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ Maven: com.github.jhg023 SimpleNet - 1.4.13 + 1.4.14 ``` Gradle: ```groovy -implementation 'com.github.jhg023:SimpleNet:1.4.13' +implementation 'com.github.jhg023:SimpleNet:1.4.14' ``` 2. Because SimpleNet is compiled with Java 11, you must first require its module in your `module-info.java`: diff --git a/pom.xml b/pom.xml index 9b2b5bd..3cdacce 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ com.github.jhg023 SimpleNet - 1.4.13 + 1.4.14 jar diff --git a/src/main/java/simplenet/Client.java b/src/main/java/simplenet/Client.java index bfe558a..0f6fda1 100644 --- a/src/main/java/simplenet/Client.java +++ b/src/main/java/simplenet/Client.java @@ -137,8 +137,12 @@ public void completed(Integer result, Client client) { queue.pollLast(); } - // TODO: After logging is added, warn the user if wrappedBuffer.hasRemaining() is true. - + if (wrappedBuffer.hasRemaining()) { + if (Utility.isDebug()) { + System.err.println(wrappedBuffer.remaining() + " byte(s) still need to be read!"); + } + } + while (!stack.isEmpty()) { queue.offerLast(stack.pop()); } @@ -152,10 +156,7 @@ public void completed(Integer result, Client client) { client.inCallback.set(false); if (client.size.get() > 0) { - // If we are about to call `channel.read`, then the position - // of the buffer must be placed after any remaining, unprocessed - // data. Regardless, it should be compacted as well. - buffer.compact().position(isQueueEmpty ? 0 : client.size.get()); + buffer.compact(); } else { buffer.clear(); } @@ -163,6 +164,7 @@ public void completed(Integer result, Client client) { if (isQueueEmpty) { // Because the queue is empty, the client should not attempt to read more data until // more is requested by the user. + buffer.position(0); client.readInProgress.set(false); } else { // Because the queue is NOT empty and we don't have enough data to process the request, @@ -548,17 +550,23 @@ public void readUntil(int n, Predicate predicate, ByteOrder order) { var wrappedBuffer = ByteBuffer.wrap(data).order(order); - if (!predicate.test(wrappedBuffer)) { + boolean shouldReturn = !predicate.test(wrappedBuffer); + + if (wrappedBuffer.hasRemaining()) { + if (Utility.isDebug()) { + System.err.println(wrappedBuffer.remaining() + " byte(s) still need to be read!"); + } + } + + if (shouldReturn) { return; } - - // TODO: After logging is added, warn the user if wrappedBuffer.hasRemaining() is true. } queue.offerFirst(pair); if (!readInProgress.getAndSet(true)) { - channel.read(buffer, this, Listener.INSTANCE); + channel.read(buffer.position(size.get()), this, Listener.INSTANCE); } } } diff --git a/src/test/java/ReadTest.java b/src/test/java/ReadTest.java index b7026c8..e500616 100644 --- a/src/test/java/ReadTest.java +++ b/src/test/java/ReadTest.java @@ -27,6 +27,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -340,6 +341,30 @@ void testReadNestedCallbacksExecuteInCorrectOrder() { }); } + @Test + void readWithSmallBuffer() { + byte b = 42; + long l = ThreadLocalRandom.current().nextLong(); + client = new Client(Long.BYTES); + client.onConnect(() -> { + Packet.builder().putByte(b).write(client); + Packet.builder().putLong(l).writeAndFlush(client); + }); + server.close(); + server = new Server(Long.BYTES); + server.bind(HOST, PORT); + server.onConnect(client -> { + client.readByte(first -> { + assertEquals(b, first); + + client.readLong(second -> { + assertEquals(l, second); + latch.countDown(); + }); + }); + }); + } + private void readStringHelper(String s, Charset charset, ByteOrder order) { client.onConnect(() -> Packet.builder().putString(s, charset, order).writeAndFlush(client)); server.onConnect(client -> client.readString(readString -> {