@Test
  public void testGetQuotaAndUsageAndCharge() throws Exception {
    int initNumAccounts = 10;
    Map<String, Map<String, Long>> containerUsage = TestUtils.makeStorageMap(initNumAccounts, 10, 10000, 1000);
    InMemAccountService accountService = new InMemAccountService(false, false);
    Map<String, Long> storageQuota = new HashMap<>();
    // Account and container id's base is 1, not 0
    for (int i = 1; i <= initNumAccounts; i++) {
      QuotaResourceType resourceType =
          i <= containerUsage.size() / 2 ? QuotaResourceType.CONTAINER : QuotaResourceType.ACCOUNT;
      AccountBuilder accountBuilder =
          new AccountBuilder((short) i, String.valueOf(i), Account.AccountStatus.ACTIVE, resourceType);
      for (int j = 1; j <= 10; j++) {
        accountBuilder.addOrUpdateContainer(
            new ContainerBuilder((short) j, String.valueOf(j), Container.ContainerStatus.ACTIVE, "",
                (short) i).build());
      }
      accountService.updateAccounts(Collections.singleton(accountBuilder.build()));
      if (resourceType == QuotaResourceType.ACCOUNT) {
        storageQuota.put(QuotaResource.fromAccount(accountService.getAccountById((short) i)).getResourceId(),
            containerUsage.get(String.valueOf(i)).values().stream().mapToLong(Long::longValue).sum());
      } else {
        accountService.getAccountById((short) i)
            .getAllContainers()
            .forEach(c -> storageQuota.put(QuotaResource.fromContainer(c).getResourceId(),
                containerUsage.get(String.valueOf(c.getParentAccountId())).get(String.valueOf(c.getId()))));
      }
    }
    JSONStringStorageQuotaSource quotaSource = new JSONStringStorageQuotaSource(storageQuota, accountService);
    StorageQuotaEnforcer enforcer = new StorageQuotaEnforcer(config, quotaSource, (StorageUsageRefresher) null);
    enforcer.initStorageUsage(Collections.EMPTY_MAP);

    for (Map.Entry<String, Map<String, Long>> accountEntry : containerUsage.entrySet()) {
      short accountId = Short.valueOf(accountEntry.getKey());
      if (accountService.getAccountById(accountId).getQuotaResourceType() == QuotaResourceType.ACCOUNT) {
        long quota = (long) (quotaSource.getQuota(QuotaResource.fromAccount(accountService.getAccountById(accountId)),
            QuotaName.STORAGE_IN_GB).getQuotaValue()) * BYTES_IN_GB;
        RestRequest restRequest = createRestRequest(accountService, accountId, (short) 1);
        Pair<Long, Long> quotaAndUsage = enforcer.getQuotaAndUsage(restRequest);
        assertEquals("Account id: " + accountEntry.getKey(), quota, quotaAndUsage.getFirst().longValue());
        assertEquals(0L, quotaAndUsage.getSecond().longValue());

        quotaAndUsage = enforcer.charge(restRequest, quota / 2);
        assertEquals(quota, quotaAndUsage.getFirst().longValue());
        assertEquals(quota / 2, quotaAndUsage.getSecond().longValue());

        quotaAndUsage = enforcer.charge(restRequest, quota);
        assertEquals(quota, quotaAndUsage.getFirst().longValue());
        assertEquals(quota / 2 + quota, quotaAndUsage.getSecond().longValue());
      } else {
        for (Map.Entry<String, Long> containerEntry : accountEntry.getValue().entrySet()) {
          short containerId = Short.valueOf(containerEntry.getKey());
          long quota = containerEntry.getValue() * BYTES_IN_GB;
          RestRequest restRequest = createRestRequest(accountService, accountId, containerId);
          Pair<Long, Long> quotaAndUsage = enforcer.getQuotaAndUsage(restRequest);
          assertEquals(quota, quotaAndUsage.getFirst().longValue());
          assertEquals(0L, quotaAndUsage.getSecond().longValue());

          quotaAndUsage = enforcer.charge(restRequest, quota / 2);
          assertEquals(quota, quotaAndUsage.getFirst().longValue());
          assertEquals(quota / 2, quotaAndUsage.getSecond().longValue());

          quotaAndUsage = enforcer.charge(restRequest, quota);
          assertEquals(quota, quotaAndUsage.getFirst().longValue());
          assertEquals(quota / 2 + quota, quotaAndUsage.getSecond().longValue());
        }
      }
    }

    // Now create a restRequest that doesn't carry account and container
    RestRequest restRequest = createRestRequest();
    Pair<Long, Long> quotaAndUsage = enforcer.getQuotaAndUsage(restRequest);
    assertEquals(-1L, quotaAndUsage.getFirst().longValue());
    assertEquals(0L, quotaAndUsage.getSecond().longValue());
    quotaAndUsage = enforcer.charge(restRequest, 100L);
    assertEquals(-1L, quotaAndUsage.getFirst().longValue());
    assertEquals(0L, quotaAndUsage.getSecond().longValue());

    Account account = new AccountBuilder((short) 1000, String.valueOf(1000), Account.AccountStatus.ACTIVE,
        QuotaResourceType.CONTAINER).addOrUpdateContainer(
        new ContainerBuilder((short) 10000, String.valueOf(10000), Container.ContainerStatus.ACTIVE, "",
            (short) 1000).build()).build();
    accountService.updateAccounts(Collections.singleton(account));
    restRequest = createRestRequest(accountService, (short) 1000, (short) 10000);
    quotaAndUsage = enforcer.getQuotaAndUsage(restRequest);
    assertEquals(-1L, quotaAndUsage.getFirst().longValue());
    assertEquals(0L, quotaAndUsage.getSecond().longValue());
    quotaAndUsage = enforcer.charge(restRequest, 100L);
    assertEquals(-1L, quotaAndUsage.getFirst().longValue());
    assertEquals(0L, quotaAndUsage.getSecond().longValue());
  }
Test {@link StorageQuotaEnforcer#getQuotaAndUsage} and {@link StorageQuotaEnforcer#charge} methods.
@throws Exception
ambry-quota/src/test/java/com/github/ambry/quota/storage/StorageQuotaEnforcerTest.java