@Test
  public void testMidKeyReadSuccessfullyFromRootIndexBlock() throws IOException {
    conf.setInt(HFileBlockIndex.MAX_CHUNK_SIZE_KEY, 128);
    Path hfilePath =
      new Path(TEST_UTIL.getDataTestDir(), "testMidKeyReadSuccessfullyFromRootIndexBlock");
    Compression.Algorithm compressAlgo = Compression.Algorithm.NONE;
    int entryCount = 50000;
    HFileContext context = new HFileContextBuilder().withBlockSize(4096).withIncludesTags(false)
      .withDataBlockEncoding(DataBlockEncoding.NONE).withCompression(compressAlgo).build();

    try (HFile.Writer writer = new HFile.WriterFactory(conf, new CacheConfig(conf))
      .withPath(fs, hfilePath).withFileContext(context).create()) {

      List<KeyValue> keyValues = new ArrayList<>(entryCount);
      for (int i = 0; i < entryCount; ++i) {
        byte[] keyBytes = RandomKeyValueUtil.randomOrderedKey(RNG, i);
        // A random-length random value.
        byte[] valueBytes = RandomKeyValueUtil.randomValue(RNG);
        KeyValue keyValue =
          new KeyValue(keyBytes, null, null, HConstants.LATEST_TIMESTAMP, valueBytes);
        writer.append(keyValue);
        keyValues.add(keyValue);
      }
    }

    try (FSDataInputStream fsdis = fs.open(hfilePath)) {
      long fileSize = fs.getFileStatus(hfilePath).getLen();
      FixedFileTrailer trailer = FixedFileTrailer.readFromStream(fsdis, fileSize);

      assertEquals(3, trailer.getMajorVersion());
      assertEquals(entryCount, trailer.getEntryCount());
      HFileContext meta = new HFileContextBuilder().withCompression(compressAlgo)
        .withIncludesMvcc(false).withIncludesTags(false)
        .withDataBlockEncoding(DataBlockEncoding.NONE).withHBaseCheckSum(true).build();
      ReaderContext readerContext =
        new ReaderContextBuilder().withInputStreamWrapper(new FSDataInputStreamWrapper(fsdis))
          .withFilePath(hfilePath).withFileSystem(fs).withFileSize(fileSize).build();
      HFileBlock.FSReader blockReader =
        new HFileBlock.FSReaderImpl(readerContext, meta, ByteBuffAllocator.HEAP, conf);

      MyEncoder encoder = new MyEncoder();
      HFileBlockIndex.CellBasedKeyBlockIndexReaderV2 dataBlockIndexReader =
        new HFileBlockIndex.CellBasedKeyBlockIndexReaderV2(trailer.createComparator(),
          trailer.getNumDataIndexLevels(), encoder);

      HFileBlock.BlockIterator blockIter = blockReader.blockRange(trailer.getLoadOnOpenDataOffset(),
        fileSize - trailer.getTrailerSize());
      // Data index. We also read statistics about the block index written after
      // the root level.
      dataBlockIndexReader.readMultiLevelIndexRoot(
        blockIter.nextBlockWithBlockType(BlockType.ROOT_INDEX), trailer.getDataIndexCount());
      NoOpEncodedSeeker noOpEncodedSeeker = (NoOpEncodedSeeker) encoder.encoderSeeker;
      // Assert we have read midkey metadata successfully.
      assertTrue(noOpEncodedSeeker.midLeafBlockOffset >= 0);
      assertTrue(noOpEncodedSeeker.midLeafBlockOnDiskSize > 0);
      assertTrue(noOpEncodedSeeker.midKeyEntry >= 0);
    }
  }
This test is for HBASE-27940, which midkey metadata in root index block would always be ignored
by {@link BlockIndexReader#readMultiLevelIndexRoot}.
hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestHFileBlockIndex.java