/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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
*
* http://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 org.apache.bookkeeper.util.collections;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import com.google.common.collect.Lists;
public class GrowableArrayBlockingQueueTest {
@Test
public void simple() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>(4);
assertEquals(null, queue.poll());
assertEquals(Integer.MAX_VALUE, queue.remainingCapacity());
assertEquals("[]", queue.toString());
try {
queue.element();
fail("Should have thrown exception");
} catch (NoSuchElementException e) {
// Expected
}
try {
queue.iterator();
fail("Should have thrown exception");
} catch (UnsupportedOperationException e) {
// Expected
}
// Test index rollover
for (int i = 0; i < 100; i++) {
queue.add(i);
assertEquals(i, queue.take().intValue());
}
queue.offer(1);
assertEquals("[1]", queue.toString());
queue.offer(2);
assertEquals("[1, 2]", queue.toString());
queue.offer(3);
assertEquals("[1, 2, 3]", queue.toString());
queue.offer(4);
assertEquals("[1, 2, 3, 4]", queue.toString());
assertEquals(4, queue.size());
List<Integer> list = new ArrayList<>();
queue.drainTo(list, 3);
assertEquals(1, queue.size());
assertEquals(Lists.newArrayList(1, 2, 3), list);
assertEquals("[4]", queue.toString());
assertEquals(4, queue.peek().intValue());
assertEquals(4, queue.element().intValue());
assertEquals(4, queue.remove().intValue());
try {
queue.remove();
fail("Should have thrown exception");
} catch (NoSuchElementException e) {
// Expected
}
}
@Test(timeout = 10000)
public void blockingTake() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>();
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
int expected = 0;
for (int i = 0; i < 100; i++) {
int n = queue.take();
assertEquals(expected++, n);
}
latch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
int n = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
queue.put(n);
++n;
}
// Wait until all the entries are consumed
while (!queue.isEmpty()) {
Thread.sleep(1);
}
}
latch.await();
}
@Test
public void growArray() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>(4);
assertEquals(null, queue.poll());
assertTrue(queue.offer(1));
assertTrue(queue.offer(2));
assertTrue(queue.offer(3));
assertTrue(queue.offer(4));
assertTrue(queue.offer(5));
assertEquals(5, queue.size());
queue.clear();
assertEquals(0, queue.size());
assertTrue(queue.offer(1, 1, TimeUnit.SECONDS));
assertTrue(queue.offer(2, 1, TimeUnit.SECONDS));
assertTrue(queue.offer(3, 1, TimeUnit.SECONDS));
assertEquals(3, queue.size());
List<Integer> list = new ArrayList<>();
queue.drainTo(list);
assertEquals(0, queue.size());
assertEquals(Lists.newArrayList(1, 2, 3), list);
}
@Test(timeout = 10000)
public void pollTimeout() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>(4);
assertEquals(null, queue.poll(1, TimeUnit.MILLISECONDS));
queue.put(1);
assertEquals(1, queue.poll(1, TimeUnit.MILLISECONDS).intValue());
// 0 timeout should not block
assertEquals(null, queue.poll(0, TimeUnit.HOURS));
queue.put(2);
queue.put(3);
assertEquals(2, queue.poll(1, TimeUnit.HOURS).intValue());
assertEquals(3, queue.poll(1, TimeUnit.HOURS).intValue());
}
@Test(timeout = 10000)
public void pollTimeout2() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>();
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> {
try {
queue.poll(1, TimeUnit.HOURS);
latch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
// Make sure background thread is waiting on poll
Thread.sleep(100);
queue.put(1);
latch.await();
}
}