@Test
  public void testUnregisterTwice() throws Exception {

    AeroGearGCMPushConfiguration config =
        new AeroGearGCMPushConfiguration()
            .setSenderId(TEST_SENDER_ID)
            .setVariantID(TEST_SENDER_VARIANT)
            .setSecret(TEST_SENDER_PASSWORD)
            .setPushServerURI(new URI("https://testuri"));

    AeroGearGCMPushRegistrar registrar = (AeroGearGCMPushRegistrar) config.asRegistrar();
    CountDownLatch latch = new CountDownLatch(1);
    StubHttpProvider provider = new StubHttpProvider();
    UnitTestUtils.setPrivateField(registrar, "httpProviderProvider", provider);

    StubInstanceIDProvider instanceIdProvider = new StubInstanceIDProvider();
    UnitTestUtils.setPrivateField(registrar, "instanceIdProvider", instanceIdProvider);

    VoidCallback callback = new VoidCallback(latch);

    AeroGearGCMPushRegistrar spy = Mockito.spy(registrar);

    spy.register(super.getActivity(), callback);
    latch.await(1, TimeUnit.SECONDS);

    latch = new CountDownLatch(2);
    callback = new VoidCallback(latch);
    spy.unregister(super.getActivity(), callback);
    spy.unregister(super.getActivity(), callback);
    latch.await(4, TimeUnit.SECONDS);

    Assert.assertNotNull(callback.exception);
    Assert.assertTrue(callback.exception instanceof IllegalStateException);
  }
  @Test
  public void testRegistrationTokensAreNotCached() throws Exception {

    AeroGearGCMPushConfiguration config =
        new AeroGearGCMPushConfiguration()
            .setSenderId(TEST_SENDER_ID)
            .setVariantID(TEST_SENDER_VARIANT)
            .setSecret(TEST_SENDER_PASSWORD)
            .setPushServerURI(new URI("https://testuri"));

    AeroGearGCMPushRegistrar registrar = (AeroGearGCMPushRegistrar) config.asRegistrar();
    CountDownLatch latch = new CountDownLatch(1);
    StubHttpProvider provider = new StubHttpProvider();
    UnitTestUtils.setPrivateField(registrar, "httpProviderProvider", provider);

    StubInstanceIDProvider instanceIdProvider = new StubInstanceIDProvider();
    UnitTestUtils.setPrivateField(registrar, "instanceIdProvider", instanceIdProvider);

    UnitTestUtils.setPrivateField(
        registrar,
        "preferenceProvider",
        new Provider<SharedPreferences>() {

          @Override
          public SharedPreferences get(Object... in) {
            return new GCMSharedPreferenceProvider().get(getActivity());
          }
        });

    VoidCallback callback = new VoidCallback(latch);

    registrar.register(super.getActivity(), callback);
    latch.await(5, TimeUnit.SECONDS);
    Assert.assertNotNull(
        new GCMSharedPreferenceProvider()
            .get(getActivity())
            .getString(
                "org.jboss.aerogear.android.unifiedpush.gcm.AeroGearGCMPushRegistrar:"
                    + TEST_SENDER_ID,
                null));

    latch = new CountDownLatch(1);
    callback = new VoidCallback(latch);
    registrar.unregister(super.getActivity(), callback);
    latch.await(5, TimeUnit.SECONDS);
    Assert.assertNull(
        new GCMSharedPreferenceProvider()
            .get(getActivity())
            .getString(
                "org.jboss.aerogear.android.unifiedpush.gcm.AeroGearGCMPushRegistrar:"
                    + TEST_SENDER_ID,
                null));
    Mockito.verify(instanceIdProvider.mock, Mockito.times(1))
        .deleteToken(
            Mockito.eq(TEST_SENDER_ID), Mockito.eq(GoogleCloudMessaging.INSTANCE_ID_SCOPE));
  }
  @Test
  public void testRegister() throws Exception {
    AeroGearGCMPushConfiguration config =
        new AeroGearGCMPushConfiguration()
            .setSenderId(TEST_SENDER_ID)
            .setVariantID(TEST_SENDER_VARIANT)
            .setSecret(TEST_SENDER_PASSWORD)
            .setPushServerURI(new URI("https://testuri"));

    AeroGearGCMPushRegistrar registrar = (AeroGearGCMPushRegistrar) config.asRegistrar();
    CountDownLatch latch = new CountDownLatch(1);
    StubHttpProvider provider = new StubHttpProvider();
    UnitTestUtils.setPrivateField(registrar, "httpProviderProvider", provider);
    VoidCallback callback = new VoidCallback(latch);

    registrar.register(super.getActivity(), callback);
    if (!latch.await(60, TimeUnit.SECONDS)) {
      try {
        Process process = Runtime.getRuntime().exec("logcat -d");
        BufferedReader bufferedReader =
            new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder log = new StringBuilder();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
          log.append(line);
        }
        Log.e(TAG, log.toString());
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
      }
      Assert.fail("Latch wasn't called");
    }

    if (callback.exception != null) {
      Log.e(TAG, callback.exception.getMessage(), callback.exception);
      Assert.fail(callback.exception.getMessage());
    }

    ArgumentCaptor<String> postCaptore = ArgumentCaptor.forClass(String.class);
    Mockito.verify(provider.mock).post(postCaptore.capture());
    JSONObject object = new JSONObject(postCaptore.getValue());
    Assert.assertEquals(
        UnitTestUtils.getPrivateField(registrar, "deviceToken"), object.getString("deviceToken"));
    String jsonData =
        new GCMSharedPreferenceProvider()
            .get(getActivity())
            .getString(TEST_REGISTRAR_PREFERENCES_KEY, TAG);
    Assert.assertNotNull(jsonData);
    Assert.assertEquals(
        UnitTestUtils.getPrivateField(registrar, "deviceToken"),
        new JSONObject(jsonData).getString("deviceToken"));
  }
  @Test
  public void testAsRegistrarFailsOnNullPushServerURI() {
    try {
      AeroGearGCMPushConfiguration config =
          new AeroGearGCMPushConfiguration().setSenderId(TEST_SENDER_ID);

      config.asRegistrar();

    } catch (IllegalStateException ex) {
      // TO check the message I need to use a exception Rule which
      // I am having trouble getting to work right in Android
      Assert.assertEquals("PushServerURI can't be null", ex.getMessage());
      return; // pass
    }
    Assert.fail();
  }
  @Test
  public void testAsRegistrarFailsOnNullSenderId() throws URISyntaxException {
    try {
      AeroGearGCMPushConfiguration config =
          new AeroGearGCMPushConfiguration().setPushServerURI(new URI("https://testuri"));

      config.asRegistrar();

    } catch (IllegalStateException ex) {
      // TO check the message I need to use a exception Rule which
      // I am having trouble getting to work right in Android
      Assert.assertEquals("SenderId can't be null or empty", ex.getMessage());
      return; // pass
    }
    Assert.fail();
  }
  @Test
  public void testAeroGearGCMPushConfigurationWithoutSecret() throws Exception {

    try {

      AeroGearGCMPushConfiguration config = new AeroGearGCMPushConfiguration();
      config
          .setSenderId(TEST_SENDER_ID)
          .setPushServerURI(new URI("https://testuri"))
          .setVariantID(TEST_SENDER_VARIANT)
          .asRegistrar();

    } catch (IllegalStateException ex) {
      Assert.assertEquals("Secret can't be null", ex.getMessage());
      return; // pass
    }

    Assert.fail();
  }
  @Test
  public void testRegisterExceptionsAreCaught() throws Exception {
    AeroGearGCMPushConfiguration config =
        new AeroGearGCMPushConfiguration()
            .setSenderId(TEST_SENDER_ID)
            .setVariantID(TEST_SENDER_VARIANT)
            .setSecret(TEST_SENDER_PASSWORD)
            .setPushServerURI(new URI("https://testuri"));

    AeroGearGCMPushRegistrar registrar = (AeroGearGCMPushRegistrar) config.asRegistrar();
    CountDownLatch latch = new CountDownLatch(1);
    VoidCallback callback = new VoidCallback(latch);

    StubInstanceIDProvider instanceIdProvider = new StubInstanceIDProvider();
    UnitTestUtils.setPrivateField(registrar, "instanceIdProvider", instanceIdProvider);

    registrar.register(getActivity(), callback);
    latch.await(2, TimeUnit.SECONDS);
    Assert.assertNotNull(callback.exception);
    Assert.assertFalse(callback.exception instanceof IOException);
  }
  @Test
  public void testUnregister() throws Exception {
    AeroGearGCMPushConfiguration config =
        new AeroGearGCMPushConfiguration()
            .setSenderId(TEST_SENDER_ID)
            .setVariantID(TEST_SENDER_VARIANT)
            .setSecret(TEST_SENDER_PASSWORD)
            .setPushServerURI(new URI("https://testuri"));

    AeroGearGCMPushRegistrar registrar = (AeroGearGCMPushRegistrar) config.asRegistrar();
    CountDownLatch latch = new CountDownLatch(1);
    StubHttpProvider provider = new StubHttpProvider();
    UnitTestUtils.setPrivateField(registrar, "httpProviderProvider", provider);

    StubInstanceIDProvider instanceIdProvider = new StubInstanceIDProvider();
    UnitTestUtils.setPrivateField(registrar, "instanceIdProvider", instanceIdProvider);

    VoidCallback callback = new VoidCallback(latch);

    AeroGearGCMPushRegistrar spy = Mockito.spy(registrar);

    spy.register(super.getActivity(), callback);
    latch.await(1, TimeUnit.SECONDS);

    latch = new CountDownLatch(1);
    callback = new VoidCallback(latch);
    spy.unregister(super.getActivity(), callback);
    latch.await(1, TimeUnit.SECONDS);

    if (callback.exception != null) {
      Log.e(TAG, callback.exception.getMessage(), callback.exception);
      Assert.fail(callback.exception.getMessage());
    }

    Mockito.verify(instanceIdProvider.mock).deleteToken(anyString(), anyString());
    Mockito.verify(provider.mock).delete(Mockito.matches("tempId"));
    Assert.assertNull(callback.exception);
    Assert.assertEquals("", UnitTestUtils.getPrivateField(registrar, "deviceToken"));
  }