use of com.radixdlt.hotstuff.liveness.ProposerElection in project radixdlt by radixdlt.
the class PacemakerViewUpdateRaceConditionTest method test_pacemaker_view_update_race_condition.
@Test
public void test_pacemaker_view_update_race_condition() {
final DeterministicTest test = DeterministicTest.builder().numNodes(numNodes).messageSelector(MessageSelector.randomSelector(random)).messageMutator(messUpMessagesForNodeUnderTest()).pacemakerTimeout(pacemakerTimeout).overrideWithIncorrectModule(new AbstractModule() {
@ProvidesIntoSet
@ProcessOnDispatch
private EventProcessor<BFTInsertUpdate> bftInsertUpdateProcessor() {
final Map<HashCode, PreparedVertex> insertedVertices = new HashMap<>();
return bftInsertUpdate -> {
final PreparedVertex inserted = bftInsertUpdate.getInserted();
insertedVertices.putIfAbsent(inserted.getId(), inserted);
final Optional<PreparedVertex> maybeParent = Optional.ofNullable(insertedVertices.get(inserted.getParentId()));
maybeParent.ifPresent(parent -> {
if (parent.getView().equals(inserted.getView())) {
throw new IllegalStateException("Vertex can't have the same view as its parent.");
}
});
};
}
@Provides
public ProposerElection proposerElection(BFTValidatorSet validatorSet) {
final var sortedValidators = validatorSet.getValidators().stream().map(BFTValidator::getNode).sorted(Comparator.comparing(BFTNode::getKey, KeyComparator.instance().reversed())).toList();
return view -> sortedValidators.get(((int) view.number() - 1) % sortedValidators.size());
}
}).buildWithoutEpochs().runUntil(nodeUnderTestReachesView(View.of(3)));
final var counters = test.getSystemCounters(nodeUnderTestIndex);
assertThat(counters.get(SystemCounters.CounterType.BFT_VOTE_QUORUMS)).isEqualTo(// ensure that quorum was formed
2);
assertThat(counters.get(SystemCounters.CounterType.BFT_PACEMAKER_TIMEOUTS_SENT)).isEqualTo(// ensure that timeouts were processed
2);
}
Aggregations