### Question:
RoundChangeManager { public Optional<Collection<RoundChange>> appendRoundChangeMessage(final RoundChange msg) { if (!isMessageValid(msg)) { LOG.info("RoundChange message was invalid."); return Optional.empty(); } final RoundChangeStatus roundChangeStatus = storeRoundChangeMessage(msg); if (roundChangeStatus.roundChangeReady()) { return Optional.of(roundChangeStatus.createRoundChangeCertificate()); } return Optional.empty(); } RoundChangeManager(
      final long quorum, final RoundChangeMessageValidator roundChangeMessageValidator); Optional<Collection<RoundChange>> appendRoundChangeMessage(final RoundChange msg); void discardRoundsPriorTo(final ConsensusRoundIdentifier completedRoundIdentifier);  }### Answer:
@Test public void rejectsInvalidRoundChangeMessage() { final RoundChange roundChangeData = makeRoundChangeMessage(nonValidatorKey, ri1); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.roundChangeCache.get(ri1)).isNull(); }
@Test public void acceptsValidRoundChangeMessage() { final RoundChange roundChangeData = makeRoundChangeMessage(proposerKey, ri2); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(1); }
@Test public void doesntAcceptDuplicateValidRoundChangeMessage() { final RoundChange roundChangeData = makeRoundChangeMessage(proposerKey, ri2); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(1); }
@Test public void becomesReadyAtThreshold() { final RoundChange roundChangeDataProposer = makeRoundChangeMessage(proposerKey, ri2); final RoundChange roundChangeDataValidator1 = makeRoundChangeMessage(validator1Key, ri2); assertThat(manager.appendRoundChangeMessage(roundChangeDataProposer)) .isEqualTo(Optional.empty()); assertThat(manager.appendRoundChangeMessage(roundChangeDataValidator1).isPresent()).isTrue(); }
@Test public void doesntReachReadyWhenSuppliedWithDifferentRounds() { final RoundChange roundChangeDataProposer = makeRoundChangeMessage(proposerKey, ri2); final RoundChange roundChangeDataValidator1 = makeRoundChangeMessage(validator1Key, ri3); assertThat(manager.appendRoundChangeMessage(roundChangeDataProposer)) .isEqualTo(Optional.empty()); assertThat(manager.appendRoundChangeMessage(roundChangeDataValidator1)) .isEqualTo(Optional.empty()); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(1); assertThat(manager.roundChangeCache.get(ri3).receivedMessages.size()).isEqualTo(1); }
@Test public void stopsAcceptingMessagesAfterReady() { final RoundChange roundChangeDataProposer = makeRoundChangeMessage(proposerKey, ri2); final RoundChange roundChangeDataValidator1 = makeRoundChangeMessage(validator1Key, ri2); final RoundChange roundChangeDataValidator2 = makeRoundChangeMessage(validator2Key, ri2); assertThat(manager.appendRoundChangeMessage(roundChangeDataProposer)) .isEqualTo(Optional.empty()); assertThat(manager.appendRoundChangeMessage(roundChangeDataValidator1).isPresent()).isTrue(); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(2); assertThat(manager.appendRoundChangeMessage(roundChangeDataValidator2)) .isEqualTo(Optional.empty()); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(2); }
@Test public void roundChangeMessagesWithPreparedCertificateMustHaveSufficientPrepareMessages() { RoundChange roundChangeData = makeRoundChangeMessageWithPreparedCert(proposerKey, ri2, Collections.emptyList()); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.roundChangeCache.get(ri2)).isNull(); roundChangeData = makeRoundChangeMessageWithPreparedCert( proposerKey, ri2, Lists.newArrayList(validator1Key, validator2Key)); assertThat(manager.appendRoundChangeMessage(roundChangeData)).isEmpty(); assertThat(manager.roundChangeCache.get(ri2).receivedMessages.size()).isEqualTo(1); }