/**
* Copyright 2016 Yahoo Inc.
*
* Licensed 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 com.yahoo.pulsar.common.util.collections;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
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.testng.annotations.Test;
import com.google.common.collect.Lists;
public class GrowableArrayBlockingQueueTest {
@Test
public void simple() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>(4);
assertEquals(queue.poll(), null);
assertEquals(queue.remainingCapacity(), Integer.MAX_VALUE);
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(queue.take().intValue(), i);
}
queue.offer(1);
assertEquals(queue.toString(), "[1]");
queue.offer(2);
assertEquals(queue.toString(), "[1, 2]");
queue.offer(3);
assertEquals(queue.toString(), "[1, 2, 3]");
queue.offer(4);
assertEquals(queue.toString(), "[1, 2, 3, 4]");
assertEquals(queue.size(), 4);
List<Integer> list = new ArrayList<>();
queue.drainTo(list, 3);
assertEquals(queue.size(), 1);
assertEquals(list, Lists.newArrayList(1, 2, 3));
assertEquals(queue.toString(), "[4]");
assertEquals(queue.peek().intValue(), 4);
assertEquals(queue.element().intValue(), 4);
assertEquals(queue.remove().intValue(), 4);
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(n, expected++);
}
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(queue.poll(), null);
assertTrue(queue.offer(1));
assertTrue(queue.offer(2));
assertTrue(queue.offer(3));
assertTrue(queue.offer(4));
assertTrue(queue.offer(5));
assertEquals(queue.size(), 5);
queue.clear();
assertEquals(queue.size(), 0);
assertTrue(queue.offer(1, 1, TimeUnit.SECONDS));
assertTrue(queue.offer(2, 1, TimeUnit.SECONDS));
assertTrue(queue.offer(3, 1, TimeUnit.SECONDS));
assertEquals(queue.size(), 3);
List<Integer> list = new ArrayList<>();
queue.drainTo(list);
assertEquals(queue.size(), 0);
assertEquals(list, Lists.newArrayList(1, 2, 3));
}
@Test(timeOut = 10000)
public void pollTimeout() throws Exception {
BlockingQueue<Integer> queue = new GrowableArrayBlockingQueue<>(4);
assertEquals(queue.poll(1, TimeUnit.MILLISECONDS), null);
queue.put(1);
assertEquals(queue.poll(1, TimeUnit.MILLISECONDS).intValue(), 1);
// 0 timeout should not block
assertEquals(queue.poll(0, TimeUnit.HOURS), null);
queue.put(2);
queue.put(3);
assertEquals(queue.poll(1, TimeUnit.HOURS).intValue(), 2);
assertEquals(queue.poll(1, TimeUnit.HOURS).intValue(), 3);
}
@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();
}
}