@Test
 public void testConnectFailure() throws Exception {
   final CountDownLatch done = new CountDownLatch(1);
   final AtomicBoolean success = new AtomicBoolean();
   final AtomicReference<Throwable> failure = new AtomicReference<>();
   Promise<RedisClientBase> connect = RedisClientBase.connect("localhost", 6380);
   connect
       .onSuccess(
           new Block<RedisClientBase>() {
             @Override
             public void apply(RedisClientBase redisClientBase) {
               success.set(true);
               done.countDown();
             }
           })
       .onFailure(
           new Block<Throwable>() {
             @Override
             public void apply(Throwable throwable) {
               success.set(false);
               failure.set(throwable);
               done.countDown();
             }
           });
   done.await(5000, TimeUnit.MILLISECONDS);
   assertFalse(success.get());
   assertEquals("Connection refused", failure.get().getMessage());
 }
 @Test
 public void testConnect() throws Exception {
   final CountDownLatch done = new CountDownLatch(1);
   final AtomicBoolean success = new AtomicBoolean();
   final AtomicReference<RedisClientBase> client = new AtomicReference<>();
   Promise<RedisClientBase> connect = RedisClientBase.connect("localhost", 6379);
   connect
       .onSuccess(
           new Block<RedisClientBase>() {
             @Override
             public void apply(RedisClientBase redisClientBase) {
               success.set(true);
               client.set(redisClientBase);
               done.countDown();
             }
           })
       .onFailure(
           new Block<Throwable>() {
             @Override
             public void apply(Throwable throwable) {
               success.set(false);
               done.countDown();
             }
           });
   done.await(5000, TimeUnit.MILLISECONDS);
   final CountDownLatch done2 = new CountDownLatch(1);
   assertTrue(success.get());
   client
       .get()
       .close()
       .onSuccess(
           new Block<Void>() {
             @Override
             public void apply(Void aVoid) {
               success.set(true);
               done2.countDown();
             }
           })
       .onFailure(
           new Block<Throwable>() {
             @Override
             public void apply(Throwable throwable) {
               success.set(false);
               done2.countDown();
             }
           });
   done2.await(5000, TimeUnit.MILLISECONDS);
   assertTrue(success.get());
 }
  @Test
  public void testPubSubPerformance() throws InterruptedException {
    final CountDownLatch done = new CountDownLatch(1);
    final Semaphore semaphore = new Semaphore(100);
    final AtomicInteger total = new AtomicInteger();
    Promise<RedisClient> redisClient =
        RedisClient.connect("localhost", 6379)
            .onSuccess(
                new Block<RedisClient>() {
                  @Override
                  public void apply(RedisClient redisClient) {
                    redisClient.addListener(
                        new MessageListener() {
                          @Override
                          public void message(byte[] channel, byte[] message) {
                            semaphore.release();
                            total.incrementAndGet();
                          }

                          @Override
                          public void pmessage(byte[] pattern, byte[] channel, byte[] message) {}
                        });
                    redisClient
                        .subscribe("test")
                        .onSuccess(
                            new Block<Void>() {
                              @Override
                              public void apply(Void aVoid) {
                                RedisClient.connect("localhost", 6379)
                                    .onSuccess(
                                        new Block<RedisClient>() {
                                          @Override
                                          public void apply(final RedisClient redisClient) {
                                            new Thread(
                                                    new Runnable() {
                                                      @Override
                                                      public void run() {
                                                        long start = System.currentTimeMillis();
                                                        while (System.currentTimeMillis() - start
                                                            < 5000) {
                                                          semaphore.acquireUninterruptibly();
                                                          redisClient.publish("test", "hello");
                                                        }
                                                        redisClient.close();
                                                        done.countDown();
                                                      }
                                                    })
                                                .start();
                                          }
                                        });
                              }
                            });
                  }
                });
    done.await(6000, TimeUnit.MILLISECONDS);
    redisClient.onSuccess(
        new Block<RedisClient>() {
          @Override
          public void apply(RedisClient redisClient) {
            redisClient.close();
          }
        });
    System.out.println(total.get() / 5 + " per second");
  }
  @Test
  public void testPubSub() throws InterruptedException, ExecutionException {
    final CountDownLatch done = new CountDownLatch(2);
    final Promise<Void> wassubscribed = new Promise<>();
    final AtomicReference<byte[]> gotmessage = new AtomicReference<>();
    final AtomicLong listeners = new AtomicLong(0);
    final AtomicBoolean failed = new AtomicBoolean();
    RedisClient.connect("localhost", 6379)
        .onSuccess(
            new Block<RedisClient>() {
              @Override
              public void apply(final RedisClient redisClient) {
                redisClient.addListener(
                    new ReplyListener() {
                      @Override
                      public void subscribed(byte[] name, int channels) {
                        wassubscribed.set(null);
                      }

                      @Override
                      public void psubscribed(byte[] name, int channels) {
                        failed.set(true);
                      }

                      @Override
                      public void unsubscribed(byte[] name, int channels) {
                        failed.set(true);
                      }

                      @Override
                      public void punsubscribed(byte[] name, int channels) {
                        failed.set(true);
                      }

                      @Override
                      public void message(byte[] channel, byte[] message) {
                        gotmessage.set(message);
                        redisClient.close();
                        done.countDown();
                      }

                      @Override
                      public void pmessage(byte[] pattern, byte[] channel, byte[] message) {
                        failed.set(true);
                      }
                    });
                redisClient
                    .subscribe("test")
                    .onSuccess(
                        new Block<Void>() {
                          @Override
                          public void apply(Void aVoid) {
                            RedisClient.connect("localhost", 6379)
                                .onSuccess(
                                    new Block<RedisClient>() {
                                      @Override
                                      public void apply(final RedisClient redisClient) {
                                        wassubscribed.onSuccess(
                                            new Block<Void>() {
                                              @Override
                                              public void apply(Void aVoid) {
                                                redisClient
                                                    .publish("test", "hello")
                                                    .onSuccess(
                                                        new Block<IntegerReply>() {
                                                          @Override
                                                          public void apply(
                                                              IntegerReply integerReply) {
                                                            listeners.set(integerReply.data());
                                                            redisClient.close();
                                                            done.countDown();
                                                          }
                                                        });
                                              }
                                            });
                                      }
                                    });
                          }
                        });
              }
            });
    done.await(10000, TimeUnit.MILLISECONDS);
    assertTrue(wassubscribed.get() == null);
    assertEquals("hello", new String(gotmessage.get()));
    assertEquals(1, listeners.get());
    assertFalse(failed.get());
  }