@Test
  public void testMergeEmptyWithMetaCache() throws Throwable {
    TableName tableName = TableName.valueOf("testMergeEmptyWithMetaCache");
    byte[] family = Bytes.toBytes("CF");
    TableDescriptor td = TableDescriptorBuilder.newBuilder(tableName)
      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(family)).build();
    TEST_UTIL.getAdmin().createTable(td, new byte[][] { Bytes.toBytes(2), Bytes.toBytes(5) });
    TEST_UTIL.waitTableAvailable(tableName);
    TEST_UTIL.waitUntilNoRegionsInTransition();
    RegionInfo regionA = null;
    RegionInfo regionB = null;
    RegionInfo regionC = null;
    for (RegionInfo region : TEST_UTIL.getAdmin().getRegions(tableName)) {
      if (region.getStartKey().length == 0) {
        regionA = region;
      } else if (Bytes.equals(region.getStartKey(), Bytes.toBytes(2))) {
        regionB = region;
      } else if (Bytes.equals(region.getStartKey(), Bytes.toBytes(5))) {
        regionC = region;
      }
    }

    assertNotNull(regionA);
    assertNotNull(regionB);
    assertNotNull(regionC);

    TEST_UTIL.getConfiguration().setBoolean(MetricsConnection.CLIENT_SIDE_METRICS_ENABLED_KEY,
      true);
    try (AsyncConnection asyncConn =
      ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get()) {
      AsyncConnectionImpl asyncConnImpl = (AsyncConnectionImpl) asyncConn;

      MetricsConnection asyncMetrics = asyncConnImpl.getConnectionMetrics().get();

      // warm meta cache
      asyncConn.getRegionLocator(tableName).getAllRegionLocations().get();

      assertEquals(3, TEST_UTIL.getAdmin().getRegions(tableName).size());

      // Merge the 3 regions into one
      TEST_UTIL.getAdmin().mergeRegionsAsync(
        new byte[][] { regionA.getRegionName(), regionB.getRegionName(), regionC.getRegionName() },
        false).get(30, TimeUnit.SECONDS);

      assertEquals(1, TEST_UTIL.getAdmin().getRegions(tableName).size());

      AsyncTable<?> asyncTable = asyncConn.getTable(tableName);

      // This request should cause us to cache the newly merged region.
      // As part of caching that region, it should clear out any cached merge parent regions which
      // are overlapped by the new region. That way, subsequent calls below won't fall into the
      // bug in HBASE-27650. Otherwise, a request for row 6 would always get stuck on cached
      // regionB and we'd continue to see cache misses below.
      assertTrue(
        executeAndGetNewMisses(() -> asyncTable.get(new Get(Bytes.toBytes(6))).get(), asyncMetrics)
            > 0);

      // We verify no new cache misses here due to above, which proves we've fixed up the cache
      assertEquals(0, executeAndGetNewMisses(() -> asyncTable.get(new Get(Bytes.toBytes(6))).get(),
        asyncMetrics));
    }
  }
Test that our cleanOverlappingRegions doesn't incorrectly remove regions from cache. Originally
encountered when using floorEntry rather than lowerEntry.
hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMetaCache.java