@Override
  public void incrementThreads() {
    consumeTokens();
    super.incrementThreads();
  }
@Test
  public void testIncrementThreads()
      throws Exception {
    // set test time first
    _timeMillis = 100;
    TestTokenSchedulerGroup group = new TestTokenSchedulerGroup();

    int availableTokens = group.getAvailableTokens();
    // verify token count is correctly set
    assertEquals(availableTokens,
        TestTokenSchedulerGroup.NUM_TOKENS_PER_MS * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS);

    // no threads in use...incrementing time has no effect
    _timeMillis += 2 * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS;
    availableTokens = group.getAvailableTokens();
    int startTime = _timeMillis;
    assertEquals(availableTokens,
        TestTokenSchedulerGroup.NUM_TOKENS_PER_MS * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS);

    int nThreads = 1;
    incrementThreads(group, nThreads);
    assertEquals(group.getThreadsInUse(), nThreads);
    assertEquals(group.getAvailableTokens(), availableTokens);

    // advance time
    int timeIncrement = 20;
    _timeMillis += timeIncrement;
    group.decrementThreads();
    assertEquals(group.getThreadsInUse(), 0);
    assertEquals(group.getAvailableTokens(), availableTokens - timeIncrement * nThreads);

    // more threads
    availableTokens = group.getAvailableTokens();
    nThreads = 5;
    incrementThreads(group, nThreads);
    assertEquals(group.getThreadsInUse(), nThreads);
    // advance time now
    _timeMillis += timeIncrement;
    assertEquals(group.getAvailableTokens(), availableTokens - timeIncrement * nThreads);

    // simple getAvailableTokens() updates tokens and reservedThreads has no effect
    group.addReservedThreads(2 * nThreads);
    availableTokens = group.getAvailableTokens();
    timeIncrement = 10;
    _timeMillis += timeIncrement;
    assertEquals(group.getAvailableTokens(), availableTokens - timeIncrement * nThreads);
    availableTokens = group.getAvailableTokens();

    // decrement some threads
    decrementThreads(group, 2);
    nThreads -= 2;
    _timeMillis += timeIncrement;
    assertEquals(group.getAvailableTokens(), availableTokens - timeIncrement * nThreads);

    // 3 threads still in use. Advance time beyond time quantum
    availableTokens = group.getAvailableTokens();
    int pendingTimeInQuantum = startTime + TestTokenSchedulerGroup.TOKEN_LIFETIME_MS - _timeMillis;
    _timeMillis = startTime + TestTokenSchedulerGroup.TOKEN_LIFETIME_MS + timeIncrement;
    int timeAdvance = pendingTimeInQuantum + timeIncrement;
    // these are "roughly" the tokens in use since we apply decay. So we don't test for exact value
    int expectedTokens =
        TestTokenSchedulerGroup.NUM_TOKENS_PER_MS * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS - timeAdvance * nThreads;
    assertTrue(group.getAvailableTokens() < expectedTokens);
    availableTokens = group.getAvailableTokens();

    // increment by multiple quantums
    _timeMillis = startTime + 3 * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS + timeIncrement;
    expectedTokens = TestTokenSchedulerGroup.NUM_TOKENS_PER_MS * TestTokenSchedulerGroup.TOKEN_LIFETIME_MS
        - timeIncrement * nThreads;
    assertTrue(group.getAvailableTokens() < expectedTokens);
  }