#8414: fix drainTo when head == tail but the queue isn't empty

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2022-08-05 13:22:36 +02:00
parent 998bc8c7e8
commit 110896b4d1
2 changed files with 45 additions and 12 deletions

View File

@ -608,13 +608,19 @@ public class BlockingArrayQueue<E> extends AbstractList<E> 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;

View File

@ -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<String> queue = new BlockingArrayQueue<>(3);
@ -78,7 +79,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testRemove() throws Exception
public void testRemove()
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(3, 3);
@ -100,7 +101,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testLimit() throws Exception
public void testLimit()
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(1, 0, 1);
@ -113,7 +114,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testGrow() throws Exception
public void testGrow()
{
BlockingArrayQueue<String> 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<String> queue = new BlockingArrayQueue<>(6);
// Wrap the tail
@ -361,7 +362,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testRemoveObject() throws Exception
public void testRemoveObject()
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(4, 0, 4);
@ -395,7 +396,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testRemoveWithMaxCapacityOne() throws Exception
public void testRemoveWithMaxCapacityOne()
{
BlockingArrayQueue<String> queue = new BlockingArrayQueue<>(1);
@ -408,7 +409,7 @@ public class BlockingArrayQueueTest
}
@Test
public void testIteratorWithModification() throws Exception
public void testIteratorWithModification()
{
BlockingArrayQueue<String> 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<String> 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<String> 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<String> 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<Integer> queue = new BlockingArrayQueue<>();
for (int i = 0; i < BlockingArrayQueue.DEFAULT_GROWTH * 2; i++)
{
queue.add(i);
}
List<Integer> 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<Integer> queue = new BlockingArrayQueue<>();
List<Integer> list = new ArrayList<>();
assertThat(queue.drainTo(list), is(0));
assertThat(list.size(), is(0));
assertThat(queue.size(), is(0));
}
}