@Test
  public void undeleteCrossLogSegmentTest_DeleteAsFinal() throws Exception {
    assumeTrue(withUndelete);
    for (long deleteReferenceTime : new long[]{-1, 0}) {
      refreshState(false, false, false);
      int numPuts = (int) Math.floorDiv(state.log.getSegmentCapacity() - LogSegment.HEADER_SIZE,
          PUT_RECORD_SIZE + (DELETE_RECORD_SIZE) / 2) - 1;
      List<IndexEntry> entries = state.addPutEntries(numPuts, PUT_RECORD_SIZE, Utils.Infinite_Time);
      for (IndexEntry entry : entries) {
        state.addDeleteEntry((MockId) entry.getKey());
      }
      for (IndexEntry entry : entries) {
        state.addUndeleteEntry((MockId) entry.getKey());
      }
      writeDataToMeetRequiredSegmentCount(state.index.getLogSegmentCount() + 1, null);
      for (IndexEntry entry : entries) {
        state.addDeleteEntry((MockId) entry.getKey());
      }
      writeDataToMeetRequiredSegmentCount(state.index.getLogSegmentCount() + 1, null);
      state.reloadIndex(true, false);

      List<LogSegmentName> segmentsUnderCompaction = getLogSegments(0, state.index.getLogSegmentCount() - 1);
      long realDeleteReferenceTime = deleteReferenceTime < 0 ? state.time.milliseconds() : deleteReferenceTime;
      compactAndVerify(segmentsUnderCompaction, realDeleteReferenceTime, true);

      for (IndexEntry entry : entries) {
        List<IndexValue> values = state.index.findAllIndexValuesForKey(entry.getKey(), null);
        assertNotNull(values);
        IndexValue delete = values.get(0);
        assertFalse(delete.isUndelete());
        assertTrue(delete.isDelete());
        assertEquals((short) 1, delete.getLifeVersion());
        if (deleteReferenceTime < 0) {
          assertEquals(1, values.size());
        } else {
          assertEquals(2, values.size());
          IndexValue put = values.get(1);
          IndexValue expected = entry.getValue();
          assertEquals(expected.isPut(), put.isPut());
          assertEquals(expected.getLifeVersion(), put.getLifeVersion());
          assertEquals(expected.getAccountId(), put.getAccountId());
          assertEquals(expected.getContainerId(), put.getContainerId());
          assertEquals(expected.getSize(), put.getSize());
          assertEquals(expected.getExpiresAtMs(), put.getExpiresAtMs());
          assertEquals(expected.getOperationTimeInMs(), put.getOperationTimeInMs());
        }
      }
    }
  }
Tests when the PUT DELETE and UNDELETE are located in different log segments and the delete is the final state.
@throws Exception
ambry-store/src/test/java/com/github/ambry/store/BlobStoreCompactorTest.java