From 3e6fd5705bc90f0d07cbd69f4700fe4be228bc53 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Fri, 16 Apr 2021 01:15:31 +0300 Subject: [PATCH] raft: (testing) test that non-voter stays in PIPELINE mode Test that configuration changes preserve PIPELINE mode. --- test/raft/fsm_test.cc | 38 ++++++++++++++++++++++++++++++++++++++ test/raft/helpers.hh | 6 ++++++ 2 files changed, 44 insertions(+) diff --git a/test/raft/fsm_test.cc b/test/raft/fsm_test.cc index 0b8e24edfb..d25db45eb6 100644 --- a/test/raft/fsm_test.cc +++ b/test/raft/fsm_test.cc @@ -1549,3 +1549,41 @@ BOOST_AUTO_TEST_CASE(test_reordered_reject) { raft::logger.trace("delivering second reject"); deliver(routes, fsm2.id(), std::move(reject_2.messages)); } + +BOOST_AUTO_TEST_CASE(test_non_voter_stays_pipeline) { + // Check that a node stays in PIPELINE mode + // through configuration changes. + server_id A_id = id(), B_id = id(); + raft::server_address_set addrset{raft::server_address{A_id}, raft::server_address{B_id, false}}; + raft::configuration cfg(addrset); + raft::log log(raft::snapshot{.idx = index_t{0}, .config = cfg}); + auto A = create_follower(A_id, log); + auto B = create_follower(B_id, log); + election_timeout(A); + communicate(A); + BOOST_CHECK(A.is_leader()); + BOOST_CHECK(A.get_progress(B_id).state == raft::follower_progress::state::PROBE); + A.add_entry(log_entry::dummy{}); + // We need to deliver a probe from A to B so that B gets + // a change to respond and A can switch B to PIPELINE mode. + A.tick(); + communicate(A, B); + BOOST_CHECK(A.get_progress(B_id).state == raft::follower_progress::state::PIPELINE); + raft::configuration newcfg({A_id, B_id}); + A.add_entry(newcfg); + communicate(A, B); + BOOST_CHECK_EQUAL(A.get_configuration().is_joint(), false); + BOOST_CHECK_EQUAL(A.get_configuration().current.find(raft::server_address{B_id})->can_vote, true); + BOOST_CHECK(A.get_progress(B_id).state == raft::follower_progress::state::PIPELINE); + A.add_entry(cfg); + auto tick_occasionally = [&A, &B]() { + if (rolladice()) { + A.tick(); B.tick(); + } + return false; + }; + communicate_until(tick_occasionally, A, B); + BOOST_CHECK_EQUAL(A.get_configuration().is_joint(), false); + BOOST_CHECK_EQUAL(A.get_configuration().current.find(raft::server_address{B_id})->can_vote, false); + BOOST_CHECK(A.get_progress(B_id).state == raft::follower_progress::state::PIPELINE); +} diff --git a/test/raft/helpers.hh b/test/raft/helpers.hh index 51ca86b23a..a56d84973a 100644 --- a/test/raft/helpers.hh +++ b/test/raft/helpers.hh @@ -29,6 +29,7 @@ #include #include "test/lib/log.hh" +#include "test/lib/random_utils.hh" #include "serializer_impl.hh" #include @@ -241,3 +242,8 @@ raft::server_address to_server_address(size_t local_id) { size_t to_local_id(utils::UUID uuid) { return uuid.get_least_significant_bits() - 1; } + +// Return true upon a random event with given probability +bool rolladice(float probability = 1.0/2.0) { + return tests::random::get_real(0.0, 1.0) < probability; +}