@Test
  public void testReverseScanner_FromMemStoreAndHFiles_MultiCFs1() throws IOException {
    byte[] row0 = Bytes.toBytes("row0"); // 1 kv
    byte[] row1 = Bytes.toBytes("row1"); // 2 kv
    byte[] row2 = Bytes.toBytes("row2"); // 4 kv
    byte[] row3 = Bytes.toBytes("row3"); // 2 kv
    byte[] row4 = Bytes.toBytes("row4"); // 5 kv
    byte[] row5 = Bytes.toBytes("row5"); // 2 kv
    byte[] cf1 = Bytes.toBytes("CF1");
    byte[] cf2 = Bytes.toBytes("CF2");
    byte[] cf3 = Bytes.toBytes("CF3");
    byte[][] families = { cf1, cf2, cf3 };
    byte[] col = Bytes.toBytes("C");
    long ts = 1;
    Configuration conf = new Configuration(CONF);
    // disable compactions in this test.
    conf.setInt("hbase.hstore.compactionThreshold", 10000);
    this.region = initHRegion(tableName, method, conf, families);
    // kv naming style: kv(row number) totalKvCountInThisRow seq no
    KeyValue kv0_1_1 = new KeyValue(row0, cf1, col, ts, KeyValue.Type.Put, null);
    KeyValue kv1_2_1 = new KeyValue(row1, cf2, col, ts, KeyValue.Type.Put, null);
    KeyValue kv1_2_2 = new KeyValue(row1, cf1, col, ts + 1, KeyValue.Type.Put, null);
    KeyValue kv2_4_1 = new KeyValue(row2, cf2, col, ts, KeyValue.Type.Put, null);
    KeyValue kv2_4_2 = new KeyValue(row2, cf1, col, ts, KeyValue.Type.Put, null);
    KeyValue kv2_4_3 = new KeyValue(row2, cf3, col, ts, KeyValue.Type.Put, null);
    KeyValue kv2_4_4 = new KeyValue(row2, cf1, col, ts + 4, KeyValue.Type.Put, null);
    KeyValue kv3_2_1 = new KeyValue(row3, cf2, col, ts, KeyValue.Type.Put, null);
    KeyValue kv3_2_2 = new KeyValue(row3, cf1, col, ts + 4, KeyValue.Type.Put, null);
    KeyValue kv4_5_1 = new KeyValue(row4, cf1, col, ts, KeyValue.Type.Put, null);
    KeyValue kv4_5_2 = new KeyValue(row4, cf3, col, ts, KeyValue.Type.Put, null);
    KeyValue kv4_5_3 = new KeyValue(row4, cf3, col, ts + 5, KeyValue.Type.Put, null);
    KeyValue kv4_5_4 = new KeyValue(row4, cf2, col, ts, KeyValue.Type.Put, null);
    KeyValue kv4_5_5 = new KeyValue(row4, cf1, col, ts + 3, KeyValue.Type.Put, null);
    KeyValue kv5_2_1 = new KeyValue(row5, cf2, col, ts, KeyValue.Type.Put, null);
    KeyValue kv5_2_2 = new KeyValue(row5, cf3, col, ts, KeyValue.Type.Put, null);
    // hfiles(cf1/cf2) :"row1"(1 kv) / "row2"(1 kv) / "row4"(2 kv)
    Put put = null;
    put = new Put(row1);
    put.add(kv1_2_1);
    region.put(put);
    put = new Put(row2);
    put.add(kv2_4_1);
    region.put(put);
    put = new Put(row4);
    put.add(kv4_5_4);
    put.add(kv4_5_5);
    region.put(put);
    region.flush(true);
    // hfiles(cf1/cf3) : "row1" (1 kvs) / "row2" (1 kv) / "row4" (2 kv)
    put = new Put(row4);
    put.add(kv4_5_1);
    put.add(kv4_5_3);
    region.put(put);
    put = new Put(row1);
    put.add(kv1_2_2);
    region.put(put);
    put = new Put(row2);
    put.add(kv2_4_4);
    region.put(put);
    region.flush(true);
    // hfiles(cf1/cf3) : "row2"(2 kv) / "row3"(1 kvs) / "row4" (1 kv)
    put = new Put(row4);
    put.add(kv4_5_2);
    region.put(put);
    put = new Put(row2);
    put.add(kv2_4_2);
    put.add(kv2_4_3);
    region.put(put);
    put = new Put(row3);
    put.add(kv3_2_2);
    region.put(put);
    region.flush(true);
    // memstore(cf1/cf2/cf3) : "row0" (1 kvs) / "row3" ( 1 kv) / "row5" (max)
    // ( 2 kv)
    put = new Put(row0);
    put.add(kv0_1_1);
    region.put(put);
    put = new Put(row3);
    put.add(kv3_2_1);
    region.put(put);
    put = new Put(row5);
    put.add(kv5_2_1);
    put.add(kv5_2_2);
    region.put(put);
    // scan range = ["row4", min), skip the max "row5"
    Scan scan = new Scan().withStartRow(row4);
    scan.readVersions(5);
    scan.setBatch(3);
    scan.setReversed(true);
    try (InternalScanner scanner = region.getScanner(scan)) {
      List<Cell> currRow = new ArrayList<>();
      boolean hasNext = false;
      // 1. scan out "row4" (5 kvs), "row5" can't be scanned out since not
      // included in scan range
      // "row4" takes 2 next() calls since batch=3
      hasNext = scanner.next(currRow);
      assertEquals(3, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row4, 0, row4.length));
      assertTrue(hasNext);
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(2, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row4, 0, row4.length));
      assertTrue(hasNext);
      // 2. scan out "row3" (2 kv)
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(2, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row3, 0, row3.length));
      assertTrue(hasNext);
      // 3. scan out "row2" (4 kvs)
      // "row2" takes 2 next() calls since batch=3
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(3, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row2, 0, row2.length));
      assertTrue(hasNext);
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(1, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row2, 0, row2.length));
      assertTrue(hasNext);
      // 4. scan out "row1" (2 kv)
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(2, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row1, 0, row1.length));
      assertTrue(hasNext);
      // 5. scan out "row0" (1 kv)
      currRow.clear();
      hasNext = scanner.next(currRow);
      assertEquals(1, currRow.size());
      assertTrue(Bytes.equals(currRow.get(0).getRowArray(), currRow.get(0).getRowOffset(),
        currRow.get(0).getRowLength(), row0, 0, row0.length));
      assertFalse(hasNext);
    }
  }
Assert that the passed in Cell has expected contents for the specified row, column & timestamp.
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java