@Test
  public void testNamespace() throws Exception {
    Timing timing = new Timing();
    ChildReaper reaper = null;
    CuratorFramework client =
        CuratorFrameworkFactory.builder()
            .connectString(server.getConnectString())
            .sessionTimeoutMs(timing.session())
            .connectionTimeoutMs(timing.connection())
            .retryPolicy(new RetryOneTime(1))
            .namespace("foo")
            .build();
    try {
      client.start();

      for (int i = 0; i < 10; ++i) {
        client.create().creatingParentsIfNeeded().forPath("/test/" + Integer.toString(i));
      }

      reaper = new ChildReaper(client, "/test", Reaper.Mode.REAP_UNTIL_DELETE, 1);
      reaper.start();

      timing.forWaiting().sleepABit();

      Stat stat = client.checkExists().forPath("/test");
      Assert.assertEquals(stat.getNumChildren(), 0);

      stat = client.usingNamespace(null).checkExists().forPath("/foo/test");
      Assert.assertNotNull(stat);
      Assert.assertEquals(stat.getNumChildren(), 0);
    } finally {
      Closeables.closeQuietly(reaper);
      Closeables.closeQuietly(client);
    }
  }
  @Test
  public void testSomeNodes() throws Exception {

    Timing timing = new Timing();
    ChildReaper reaper = null;
    CuratorFramework client =
        CuratorFrameworkFactory.newClient(
            server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
    try {
      client.start();

      Random r = new Random();
      int nonEmptyNodes = 0;
      for (int i = 0; i < 10; ++i) {
        client.create().creatingParentsIfNeeded().forPath("/test/" + Integer.toString(i));
        if (r.nextBoolean()) {
          client.create().forPath("/test/" + Integer.toString(i) + "/foo");
          ++nonEmptyNodes;
        }
      }

      reaper = new ChildReaper(client, "/test", Reaper.Mode.REAP_UNTIL_DELETE, 1);
      reaper.start();

      timing.forWaiting().sleepABit();

      Stat stat = client.checkExists().forPath("/test");
      Assert.assertEquals(stat.getNumChildren(), nonEmptyNodes);
    } finally {
      Closeables.closeQuietly(reaper);
      Closeables.closeQuietly(client);
    }
  }
 public static IZkConnection createZkConnection(String connectString) {
   Timing timing = new Timing();
   CuratorFramework client =
       CuratorFrameworkFactory.newClient(
           connectString, timing.session(), timing.connection(), new RetryOneTime(1));
   client.start();
   try {
     return new CuratorZKClientBridge(client);
   } catch (Exception e) {
     throw new RuntimeException(e);
   }
 }
  @Test
  public void testOverSubscribed() throws Exception {
    final Timing timing = new Timing();
    final CuratorFramework client =
        CuratorFrameworkFactory.newClient(
            server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
    ExecutorService service = Executors.newCachedThreadPool();
    ExecutorCompletionService<Void> completionService =
        new ExecutorCompletionService<Void>(service);
    try {
      client.start();

      final Semaphore semaphore = new Semaphore(0);
      final CountDownLatch latch = new CountDownLatch(1);
      for (int i = 0; i < (QTY + 1); ++i) {
        completionService.submit(
            new Callable<Void>() {
              @Override
              public Void call() throws Exception {
                DistributedDoubleBarrier barrier =
                    new DistributedDoubleBarrier(client, "/barrier", QTY) {
                      @Override
                      protected List<String> getChildrenForEntering() throws Exception {
                        semaphore.release();
                        Assert.assertTrue(timing.awaitLatch(latch));
                        return super.getChildrenForEntering();
                      }
                    };
                Assert.assertTrue(barrier.enter(timing.seconds(), TimeUnit.SECONDS));
                Assert.assertTrue(barrier.leave(timing.seconds(), TimeUnit.SECONDS));
                return null;
              }
            });
      }

      Assert.assertTrue(
          semaphore.tryAcquire(
              QTY + 1,
              timing.seconds(),
              TimeUnit.SECONDS)); // wait until all QTY+1 barriers are trying to enter
      latch.countDown();

      for (int i = 0; i < (QTY + 1); ++i) {
        completionService.take().get(); // to check for assertions
      }
    } finally {
      service.shutdown();
      Closeables.close(client, true);
    }
  }
  @Test
  public void testInCluster() throws Exception {
    final int PARTICIPANT_QTY = 3;

    List<ClientAndLatch> clients = Lists.newArrayList();
    Timing timing = new Timing();
    TestingCluster cluster = new TestingCluster(PARTICIPANT_QTY);
    try {
      cluster.start();

      List<InstanceSpec> instances = Lists.newArrayList(cluster.getInstances());
      for (int i = 0; i < PARTICIPANT_QTY; ++i) {
        CuratorFramework client =
            CuratorFrameworkFactory.newClient(
                instances.get(i).getConnectString(),
                timing.session(),
                timing.connection(),
                new RetryOneTime(1));
        LeaderLatch latch = new LeaderLatch(client, "/latch");

        clients.add(new ClientAndLatch(client, latch, i));
        client.start();
        latch.start();
      }

      ClientAndLatch leader = waitForALeader(clients, timing);
      Assert.assertNotNull(leader);

      cluster.killServer(instances.get(leader.index));

      Thread.sleep(timing.multiple(2).session());

      leader = waitForALeader(clients, timing);
      Assert.assertNotNull(leader);

      Assert.assertEquals(getLeaders(clients).size(), 1);
    } finally {
      for (ClientAndLatch client : clients) {
        Closeables.close(client.latch, true);
        Closeables.close(client.client, true);
      }
      Closeables.close(cluster, true);
    }
  }
  @Test
  public void testBasic() throws Exception {
    final Timing timing = new Timing();
    final List<Closeable> closeables = Lists.newArrayList();
    final CuratorFramework client =
        CuratorFrameworkFactory.newClient(
            server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
    try {
      closeables.add(client);
      client.start();

      final CountDownLatch postEnterLatch = new CountDownLatch(QTY);
      final CountDownLatch postLeaveLatch = new CountDownLatch(QTY);
      final AtomicInteger count = new AtomicInteger(0);
      final AtomicInteger max = new AtomicInteger(0);
      List<Future<Void>> futures = Lists.newArrayList();
      ExecutorService service = Executors.newCachedThreadPool();
      for (int i = 0; i < QTY; ++i) {
        Future<Void> future =
            service.submit(
                new Callable<Void>() {
                  @Override
                  public Void call() throws Exception {
                    DistributedDoubleBarrier barrier =
                        new DistributedDoubleBarrier(client, "/barrier", QTY);

                    Assert.assertTrue(barrier.enter(timing.seconds(), TimeUnit.SECONDS));

                    synchronized (TestDistributedDoubleBarrier.this) {
                      int thisCount = count.incrementAndGet();
                      if (thisCount > max.get()) {
                        max.set(thisCount);
                      }
                    }

                    postEnterLatch.countDown();
                    Assert.assertTrue(timing.awaitLatch(postEnterLatch));

                    Assert.assertEquals(count.get(), QTY);

                    Assert.assertTrue(barrier.leave(10, TimeUnit.SECONDS));
                    count.decrementAndGet();

                    postLeaveLatch.countDown();
                    Assert.assertTrue(timing.awaitLatch(postLeaveLatch));

                    return null;
                  }
                });
        futures.add(future);
      }

      for (Future<Void> f : futures) {
        f.get();
      }
      Assert.assertEquals(count.get(), 0);
      Assert.assertEquals(max.get(), QTY);
    } finally {
      for (Closeable c : closeables) {
        Closeables.close(c, true);
      }
    }
  }