@Test
  public void testGetCompactionDetailsTest() throws StoreException, InterruptedException {
    // null logSegmentsNotInJournal to mimic all log segments overlapping with journal
    blobStore.logSegmentsNotInJournal = null;
    CompactionPolicyTest.verifyCompactionDetails(null, blobStore, compactionPolicy);

    // normal case where in some log segments are non overlapping with journal
    long maxLogSegmentCapacity = blobStore.segmentCapacity - blobStore.segmentHeaderSize - DEFAULT_MAX_BLOB_SIZE;
    long logSegmentCount = blobStore.capacityInBytes / blobStore.segmentCapacity;
    blobStore.logSegmentsNotInJournal = CompactionPolicyTest.generateRandomLogSegmentName((int) logSegmentCount);
    for (int k = 0; k < 5; k++) {
      for (int i = 0; i < logSegmentCount; i++) {
        for (int j = i; j < logSegmentCount; j++) {
          List<LogSegmentName> bestCandidates = blobStore.logSegmentsNotInJournal.subList(i, j + 1);
          long bestCost = maxLogSegmentCapacity / bestCandidates.size();
          // this best cost is to ensure that no of segments reclaimed will be "bestCandidates" count - 1
          NavigableMap<LogSegmentName, Long> validDataSize =
              CompactionPolicyTest.generateValidDataSize(blobStore.logSegmentsNotInJournal, bestCandidates, bestCost,
                  maxLogSegmentCapacity);
          mockBlobStoreStats.validDataSizeByLogSegments = validDataSize;
          if ((j - i) >= config.storeMinLogSegmentCountToReclaimToTriggerCompaction) {
            CompactionPolicyTest.verifyCompactionDetails(
                new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, bestCandidates, null), blobStore,
                compactionPolicy);
            Pair<Integer, Integer> bestCandidateIndexes = new Pair<>(i, j);
            Pair<Integer, Integer> secondBestCandidateIndexes =
                findNonOverLappingCandidate(bestCandidateIndexes, (int) logSegmentCount - 1);
            if (secondBestCandidateIndexes != null) {
              // set cost benefit of 2nd best candidate to 1 more than best candidate's cost benefit ratio.
              CompactionPolicyTest.updateValidDataSize(validDataSize,
                  blobStore.logSegmentsNotInJournal.subList(secondBestCandidateIndexes.getFirst(),
                      secondBestCandidateIndexes.getSecond() + 1), bestCost + 1);
              List<LogSegmentName> secondBestCandidate =
                  blobStore.logSegmentsNotInJournal.subList(secondBestCandidateIndexes.getFirst(),
                      secondBestCandidateIndexes.getSecond() + 1);
              mockBlobStoreStats.validDataSizeByLogSegments = validDataSize;
              // ensure that the best remains the best as it has the lowest cost benefit ratio
              CompactionPolicyTest.verifyCompactionDetails(
                  new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, bestCandidates, null), blobStore,
                  compactionPolicy);
              // set cost benefit of 2nd best to 1 less than the best candidate's cost benefit ratio
              CompactionPolicyTest.updateValidDataSize(validDataSize,
                  blobStore.logSegmentsNotInJournal.subList(secondBestCandidateIndexes.getFirst(),
                      secondBestCandidateIndexes.getSecond() + 1), bestCost - 1);
              mockBlobStoreStats.validDataSizeByLogSegments = validDataSize;
              // ensure that the 2nd best is now the best candidate to compact
              CompactionPolicyTest.verifyCompactionDetails(
                  new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, secondBestCandidate, null), blobStore,
                  compactionPolicy);
            }
          } else {
            CompactionPolicyTest.verifyCompactionDetails(null, blobStore, compactionPolicy);
          }
        }
      }
    }
  }
Tests {@link CompactionManager#getCompactionDetails(BlobStore)}
@throws StoreException
@throws InterruptedException
ambry-store/src/test/java/com/github/ambry/store/StatsBasedCompactionPolicyTest.java