@Test
  public void replicateUsingWALTest() throws IOException, InterruptedException, ConsensusException {
    logger.info("Start ReplicateUsingWALTest");
    servers.get(0).createLocalPeer(group.getGroupId(), group.getPeers());
    servers.get(1).createLocalPeer(group.getGroupId(), group.getPeers());

    Assert.assertEquals(0, servers.get(0).getImpl(gid).getSearchIndex());
    Assert.assertEquals(0, servers.get(1).getImpl(gid).getSearchIndex());

    for (int i = 0; i < CHECK_POINT_GAP; i++) {
      servers.get(0).write(gid, new TestEntry(i, peers.get(0)));
      servers.get(1).write(gid, new TestEntry(i, peers.get(1)));
      Assert.assertEquals(i + 1, servers.get(0).getImpl(gid).getSearchIndex());
      Assert.assertEquals(i + 1, servers.get(1).getImpl(gid).getSearchIndex());
    }

    Assert.assertEquals(0, servers.get(0).getImpl(gid).getMinSyncIndex());
    Assert.assertEquals(0, servers.get(1).getImpl(gid).getMinSyncIndex());

    try {
      stopServer();
      initServer();

      servers.get(2).createLocalPeer(group.getGroupId(), group.getPeers());
      checkPeerList(servers.get(0).getImpl(gid));
      checkPeerList(servers.get(1).getImpl(gid));
      checkPeerList(servers.get(2).getImpl(gid));

      Assert.assertEquals(CHECK_POINT_GAP, servers.get(0).getImpl(gid).getSearchIndex());
      Assert.assertEquals(CHECK_POINT_GAP, servers.get(1).getImpl(gid).getSearchIndex());
      Assert.assertEquals(0, servers.get(2).getImpl(gid).getSearchIndex());

      for (int i = 0; i < 2; i++) {
        long start = System.currentTimeMillis();
        // should be [CHECK_POINT_GAP, CHECK_POINT_GAP * 2 - 1] after
        // replicating all entries
        while (servers.get(i).getImpl(gid).getMinSyncIndex() < CHECK_POINT_GAP) {
          long current = System.currentTimeMillis();
          if ((current - start) > 60 * 1000) {
            logger.error("{}", servers.get(i).getImpl(gid).getMinSyncIndex());
            Assert.fail("Unable to replicate entries");
          }
          Thread.sleep(100);
        }
      }

      Assert.assertEquals(CHECK_POINT_GAP * 2, stateMachines.get(0).getRequestSet().size());
      Assert.assertEquals(CHECK_POINT_GAP * 2, stateMachines.get(1).getRequestSet().size());
      Assert.assertEquals(CHECK_POINT_GAP * 2, stateMachines.get(2).getRequestSet().size());

      Assert.assertEquals(stateMachines.get(0).getData(), stateMachines.get(1).getData());
      Assert.assertEquals(stateMachines.get(2).getData(), stateMachines.get(1).getData());
    } catch (IOException e) {
      if (e.getCause() instanceof StartupException) {
        // just succeed when can not bind socket
        logger.info("Can not start IoTConsensus because", e);
      } else {
        logger.error("Failed because", e);
        Assert.fail("Failed because " + e.getMessage());
      }
    }
  }
First, suspend one node to test that the request replication between the two alive nodes is ok,
then restart all nodes to lose state in the queue, and test using WAL replication to make all
nodes finally consistent.
iotdb-core/consensus/src/test/java/org/apache/iotdb/consensus/iot/ReplicateTest.java