private void testScan(final int[] columnArr, final boolean lazySeekEnabled, final int startRow,
    final int endRow, int maxVersions) throws IOException {
    StoreScanner.enableLazySeekGlobally(lazySeekEnabled);
    final Scan scan = new Scan();
    final Set<String> qualSet = new HashSet<>();
    for (int iColumn : columnArr) {
      String qualStr = getQualStr(iColumn);
      scan.addColumn(FAMILY_BYTES, Bytes.toBytes(qualStr));
      qualSet.add(qualStr);
    }
    scan.readVersions(maxVersions);
    scan.withStartRow(rowBytes(startRow));

    // Adjust for the fact that for multi-row queries the end row is exclusive.
    if (startRow != endRow) {
      scan.withStopRow(rowBytes(endRow + 1));
    } else {
      scan.withStopRow(rowBytes(endRow), true);
    }

    final long initialSeekCount = StoreFileScanner.getSeekCount();
    final InternalScanner scanner = region.getScanner(scan);
    final List<Cell> results = new ArrayList<>();
    final List<Cell> actualKVs = new ArrayList<>();

    // Such a clumsy do-while loop appears to be the official way to use an
    // internalScanner. scanner.next() return value refers to the _next_
    // result, not to the one already returned in results.
    boolean hasNext;
    do {
      hasNext = scanner.next(results);
      actualKVs.addAll(results);
      results.clear();
    } while (hasNext);

    List<Cell> filteredKVs =
      filterExpectedResults(qualSet, rowBytes(startRow), rowBytes(endRow), maxVersions);
    final String rowRestrictionStr = (startRow == -1 && endRow == -1)
      ? "all rows"
      : (startRow == endRow
        ? ("row=" + startRow)
        : ("startRow=" + startRow + ", " + "endRow=" + endRow));
    final String columnRestrictionStr =
      columnArr.length == 0 ? "all columns" : ("columns=" + Arrays.toString(columnArr));
    final String testDesc = "Bloom=" + bloomType + ", compr=" + comprAlgo + ", "
      + (scan.isGetScan() ? "Get" : "Scan") + ": " + columnRestrictionStr + ", " + rowRestrictionStr
      + ", maxVersions=" + maxVersions + ", lazySeek=" + lazySeekEnabled;
    long seekCount = StoreFileScanner.getSeekCount() - initialSeekCount;
    if (VERBOSE) {
      System.err.println("Seek count: " + seekCount + ", KVs returned: " + actualKVs.size() + ". "
        + testDesc + (lazySeekEnabled ? "\n" : ""));
    }
    if (lazySeekEnabled) {
      totalSeekLazy += seekCount;
    } else {
      totalSeekDiligent += seekCount;
    }
    assertKVListsEqual(testDesc, filteredKVs, actualKVs);
  }
Disable this when this test fails hopelessly and you need to debug a simpler case.
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestSeekOptimizations.java