@Test
  public void testGetAccessTokenWithScope() {
    Date beforeRequest = new Date();
    List<String> scopes = new ArrayList<>();
    scopes.add("https://www.googleapis.com/auth/urlshortener");
    AppIdentityService.GetAccessTokenResult tokenResult = appIdentity.getAccessToken(scopes);

    Assert.assertNotNull(tokenResult);
    Assert.assertTrue("Token should not be blank.", !tokenResult.getAccessToken().isEmpty());

    String errMsg =
        "Expiration time should at least be after request time. "
            + dateDebugStr("Before-Request", beforeRequest)
            + ", "
            + dateDebugStr("Expiration-Time=", tokenResult.getExpirationTime());
    Assert.assertTrue(errMsg, beforeRequest.getTime() < tokenResult.getExpirationTime().getTime());
    log.info(
        "AccessToken: "
            + tokenResult.getAccessToken()
            + " Expiration: "
            + tokenResult.getExpirationTime());

    // Retrieve it again, should be same since it grabs it from a cache.
    AppIdentityService.GetAccessTokenResult tokenResult2 = appIdentity.getAccessToken(scopes);

    Assert.assertEquals(tokenResult.getAccessToken(), tokenResult2.getAccessToken());
  }
  @Test
  public void testGetAccessTokenUncached() {
    Date beforeRequest = new Date();
    List<String> scopes = new ArrayList<>();
    scopes.add("https://www.googleapis.com/auth/urlshortener");

    // Although we do not verify whether the result came from the cache or not,
    // the token should at least be valid.
    AppIdentityService.GetAccessTokenResult tokenResult =
        appIdentity.getAccessTokenUncached(scopes);

    Assert.assertNotNull(tokenResult);
    Assert.assertTrue("Token should not be blank.", !tokenResult.getAccessToken().isEmpty());

    String errMsg =
        "Expiration time should at least be after request time. "
            + dateDebugStr("Before-Request", beforeRequest)
            + ", "
            + dateDebugStr("Expiration-Time=", tokenResult.getExpirationTime());
    Assert.assertTrue(errMsg, beforeRequest.getTime() < tokenResult.getExpirationTime().getTime());
    log.info(
        "AccessToken: "
            + tokenResult.getAccessToken()
            + " Expiration: "
            + tokenResult.getExpirationTime());
  }
  @Test
  /**
   * Verify that all certificates returned will validate signForApp(). Any invalid signature or
   * exception will cause the test to fail.
   */
  public void testSignForApp() throws Exception {
    Collection<PublicCertificate> certs = appIdentity.getPublicCertificatesForApp();
    byte[] blob = "abcdefg".getBytes();
    AppIdentityService.SigningResult result = appIdentity.signForApp(blob);
    byte[] signedBlob = result.getSignature();
    boolean res = verifySignatureWithAllCertsForApp(blob, signedBlob, certs);

    // assertTrue(res) returns null, so using assertEquals()
    Assert.assertEquals("signature.verify() returned false. See logs.", true, res);
    Assert.assertTrue(!result.getKeyName().isEmpty());
  }
  @Test
  public void testGetServiceAccountName() {
    assumeEnvironment(Environment.APPSPOT, Environment.CAPEDWARF);

    String serviceAccountName = appIdentity.getServiceAccountName();
    String errMsg = serviceAccountName + " is not valid.";
    Assert.assertTrue(errMsg, EmailValidator.getInstance().isValid(serviceAccountName));
  }
  @Test
  public void testParseFullAppId() {
    // [(partition)~][(domain):](display-app-id)
    ApiProxy.Environment env = ApiProxy.getCurrentEnvironment();
    String hostname =
        (String) env.getAttributes().get("com.google.appengine.runtime.default_version_hostname");
    AppIdentityService.ParsedAppId parsed = appIdentity.parseFullAppId(hostname);

    String message = createParsed(parsed);
    Assert.assertEquals(
        message,
        property("testParseFullAppId_partition").getPropertyValue(),
        parsed.getPartition());
    Assert.assertEquals(
        message, getExpectedAppHostname("testParseFullAppId_domain"), parsed.getDomain());
    Assert.assertEquals(message, getExpectedAppId("testParseFullAppId_id"), parsed.getId());
  }
  /*
   * Retrieve the default Google Cloud Storage bucket name.
   */
  @Test
  public void testGetDefaultGcsBucketName() {
    ApiProxy.Environment env = ApiProxy.getCurrentEnvironment();
    String expectedBucketName;
    Property property = property("testGetDefaultGcsBucketName");
    if (property.exists()) {
      expectedBucketName = property.getPropertyValue();
    } else {
      expectedBucketName =
          (String) env.getAttributes().get("com.google.appengine.runtime.default_version_hostname");
    }

    try {
      String bucketName = appIdentity.getDefaultGcsBucketName();
      Assert.assertEquals(expectedBucketName, bucketName);
    } catch (AppIdentityServiceFailureException aisfe) {
      // TODO: This means that there is no default bucket setup for this project.  Have a better way
      // to verify this.
    }
  }
  @Test
  public void testGetPublicCertificates() throws Exception {
    Collection<PublicCertificate> certs = appIdentity.getPublicCertificatesForApp();
    Assert.assertTrue("No certificates returned.", !certs.isEmpty());

    for (PublicCertificate publicCert : certs) {
      Assert.assertTrue(
          "No name for certificate.", !publicCert.getCertificateName().trim().isEmpty());

      String pemFormat = publicCert.getX509CertificateInPemFormat();
      String errMsg = "getX509CertificateInPemFormat():" + pemFormat;
      // TODO better check?
      Assert.assertTrue(errMsg, pemFormat.startsWith("-----BEGIN"));
      Assert.assertTrue(errMsg, pemFormat.contains("-----END"));

      InputStream stream =
          new ByteArrayInputStream(publicCert.getX509CertificateInPemFormat().getBytes("UTF-8"));
      CertificateFactory cf = CertificateFactory.getInstance("X.509");
      Certificate cert = cf.generateCertificate(stream);

      PublicKey pk = cert.getPublicKey();
      Assert.assertNotNull(pk.getEncoded());
    }
  }