@Test
  public void createAuthenticatableResource_withExtId_validAsUnauthenticated() {
    final String domainName = generateDomain();
    final String resourceClassName = generateResourceClass(true, true);
    final String permissionName = generateResourceClassPermission(resourceClassName);
    final String permissionName2 = generateResourceClassPermission(resourceClassName);
    final char[] password = generateUniquePassword();
    final String externalId = generateUniqueExternalId();

    // (ironically,) set up an authenticatable resource with resource class create permission
    final Resource authenticatedResource = generateResourceAndAuthenticate();
    grantResourceCreatePermission(authenticatedResource, resourceClassName, domainName);

    final ResourcePermission implicitResourcePermission =
        ResourcePermissions.getInstance(permissionName);
    final ResourcePermission implicitResourcePermission2 =
        ResourcePermissions.getInstance(permissionName2);
    Set<Resource> resourcesByPermission =
        accessControlContext.getResourcesByResourcePermissions(
            authenticatedResource, resourceClassName, implicitResourcePermission);
    assertThat(resourcesByPermission.isEmpty(), is(true));
    Set<Resource> resourcesByPermission2 =
        accessControlContext.getResourcesByResourcePermissions(
            authenticatedResource, resourceClassName, implicitResourcePermission2);
    assertThat(resourcesByPermission2.isEmpty(), is(true));

    // create resource while unauthenticated and verify
    accessControlContext.unauthenticate();
    final Resource resource =
        accessControlContext.createResource(
            resourceClassName, domainName, externalId, PasswordCredentials.newInstance(password));

    assertThat(resource, is(not(nullValue())));
    assertThat(resource.getExternalId(), is(externalId));
    // re-authenticate as System Resource (because we don't have the previous credentials) and
    // verify created resource
    authenticateSystemResource();
    assertThat(accessControlContext.getDomainNameByResource(resource), is(domainName));
    final ResourceClassInfo resourceClassInfo =
        accessControlContext.getResourceClassInfoByResource(resource);
    assertThat(resourceClassInfo.getResourceClassName(), is(resourceClassName));

    // verify resource created while unauthenticated gets *ALL* available resource class permissions
    resourcesByPermission =
        accessControlContext.getResourcesByResourcePermissions(
            SYS_RESOURCE, resourceClassName, implicitResourcePermission);
    assertThat(resourcesByPermission.size(), is(1));
    resourcesByPermission2 =
        accessControlContext.getResourcesByResourcePermissions(
            SYS_RESOURCE, resourceClassName, implicitResourcePermission2);
    assertThat(resourcesByPermission2.size(), is(1));

    // verify we can authenticate
    accessControlContext.authenticate(resource, PasswordCredentials.newInstance(password));
  }
  @Test
  public void createAuthenticatableResource_withExtId_validAsAuthorized() {
    final String domainName = generateDomain();
    final String resourceClassName = generateResourceClass(true, false);
    final char[] password = generateUniquePassword();
    final char[] passwordBase = generateUniquePassword();
    final char[] shortPwd = (passwordBase + "123").substring(0, 3).toCharArray();
    final char[] whitespacedPwd = (" " + passwordBase + "\t").toCharArray();
    final String externalId = generateUniqueExternalId();

    // (ironically,) set up an authenticatable resource with resource class create permission
    final Resource authenticatedResource = generateResourceAndAuthenticate();
    final String permissionName = generateResourceClassPermission(resourceClassName);
    final ResourcePermission grantedResourcePermission =
        ResourcePermissions.getInstance(permissionName);
    grantResourceCreatePermission(
        authenticatedResource, resourceClassName, domainName, permissionName);

    Set<Resource> resourcesByPermission =
        accessControlContext.getResourcesByResourcePermissions(
            authenticatedResource, resourceClassName, grantedResourcePermission);
    assertThat(resourcesByPermission.isEmpty(), is(true));

    // create resource and verify
    final Resource resource =
        accessControlContext.createResource(
            resourceClassName, domainName, externalId, PasswordCredentials.newInstance(password));

    assertThat(resource, is(not(nullValue())));
    resourcesByPermission =
        accessControlContext.getResourcesByResourcePermissions(
            authenticatedResource, resourceClassName, grantedResourcePermission);
    assertThat(resourcesByPermission.size(), is(1));
    assertThat(accessControlContext.getDomainNameByResource(resource), is(domainName));
    final ResourceClassInfo resourceClassInfo =
        accessControlContext.getResourceClassInfoByResource(resource);
    assertThat(resourceClassInfo.getResourceClassName(), is(resourceClassName));
    assertThat(resource.getExternalId(), is(externalId));

    // verify we can authenticate
    accessControlContext.authenticate(resource, PasswordCredentials.newInstance(password));
  }
  @Test
  public void createAuthenticatableResource_withExtId_validAsSystemResource() {
    authenticateSystemResource();

    final String domainName = generateDomain();
    final String resourceClassName = generateResourceClass(true, false);
    final char[] password = generateUniquePassword();
    final String externalId = generateUniqueExternalId();

    // create resource and verify
    final Resource resource =
        accessControlContext.createResource(
            resourceClassName, domainName, externalId, PasswordCredentials.newInstance(password));

    assertThat(resource, is(not(nullValue())));
    accessControlContext.authenticate(resource, PasswordCredentials.newInstance(password));
    assertThat(accessControlContext.getDomainNameByResource(resource), is(domainName));
    final ResourceClassInfo resourceClassInfo =
        accessControlContext.getResourceClassInfoByResource(resource);
    assertThat(resourceClassInfo.getResourceClassName(), is(resourceClassName));
    assertThat(resource.getExternalId(), is(externalId));
  }
  @Test
  public void createAuthenticatableResource_duplicateExternalId_shouldFail() {
    authenticateSystemResource();

    final String domainName1 = generateDomain();
    final String resourceClassName1 = generateResourceClass(true, false);
    final String domainName2 = generateDomain();
    final String resourceClassName2 = generateResourceClass(true, false);
    final Credentials password = PasswordCredentials.newInstance(generateUniquePassword());
    final String externalId = generateUniqueExternalId();

    // create resource
    final Resource resource =
        accessControlContext.createResource(resourceClassName1, domainName1, externalId, password);
    assertThat(resource.getExternalId(), is(externalId));

    // create resource with same external id and verify
    try {
      accessControlContext.createResource(resourceClassName2, domainName2, externalId, password);
      fail("creating resource with duplicate (i.e. non-unique) external id should have failed");
    } catch (IllegalArgumentException e) {
      assertThat(e.getMessage().toLowerCase(), containsString("external id is not unique"));
    }
  }
  @Test
  public void createAuthenticatableResource_caseSensitiveConsistent_duplicateExternalId() {
    authenticateSystemResource();

    final String domainName = generateDomain();
    final String resourceClassName = generateResourceClass(true, false);
    final String permissionName = generateUniquePermissionName();
    final Credentials password = PasswordCredentials.newInstance(generateUniquePassword());
    final String externalId = generateUniqueExternalId();
    final String externalId_lower = externalId + "_eee";
    final String externalId_UPPER = externalId + "_EEE";

    accessControlContext.createResourcePermission(resourceClassName, permissionName);

    // set up an authenticatable resource with resource class create permission
    // so that we can look up the resources later via that permission
    final Resource authenticatedResource = generateResourceAndAuthenticate();
    grantResourceCreatePermission(
        authenticatedResource, resourceClassName, domainName, permissionName);
    final ResourcePermission grantedResourcePermission =
        ResourcePermissions.getInstance(permissionName);

    Set<Resource> resourcesByPermission;
    resourcesByPermission =
        accessControlContext.getResourcesByResourcePermissions(
            authenticatedResource, resourceClassName, grantedResourcePermission);
    assertThat(resourcesByPermission.isEmpty(), is(true));

    // check case sensitivity
    if (isDatabaseCaseSensitive()) {
      // create resource
      final Resource resource =
          accessControlContext.createResource(
              resourceClassName, domainName, externalId_lower, password);
      assertThat(resource.getExternalId(), is(externalId_lower));

      // create resource with same but case-sensitive external id and verify
      final Resource resource2 =
          accessControlContext.createResource(
              resourceClassName, domainName, externalId_UPPER, password);
      assertThat(resource2.getExternalId(), is(externalId_UPPER));

      resourcesByPermission =
          accessControlContext.getResourcesByResourcePermissions(
              authenticatedResource, resourceClassName, grantedResourcePermission);
      assertThat(resourcesByPermission.size(), is(2));
    } else {
      // create resource
      final Resource resource =
          accessControlContext.createResource(
              resourceClassName, domainName, externalId_lower, password);
      assertThat(resource.getExternalId(), is(externalId_lower));

      // create resource with same but case-insensitive external id and verify
      try {
        accessControlContext.createResource(
            resourceClassName, domainName, externalId_UPPER, password);
        fail(
            "creating resource with external id that differs in case should have failed for case-insensitive database");
      } catch (IllegalArgumentException e) {
        assertThat(e.getMessage().toLowerCase(), containsString("external id is not unique"));
      }

      resourcesByPermission =
          accessControlContext.getResourcesByResourcePermissions(
              authenticatedResource, resourceClassName, grantedResourcePermission);
      assertThat(resourcesByPermission.size(), is(1));
    }
  }