@Test
  public void testMergeFilterResponseCase1() throws IOException {
    List<MatchCode> expected = new ArrayList<>();
    expected.add(MatchCode.INCLUDE);
    expected.add(MatchCode.INCLUDE);
    expected.add(MatchCode.SEEK_NEXT_ROW);

    Scan scanWithFilter = new Scan(scan).setFilter(new AlwaysIncludeFilter()).readVersions(2);

    long now = EnvironmentEdgeManager.currentTime();
    // scan with column 2,4,5, the family with maxVersion = 3
    UserScanQueryMatcher qm = UserScanQueryMatcher.create(
      scanWithFilter, new ScanInfo(this.conf, fam2, 0, 3, ttl, KeepDeletedCells.FALSE,
        HConstants.DEFAULT_BLOCKSIZE, 0, rowComparator, false),
      get.getFamilyMap().get(fam2), now - ttl, now, null);

    List<KeyValue> memstore = new ArrayList<>();
    memstore.add(new KeyValue(row1, fam1, col5, 1, data)); // match code will be INCLUDE
    memstore.add(new KeyValue(row1, fam1, col5, 2, data)); // match code will be INCLUDE

    // match code will be SEEK_NEXT_ROW , which is max(INCLUDE_AND_SEEK_NEXT_ROW, SEEK_NEXT_COL).
    memstore.add(new KeyValue(row1, fam1, col5, 3, data));

    KeyValue k = memstore.get(0);
    qm.setToNewRow(k);

    for (int i = 0; i < memstore.size(); i++) {
      assertEquals(expected.get(i), qm.match(memstore.get(i)));
    }

    scanWithFilter = new Scan(scan).setFilter(new AlwaysIncludeFilter()).readVersions(1);
    qm = UserScanQueryMatcher.create(
      scanWithFilter, new ScanInfo(this.conf, fam2, 0, 2, ttl, KeepDeletedCells.FALSE,
        HConstants.DEFAULT_BLOCKSIZE, 0, rowComparator, false),
      get.getFamilyMap().get(fam2), now - ttl, now, null);

    List<KeyValue> memstore2 = new ArrayList<>();
    memstore2.add(new KeyValue(row2, fam1, col2, 1, data)); // match code will be INCLUDE
    // match code will be SEEK_NEXT_COL, which is max(INCLUDE_AND_SEEK_NEXT_COL, SEEK_NEXT_COL).
    memstore2.add(new KeyValue(row2, fam1, col2, 2, data));

    k = memstore2.get(0);
    qm.setToNewRow(k);

    assertEquals(MatchCode.INCLUDE, qm.match(memstore2.get(0)));
    assertEquals(MatchCode.SEEK_NEXT_COL, qm.match(memstore2.get(1)));
  }
Here is the unit test for UserScanQueryMatcher#mergeFilterResponse, when the number of cells
exceed the versions requested in scan, we should return SEEK_NEXT_COL, but if current match
code is INCLUDE_AND_SEEK_NEXT_ROW, we can optimize to choose the max step between SEEK_NEXT_COL
and INCLUDE_AND_SEEK_NEXT_ROW, which is SEEK_NEXT_ROW. <br/>
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/querymatcher/TestUserScanQueryMatcher.java