From 110896b4d1b26698f4a72912d1ef8527156d3ac7 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Fri, 5 Aug 2022 13:22:36 +0200 Subject: [PATCH] #8414: fix drainTo when head == tail but the queue isn't empty Signed-off-by: Ludovic Orban --- .../jetty/util/BlockingArrayQueue.java | 8 ++- .../jetty/util/BlockingArrayQueueTest.java | 49 ++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BlockingArrayQueue.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BlockingArrayQueue.java index df0e4a1dbf6..964b705f7e2 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/BlockingArrayQueue.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BlockingArrayQueue.java @@ -608,13 +608,19 @@ public class BlockingArrayQueue extends AbstractList implements BlockingQu _headLock.lock(); try { + if (_size.get() == 0) + return 0; + final int head = _indexes[HEAD_OFFSET]; final int tail = _indexes[TAIL_OFFSET]; final int capacity = _elements.length; int i = head; - while (i != tail && elements < maxElements) + while (elements < maxElements) { + if (i == tail && elements > 0) + break; + elements++; c.add((E)_elements[i]); ++i; diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/BlockingArrayQueueTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/BlockingArrayQueueTest.java index 69a0d916756..f7797ab6882 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/BlockingArrayQueueTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/BlockingArrayQueueTest.java @@ -28,6 +28,7 @@ import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import static org.awaitility.Awaitility.await; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -38,7 +39,7 @@ import static org.junit.jupiter.api.Assertions.fail; public class BlockingArrayQueueTest { @Test - public void testWrap() throws Exception + public void testWrap() { BlockingArrayQueue queue = new BlockingArrayQueue<>(3); @@ -78,7 +79,7 @@ public class BlockingArrayQueueTest } @Test - public void testRemove() throws Exception + public void testRemove() { BlockingArrayQueue queue = new BlockingArrayQueue<>(3, 3); @@ -100,7 +101,7 @@ public class BlockingArrayQueueTest } @Test - public void testLimit() throws Exception + public void testLimit() { BlockingArrayQueue queue = new BlockingArrayQueue<>(1, 0, 1); @@ -113,7 +114,7 @@ public class BlockingArrayQueueTest } @Test - public void testGrow() throws Exception + public void testGrow() { BlockingArrayQueue queue = new BlockingArrayQueue<>(3, 2); assertEquals(3, queue.getCapacity()); @@ -339,7 +340,7 @@ public class BlockingArrayQueueTest } @Test - public void testRemoveObjectWithWrappedTail() throws Exception + public void testRemoveObjectWithWrappedTail() { BlockingArrayQueue queue = new BlockingArrayQueue<>(6); // Wrap the tail @@ -361,7 +362,7 @@ public class BlockingArrayQueueTest } @Test - public void testRemoveObject() throws Exception + public void testRemoveObject() { BlockingArrayQueue queue = new BlockingArrayQueue<>(4, 0, 4); @@ -395,7 +396,7 @@ public class BlockingArrayQueueTest } @Test - public void testRemoveWithMaxCapacityOne() throws Exception + public void testRemoveWithMaxCapacityOne() { BlockingArrayQueue queue = new BlockingArrayQueue<>(1); @@ -408,7 +409,7 @@ public class BlockingArrayQueueTest } @Test - public void testIteratorWithModification() throws Exception + public void testIteratorWithModification() { BlockingArrayQueue queue = new BlockingArrayQueue<>(4, 0, 4); int count = queue.getMaxCapacity() - 1; @@ -430,7 +431,7 @@ public class BlockingArrayQueueTest } @Test - public void testListIterator() throws Exception + public void testListIterator() { BlockingArrayQueue queue = new BlockingArrayQueue<>(4, 0, 4); String element1 = "A"; @@ -464,7 +465,7 @@ public class BlockingArrayQueueTest } @Test - public void testListIteratorWithWrappedHead() throws Exception + public void testListIteratorWithWrappedHead() { BlockingArrayQueue queue = new BlockingArrayQueue<>(4, 0, 4); // This sequence of offers and polls wraps the head around the array @@ -504,7 +505,7 @@ public class BlockingArrayQueueTest } @Test - public void testDrainTo() throws Exception + public void testDrainTo() { BlockingArrayQueue queue = new BlockingArrayQueue<>(); queue.add("one"); @@ -525,4 +526,30 @@ public class BlockingArrayQueueTest assertThat(queue.size(), Matchers.is(0)); assertThat(queue, Matchers.empty()); } + + @Test + public void testDrainToAtDefaultGrowthSize() + { + BlockingArrayQueue queue = new BlockingArrayQueue<>(); + for (int i = 0; i < BlockingArrayQueue.DEFAULT_GROWTH * 2; i++) + { + queue.add(i); + } + + List list = new ArrayList<>(); + assertThat(queue.drainTo(list), is(BlockingArrayQueue.DEFAULT_GROWTH * 2)); + assertThat(list.size(), is(BlockingArrayQueue.DEFAULT_GROWTH * 2)); + assertThat(queue.size(), is(0)); + } + + @Test + public void testDrainToAtZeroSize() + { + BlockingArrayQueue queue = new BlockingArrayQueue<>(); + + List list = new ArrayList<>(); + assertThat(queue.drainTo(list), is(0)); + assertThat(list.size(), is(0)); + assertThat(queue.size(), is(0)); + } }