@Test
public void misbehavingClient() throws Exception {

    final int propagationTime = 5;
    final AtomicBoolean triggerExceptions = new AtomicBoolean(false);
    final CountDownLatch createLatch = new CountDownLatch(1);
    final CountDownLatch dataLatch = new CountDownLatch(1);
    final CountDownLatch removeLatch = new CountDownLatch(1);
    final NodeWatcherListener listener = new NodeWatcherListener() {
        @Override
        public void nodeCreated(String zkPath, String data) {
            if (triggerExceptions.get()) {
                throw new RuntimeException("boo!");
            }
            createLatch.countDown();
        }
        @Override
        public void dataChanged(String zkPath, String data) {
            if (triggerExceptions.get()) {
                throw new RuntimeException("boo!");
            }
            dataLatch.countDown();
        }
        @Override
        public void nodeRemoved(String zkPath) {
            if (triggerExceptions.get()) {
                throw new RuntimeException("boo!");
            }
            removeLatch.countDown();
        }
    };
    final String pathPrefix = "/foo/misbehaving";
    curator.create().creatingParentsIfNeeded().forPath(pathPrefix);
    final NodeCollectionWatcher nodeCollectionWatcher = new NodeCollectionWatcher(zooKeeper, pathPrefix, listener);
    triggerExceptions.set(true);
    curator.create().forPath(pathPrefix + "/first", getData());
    Thread.sleep(propagationTime);
    curator.setData().forPath(pathPrefix + "/first", getData());
    Thread.sleep(propagationTime);
    curator.delete().forPath(pathPrefix + "/first");
    Thread.sleep(propagationTime);
    // Now create a node but without setting the data field.
    triggerExceptions.set(false);
    curator.create().forPath(pathPrefix + "/second");
    assertTrue(createLatch.await(propagationTime, TimeUnit.MILLISECONDS));
    curator.setData().forPath(pathPrefix + "/second", getData());
    assertTrue(dataLatch.await(propagationTime, TimeUnit.MILLISECONDS));
    curator.delete().forPath(pathPrefix + "/second");
    assertTrue(removeLatch.await(propagationTime, TimeUnit.MILLISECONDS));
    nodeCollectionWatcher.shutdown();
}