@Test
  public void testIndexSegmentRollOverKeySizeAndValueSizeChange() throws StoreException, IOException {
    state.closeAndClearIndex();
    int persistedEntryMinBytes = 100;
    state.properties.put("store.index.persisted.entry.min.bytes", Long.toString(persistedEntryMinBytes));
    state.properties.put("store.index.max.number.of.inmem.elements", Integer.toString(10));
    StoreConfig config = new StoreConfig(new VerifiableProperties(state.properties));
    state.reloadIndex(false, false);

    List<IndexEntry> indexEntries = new ArrayList<>();
    int indexCount = state.index.getIndexSegments().size();
    // get the overhead of the key besides the String ID.
    int keyOverheadBytes = state.getUniqueId(10).sizeInBytes() - 10;

    // add first entry with size under storeIndexPersistedEntryMinBytes.
    int indexValueSize =
        PersistentIndex.CURRENT_VERSION >= PersistentIndex.VERSION_3 ? IndexValue.INDEX_VALUE_SIZE_IN_BYTES_V3_V4
            : IndexValue.INDEX_VALUE_SIZE_IN_BYTES_V1_V2;
    int keySize = config.storeIndexPersistedEntryMinBytes / 2 - indexValueSize - keyOverheadBytes;
    int expectedEntrySize = keySize + indexValueSize + keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 1, ++indexCount, expectedEntrySize, false);

    // Now, the active segment consists of one element. Add 2nd element of a smaller key size; entry size remains.
    keySize = keySize / 2;
    addEntriesAndAssert(indexEntries, keySize, 1, indexCount, expectedEntrySize, false);

    // 3rd element with key size greater than the first entry, but still under storeIndexPersistedEntryMinBytes.
    keySize = keySize * 3;
    expectedEntrySize = keySize + indexValueSize + keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 1, indexCount, expectedEntrySize, false);

    // 4th element key size increase, and above storeIndexPersistedEntryMinBytes. Won't cause rollover.
    keySize = config.storeIndexPersistedEntryMinBytes - indexValueSize - keyOverheadBytes + 1;
    expectedEntrySize = config.storeIndexPersistedEntryMinBytes + 1;
    addEntriesAndAssert(indexEntries, keySize, 1, indexCount, expectedEntrySize, false);

    // more elements in the next segment. This should be accommodated in the same segment.
    keySize = config.storeIndexPersistedEntryMinBytes - indexValueSize - keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 2, indexCount, expectedEntrySize, false);

    // verify index values
    verifyIndexValues(indexEntries);

    // Verify that a decrease in the config value for persistedEntryMinBytes does not affect the persisted segment.
    // Now close and reload index with a change in the minPersistedBytes.
    state.properties.put("store.index.persisted.entry.min.bytes", Long.toString(persistedEntryMinBytes / 2));
    state.reloadIndex(true, false);
    keySize = (expectedEntrySize - indexValueSize - keyOverheadBytes) / 2;
    addEntriesAndAssert(indexEntries, keySize, 4, indexCount, expectedEntrySize, false);

    // At this point, index will rollover due to max number of entries being reached.
    // Verify that the new segment that is created honors the entry size.
    keySize = 10;
    expectedEntrySize = keySize + indexValueSize + keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 1, ++indexCount, expectedEntrySize, false);

    // verify index values
    verifyIndexValues(indexEntries);

    // Verify that an increase in the config value for persistedEntryMinBytes does not affect anything.
    // Now close and reload index with a change in the minPersistedBytes.
    state.properties.put("store.index.persisted.entry.min.bytes", Long.toString(persistedEntryMinBytes * 2));
    state.reloadIndex(true, false);
    // Make sure we add entries that can fit in the latest segment.
    keySize = expectedEntrySize - indexValueSize - keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 9, indexCount, expectedEntrySize, false);

    // At this point, index will rollover due to max number of entries being reached. Verify that the new segment that is
    // created has the new entry size.
    keySize = 20;
    expectedEntrySize = keySize + indexValueSize + keyOverheadBytes;
    addEntriesAndAssert(indexEntries, keySize, 1, ++indexCount, expectedEntrySize, false);

    // verify index values
    verifyIndexValues(indexEntries);

    // Verify that a value size change will cause a rollover
    expectedEntrySize = keySize + keyOverheadBytes + IndexValue.INDEX_VALUE_SIZE_IN_BYTES_V0;
    addEntriesAndAssert(indexEntries, keySize, 1, ++indexCount, expectedEntrySize, true);
    verifyIndexValues(indexEntries);
  }
Tests index segment rollover behavior with respect to key size changes.
For the current version, we don't reply on the config.storeIndexPersistedEntryMinBytes.
We dynamically monitor the max entry size and add the padding if needed.
A change in key size shouldn't cause a rollover.
Also test index segment rollover with respect to a value size change.
@throws StoreException
@throws IOException
ambry-store/src/test/java/com/github/ambry/store/IndexTest.java