@Test
  public void getIndexEntriesCornerCasesTest() throws IOException, StoreException {
    LogSegmentName logSegmentName = LogSegmentName.fromPositionAndGeneration(0, 0);
    MockId id1 = new MockId("0" + TestUtils.getRandomString(CUSTOM_ID_SIZE - 1));
    MockId id2 = new MockId("1" + TestUtils.getRandomString(CUSTOM_ID_SIZE - 1));
    MockId id3 = new MockId("2" + TestUtils.getRandomString(CUSTOM_ID_SIZE - 1));
    short accountId = Utils.getRandomShort(TestUtils.RANDOM);
    short containerId = Utils.getRandomShort(TestUtils.RANDOM);
    short lifeVersion = (short) 0;
    IndexValue value1 =
        IndexValueTest.getIndexValue(1000, new Offset(logSegmentName, 0), Utils.Infinite_Time, time.milliseconds(),
            accountId, containerId, lifeVersion, formatVersion);
    IndexValue value2 =
        IndexValueTest.getIndexValue(1000, new Offset(logSegmentName, 1000), Utils.Infinite_Time, time.milliseconds(),
            accountId, containerId, lifeVersion, formatVersion);
    IndexValue value3 =
        IndexValueTest.getIndexValue(1000, new Offset(logSegmentName, 2000), Utils.Infinite_Time, time.milliseconds(),
            accountId, containerId, lifeVersion, formatVersion);
    time.sleep(TimeUnit.SECONDS.toMillis(1));
    // generate a TTL Update
    IndexValue ttlUpValue2 =
        IndexValueTest.getIndexValue(value2.getSize(), value2.getOffset(), Utils.Infinite_Time, time.milliseconds(),
            value2.getAccountId(), value2.getContainerId(), lifeVersion, formatVersion);
    ttlUpValue2.setNewOffset(new Offset(logSegmentName, 3000));
    ttlUpValue2.setNewSize(50);
    ttlUpValue2.setFlag(IndexValue.Flags.Ttl_Update_Index);
    time.sleep(TimeUnit.SECONDS.toMillis(1));
    // generate a DELETE
    IndexValue delValue2 = IndexValueTest.getIndexValue(value2.getSize(), value2.getOffset(), ttlUpValue2.getFlags(),
        value2.getExpiresAtMs(), value2.getOffset().getOffset(), time.milliseconds(), value2.getAccountId(),
        value2.getContainerId(), lifeVersion, formatVersion);
    delValue2.setNewOffset(new Offset(logSegmentName, 3050));
    delValue2.setNewSize(100);
    delValue2.setFlag(IndexValue.Flags.Delete_Index);
    IndexSegment indexSegment = generateIndexSegment(new Offset(logSegmentName, 0), STORE_KEY_FACTORY);
    // inserting in the opposite order by design to ensure that writes are based on offset ordering and not key ordering
    indexSegment.addEntry(new IndexEntry(id3, value1), new Offset(logSegmentName, 1000));
    indexSegment.addEntry(new IndexEntry(id2, value2), new Offset(logSegmentName, 2000));
    indexSegment.addEntry(new IndexEntry(id1, value3), new Offset(logSegmentName, 3000));
    indexSegment.addEntry(new IndexEntry(id2, ttlUpValue2), new Offset(logSegmentName, 3050));
    indexSegment.addEntry(new IndexEntry(id2, delValue2), new Offset(logSegmentName, 3150));

    indexSegment.writeIndexSegmentToFile(new Offset(logSegmentName, 3150));
    indexSegment.seal();
    List<IndexEntry> entries = new ArrayList<>();
    for (boolean sealed : new boolean[]{false, true}) {
      Journal journal = new Journal(tempDir.getAbsolutePath(), 3, 3);
      IndexSegment fromDisk =
          new IndexSegment(indexSegment.getFile(), sealed, STORE_KEY_FACTORY, config, metrics, journal, time);
      // getIndexEntriesSince with maxSize = 0 should not return anything
      FindEntriesCondition condition = new FindEntriesCondition(0);
      assertFalse("getIndexEntriesSince() should not return anything",
          fromDisk.getIndexEntriesSince(null, condition, entries, new AtomicLong(0), false, false));
      assertEquals("There should be no entries returned", 0, entries.size());
      // getIndexEntriesSince with maxSize <= 1000 should return only the first key (id1)
      condition = new FindEntriesCondition(1000);
      assertTrue("getIndexEntriesSince() should return one entry",
          fromDisk.getIndexEntriesSince(null, condition, entries, new AtomicLong(0), false, false));
      assertEquals("There should be one entry returned", 1, entries.size());
      assertEquals("Key in entry is incorrect", id1, entries.get(0).getKey());
      assertEquals("Value in entry is incorrect", value3.getBytes(), entries.get(0).getValue().getBytes());
      entries.clear();
      // getIndexEntriesSince with maxSize > 1000 and <= 2150 should return four entries
      for (int maxSize : new int[]{1001, 2050, 2150}) {
        condition = new FindEntriesCondition(maxSize);
        assertTrue("getIndexEntriesSince() should return entries",
            fromDisk.getIndexEntriesSince(null, condition, entries, new AtomicLong(0), false, false));
        assertEquals("There should be four entries returned", 4, entries.size());
        assertEquals("Key in entry is incorrect", id1, entries.get(0).getKey());
        assertEquals("Value in entry is incorrect", value3.getBytes(), entries.get(0).getValue().getBytes());
        assertEquals("Key in entry is incorrect", id2, entries.get(1).getKey());
        assertEquals("Value in entry is incorrect", value2.getBytes(), entries.get(1).getValue().getBytes());
        assertEquals("Key in entry is incorrect", id2, entries.get(2).getKey());
        assertEquals("Value in entry is incorrect", ttlUpValue2.getBytes(), entries.get(2).getValue().getBytes());
        assertEquals("Key in entry is incorrect", id2, entries.get(3).getKey());
        assertEquals("Value in entry is incorrect", delValue2.getBytes(), entries.get(3).getValue().getBytes());
        entries.clear();
      }
      // getIndexEntriesSince with maxSize > 2150 should return five entries
      condition = new FindEntriesCondition(2151);
      assertTrue("getIndexEntriesSince() should return entries",
          fromDisk.getIndexEntriesSince(null, condition, entries, new AtomicLong(0), false, false));
      assertEquals("There should be five entries returned", 5, entries.size());
      assertEquals("Key in entry is incorrect", id1, entries.get(0).getKey());
      assertEquals("Value in entry is incorrect", value3.getBytes(), entries.get(0).getValue().getBytes());
      assertEquals("Key in entry is incorrect", id2, entries.get(1).getKey());
      assertEquals("Value in entry is incorrect", value2.getBytes(), entries.get(1).getValue().getBytes());
      assertEquals("Key in entry is incorrect", id2, entries.get(2).getKey());
      assertEquals("Value in entry is incorrect", ttlUpValue2.getBytes(), entries.get(2).getValue().getBytes());
      assertEquals("Key in entry is incorrect", id2, entries.get(3).getKey());
      assertEquals("Value in entry is incorrect", delValue2.getBytes(), entries.get(3).getValue().getBytes());
      assertEquals("Key in entry is incorrect", id3, entries.get(4).getKey());
      assertEquals("Value in entry is incorrect", value1.getBytes(), entries.get(4).getValue().getBytes());
      entries.clear();
      // getIndexEntriesSince with maxSize > 0 and <= 1150 starting from id2 should return two entries
      for (int maxSize : new int[]{1, 1050, 1150}) {
        condition = new FindEntriesCondition(maxSize);
        assertTrue("getIndexEntriesSince() should return entries",
            fromDisk.getIndexEntriesSince(id1, condition, entries, new AtomicLong(0), false, false));
        assertEquals("There should be three entries returned", 3, entries.size());
        assertEquals("Key in entry is incorrect", id2, entries.get(0).getKey());
        assertEquals("Value in entry is incorrect", value2.getBytes(), entries.get(0).getValue().getBytes());
        assertEquals("Key in entry is incorrect", id2, entries.get(1).getKey());
        assertEquals("Value in entry is incorrect", ttlUpValue2.getBytes(), entries.get(1).getValue().getBytes());
        assertEquals("Key in entry is incorrect", id2, entries.get(2).getKey());
        assertEquals("Value in entry is incorrect", delValue2.getBytes(), entries.get(2).getValue().getBytes());
        entries.clear();
      }
      if (formatVersion >= PersistentIndex.VERSION_1) {
        verifyResetKeyInfo(id3, value1, fromDisk.getResetKey(), fromDisk.getResetKeyType(),
            fromDisk.getResetKeyLifeVersion());
      }
    }
  }
Tests some corner cases with
{@link IndexSegment#getIndexEntriesSince(StoreKey, FindEntriesCondition, List, AtomicLong, boolean, boolean)}
- tests that all values of a key are returned even if the find entries condition max size expires when the first
value is loaded
@throws StoreException
ambry-store/src/test/java/com/github/ambry/store/IndexSegmentTest.java