@Test
  public void rebuildTokenBasedOnResetKeyTest() throws StoreException {
    assumeTrue(isLogSegmented);
    IndexSegment firstIndexSegment = stateForTokenTest.index.getIndexSegments().firstEntry().getValue();
    IndexSegment secondIndexSegment =
        stateForTokenTest.index.getIndexSegments().higherEntry(firstIndexSegment.getStartOffset()).getValue();
    StoreKey firstKey = firstIndexSegment.iterator().next().getKey();
    StoreKey keyFromFirstSegment = firstIndexSegment.listIterator(DEFAULT_MAX_IN_MEM_ELEMENTS - 2).next().getKey();
    // 1. generate an invalid index-based token with reset key and the key can be found in current index
    Offset invalidOffset =
        new Offset(firstIndexSegment.getLogSegmentName(), firstIndexSegment.getStartOffset().getOffset() - 1);
    StoreFindToken startToken = new StoreFindToken(keyFromFirstSegment, invalidOffset, stateForTokenTest.sessionId,
        stateForTokenTest.incarnationId, firstIndexSegment.getResetKey(), firstIndexSegment.getResetKeyType(),
        firstIndexSegment.getResetKeyLifeVersion());
    //  the invalid token should be revalidated by looking up reset key in index
    FindInfo findInfo = stateForTokenTest.index.findEntriesSince(startToken, 1);
    StoreFindToken token = (StoreFindToken) findInfo.getFindToken();
    // the key in the token should be first key in first index segment, as we only get one entry from new start point,
    // which is first key in first index segment (inclusive)
    StoreFindToken expectedToken =
        new StoreFindToken(firstKey, firstIndexSegment.getStartOffset(), stateForTokenTest.sessionId,
            stateForTokenTest.incarnationId, firstIndexSegment.getResetKey(), firstIndexSegment.getResetKeyType(),
            firstIndexSegment.getResetKeyLifeVersion());
    compareTokens(expectedToken, token);

    // 2. generate an invalid journal based token with reset key pointing to 2nd index segment (this is to mock that the
    // reset key fell out of journal and was copied to 2nd index segment by compaction)
    IndexSegment lastIndexSegment = stateForTokenTest.index.getIndexSegments().lastEntry().getValue();
    invalidOffset = new Offset(lastIndexSegment.getLogSegmentName().getNextGenerationName(),
        lastIndexSegment.getStartOffset().getOffset() + 1);
    startToken = new StoreFindToken(invalidOffset, stateForTokenTest.sessionId, stateForTokenTest.incarnationId, false,
        secondIndexSegment.getResetKey(), secondIndexSegment.getResetKeyType(),
        secondIndexSegment.getResetKeyLifeVersion());
    findInfo = stateForTokenTest.index.findEntriesSince(startToken, 1);
    token = (StoreFindToken) findInfo.getFindToken();
    // expected token should be the first key in 2nd index segment (index-based)
    StoreKey firstKeyFromSecondSegment = secondIndexSegment.iterator().next().getKey();
    expectedToken =
        new StoreFindToken(firstKeyFromSecondSegment, secondIndexSegment.getStartOffset(), stateForTokenTest.sessionId,
            stateForTokenTest.incarnationId, secondIndexSegment.getResetKey(), secondIndexSegment.getResetKeyType(),
            secondIndexSegment.getResetKeyLifeVersion());
    compareTokens(expectedToken, token);

    // 3. generate an invalid token with reset key but the reset key is not found in current index
    StoreKey keyNotFound = stateForTokenTest.getUniqueId();
    startToken = new StoreFindToken(invalidOffset, stateForTokenTest.sessionId, stateForTokenTest.incarnationId, false,
        keyNotFound, PersistentIndex.IndexEntryType.PUT, (short) 0);
    findInfo = stateForTokenTest.index.findEntriesSince(startToken, 1);
    token = (StoreFindToken) findInfo.getFindToken();
    // token should be reset to the very beginning which is the first index segment
    expectedToken = new StoreFindToken(firstKey, firstIndexSegment.getStartOffset(), stateForTokenTest.sessionId,
        stateForTokenTest.incarnationId, firstIndexSegment.getResetKey(), firstIndexSegment.getResetKeyType(),
        firstIndexSegment.getResetKeyLifeVersion());
    compareTokens(expectedToken, token);
  }
Tests cases where find token is rebuilt based on reset key.
@throws StoreException
ambry-store/src/test/java/com/github/ambry/store/IndexTest.java