@Test
  public void testRecoverDuplicate()
      throws IllegalPathException,
          IOException,
          WriteProcessException,
          DataRegionException,
          WALRecoverException {
    // generate crashed .tsfile
    File file = new File(FILE_NAME);
    generateCrashedFile(file);
    assertTrue(file.exists());
    assertFalse(new File(FILE_NAME.concat(TsFileResource.RESOURCE_SUFFIX)).exists());
    assertFalse(ModificationFile.getExclusiveMods(new File(FILE_NAME)).exists());
    tsFileResource = new TsFileResource(file);

    int fakeMemTableId = 1;

    IMemTable memTable = new PrimitiveMemTable();
    memTable.setDatabaseAndDataRegionId(SG_NAME, "0");
    List<IMeasurementSchema> schemaList = new ArrayList<>();
    schemaList.add(new MeasurementSchema("s1", TSDataType.INT32));
    memTable.write(DEVICE1_NAME, schemaList, 1, new Object[] {100000});
    WALEntry duplicateMemTableSnapshotWalEntry = new WALInfoEntry(fakeMemTableId++, memTable);

    InsertRowNode insertRowNode =
        new InsertRowNode(
            new PlanNodeId("plannode 1"),
            new PartialPath(DEVICE1_NAME),
            false,
            new String[] {"s1"},
            new TSDataType[] {TSDataType.INT32},
            2,
            new Integer[] {20},
            false);
    insertRowNode.setMeasurementSchemas(
        new MeasurementSchema[] {new MeasurementSchema("s1", TSDataType.INT32)});
    WALEntry duplicateWalEntry = new WALInfoEntry(fakeMemTableId++, insertRowNode);

    InsertRowNode insertRowNode2 =
        new InsertRowNode(
            new PlanNodeId("plannode 2"),
            new PartialPath(DEVICE1_NAME),
            false,
            new String[] {"s1"},
            new TSDataType[] {TSDataType.INT32},
            10,
            new Integer[] {10},
            false);
    insertRowNode2.setMeasurementSchemas(
        new MeasurementSchema[] {new MeasurementSchema("s1", TSDataType.INT32)});

    WALEntry normalWalEntry = new WALInfoEntry(fakeMemTableId++, insertRowNode2);

    try (UnsealedTsFileRecoverPerformer performer =
        new UnsealedTsFileRecoverPerformer(tsFileResource, true, p -> assertFalse(p.canWrite()))) {
      performer.startRecovery();
      performer.redoLog(duplicateMemTableSnapshotWalEntry);
      performer.redoLog(duplicateWalEntry);
      performer.redoLog(normalWalEntry);
      performer.endRecovery();
      performer.getTsFileResource();
    }

    try (TsFileSequenceReader reader = new TsFileSequenceReader(FILE_NAME)) {
      List<ChunkMetadata> chunkMetadataList =
          reader.getChunkMetadataList(new Path(DEVICE1_NAME, "s1", true));
      for (ChunkMetadata chunkMetadata : chunkMetadataList) {
        Chunk chunk = reader.readMemChunk(chunkMetadata);
        ChunkReader chunkReader = new ChunkReader(chunk);
        while (chunkReader.hasNextSatisfiedPage()) {
          BatchData batchData = chunkReader.nextPageData();
          while (batchData.hasCurrent()) {
            Assert.assertEquals((int) batchData.currentTime(), batchData.currentValue());
            batchData.next();
          }
        }
      }
    }
  }
Recover WALEntry that only contains InsertRowNode/InsertTabletNode with null values. This type
of node will be generated when inserting mismatched type data.
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/file/UnsealedTsFileRecoverPerformerTest.java