From: <ble...@us...> - 2010-09-21 16:47:28
|
Revision: 3605 http://bigdata.svn.sourceforge.net/bigdata/?rev=3605&view=rev Author: blevine218 Date: 2010-09-21 16:47:18 +0000 (Tue, 21 Sep 2010) Log Message: ----------- Adding zookeeper suite of tests All tests now run without failures Modified Paths: -------------- branches/maven_scaleout/bigdata-integ/pom.xml branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java Added Paths: ----------- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooBarrier.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooElection.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZooQueue.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZookeeperAccessor.java branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/ZookeeperSuite.java Modified: branches/maven_scaleout/bigdata-integ/pom.xml =================================================================== --- branches/maven_scaleout/bigdata-integ/pom.xml 2010-09-21 15:00:39 UTC (rev 3604) +++ branches/maven_scaleout/bigdata-integ/pom.xml 2010-09-21 16:47:18 UTC (rev 3605) @@ -108,7 +108,11 @@ <include>**/Test*Remote.java</include> </includes> <excludes> + <!-- Don't include suites as part of the normal test run --> <exclude>**/*Suite.java</exclude> + + <!-- Don't include anonymous inner classes that happen to match the test pattern --> + <exclude>**/*$*.java</exclude> </excludes> <systemPropertyVariables> Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java 2010-09-21 15:00:39 UTC (rev 3604) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/AbstractFedZooTestCase.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -38,9 +38,8 @@ import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.data.ACL; -import org.junit.Rule; -import org.junit.rules.TestName; + import com.bigdata.jini.start.config.ZookeeperClientConfig; import com.bigdata.jini.start.process.ProcessHelper; import com.bigdata.jini.start.process.ZookeeperProcessHelper; Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java 2010-09-21 15:00:39 UTC (rev 3604) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/JiniStartSuite.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -1,17 +1,4 @@ -/*********************************************************************** - * - * $Id$ - * - * Copyright (c) 2000-2010 Nokia Corporation. - * - * This material, including documentation and any related computer - * programs, is protected by copyright controlled by Nokia Corporation. - * All rights are reserved. Copying, including reproducing, storing, - * adapting or translating, any or all of this material requires the prior - * written consent of Nokia Corporation. This material also contains - * confidential information which may not be disclosed to others without - * the prior written consent of Nokia Corporation. - **********************************************************************/ + package com.bigdata.jini.start; import org.junit.runner.RunWith; Modified: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java 2010-09-21 15:00:39 UTC (rev 3604) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/jini/start/config/JiniStartConfigSuite.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -1,17 +1,4 @@ -/*********************************************************************** - * - * $Id$ - * - * Copyright (c) 2000-2010 Nokia Corporation. - * - * This material, including documentation and any related computer - * programs, is protected by copyright controlled by Nokia Corporation. - * All rights are reserved. Copying, including reproducing, storing, - * adapting or translating, any or all of this material requires the prior - * written consent of Nokia Corporation. This material also contains - * confidential information which may not be disclosed to others without - * the prior written consent of Nokia Corporation. - **********************************************************************/ + package com.bigdata.jini.start.config; import org.junit.runner.RunWith; Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/AbstractZooTestCase.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -0,0 +1,528 @@ +/* + + Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + + Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * Created on Jan 4, 2009 + */ + +package com.bigdata.zookeeper; + +import java.io.File; +import java.io.IOException; +import java.net.BindException; +import java.net.ServerSocket; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +import com.bigdata.DataFinder; +import net.jini.config.Configuration; +import net.jini.config.ConfigurationProvider; + +import org.apache.log4j.Logger; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.KeeperException.NodeExistsException; +import org.apache.zookeeper.KeeperException.SessionExpiredException; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.data.ACL; +import org.apache.zookeeper.server.quorum.QuorumPeerMain; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; + +import com.bigdata.jini.start.MockListener; +import com.bigdata.jini.start.config.ZookeeperServerConfiguration; +import com.bigdata.jini.start.process.ProcessHelper; +import com.bigdata.jini.start.process.ZookeeperProcessHelper; +import com.bigdata.jini.util.ConfigMath; +import com.bigdata.resources.ResourceFileFilter; + +/** + * Abstract base class for zookeeper integration tests. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + */ +public abstract class AbstractZooTestCase { + + public final static Logger log = Logger.getLogger(AbstractZooTestCase.class); + + /** + * Constructor + */ + public AbstractZooTestCase() { + + } + + /** + * Return an open port on current machine. Try the suggested port first. If + * suggestedPort is zero, just select a random port + */ + protected static int getPort(final int suggestedPort) throws IOException { + + ServerSocket openSocket; + + try { + openSocket = new ServerSocket(suggestedPort); + } catch (BindException ex) { + // the port is busy, so look for a random open port + openSocket = new ServerSocket(0); + } + + final int port = openSocket.getLocalPort(); + + openSocket.close(); + + return port; + } + + /** + * A configuration file used by some of the unit tests in this package. It + * contains a description of the zookeeper server instance in case we need + * to start one. + */ + protected final String configFile = DataFinder.bestURI("testing/data/com/bigdata/zookeeper/testzoo.config").toASCIIString(); + + /** + * Note: The sessionTimeout is computed as 2x the tickTime as read out of + * the configuration file by {@link #setUp()}. This corresponds to the + * actual sessionTimeout for the client rather than a requested value. + */ + int sessionTimeout; + + /** + * The initial {@link ZooKeeper} instance obtained from the + * {@link #zookeeperAccessor} when the test was setup. + * <p> + * Note: Some unit tests use {@link #expireSession(ZooKeeper)} to expire the + * session associated with this {@link ZooKeeper} instance. + * + * @see ZooKeeperAccessor + */ + protected ZooKeeper zookeeper; + + /** + * Factory for {@link ZooKeeper} instances using the configured hosts and + * session timeout. + */ + protected ZooKeeperAccessor zookeeperAccessor; + + /** + * ACL used by the unit tests. + */ + protected final List<ACL> acl = Ids.OPEN_ACL_UNSAFE; + + protected final MockListener listener = new MockListener(); + + private File dataDir = null; + + // the chosen client port. + int clientPort = -1; + + @Before + public void setUp() throws Exception { + + try { + // find ports that are not in use. + clientPort = getPort(2181/* suggestedPort */); + final int peerPort = getPort(2888/* suggestedPort */); + final int leaderPort = getPort(3888/* suggestedPort */); + final String servers = "1=localhost:" + peerPort + ":" + leaderPort; + + // create a temporary file for zookeeper's state. + dataDir = File.createTempFile("test", ".zoo"); + // delete the file so that it can be re-created as a directory. + dataDir.delete(); + // recreate the file as a directory. + dataDir.mkdirs(); + + final String[] args = new String[] { + // The configuration file (overrides follow). + configFile, + // overrides the clientPort to be unique. + QuorumPeerMain.class.getName() + "." + + ZookeeperServerConfiguration.Options.CLIENT_PORT + "=" + + clientPort, + // overrides servers declaration. + QuorumPeerMain.class.getName() + "." + + ZookeeperServerConfiguration.Options.SERVERS + "=\"" + + servers + "\"", + // overrides the dataDir + QuorumPeerMain.class.getName() + "." + + ZookeeperServerConfiguration.Options.DATA_DIR + + "=new java.io.File(" + + ConfigMath.q(dataDir.toString()) + ")"// + }; + + System.err.println("args=" + Arrays.toString(args)); + + final Configuration config = ConfigurationProvider.getInstance(args); + + final int tickTime = (Integer) config.getEntry(QuorumPeerMain.class + .getName(), ZookeeperServerConfiguration.Options.TICK_TIME, + Integer.TYPE); + + /* + * Note: This is the actual session timeout that the zookeeper service + * will impose on the client. + */ + this.sessionTimeout = tickTime * 2; + + // if necessary, start zookeeper (a server instance). + ZookeeperProcessHelper.startZookeeper(config, listener); + + zookeeperAccessor = new ZooKeeperAccessor("localhost:" + clientPort, sessionTimeout); + + zookeeper = zookeeperAccessor.getZookeeper(); + + try { + + /* + * Since all unit tests use children of this node we must make sure + * that it exists. + */ + zookeeper + .create("/test", new byte[] {}, acl, CreateMode.PERSISTENT); + + } catch (NodeExistsException ex) { + + if (log.isInfoEnabled()) + log.info("/test already exits."); + + } + + } catch (Throwable t) { + + // don't leave around the dataDir if the setup fails. + recursiveDelete(dataDir); + + throw new Exception(t); + + } + + } + + @After + public void tearDown() throws Exception { + try { + if (zookeeperAccessor != null) { + zookeeperAccessor.close(); + } + + for (ProcessHelper h : listener.running) { + // destroy zookeeper service iff we started it. + h.kill(true/* immediateShutdown */); + } + + if (dataDir != null) { + // clean out the zookeeper data dir. + recursiveDelete(dataDir); + } + + } catch (Throwable t) { + log.error(t, t); + } + } + + /** + * Return a new {@link Zookeeper} instance that is connected to the same + * zookeeper ensemble but which has a distinct session. + * + * @return + * @throws IOException + * @throws InterruptedException + */ + protected ZooKeeper getDistinctZooKeeperWithDistinctSession() throws IOException, InterruptedException { + + final ZooKeeper zookeeper2 = new ZooKeeper(zookeeperAccessor.hosts, + zookeeperAccessor.sessionTimeout, new Watcher() { + public void process(WatchedEvent e) { + + } + }); + + /* + * Wait until this instance is connected. + */ + final long timeout = TimeUnit.MILLISECONDS.toNanos(1000/* ms */); + + final long begin = System.nanoTime(); + + while (zookeeper2.getState() != ZooKeeper.States.CONNECTED + && zookeeper2.getState().isAlive()) { + + final long elapsed = System.nanoTime() - begin; + + if (elapsed > timeout) { + Assert.fail("ZooKeeper session did not connect? elapsed="+ TimeUnit.NANOSECONDS.toMillis(elapsed)); + } + + if (log.isInfoEnabled()) { + log.info("Awaiting connected."); + } + + Thread.sleep(100/* ms */); + + } + + if (!zookeeper2.getState().isAlive()) { + Assert.fail("Zookeeper died?"); + } + + if(log.isInfoEnabled()) + log.info("Zookeeper connected."); + + return zookeeper2; + + } + + /** + * Return a new {@link ZooKeeper} instance that is connected to the same + * zookeeper ensemble as the given instance and is using the same session + * but is nevertheless a distinct instance. + * <p> + * Note: This is used by some unit tests to force the given + * {@link ZooKeeper} to report a {@link SessionExpiredException} by closing + * the returned instance. + * + * @param zookeeper + * A zookeeper instance. + * + * @return A distinct instance associated with the same session. + * + * @throws IOException + * @throws InterruptedException + */ + protected ZooKeeper getDistinctZooKeeperForSameSession(ZooKeeper zookeeper1) + throws IOException, InterruptedException { + + final ZooKeeper zookeeper2 = new ZooKeeper(zookeeperAccessor.hosts, + zookeeperAccessor.sessionTimeout, new Watcher() { + public void process(WatchedEvent e) { + + } + }, zookeeper1.getSessionId(), zookeeper1.getSessionPasswd()); + + /* + * Wait until this instance is connected. + */ + final long timeout = TimeUnit.MILLISECONDS.toNanos(1000/* ms */); + final long begin = System.nanoTime(); + + while (zookeeper2.getState() != ZooKeeper.States.CONNECTED + && zookeeper2.getState().isAlive()) { + final long elapsed = System.nanoTime() - begin; + + if (elapsed > timeout) { + Assert.fail("ZooKeeper session did not connect? elapsed=" + TimeUnit.NANOSECONDS.toMillis(elapsed)); + } + + if (log.isInfoEnabled()) { + log.info("Awaiting connected."); + } + + Thread.sleep(100/* ms */); + } + + if (!zookeeper2.getState().isAlive()) { + Assert.fail("Zookeeper died?"); + } + + if(log.isInfoEnabled()) + log.info("Zookeeper connected."); + + return zookeeper2; + } + + /** + * Expires the session associated with the {@link Zookeeper} client + * instance. + * + * @param zookeeper + * + * @throws IOException + * @throws InterruptedException + */ + protected void expireSession(ZooKeeper zookeeper) throws IOException,InterruptedException { + + /* + * Obtain a distinct ZooKeeper instance associated with the _same_ + * session. + */ + final ZooKeeper zookeeper2 = getDistinctZooKeeperForSameSession(zookeeper); + + /* + * Close this instance, forcing the original instance to report a + * SessionExpiredException. Note that this is not synchronous so we need + * to wait until the original ZooKeeper instance notices that its + * session is expired. + */ + zookeeper2.close(); + + /* + * Wait up to the session timeout and then wait some more so that the + * events triggered by that timeout have time to propagate. + */ + final long timeout = TimeUnit.MILLISECONDS.toNanos(sessionTimeout * 2); + final long begin = System.nanoTime(); + + while (zookeeper.getState().isAlive()) { + final long elapsed = System.nanoTime() - begin; + + if (elapsed > timeout) { + Assert.fail("ZooKeeper session did not expire? elapsed=" + + TimeUnit.NANOSECONDS.toMillis(elapsed) + + ", sessionTimeout=" + sessionTimeout); + } + + if(log.isInfoEnabled()) { + log.info("Awaiting session expired."); + } + + Thread.sleep(500/* ms */); + } + + if (log.isInfoEnabled()) { + final long elapsed = System.nanoTime() - begin; + + log.info("Session was expired: elapsed=" + + TimeUnit.NANOSECONDS.toMillis(elapsed) + + ", sessionTimeout=" + sessionTimeout); + } + } + + /** + * Class used to test concurrency primitives. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + */ + abstract protected class ClientThread extends Thread { + + private final Thread main; + protected final ReentrantLock lock; + + /** + * + * @param main + * The thread in which the test is running. + * @param lock + * A lock. + */ + public ClientThread(final Thread main, final ReentrantLock lock) { + + if (main == null) + throw new IllegalArgumentException(); + + if (lock == null) + throw new IllegalArgumentException(); + + this.main = main; + this.lock = lock; + setDaemon(true); + } + + public void run() { + try { + run2(); + } catch (Throwable t) { + + // log error since won't be seen otherwise. + log.error(t.getLocalizedMessage(), t); + + // interrupt the main thread. + main.interrupt(); + } + } + + abstract void run2() throws Exception; + } + + /** + * Recursively removes any files and subdirectories and then removes the + * file (or directory) itself. + * <p> + * Note: Files that are not recognized will be logged by the + * {@link ResourceFileFilter}. + * + * @param f + * A file or directory. + */ + private void recursiveDelete(final File f) { + + if (f.isDirectory()) { + + final File[] children = f.listFiles(); + + if (children == null) { + // The directory does not exist. + return; + } + + for (int i = 0; i < children.length; i++) { + recursiveDelete(children[i]); + } + } + + if(log.isInfoEnabled()) + log.info("Removing: " + f); + + if (f.exists() && !f.delete()) { + log.warn("Could not remove: " + f); + } + } + + /** + * Recursive delete of znodes. + * + * @param zpath + * + * @throws KeeperException + * @throws InterruptedException + */ + protected void destroyZNodes(final ZooKeeper zookeeper, final String zpath) + throws KeeperException, InterruptedException { + + // System.err.println("enter : " + zpath); + + final List<String> children = zookeeper.getChildren(zpath, false); + + for (String child : children) { + destroyZNodes(zookeeper, zpath + "/" + child); + } + + if(log.isInfoEnabled()) + log.info("delete: " + zpath); + + zookeeper.delete(zpath, -1/* version */); + } + + protected String getName() { + return getClass().getSimpleName(); + } +} Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestHierarchicalZNodeWatcher.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -0,0 +1,317 @@ +/* + +Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jan 12, 2009 + */ + +package com.bigdata.zookeeper; + +import java.util.concurrent.TimeUnit; + +import junit.framework.AssertionFailedError; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher.Event; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Test suite for {@link HierarchicalZNodeWatcher}. + * <p> + * Note: Zookeeper has other events that could appear during these unit tests, + * such as the connection status change events. However the unit test are not + * expecting such events during testing. If they appear, those events could + * cause test failures when we examine the queue. Basically, the tests are not + * robust if your zookeeper client is flakey. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + */ +public class TestHierarchicalZNodeWatcher extends AbstractZooTestCase implements + HierarchicalZNodeWatcherFlags { + + /** + * + */ + public TestHierarchicalZNodeWatcher() { + + } + + + protected String zroot; + + /** + * Sets up a unique {@link #zroot}. + */ + @Before + public void setUp() throws Exception { + super.setUp(); + zroot = zookeeper.create("/test", new byte[0], acl, CreateMode.PERSISTENT_SEQUENTIAL); + } + + /** + * Destroys the {@link #zroot} and its children. + */ + @After + public void tearDown() throws Exception { + if (zroot != null) { + destroyZNodes(zookeeperAccessor.getZookeeper(), zroot); + } + super.tearDown(); + } + + /** + * Test when the node at the root of the hierarchy does not exist when we + * setup the watcher, then create the znode and verify that we see the event + * in the queue. + * + * @throws KeeperException + * @throws InterruptedException + */ + @Test + public void test_noticeCreate() throws KeeperException, + InterruptedException { + + WatchedEvent e; + + final String zroot = this.zroot + "/" + "a"; + final HierarchicalZNodeWatcher watcher = new HierarchicalZNodeWatcher( + zookeeper, zroot, EXISTS) { + + @Override + protected int watch(String path, String child) { + return NONE; + } + }; + + Assert.assertTrue(watcher.queue.isEmpty()); + Assert.assertTrue(watcher.isWatched(zroot)); + + /* + * Create the zroot and verify the event is placed into the queue. + */ + + zookeeper.create(zroot, new byte[0], acl, CreateMode.PERSISTENT); + + // look for the create event. + e= watcher.queue.poll(1000, TimeUnit.MILLISECONDS); + + Assert.assertNotNull(e); + Assert.assertEquals(zroot,e.getPath()); + Assert.assertEquals(Event.EventType.NodeCreated,e.getType()); + Assert.assertTrue(watcher.queue.isEmpty()); + + /* + * Delete the znode and verify the event is placed into the queue. + */ + + zookeeper.delete(zroot, -1/*version*/); + + // look for the delete event. + e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS); + + Assert.assertNotNull(e); + Assert.assertEquals(zroot,e.getPath()); + Assert.assertEquals(Event.EventType.NodeDeleted, e.getType()); + Assert.assertTrue(watcher.queue.isEmpty()); + + /* + * Re-create the zroot and verify the event is placed into the queue + * (this makes sure that we are keeping the watch in place). + */ + + zookeeper.create(zroot, new byte[0], acl, CreateMode.PERSISTENT); + + // look for the create event. + e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS); + + Assert.assertNotNull(e); + Assert.assertEquals(zroot, e.getPath()); + Assert.assertEquals(Event.EventType.NodeCreated, e.getType()); + Assert.assertTrue(watcher.queue.isEmpty()); + + /* + * cancel the watcher and verify that it does not notice a delete of the + * zroot after it was cancelled. + */ + watcher.cancel(); + + /* + * Delete the znode - no event should appear. + */ + + zookeeper.delete(zroot, -1/*version*/); + + // look for the delete event. + e = watcher.queue.poll(1000, TimeUnit.MILLISECONDS); + + Assert.assertNull(e); + + } + + /** + * Unit test verifies that we notice specific children as they are created + * and destroyed. "red" znodes are ignored. if the znode is "blue" then we + * extend the watch over its children as well. + * + * @throws KeeperException + * @throws InterruptedException + * + * @todo test queue when data is changed. + */ + @Test + public void test_noticeChildren() throws InterruptedException, KeeperException { + + WatchedEvent e; + + HierarchicalZNodeWatcher watcher = new HierarchicalZNodeWatcher(zookeeper, zroot, EXISTS | CHILDREN) { + + @Override + protected int watch(String path, String child) { + + if (child.equals("red")) + return NONE; + + if (child.equals("blue")) + return EXISTS | CHILDREN; + + if (child.equals("green")) + return DATA; + + throw new AssertionFailedError("Not expecting: path=" + path + + ", child=" + child); + + } + + }; + + zookeeper.create(zroot + "/" + "red", new byte[0], acl, CreateMode.PERSISTENT); + + e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS); + Assert.assertNotNull(e); + Assert.assertEquals(zroot,e.getPath()); + Assert.assertEquals(Event.EventType.NodeChildrenChanged,e.getType()); + + zookeeper.create(zroot + "/" + "blue", new byte[0], acl, + CreateMode.PERSISTENT); + +// e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS); +// assertNotNull(e); +// assertEquals(zroot+"/"+"red",e.getPath()); +// assertEquals(Event.EventType.NodeCreated,e.getType()); + + zookeeper.create(zroot + "/" + "blue" + "/" + "green", new byte[0], + acl, CreateMode.PERSISTENT); + + Assert.assertEquals(NONE, watcher.getFlags(zroot + "/" + "red")); + Assert.assertEquals(EXISTS | CHILDREN, watcher.getFlags(zroot + "/" + "blue")); + Assert.assertEquals(DATA, watcher.getFlags(zroot + "/" + "blue" + "/" + "green")); + + // clear any events in the queue. + watcher.queue.clear(); + + // update the data. + zookeeper.setData(zroot + "/" + "blue" + "/" + "green", new byte[] { 1 }, -1/* version */); + + // verify event. + e = watcher.queue.poll(1000,TimeUnit.MILLISECONDS); + Assert.assertNotNull(e); + Assert.assertEquals(zroot + "/" + "blue" + "/" + "green",e.getPath()); + Assert.assertEquals(Event.EventType.NodeDataChanged,e.getType()); + + // won't been seen since a "red" path. + zookeeper.create(zroot + "/" + "red" + "/" + "blue", new byte[0], acl, CreateMode.PERSISTENT); + + Assert.assertEquals(NONE, watcher.getFlags(zroot + "/" + "red" + "/" + "blue")); + + /* + * There should be three watched znodes: zroot; zroot/blue; and + * zroot/blue/green + */ + Assert.assertEquals(3,watcher.getWatchedSize()); + + watcher.cancel(); + + Assert.assertEquals(0,watcher.getWatchedSize()); + Assert.assertFalse(watcher.isWatched(zroot)); + Assert.assertFalse(watcher.isWatched(zroot+"/"+"blue")); + Assert.assertFalse(watcher.isWatched(zroot+"/"+"blue"+"/"+"green")); + + Assert.assertTrue(watcher.queue.isEmpty()); + + /* + * Setup a new watcher that wathes all paths but the red ones. The + * znodes already exist. Now verify that we receive various notices when + * the watcher is created. + */ + watcher = new HierarchicalZNodeWatcher(zookeeper, zroot, ALL, true/* pumpMockEventsDuringStartup */) { + + @Override + protected int watch(String path, String child) { + + return ALL; + + } + +// @Override +// protected void addedWatch(String path, int flags) { +// +// placeMockEventInQueue(path, flags); +// +// } + + }; + + /* + * We created 4 znodes plus the pre-existing zroot, so there should be + * five nodes picked up by the new watcher. + */ + final String[] nodes = new String[] { + zroot, + zroot + "/" + "red", + zroot + "/" + "red" + "/" + "blue", + zroot + "/" + "blue", + zroot + "/" + "green" + "/" + "green", + }; + + // verify new watched size. + Assert.assertEquals(nodes.length, watcher.getWatchedSize()); + + /* + * Verify mock events were pumped into the queue. Since we specified + * ALL, there should be three events for each znode. + */ + Assert.assertEquals(3 * 5, watcher.queue.size()); + + while ((e = watcher.queue.poll()) != null) { + System.err.println("mockEvent: "+e); + } + + watcher.cancel(); + } +} Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestUnknownChildrenWatcher.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -0,0 +1,53 @@ +/* + +Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jan 22, 2009 + */ + +package com.bigdata.zookeeper; + +import org.junit.Test; + +/** + * Test suite for watcher for unknown children (those not previously seen). + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + */ +public class TestUnknownChildrenWatcher extends AbstractZooTestCase { + + /** + * + */ + public TestUnknownChildrenWatcher() { + } + + + /** @todo place holder for unit tests. */ + @Test + public void test_nothing() { + + } + +} Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZLockImpl.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -0,0 +1,626 @@ +/* + + Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + + Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* + * Created on Jan 7, 2009 + */ + +package com.bigdata.zookeeper; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.KeeperException.NoNodeException; +import org.apache.zookeeper.KeeperException.SessionExpiredException; +import org.junit.Assert; +import org.junit.Test; + +import com.bigdata.util.concurrent.DaemonThreadFactory; + +/** + * Test suite for {@link ZLockImpl}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + * + * @todo do test w/ ensemble where we kill the server to which the client is + * connected and verify that the client transparently reconnects to + * another server and continues to await the lock. + */ +public class TestZLockImpl extends AbstractZooTestCase { + + /** + * + */ + public TestZLockImpl() { + } + + + /** + * Simple lock protocol test. + * + * @todo test w/ timeout. + * + * @throws KeeperException + * @throws InterruptedException + */ + @Test + public void test_lock() throws KeeperException, InterruptedException { + + final Thread mainThread = Thread.currentThread(); + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + try { + /* + * verify no such node (should be unique and therefore not + * preexist). + */ + zookeeper.getChildren(zpath, false); + Assert.fail("zpath exists: " + zpath); + } catch (NoNodeException ex) { + // ignore. + } + + // instances that can contend for the lock. + final ZLockImpl lock1 = ZLockImpl.getLock(zookeeper, zpath, acl); + + // znode not created during ctor (more robust this way). + Assert.assertNull(zookeeper.exists(zpath, false)); + + final ZLockImpl lock2 = ZLockImpl.getLock(zookeeper, zpath, acl); + + // znode not created during ctor (more robust this way). + Assert.assertNull(zookeeper.exists(zpath, false)); + + // obtain the lock. + lock1.lock(); + + log.info("lock1 was granted in main thread"); + + // one child in the queue - the one that holds the lock. + Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size()); + + Assert.assertTrue(lock1.isLockHeld()); + + // run a thread that will contend for the lock. + final Thread t2 = new Thread() { + + public void run() { + + try { + + log.info("Starting 2nd thread."); + + Assert.assertTrue(lock1.isLockHeld()); + + log.info("Should block seeking lock2 in 2nd thread."); + + lock2.lock(); + + log.info("lock2 was granted"); + + // one child in the queue - the one that holds the lock. + Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size()); + + } catch (Throwable t) { + + // log error + log.error(t, t); + + // interrupt the main thread. + mainThread.interrupt(); + + } + } + + }; + + t2.setDaemon(true); + + t2.start(); + + // wait until the other child is also contending for the lock + for (int i = 0; i < 10; i++) { + + final int n = zookeeper.getChildren(zpath, false).size(); + + log.info("nchildren=" + n); + + if (n == 2) + break; + + Thread.sleep(10/* ms */); + + } + + // should be exactly two children in the queue. + Assert.assertEquals(2, zookeeper.getChildren(zpath, false).size()); + + log.info("Will release lock1."); + + // release the lock. + lock1.unlock(); + + log.info("Released lock1."); + + // wait until the other thread gains the lock. + for (int i = 0; i < 10 && !lock2.isLockHeld(); i++) { + + Thread.sleep(10/* ms */); + + } + + log.info("Verifying lock2 is held."); + + // verify lock is held. + Assert.assertTrue(lock2.isLockHeld()); + + log.info("Verifying queue contains only lock2."); + + // verify one child in the queue. + Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size()); + + log.info("Releasing lock2 from main thread."); + + // release the lock. + lock2.unlock(); + + log.info("Verifying queue is empty."); + + // queue is empty. + Assert.assertEquals(0, zookeeper.getChildren(zpath, false).size()); + + log.info("Test done."); + + } + + /** + * Unit test explores behavior when someone stomps on the zchild while a + * lock is held and another lock is in the queue (note that you can not + * delete the parent without deleting the children in zookeeper, so you will + * always see a queue purged of children before the queue node itself is + * deleted). + * + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void test_breakLock() throws KeeperException, InterruptedException { + + final Thread mainThread = Thread.currentThread(); + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + try { + /* + * verify no such node (should be unique and therefore not + * preexist). + */ + zookeeper.getChildren(zpath, false); + Assert.fail("zpath exists: " + zpath); + } catch (NoNodeException ex) { + // ignore. + } + + // instances that can contend for the lock. + final ZLockImpl lock1 = ZLockImpl.getLock(zookeeper, zpath, acl); + + // znode not created during ctor (more robust this way). + Assert.assertNull(zookeeper.exists(zpath, false)); + + final ZLockImpl lock2 = ZLockImpl.getLock(zookeeper, zpath, acl); + + // znode not created during ctor (more robust this way). + Assert.assertNull(zookeeper.exists(zpath, false)); + + // obtain the lock. + lock1.lock(); + + log.info("lock1 was granted"); + + // one child in the queue - the one that holds the lock. + Assert.assertEquals(1, zookeeper.getChildren(zpath, false).size()); + + Assert.assertTrue(lock1.isLockHeld()); + + // run a thread that will contend for the lock. + final Thread t2 = new Thread() { + + public void run() { + + try { + + Assert.assertTrue(lock1.isLockHeld()); + + lock2.lock(); + + log.info("lock2 granted."); + + } catch (Throwable t) { + + // log error + log.error(t, t); + + // interrupt the main thread. + mainThread.interrupt(); + + } + + } + + }; + + t2.setDaemon(true); + + t2.start(); + + // wait until the other child is also contending for the lock + for (int i = 0; i < 10 + && zookeeper.getChildren(zpath, false).size() != 2; i++) { + + Thread.sleep(10/* ms */); + + } + + // should be exactly two children in the queue. + Assert.assertEquals(2, zookeeper.getChildren(zpath, false).size()); + + // break the lock. + { + final String z = zpath + "/" + + ((ZLockImpl) lock1).getLockRequestZNode(); + log.info("breaking lock: deleting " + z); + zookeeper.delete(z, -1/* version */); + log.info("broke lock: deleted " + z); + } + + Assert.assertTrue(!lock1.isLockHeld()); + + Assert.assertTrue(lock2.isLockHeld()); + + log.info("lock1.unlock() - begin"); + + lock1.unlock(); + + log.info("lock1.unlock() - done"); + + Assert.assertFalse(lock1.isLockHeld()); + + } + + /** + * Unit test verifies that a {@link Thread} holding a {@link ZLock} may NOT + * acquire it again. + * + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void test_notReentrant() throws KeeperException, + InterruptedException { + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl); + + zlock.lock(); + + Assert.assertTrue(zlock.isLockHeld()); + + try { + zlock.lock(500, TimeUnit.MILLISECONDS); + Assert.fail("Expecting: " + TimeoutException.class); + } catch (TimeoutException ex) { + log.info("Expected exception: " + ex); + } + + // Assert.assertTrue(zlock.isLockHeld()); + // + // zlock.unlock(); + // + // Assert.assertTrue(zlock.isLockHeld()); + // + // zlock.unlock(); + // + // Assert.assertFalse(zlock.isLockHeld()); + + } + + /** + * Unit test where the session is expired before the lock is requested. + * lock() should throw out the {@link SessionExpiredException}. We then + * verify that we can obtain a new {@link ZooKeeper} instance associated + * with a new session and request and obtain the zlock. + * + * @throws IOException + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void test_sessionExpiredBeforeLockRequest() throws IOException, + KeeperException, InterruptedException { + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + expireSession(zookeeper); + + { + + // obtain a lock object. + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl); + + try { + + zlock.lock(); + + Assert.fail("Expecting: " + SessionExpiredException.class); + + } catch (SessionExpiredException ex) { + + if (log.isInfoEnabled()) + log.info("Ignoring expected exception: " + ex); + + } + + } + + // get a new instance associated with a new session. + zookeeper = zookeeperAccessor.getZookeeper(); + + // obtain a lock object. + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl); + zlock.lock(); + try { + + } finally { + zlock.unlock(); + } + + } + + /** + * Unit test where the session is expired while the caller is holding the + * lock. The test verifies that isLockHeld() throws a + * {@link SessionExpiredException}. + * + * @throws IOException + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void test_sessionExpiredWhileHoldingLock() throws IOException, + KeeperException, InterruptedException { + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + // obtain a lock object. + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl); + zlock.lock(); + try { + + Assert.assertTrue(zlock.isLockHeld()); + + expireSession(zookeeper); + + try { + + zlock.isLockHeld(); + + Assert.fail("Expecting: " + SessionExpiredException.class); + + } catch (SessionExpiredException ex) { + + if (log.isInfoEnabled()) + log.info("Ignoring expected exception: " + ex); + + } + + } finally { + /* + * Note: This also verifies that NO exception is thrown here even + * though the session has been expired. This is done to avoid have + * the expired session problem appear to arise from unlock() when it + * matters more that people see if when testing to verify that they + * hold the lock. + */ + zlock.unlock(); + } + + } + + /** + * Unit test for destroying a lock which is actively contended by other + * processes. + * + * @throws InterruptedException + * @throws KeeperException + * @throws ExecutionException + */ + @Test + public void test_destroyLock() throws KeeperException, + InterruptedException, ExecutionException { + + // a node that is guarenteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + final int ntasks = 4; + + final ExecutorService service = Executors.newFixedThreadPool(ntasks, + DaemonThreadFactory.defaultThreadFactory()); + + final LinkedList<Callable<Void>> tasks = new LinkedList<Callable<Void>>(); + + for (int i = 0; i < ntasks; i++) { + + tasks.add(new Callable<Void>() { + + /** + * Contends for the zlock. + * <p> + * Note: Task uses a distinct ZooKeeper having a distinct + * session. + */ + public Void call() throws Exception { + + final ZooKeeper zookeeper2 = getDistinctZooKeeperWithDistinctSession(); + + // obtain a lock object. + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper2, + zpath, acl); + + zlock.lock(); + try { + + Assert.fail("Should not have obtained the lock."); + + } finally { + + zlock.unlock(); + + } + + return null; + + } + + }); + + } + + final List<Future<Void>> futures = new LinkedList<Future<Void>>(); + try { + + // obtain a lock object. + final ZLockImpl zlock = ZLockImpl.getLock(zookeeper, zpath, acl); + + zlock.lock(); + try { + + // verify that the main thread holds the zlock. + Assert.assertTrue(zlock.isLockHeld()); + + // start the other tasks. they will contend for the same zlock. + for (Callable<Void> task : tasks) { + + futures.add(service.submit(task)); + + } + + // wait until everyone is contending for the lock. + int queueSize; + while ((queueSize = zlock.getQueue().length) < ntasks + 1) { + + if (log.isInfoEnabled()) + log.info("Waiting for other processes: queueSize=" + + queueSize); + + Thread.sleep(100/* ms */); + + } + + if (log.isInfoEnabled()) + log.info("Main thread will now destroy the lock."); + + zlock.destroyLock(); + + // verify lock no longer held. + Assert.assertFalse(zlock.isLockHeld()); + + } finally { + + // note: should quitely succeed if the lock was destroyed. + zlock.unlock(); + + } + + } finally { + + service.shutdownNow(); + + } + + // verify all tasks started. + Assert.assertEquals(ntasks, futures.size()); + + // check their futures. + for (Future<Void> f : futures) { + + try { + + f.get(); + + } catch (ExecutionException ex) { + + final Throwable cause = ex.getCause(); + + if (cause != null && cause instanceof InterruptedException) { + + /* + * When the lock znode is destroyed, the other processes + * contending for the zlock will notice in their + * ZLockWatcher. The ZLockWatcher will be set its + * [cancelled] flag and an InterruptedException will be + * thrown out of lock(). + */ + + if (log.isInfoEnabled()) { + + log.info("Ignoring expected exception: " + cause); + + } + + continue; + + } + + /* + * Rethrow the execption. + * + * Note: If any of the tasks gains the lock, then it will throw + * an AssertionFailedError. + */ + + throw ex; + + } + + } + } +} Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeCreatedWatcher.java 2010-09-21 16:47:18 UTC (rev 3605) @@ -0,0 +1,113 @@ +/* + +Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + * Created on Jan 7, 2009 + */ + +package com.bigdata.zookeeper; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.ZooDefs.Ids; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test suite for {@link ZNodeCreatedWatcher}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id$ + * + * @todo do test where we kill and then restart the server while awaiting the + * event and verify that we reconnect to the server and continue to await + * the event. + * + * @todo do test w/ ensemble where we kill the server to which the client is + * connected and verify that reconnect to another server and continue to + * await the event. + */ +public class TestZNodeCreatedWatcher extends AbstractZooTestCase { + + /** + * + */ + public TestZNodeCreatedWatcher() { + } + + + /** + * Verify that we can detect the create of a znode. + * + * @throws KeeperException + * @throws InterruptedException + */ + @Test + public void test_awaitCreate() throws KeeperException, InterruptedException { + + // a node that is guaranteed to be unique w/in the test namespace. + final String zpath = "/test/" + getName() + UUID.randomUUID(); + + final Thread mainThread = Thread.currentThread(); + + final Thread t = new Thread() { + + public void run() { + + try { + + Thread.sleep(100/*ms*/); + + zookeeper.create(zpath, new byte[0], Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + + } catch (Throwable t) { + + // log error + log.error(t, t); + + // interrupt the main thread. + mainThread.interrupt(); + + } + } + + }; + + t.setDaemon(true); + + t.start(); + + ZNodeCreatedWatcher.awaitCreate(zookeeper, zpath, 250, + TimeUnit.MILLISECONDS); + +// ZNodeCreatedWatcher.awaitCreate(zookeeper, zpath, 250, +// TimeUnit.MILLISECONDS); + + // verify znode was created. + Assert.assertNotNull(zookeeper.exists(zpath, false)); + } +} Copied: branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java (from rev 3580, branches/maven_scaleout/bigdata-core/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java) =================================================================== --- branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDeletedWatcher.java (rev 0) +++ branches/maven_scaleout/bigdata-integ/src/test/java/com/bigdata/zookeeper/TestZNodeDele... [truncated message content] |