@Test
  public void testPartialParse() throws Exception {
    Path walFile = UTIL.getDataTestDir("wal");
    long headerLength;
    List<Long> endOffsets = new ArrayList<>();
    try (WALProvider.Writer writer =
      WALFactory.createWALWriter(FS, walFile, UTIL.getConfiguration())) {
      headerLength = writer.getLength();
      for (int i = 0; i < 3; i++) {
        WALKeyImpl key = new WALKeyImpl(RI.getEncodedNameAsBytes(), TN, i,
          EnvironmentEdgeManager.currentTime(), HConstants.DEFAULT_CLUSTER_ID);
        WALEdit edit = new WALEdit();
        if (i % 2 == 0) {
          edit.add(ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setType(Type.Put)
            .setRow(ROW).setFamily(FAMILY).setQualifier(QUAL).setValue(VALUE).build());
        } else {
          edit.add(ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY)
            .setType(Type.DeleteFamily).setRow(ROW).setFamily(FAMILY).build());
        }
        writer.append(new WAL.Entry(key, edit));
        writer.sync(true);
        endOffsets.add(writer.getLength());
      }
    }
    long fileLength = FS.getFileStatus(walFile).getLen();
    byte[] content = new byte[(int) fileLength];
    try (FSDataInputStream in = FS.open(walFile)) {
      in.readFully(content);
    }
    // partial header, should throw WALHeaderEOFException
    for (int i = 0; i < headerLength; i++) {
      Path brokenFile = generateBrokenWALFile(content, i);
      assertThrows(WALHeaderEOFException.class,
        () -> WALFactory.createStreamReader(FS, brokenFile, UTIL.getConfiguration()));
      assertThrows(WALHeaderEOFException.class,
        () -> WALFactory.createTailingReader(FS, brokenFile, UTIL.getConfiguration(), -1));
      FS.delete(brokenFile, false);
    }
    // partial WAL entries, should be able to read some entries and the last one we will get an EOF
    for (int i = 0; i <= endOffsets.size(); i++) {
      int startOffset;
      int endOffset;
      if (i == 0) {
        startOffset = (int) headerLength;
        endOffset = endOffsets.get(i).intValue();
      } else if (i == endOffsets.size()) {
        startOffset = endOffsets.get(i - 1).intValue();
        endOffset = (int) fileLength;
      } else {
        startOffset = endOffsets.get(i - 1).intValue();
        endOffset = endOffsets.get(i).intValue();
      }
      for (int j = startOffset; j < endOffset; j++) {
        Path brokenFile = generateBrokenWALFile(content, j);
        testReadEntry(brokenFile, i);
        FS.delete(brokenFile, false);
      }
    }
    // partial trailer, should be able to read all the entries but get an EOF when trying read
    // again, as we do not know it is a trailer
    for (int i = endOffsets.get(endOffsets.size() - 1).intValue(); i < fileLength; i++) {
      Path brokenFile = generateBrokenWALFile(content, i);
      testReadEntry(brokenFile, endOffsets.size());
      FS.delete(brokenFile, false);
    }
  }
In this test, we write a small WAL file first, and then generate partial WAL file which length is
in range [0, fileLength)(we test all the possible length in the range), to see if we can
successfully get the completed entries, and also get an EOF at the end.
<p/>
It is very important to make sure 3 things:
<ul>
<li>We do not get incorrect entries. Otherwise there will be data corruption.</li>
<li>We can get all the completed entries, i.e, we do not miss some data. Otherwise there will be
data loss.</li>
<li>We will get an EOF finally, instead of a general IOException. Otherwise the split or
replication will be stuck.</li>
</ul>
hbase-server/src/test/java/org/apache/hadoop/hbase/wal/TestParsePartialWALFile.java