@Test
  public void shouldWriteNewSnapshot() throws IOException {
    Snapshot snapshot = new Snapshot();

    snapshot.setNextInstanceId(2);
    snapshot.setValue(new byte[] {1, 2, 3});

    Map<Long, Reply> lastReplyForClient = new HashMap<Long, Reply>();
    lastReplyForClient.put((long) 1, new Reply(new RequestId(3, 1), new byte[] {1}));
    snapshot.setLastReplyForClient(lastReplyForClient);

    List<Reply> partialResponseCache =
        Arrays.asList(
            new Reply(new RequestId(1, 1), new byte[] {1, 2, 3}),
            new Reply(new RequestId(2, 2), new byte[] {1, 2, 3, 4}));
    snapshot.setPartialResponseCache(partialResponseCache);

    writer.newSnapshot(snapshot);
    writer.close();

    writer = new FullSSDiscWriter(directoryPath);
    writer.load();
    Snapshot actual = writer.getSnapshot();

    assertArrayEquals(snapshot.getValue(), actual.getValue());
    assertEquals(snapshot.getNextInstanceId(), actual.getNextInstanceId());
    assertEquals(snapshot.getNextRequestSeqNo(), actual.getNextRequestSeqNo());
    assertEquals(snapshot.getStartingRequestSeqNo(), actual.getStartingRequestSeqNo());
  }
  @Test
  public void shouldLoadViewNumber() throws IOException {
    writer.changeViewNumber(5);
    writer.close();

    writer = new FullSSDiscWriter(directoryPath);
    int view = writer.loadViewNumber();
    writer.close();

    assertEquals(view, 5);
  }
  @Test
  public void shouldGetNextLogNumber() throws IOException {
    String[] s = new String[] {"sync.0.log", "invalid", "sync.2.log", "sync.1.log"};

    int lastLogNumber = writer.getLastLogNumber(s);
    assertEquals(lastLogNumber, 2);
  }
  @Test
  public void shouldLoadDataFromMoreFiles() throws IOException {
    byte[] value = new byte[] {1, 2};
    byte[] newValue = new byte[] {1, 2, 3};
    writer.changeInstanceValue(1, 2, value);
    writer.changeInstanceValue(2, 2, value);
    writer.changeInstanceValue(1, 3, newValue);
    writer.close();

    writer = new FullSSDiscWriter(directoryPath);
    writer.changeInstanceView(1, 4);
    writer.close();

    writer = new FullSSDiscWriter(directoryPath);
    ConsensusInstance[] instances = writer.load().toArray(new ConsensusInstance[0]);
    writer.close();

    ConsensusInstance instance1 = instances[0];
    ConsensusInstance instance2 = instances[1];

    assertEquals(4, instance1.getView());
    assertArrayEquals(newValue, instance1.getValue());

    assertEquals(2, instance2.getView());
    assertArrayEquals(value, instance2.getValue());
  }
  @Test
  public void shouldChangeViewNumber() throws IOException {
    writer.changeViewNumber(5);

    DataInputStream stream =
        new DataInputStream(new FileInputStream(directoryPath + "/sync.0.view"));
    int view = stream.readInt();
    stream.close();
    assertEquals(view, 5);
  }
  @Test
  public void shouldWriteOnInstanceViewChange() throws IOException {
    writer.changeInstanceView(1, 2);

    ByteBuffer buffer = ByteBuffer.allocate(9);
    buffer.put((byte) 1); // type
    buffer.putInt(1); // id
    buffer.putInt(2); // view

    assertArrayEquals(buffer.array(), readFile(directoryPath + "/sync.0.log"));
  }
  @Test
  public void shouldLoadCorruptedData() throws IOException {
    byte[] value = new byte[] {1, 2};
    byte[] newValue = new byte[] {1, 2, 3};
    writer.changeInstanceValue(1, 2, value);
    writer.changeInstanceValue(2, 2, value);
    writer.changeInstanceValue(1, 3, newValue);
    writer.changeInstanceView(1, 4);
    writer.close();

    FileOutputStream stream = new FileOutputStream(directoryPath + "/sync.0.log", true);
    stream.write(new byte[] {1, 2, 3});
    stream.close();

    writer = new FullSSDiscWriter(directoryPath);
    ConsensusInstance[] instances = writer.load().toArray(new ConsensusInstance[0]);
    writer.close();

    ConsensusInstance instance1 = instances[0];
    ConsensusInstance instance2 = instances[1];

    assertEquals(4, instance1.getView());
    assertArrayEquals(newValue, instance1.getValue());

    assertEquals(2, instance2.getView());
    assertArrayEquals(value, instance2.getValue());
  }
  @Test
  public void shouldWriteOnInstanceValueChange() throws IOException {
    byte[] value = new byte[] {1, 2};
    writer.changeInstanceValue(1, 2, value);

    ByteBuffer buffer = ByteBuffer.allocate(15);
    buffer.put((byte) 2); // type
    buffer.putInt(1); // id
    buffer.putInt(2); // view
    buffer.putInt(2); // value size
    buffer.put(value); // value

    String path = directoryPath + "/sync.0.log";
    assertArrayEquals(readFile(path), buffer.array());
  }
 @After
 public void tearDown() throws IOException {
   writer.close();
   DirectoryHelper.delete(directoryPath);
 }