HBASE-24997 [hbase-operator-tools] NPE in RegionsMerger#mergeRegions (#75)

Signed-off-by: Wellington Chevreuil <wchevreuil@apache.org>
diff --git a/hbase-tools/src/main/java/org/apache/hbase/RegionsMerger.java b/hbase-tools/src/main/java/org/apache/hbase/RegionsMerger.java
index 6a3e1e8..abfc6c9 100644
--- a/hbase-tools/src/main/java/org/apache/hbase/RegionsMerger.java
+++ b/hbase-tools/src/main/java/org/apache/hbase/RegionsMerger.java
@@ -114,6 +114,7 @@
       new SubstringComparator(tblName+","));
     SingleColumnValueFilter colFilter = new SingleColumnValueFilter(CATALOG_FAMILY,
       STATE_QUALIFIER, CompareOperator.EQUAL, Bytes.toBytes("OPEN"));
+    colFilter.setFilterIfMissing(true);
     Scan scan = new Scan();
     FilterList filter = new FilterList(FilterList.Operator.MUST_PASS_ALL);
     filter.addFilter(rowFilter);
diff --git a/hbase-tools/src/test/java/org/apache/hbase/TestRegionsMerger.java b/hbase-tools/src/test/java/org/apache/hbase/TestRegionsMerger.java
index 9c5fe37..e2513a2 100644
--- a/hbase-tools/src/test/java/org/apache/hbase/TestRegionsMerger.java
+++ b/hbase-tools/src/test/java/org/apache/hbase/TestRegionsMerger.java
@@ -22,16 +22,23 @@
 import java.io.IOException;
 import java.util.List;
 
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellBuilderFactory;
+import org.apache.hadoop.hbase.CellBuilderType;
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.MetaTableAccessor;
 import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.RegionInfo;
 import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.util.Bytes;
-import org.junit.*;
-
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
 public class TestRegionsMerger {
   private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
@@ -132,6 +139,34 @@
         originalCount, TEST_UTIL.countRows(table));
   }
 
+  @Test
+  public void testRegionHasNoState() throws Exception {
+    TEST_UTIL.getConfiguration().setInt(RegionsMerger.MAX_ROUNDS_IDLE, 3);
+    generateTableData();
+    // Turn on the replication of the table, and then merge two regions, the parent regions will
+    // not have the column info:state in the meta table, only the column
+    // rep_barrier:seqnumDuringOpen is left. And we should skip the parent regions.
+    // Here we manually put a region with no state defined.
+    String noStateRegion = TABLE_NAME.getNameAsString()+",0";
+    Put put = new Put(Bytes.toBytes(noStateRegion));
+    put.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY)
+      .setRow(put.getRow())
+      .setFamily(HConstants.REPLICATION_BARRIER_FAMILY)
+      .setQualifier(HConstants.SEQNUM_QUALIFIER)
+      .setTimestamp(put.getTimestamp())
+      .setType(Cell.Type.Put)
+      .setValue(Bytes.toBytes(1))
+      .build());
+    MetaTableAccessor.getMetaHTable(TEST_UTIL.getConnection()).put(put);
+
+    TEST_UTIL.getAdmin().flush(TABLE_NAME);
+    final int originalCount = TEST_UTIL.countRows(table);
+    List<RegionInfo> result = mergeRegionsToTarget(TABLE_NAME, 10);
+    assertEquals(10, result.size());
+    assertEquals("Row count before and after merge should be equal",
+      originalCount, TEST_UTIL.countRows(table));
+  }
+
   private void generateTableData() throws Exception {
     TEST_UTIL.getAdmin().getRegions(TABLE_NAME).forEach(r -> {
       byte[] key = r.getStartKey().length == 0 ? new byte[]{0} : r.getStartKey();