From 4fcfa51b0198a3dde4bbbff6fdbb0884281d7150 Mon Sep 17 00:00:00 2001 From: Duo Zhang Date: Fri, 12 Jun 2026 12:06:34 +0800 Subject: [PATCH 1/2] HBASE-30223 TestRegionMover2.testWithMergedRegions may merge disjoint regions and cause tests to fail --- .../hadoop/hbase/util/TestRegionMover2.java | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java index 919bf76c6619..67c18da44f1d 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java @@ -17,6 +17,10 @@ */ package org.apache.hadoop.hbase.util; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -30,11 +34,15 @@ import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; import org.apache.hadoop.hbase.master.RegionState; +import org.apache.hadoop.hbase.master.assignment.AssignmentManager; +import org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure; +import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.testclassification.LargeTests; @@ -44,7 +52,6 @@ import org.apache.hadoop.hbase.zookeeper.ZNodePaths; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; @@ -112,23 +119,36 @@ public void testWithMergedRegions() throws Exception { table.put(puts); admin.flush(tableName); HRegionServer regionServer = cluster.getRegionServer(0); + RegionInfo regionA = regionServer.getRegions(tableName).get(0).getRegionInfo(); + RegionInfo regionB = admin.getRegions(tableName).stream() + .filter(ri -> Bytes.equals(ri.getStartKey(), regionA.getEndKey())).findFirst().get(); + // if regionB is not this regionServer, move it + AssignmentManager am = cluster.getMaster().getAssignmentManager(); + while ( + !regionServer.getServerName() + .equals(am.getRegionStates().getRegionState(regionB).getServerName()) + ) { + TransitRegionStateProcedure trsp = + am.createMoveRegionProcedure(regionB, regionServer.getServerName()); + ProcedureSyncWait.submitAndWaitProcedure(cluster.getMaster().getMasterProcedureExecutor(), + trsp); + } + String rsName = regionServer.getServerName().getAddress().toString(); int numRegions = regionServer.getNumberOfOnlineRegions(); - List hRegions = regionServer.getRegions().stream() - .filter(hRegion -> hRegion.getRegionInfo().getTable().equals(tableName)) - .collect(Collectors.toList()); RegionMover.RegionMoverBuilder rmBuilder = new RegionMover.RegionMoverBuilder(rsName, TEST_UTIL.getConfiguration()).ack(true) .maxthreads(8); try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); - Assertions.assertEquals(0, regionServer.getNumberOfOnlineRegions()); + assertEquals(0, regionServer.getNumberOfOnlineRegions()); LOG.debug("Successfully Unloaded, now Loading"); - admin.mergeRegionsAsync(new byte[][] { hRegions.get(0).getRegionInfo().getRegionName(), - hRegions.get(1).getRegionInfo().getRegionName() }, true).get(5, TimeUnit.SECONDS); - Assertions.assertTrue(rm.load()); - Assertions.assertEquals(numRegions - 2, regionServer.getNumberOfOnlineRegions()); + admin + .mergeRegionsAsync(new byte[][] { regionA.getRegionName(), regionB.getRegionName() }, true) + .get(15, TimeUnit.SECONDS); + assertTrue(rm.load()); + assertEquals(numRegions - 2, regionServer.getNumberOfOnlineRegions()); } } @@ -155,7 +175,7 @@ public void testWithSplitRegions() throws Exception { try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); - Assertions.assertEquals(0, regionServer.getNumberOfOnlineRegions()); + assertEquals(0, regionServer.getNumberOfOnlineRegions()); LOG.debug("Successfully Unloaded, now Loading"); HRegion hRegion = hRegions.get(1); if (hRegion.getRegionInfo().getStartKey().length == 0) { @@ -172,8 +192,8 @@ public void testWithSplitRegions() throws Exception { int midKey = startKey + (endKey - startKey) / 2; admin.splitRegionAsync(hRegion.getRegionInfo().getRegionName(), Bytes.toBytes(midKey)).get(5, TimeUnit.SECONDS); - Assertions.assertTrue(rm.load()); - Assertions.assertEquals(numRegions - 1, regionServer.getNumberOfOnlineRegions()); + assertTrue(rm.load()); + assertEquals(numRegions - 1, regionServer.getNumberOfOnlineRegions()); } } @@ -197,11 +217,11 @@ public void testFailedRegionMove() throws Exception { try (RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); - Assertions.assertEquals(0, regionServer.getNumberOfOnlineRegions()); + assertEquals(0, regionServer.getNumberOfOnlineRegions()); LOG.debug("Successfully Unloaded, now Loading"); admin.offline(hRegions.get(0).getRegionInfo().getRegionName()); // loading regions will fail because of offline region - Assertions.assertFalse(rm.load()); + assertFalse(rm.load()); } } @@ -217,11 +237,11 @@ public void testDeletedTable() throws Exception { try (Admin admin = TEST_UTIL.getAdmin(); RegionMover rm = rmBuilder.build()) { LOG.debug("Unloading {}", regionServer.getServerName()); rm.unload(); - Assertions.assertEquals(0, regionServer.getNumberOfOnlineRegions()); + assertEquals(0, regionServer.getNumberOfOnlineRegions()); LOG.debug("Successfully Unloaded, now delete table"); admin.disableTable(tableNameToDelete); admin.deleteTable(tableNameToDelete); - Assertions.assertTrue(rm.load()); + assertTrue(rm.load()); } } @@ -388,10 +408,10 @@ public void regionIsolationOperation(ServerName sourceServerName, LOG.debug("Unloading {} except regions: {}", destinationRS.getServerName(), listOfRegionIDsToIsolate); rm.isolateRegions(); - Assertions.assertEquals(numRegionsToIsolate, destinationRS.getNumberOfOnlineRegions()); + assertEquals(numRegionsToIsolate, destinationRS.getNumberOfOnlineRegions()); List onlineRegions = destinationRS.getRegions(); for (int i = 0; i < numRegionsToIsolate; i++) { - Assertions.assertTrue( + assertTrue( listOfRegionIDsToIsolate.contains(onlineRegions.get(i).getRegionInfo().getEncodedName())); } LOG.debug("Successfully Isolated {} regions: {} on {}", listOfRegionIDsToIsolate.size(), From fc251b3fc199c89833d0dacdbefa152fdb807ae2 Mon Sep 17 00:00:00 2001 From: Duo Zhang Date: Fri, 12 Jun 2026 19:50:05 +0800 Subject: [PATCH 2/2] address review comments --- .../hadoop/hbase/util/TestRegionMover2.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java index 67c18da44f1d..fd8fc4055947 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/util/TestRegionMover2.java @@ -17,6 +17,7 @@ */ package org.apache.hadoop.hbase.util; +import static org.junit.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -118,10 +119,23 @@ public void testWithMergedRegions() throws Exception { List puts = createPuts(10000); table.put(puts); admin.flush(tableName); - HRegionServer regionServer = cluster.getRegionServer(0); - RegionInfo regionA = regionServer.getRegions(tableName).get(0).getRegionInfo(); - RegionInfo regionB = admin.getRegions(tableName).stream() - .filter(ri -> Bytes.equals(ri.getStartKey(), regionA.getEndKey())).findFirst().get(); + HRegionServer regionServer = null; + RegionInfo regionA = null; + RegionInfo regionB = null; + for (JVMClusterUtil.RegionServerThread rst : cluster.getRegionServerThreads()) { + HRegionServer rs = rst.getRegionServer(); + for (HRegion region : rs.getRegions(tableName)) { + if (!region.getRegionInfo().isLast()) { + regionServer = rs; + regionA = region.getRegionInfo(); + regionB = admin.getRegions(tableName).stream() + .filter(ri -> Bytes.equals(ri.getStartKey(), region.getRegionInfo().getEndKey())) + .findFirst().get(); + break; + } + } + } + assertNotNull(regionServer); // if regionB is not this regionServer, move it AssignmentManager am = cluster.getMaster().getAssignmentManager(); while (