@Test
  public void testListenUnlisten() throws Exception {
    final AtomicReference<Message> handshakeRef = new AtomicReference<>();
    final CountDownLatch handshakeLatch = new CountDownLatch(1);
    final AtomicReference<Message> connectRef = new AtomicReference<>();
    final CountDownLatch connectLatch = new CountDownLatch(1);
    final AtomicReference<Message> disconnectRef = new AtomicReference<>();
    final CountDownLatch disconnectLatch = new CountDownLatch(1);

    ListenUnlistenService s =
        new ListenUnlistenService(
            handshakeRef, handshakeLatch, connectRef, connectLatch, disconnectRef, disconnectLatch);
    boolean processed = processor.process(s);
    assertTrue(processed);

    bayeuxClient.handshake();
    assertTrue(handshakeLatch.await(5, TimeUnit.SECONDS));
    Message handshake = handshakeRef.get();
    assertNotNull(handshake);
    assertTrue(handshake.isSuccessful());

    assertTrue(connectLatch.await(5, TimeUnit.SECONDS));
    Message connect = connectRef.get();
    assertNotNull(connect);
    assertTrue(connect.isSuccessful());

    processed = processor.deprocessCallbacks(s);
    assertTrue(processed);

    // Listener method must not be notified, since we have deconfigured
    bayeuxClient.disconnect(1000);
  }
  @Test
  public void testResubscribeOnRehandshake() throws Exception {
    AtomicReference<CountDownLatch> messageLatch = new AtomicReference<CountDownLatch>();
    ResubscribeOnRehandshakeService s = new ResubscribeOnRehandshakeService(messageLatch);
    boolean processed = processor.process(s);
    assertTrue(processed);

    final CountDownLatch subscribeLatch = new CountDownLatch(1);
    bayeuxClient
        .getChannel(Channel.META_SUBSCRIBE)
        .addListener(
            new ClientSessionChannel.MessageListener() {
              public void onMessage(ClientSessionChannel channel, Message message) {
                subscribeLatch.countDown();
              }
            });

    bayeuxClient.handshake();
    assertTrue(bayeuxClient.waitFor(1000, BayeuxClient.State.CONNECTED));
    assertTrue(subscribeLatch.await(5, TimeUnit.SECONDS));

    messageLatch.set(new CountDownLatch(1));
    bayeuxClient.getChannel("/foo").publish(new HashMap());
    assertTrue(messageLatch.get().await(5, TimeUnit.SECONDS));

    bayeuxClient.disconnect();
    assertTrue(bayeuxClient.waitFor(1000, BayeuxClient.State.DISCONNECTED));

    // Rehandshake
    bayeuxClient.handshake();
    assertTrue(bayeuxClient.waitFor(1000, BayeuxClient.State.CONNECTED));

    // Republish, it must have resubscribed
    messageLatch.set(new CountDownLatch(1));
    bayeuxClient.getChannel("/foo").publish(new HashMap());
    assertTrue(messageLatch.get().await(5, TimeUnit.SECONDS));

    bayeuxClient.disconnect();
    assertTrue(bayeuxClient.waitFor(1000, BayeuxClient.State.DISCONNECTED));

    boolean deprocessed = processor.deprocess(s);
    assertTrue(deprocessed);

    // Rehandshake
    bayeuxClient.handshake();
    assertTrue(bayeuxClient.waitFor(1000, BayeuxClient.State.CONNECTED));

    // Republish, it must not have resubscribed
    messageLatch.set(new CountDownLatch(1));
    bayeuxClient.getChannel("/foo").publish(new HashMap());
    assertFalse(messageLatch.get().await(1, TimeUnit.SECONDS));
  }
 @Test
 public void testInjectClientSessionOnMethod() throws Exception {
   InjectClientSessionOnMethodService s = new InjectClientSessionOnMethodService();
   boolean processed = processor.process(s);
   assertTrue(processed);
   assertNotNull(s.session);
 }
 @Test
 public void testNonServiceAnnotatedClass() throws Exception {
   NonServiceAnnotatedService s = new NonServiceAnnotatedService();
   boolean processed = processor.process(s);
   assertFalse(processed);
   assertNull(s.session);
 }
  @Test
  public void testSubscribeUnsubscribe() throws Exception {
    final AtomicReference<Message> messageRef = new AtomicReference<>();
    final AtomicReference<CountDownLatch> messageLatch =
        new AtomicReference<>(new CountDownLatch(1));

    SubscribeUnsubscribeService s = new SubscribeUnsubscribeService(messageRef, messageLatch);
    boolean processed = processor.process(s);
    assertTrue(processed);

    final CountDownLatch subscribeLatch = new CountDownLatch(1);
    bayeuxClient
        .getChannel(Channel.META_SUBSCRIBE)
        .addListener(
            new ClientSessionChannel.MessageListener() {
              public void onMessage(ClientSessionChannel channel, Message message) {
                subscribeLatch.countDown();
              }
            });

    bayeuxClient.handshake();
    assertTrue(bayeuxClient.waitFor(5000, BayeuxClient.State.CONNECTED));
    assertTrue(subscribeLatch.await(5, TimeUnit.SECONDS));

    bayeuxClient.getChannel("/foo").publish(new HashMap<>());
    assertTrue(messageLatch.get().await(5, TimeUnit.SECONDS));

    final CountDownLatch unsubscribeLatch = new CountDownLatch(1);
    bayeuxClient
        .getChannel(Channel.META_UNSUBSCRIBE)
        .addListener(
            new ClientSessionChannel.MessageListener() {
              public void onMessage(ClientSessionChannel channel, Message message) {
                unsubscribeLatch.countDown();
              }
            });

    processor.deprocessCallbacks(s);
    assertTrue(unsubscribeLatch.await(5, TimeUnit.SECONDS));

    messageLatch.set(new CountDownLatch(1));

    bayeuxClient.getChannel("/foo").publish(new HashMap<>());
    assertFalse(messageLatch.get().await(1, TimeUnit.SECONDS));
  }
  @Test
  public void testInjectables() throws Exception {
    Injectable i = new DerivedInjectable();
    InjectablesService s = new InjectablesService();
    processor = new ClientAnnotationProcessor(bayeuxClient, i);
    boolean processed = processor.process(s);
    assertTrue(processed);

    assertSame(i, s.i);
  }
  @Test
  public void testUsage() throws Exception {
    final CountDownLatch connectLatch = new CountDownLatch(1);
    final AtomicReference<CountDownLatch> messageLatch = new AtomicReference<>();

    UsageService s = new UsageService(connectLatch, messageLatch);
    processor.process(s);
    assertTrue(s.initialized);
    assertFalse(s.connected);

    final CountDownLatch subscribeLatch = new CountDownLatch(1);
    bayeuxClient
        .getChannel(Channel.META_SUBSCRIBE)
        .addListener(
            new ClientSessionChannel.MessageListener() {
              public void onMessage(ClientSessionChannel channel, Message message) {
                subscribeLatch.countDown();
              }
            });

    bayeuxClient.handshake();
    assertTrue(connectLatch.await(5, TimeUnit.SECONDS));
    assertTrue(s.connected);
    assertTrue(subscribeLatch.await(5, TimeUnit.SECONDS));

    messageLatch.set(new CountDownLatch(1));
    bayeuxClient.getChannel("/foo").publish(new HashMap<>());
    assertTrue(messageLatch.get().await(5, TimeUnit.SECONDS));

    processor.deprocess(s);
    assertFalse(s.initialized);

    messageLatch.set(new CountDownLatch(1));
    bayeuxClient.getChannel("/foo").publish(new HashMap<>());
    assertFalse(messageLatch.get().await(1, TimeUnit.SECONDS));
  }
 @Test
 public void testNull() throws Exception {
   boolean processed = processor.process(null);
   assertFalse(processed);
 }