package org.apache.niolex.queue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.niolex.commons.concurrent.ThreadUtil;
import org.apache.niolex.commons.reflect.FieldUtil;
import org.apache.niolex.commons.test.MockUtil;
import org.apache.niolex.commons.util.Runner;
import org.apache.niolex.notify.AppTest;
import org.apache.niolex.queue.ZKBlockingQueue.ChildrenChangeWather;
import org.apache.niolex.zookeeper.core.ZKConnector;
import org.apache.niolex.zookeeper.core.ZKException;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class ZKBlockingQueueTest {
private static String BS = "/queue/zkc/tmp-" + MockUtil.randInt(100, 999);
private static ZKConnector ZKC;
/**
* @throws java.lang.Exception
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
ZKC = new ZKConnector(AppTest.URL, 10000);
if (ZKC.exists(BS))
ZKC.deleteTree(BS);
}
/**
* @throws java.lang.Exception
*/
@AfterClass
public static void tearDownAfterClass() throws Exception {
List<String> c = ZKC.getChildren(BS);
assertEquals(0, c.size());
ZKC.close();
}
ZKBlockingQueue<String> queue1;
ZKBlockingQueue<String> queue2;
@Before
public void setup() throws IOException {
queue1 = new ZKBlockingQueue<String>(ZKC, BS);
queue2 = new ZKBlockingQueue<String>(ZKC, BS + "/");
}
@After
public void clean() throws IOException {
queue1.poll();
queue2.poll();
queue1.close();
queue2.close();
}
@Test
public void testAddAuthInfo() throws Exception {
queue1.addAuthInfo("lex", "paS$w0rd");
queue2.addAuthInfo("lex", "paS$w0rd");
}
@Test
public void testOffer() throws Exception {
assertEquals(0, queue1.size());
assertEquals(0, queue2.size());
queue1.offer("nice-to-mm");
assertEquals(1, queue1.size());
assertEquals(1, queue2.size());
String s = queue2.poll(100, TimeUnit.MILLISECONDS);
assertEquals("nice-to-mm", s);
assertNull(queue1.peek());
assertNull(queue2.peek());
assertNull(queue1.poll());
assertNull(queue2.poll());
assertEquals(0, queue1.size());
assertEquals(0, queue2.size());
}
@Test
public void testOfferNull() throws Exception {
queue1.offer(null);
assertEquals(1, queue2.size());
assertNull(queue2.poll());
assertEquals(0, queue1.size());
}
public static class Bad implements Serializable {
private static final long serialVersionUID = -3027510281402896064L;
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
throw new IOException("Don't write this!");
}
}
@Test(expected=IllegalArgumentException.class)
public void testOfferEx() throws Exception {
ZKBlockingQueue<Bad> queue3 = new ZKBlockingQueue<Bad>(AppTest.URL, 10000, BS);
try {
queue3.offer(new Bad());
} finally {
queue3.close();
}
}
@Test
public void testGetChildren() throws Exception {
ZKC.createNode(BS + "/abc");
List<String> list = queue1.getChildren();
assertEquals(1, list.size());
assertEquals(1, queue2.size());
assertEquals("abc", list.get(0));
assertNull(queue1.peek());
assertNull(queue2.peek());
assertNull(queue1.poll());
assertNull(queue2.poll());
assertEquals(0, queue1.size());
assertEquals(0, queue2.size());
}
@Test
public void testPeek() throws Exception {
ZKBlockingQueue<Integer> queue3 = new ZKBlockingQueue<Integer>(AppTest.URL, 10000, BS);
queue3.offer(345);
try {
queue2.poll();
} finally {
queue3.close();
}
}
@Test(expected=IllegalStateException.class)
public void testPeekEx() throws Exception {
ZKC.createNode(BS + "/abc", new byte[] {33,44,55,66});
try {
queue2.peek();
} finally {
ZKC.deleteNode(BS + "/abc");
}
}
@Test(expected=ZKException.class)
public void testPoll() throws Exception {
ZKBlockingQueue<Integer> queue3 = new ZKBlockingQueue<Integer>(AppTest.URL, 10000, BS);
queue3.offer(345);
Integer c = queue3.poll(100, TimeUnit.MILLISECONDS);
assertEquals(345, c.intValue());
queue3.offer(7788);
c = queue3.peek();
assertEquals(7788, c.intValue());
try {
queue3.close();
ZooKeeper ZKC_zk = mock(ZooKeeper.class);
KeeperException ke = KeeperException.create(KeeperException.Code.NODEEXISTS);
doThrow(ke).when(ZKC_zk).getData(anyString(), anyBoolean(), any(Stat.class));
KeeperException ke2 = KeeperException.create(KeeperException.Code.AUTHFAILED);
doThrow(ke2).when(ZKC_zk).getData(anyString(), anyBoolean(), any(Stat.class));
ZKConnector zkc = FieldUtil.getValue(queue3, "zkc");
FieldUtil.setValue(zkc, "zk", ZKC_zk);
queue3.peek();
} finally {
queue2.poll(10, TimeUnit.MILLISECONDS);
queue3.close();
}
}
@Test
public void testSize() throws Exception {
queue1.put("Great!");
queue1.put("Go Away!");
assertEquals("Great!", queue1.peek());
assertEquals("Great!", queue2.peek());
assertEquals("Great!", queue2.poll());
assertEquals("Go Away!", queue2.poll());
assertNull(queue1.peek());
assertNull(queue2.peek());
}
public void offer() throws InterruptedException {
ThreadUtil.sleepAtLeast(50);
queue2.offer("after.");
}
@Test
public void testWatchQueue() throws Exception {
Thread t = Runner.run(this, "offer");
String s = queue1.take();
assertEquals("after.", s);
t.join();
}
@Test
public void testWatchQueueNormal() throws Exception {
assertNull(queue1.poll(10, TimeUnit.MICROSECONDS));
queue2.put("usage");
assertEquals("usage", queue2.peek());
queue2.watchQueue();
assertEquals("usage", queue2.poll());
}
@Test
public void testWatchQueueLongTimeUnit() throws Exception {
assertNull(queue1.poll(10, TimeUnit.MICROSECONDS));
queue2.put("usage");
assertEquals("usage", queue2.peek());
assertTrue(queue2.watchQueue(10, TimeUnit.MICROSECONDS));
assertEquals("usage", queue2.poll());
assertNull(queue1.poll(10, TimeUnit.MICROSECONDS));
}
@Test(expected=ZKException.class)
public void testWatchQueueEx() throws Exception {
ZKBlockingQueue<Integer> queue3 = new ZKBlockingQueue<Integer>(AppTest.URL, 10000, BS);
try {
queue3.close();
ZooKeeper ZKC_zk = mock(ZooKeeper.class);
KeeperException ke = KeeperException.create(KeeperException.Code.NODEEXISTS);
doThrow(ke).when(ZKC_zk).getChildren(anyString(), any(ChildrenChangeWather.class));
KeeperException ke2 = KeeperException.create(KeeperException.Code.AUTHFAILED);
doThrow(ke2).when(ZKC_zk).getChildren(anyString(), any(ChildrenChangeWather.class));
ZKConnector zkc = FieldUtil.getValue(queue3, "zkc");
FieldUtil.setValue(zkc, "zk", ZKC_zk);
queue3.watchQueue();
} finally {
queue2.poll(1, TimeUnit.MILLISECONDS);
queue3.close();
}
}
@Test(expected=ZKException.class)
public void testWatchQueueLongTimeUnitHasEx() throws Exception {
ZKBlockingQueue<Integer> queue3 = new ZKBlockingQueue<Integer>(AppTest.URL, 10000, BS);
try {
queue3.close();
ZooKeeper ZKC_zk = mock(ZooKeeper.class);
KeeperException ke = KeeperException.create(KeeperException.Code.NODEEXISTS);
doThrow(ke).when(ZKC_zk).getChildren(anyString(), any(ChildrenChangeWather.class));
KeeperException ke2 = KeeperException.create(KeeperException.Code.AUTHFAILED);
doThrow(ke2).when(ZKC_zk).getChildren(anyString(), any(ChildrenChangeWather.class));
ZKConnector zkc = FieldUtil.getValue(queue3, "zkc");
FieldUtil.setValue(zkc, "zk", ZKC_zk);
queue3.watchQueue(10, TimeUnit.MICROSECONDS);
} finally {
queue2.poll();
queue3.close();
}
}
@Test
public void testChildrenChangeWather() {
CountDownLatch latch = new CountDownLatch(1);
ZKBlockingQueue<String>.ChildrenChangeWather w = queue1.new ChildrenChangeWather(latch);
WatchedEvent event = new WatchedEvent(EventType.None, KeeperState.Expired, "/a/ab/cc");
w.process(event);
}
@Test
public void testChildrenChangeWatherProcess2() throws Exception {
ZKConnector zkc = mock(ZKConnector.class);
when(zkc.connected()).thenReturn(false, false, true);
ZKBlockingQueue<String> queue = new ZKBlockingQueue<String>(zkc, BS);
CountDownLatch latch = new CountDownLatch(1);
ZKBlockingQueue<String>.ChildrenChangeWather w = queue.new ChildrenChangeWather(latch);
w.process(new WatchedEvent(Watcher.Event.EventType.None, Watcher.Event.KeeperState.Disconnected, ""));
queue.close();
}
@Test(expected=NullPointerException.class)
public void testChildrenChangeWatherProcess3() throws Exception {
ZKConnector zkc = mock(ZKConnector.class);
when(zkc.connected()).thenReturn(false, false, true);
doThrow(new NullPointerException()).when(zkc).waitForConnectedTillDeath();
ZKBlockingQueue<String> queue = new ZKBlockingQueue<String>(zkc, BS);
CountDownLatch latch = new CountDownLatch(1);
ZKBlockingQueue<String>.ChildrenChangeWather w = queue.new ChildrenChangeWather(latch);
try {
w.process(new WatchedEvent(Watcher.Event.EventType.None, Watcher.Event.KeeperState.Disconnected, ""));
} finally {
queue.close();
}
}
}