@Test
  public void testMergeWithMergedChildRegion() throws Exception {
    TableName tn = TableName.valueOf(this.name.getMethodName());
    TEST_UTIL.createMultiRegionTable(tn, HConstants.CATALOG_FAMILY);
    List<RegionInfo> ris = MetaTableAccessor.getTableRegions(TEST_UTIL.getConnection(), tn);
    assertTrue(ris.size() > 5);
    HMaster services = TEST_UTIL.getHBaseCluster().getMaster();
    CatalogJanitor cj = services.getCatalogJanitor();
    cj.scan();
    CatalogJanitorReport report = cj.getLastReport();
    assertTrue(report.isEmpty());
    RegionInfo overlapRegion = makeOverlap(services, ris.get(1), ris.get(2));

    cj.scan();
    report = cj.getLastReport();
    assertEquals(2, report.getOverlaps().size());

    // Mark it as a merged child region.
    RegionInfo fakedParentRegion =
      RegionInfoBuilder.newBuilder(tn).setStartKey(overlapRegion.getStartKey()).build();

    Table meta = MetaTableAccessor.getMetaHTable(TEST_UTIL.getConnection());
    Put putOfMerged =
      MetaTableAccessor.makePutFromRegionInfo(overlapRegion, HConstants.LATEST_TIMESTAMP);
    String qualifier = String.format(HConstants.MERGE_QUALIFIER_PREFIX_STR + "%04d", 0);
    putOfMerged.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY)
      .setRow(putOfMerged.getRow()).setFamily(HConstants.CATALOG_FAMILY)
      .setQualifier(Bytes.toBytes(qualifier)).setTimestamp(putOfMerged.getTimestamp())
      .setType(Cell.Type.Put).setValue(RegionInfo.toByteArray(fakedParentRegion)).build());

    meta.put(putOfMerged);

    MetaFixer fixer = new MetaFixer(services);
    fixer.fixOverlaps(report);

    // Wait until all procedures settled down
    HBaseTestingUtil.await(200, () -> {
      return services.getMasterProcedureExecutor().getActiveProcIds().isEmpty();
    });

    // No merge is done, overlap is still there.
    cj.scan();
    report = cj.getLastReport();
    assertEquals(2, report.getOverlaps().size());

    fixer.fixOverlaps(report);

    // Wait until all procedures settled down
    HBaseTestingUtil.await(200, () -> {
      return services.getMasterProcedureExecutor().getActiveProcIds().isEmpty();
    });

    // Merge is done and no more overlaps
    cj.scan();
    report = cj.getLastReport();
    assertEquals(0, report.getOverlaps().size());
  }
This test covers the case that one of merged parent regions is a merged child region that has
not been GCed but there is no reference files anymore. In this case, it will kick off a GC
procedure, but no merge will happen.
hbase-server/src/test/java/org/apache/hadoop/hbase/master/janitor/TestMetaFixer.java