@Test
  public void testLogSegmentsNotInJournal() throws StoreException {
    long maxLogSegmentCapacity = blobStore.segmentCapacity - blobStore.segmentHeaderSize - DEFAULT_MAX_BLOB_SIZE;
    long logSegmentCount = blobStore.capacityInBytes / blobStore.segmentCapacity;
    blobStore.logSegmentsNotInJournal = CompactionPolicyTest.generateRandomLogSegmentName((int) logSegmentCount);

    // case 1: 1st best(index_0 to index_3) is in journal, 2nd not in journal
    List<LogSegmentName> bestCandidates = blobStore.logSegmentsNotInJournal.subList(0, 4);
    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;
    CompactionPolicyTest.verifyCompactionDetails(
        new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, bestCandidates, null), blobStore,
        compactionPolicy);
    Pair<Integer, Integer> bestCandidateIndexes = new Pair<>(0, 3);
    Pair<Integer, Integer> secondBestCandidateIndexes =
        findNonOverLappingCandidate(bestCandidateIndexes, (int) logSegmentCount - 1);
    // 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 2nd best's log segments are in journal
    blobStore.logSegmentsNotInJournal = bestCandidates;
    // ensure that the 1st best is now the best candidate to compact even though 2nd best's cost benefit ratio
    // is the lowest
    CompactionPolicyTest.verifyCompactionDetails(
        new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, bestCandidates, null), blobStore,
        compactionPolicy);

    // case 2: only one potential candidate(index_5 to index_7) to compact which is overlaps with the journal
    blobStore.logSegmentsNotInJournal = CompactionPolicyTest.generateRandomLogSegmentName((int) logSegmentCount);
    bestCandidates = blobStore.logSegmentsNotInJournal.subList(5, 8);
    bestCost = maxLogSegmentCapacity / bestCandidates.size();
    // this best cost is to ensure that no of segments reclaimed will be "bestCandidates" count - 1
    validDataSize =
        CompactionPolicyTest.generateValidDataSize(blobStore.logSegmentsNotInJournal, bestCandidates, bestCost,
            maxLogSegmentCapacity);
    mockBlobStoreStats.validDataSizeByLogSegments = validDataSize;
    blobStore.logSegmentsNotInJournal = blobStore.logSegmentsNotInJournal.subList(0, 4);
    CompactionPolicyTest.verifyCompactionDetails(null, blobStore, compactionPolicy);

    // case 3: best candidate's first few segments(index_2 to index7) are non overlapping and the rest are overlapping
    // with journal
    blobStore.logSegmentsNotInJournal = CompactionPolicyTest.generateRandomLogSegmentName((int) logSegmentCount);
    bestCandidates = blobStore.logSegmentsNotInJournal.subList(2, 8);
    bestCost = maxLogSegmentCapacity / bestCandidates.size();
    validDataSize =
        CompactionPolicyTest.generateValidDataSize(blobStore.logSegmentsNotInJournal, bestCandidates, bestCost,
            maxLogSegmentCapacity);
    mockBlobStoreStats.validDataSizeByLogSegments = validDataSize;
    blobStore.logSegmentsNotInJournal = blobStore.logSegmentsNotInJournal.subList(0, 5);
    // expected best candidate = index2 to index_4 which is first 3 entries in the actual best candidate
    CompactionPolicyTest.verifyCompactionDetails(
        new CompactionDetails(time.milliseconds() - messageRetentionTimeInMs, bestCandidates.subList(0, 3), null), blobStore,
        compactionPolicy);
  }
Tests {@link CompactionManager#getCompactionDetails(BlobStore)} for different cases for
logSegmentsNotInJournal
ambry-store/src/test/java/com/github/ambry/store/StatsBasedCompactionPolicyTest.java