private void assertTargetDoDeletesFalse(int expectedRows, HBaseTestingUtil sourceCluster,
    TableName sourceTableName, HBaseTestingUtil targetCluster, TableName targetTableName)
    throws Exception {
    try (Table sourceTable = sourceCluster.getConnection().getTable(sourceTableName);
      Table targetTable = targetCluster.getConnection().getTable(targetTableName);

      ResultScanner sourceScanner = sourceTable.getScanner(new Scan());
      ResultScanner targetScanner = targetTable.getScanner(new Scan())) {
      Result targetRow = targetScanner.next();
      Result sourceRow = sourceScanner.next();
      int rowsCount = 0;
      while (targetRow != null) {
        rowsCount++;
        // only compares values for existing rows, skipping rows existing on
        // target only that were not deleted given --doDeletes=false
        if (Bytes.toInt(sourceRow.getRow()) != Bytes.toInt(targetRow.getRow())) {
          targetRow = targetScanner.next();
          continue;
        }

        LOG.debug("SOURCE row: " + (sourceRow == null ? "null" : Bytes.toInt(sourceRow.getRow()))
          + " cells:" + sourceRow);
        LOG.debug("TARGET row: " + (targetRow == null ? "null" : Bytes.toInt(targetRow.getRow()))
          + " cells:" + targetRow);

        Cell[] sourceCells = sourceRow.rawCells();
        Cell[] targetCells = targetRow.rawCells();
        int targetRowKey = Bytes.toInt(targetRow.getRow());
        if (targetRowKey >= 70 && targetRowKey < 80) {
          if (sourceCells.length == targetCells.length) {
            LOG.debug("Source cells: " + Arrays.toString(sourceCells));
            LOG.debug("Target cells: " + Arrays.toString(targetCells));
            fail("Row " + targetRowKey + " should have more cells in " + "target than in source");
          }

        } else {
          if (sourceCells.length != targetCells.length) {
            LOG.debug("Source cells: " + Arrays.toString(sourceCells));
            LOG.debug("Target cells: " + Arrays.toString(targetCells));
            fail("Row " + Bytes.toInt(sourceRow.getRow()) + " has " + sourceCells.length
              + " cells in source table but " + targetCells.length + " cells in target table");
          }
        }
        for (int j = 0; j < sourceCells.length; j++) {
          Cell sourceCell = sourceCells[j];
          Cell targetCell = targetCells[j];
          assertCellEquals(sourceCell, targetCell, () -> targetRowKey < 80 && targetRowKey >= 90);
        }
        targetRow = targetScanner.next();
        sourceRow = sourceScanner.next();
      }
      assertEquals("Target expected rows does not match.", expectedRows, rowsCount);
    }
  }
Basic test for the SyncTable M/R tool
hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestSyncTable.java