From ae38c2a2ce960365064e25670f229ef8a12850fb Mon Sep 17 00:00:00 2001 From: Vito <5780819+Tapanito@users.noreply.github.com> Date: Wed, 28 May 2025 16:35:41 +0200 Subject: [PATCH] removes member functions from Slots used only for testing, and moves them to tests --- ...e_relay_test.cpp => base_squelch_test.cpp} | 160 ++++++++--------- src/xrpld/overlay/Slot.h | 165 ++---------------- 2 files changed, 89 insertions(+), 236 deletions(-) rename src/test/overlay/{reduce_relay_test.cpp => base_squelch_test.cpp} (94%) diff --git a/src/test/overlay/reduce_relay_test.cpp b/src/test/overlay/base_squelch_test.cpp similarity index 94% rename from src/test/overlay/reduce_relay_test.cpp rename to src/test/overlay/base_squelch_test.cpp index a8aafcfa06..a13efb39d5 100644 --- a/src/test/overlay/reduce_relay_test.cpp +++ b/src/test/overlay/base_squelch_test.cpp @@ -17,8 +17,8 @@ */ //============================================================================== -#include #include +#include #include #include @@ -33,8 +33,8 @@ #include -#include -#include +#include +#include #include #include @@ -191,52 +191,6 @@ public: } }; -/** Manually advanced clock. */ -class ManualClock -{ -public: - typedef uint64_t rep; - typedef std::milli period; - typedef std::chrono::duration duration; - typedef std::chrono::time_point time_point; - inline static bool const is_steady = false; - - static void - advance(duration d) noexcept - { - now_ += d; - } - - static void - randAdvance(milliseconds min, milliseconds max) - { - now_ += randDuration(min, max); - } - - static void - reset() noexcept - { - now_ = time_point(seconds(0)); - } - - static time_point - now() noexcept - { - return now_; - } - - static duration - randDuration(milliseconds min, milliseconds max) - { - return duration(milliseconds(rand_int(min.count(), max.count()))); - } - - explicit ManualClock() = default; - -private: - inline static time_point now_ = time_point(seconds(0)); -}; - /** Simulate server's OverlayImpl */ class Overlay { @@ -249,8 +203,7 @@ public: uint256 const& key, PublicKey const& validator, Peer::id_t id, - SquelchCB f, - protocol::MessageType type = protocol::mtVALIDATION) = 0; + SquelchCB f) = 0; virtual void deleteIdlePeers(UnsquelchCB) = 0; @@ -538,8 +491,14 @@ public: std::uint16_t inState(PublicKey const& validator, reduce_relay::PeerState state) { - auto res = slots_.inState(validator, state); - return res ? *res : 0; + auto const& it = slots_.slots_.find(validator); + if (it != slots_.slots_.end()) + return std::count_if( + it->second.peers_.begin(), + it->second.peers_.end(), + [&](auto const& it) { return (it.second.state == state); }); + + return 0; } void @@ -547,11 +506,10 @@ public: uint256 const& key, PublicKey const& validator, Peer::id_t id, - SquelchCB f, - protocol::MessageType type = protocol::mtVALIDATION) override + SquelchCB f) override { squelch_ = f; - slots_.updateSlotAndSquelch(key, validator, id, type); + slots_.updateSlotAndSquelch(key, validator, id, true); } void @@ -632,40 +590,56 @@ public: bool isCountingState(PublicKey const& validator) { - return slots_.inState(validator, reduce_relay::SlotState::Counting); + auto const& it = slots_.slots_.find(validator); + if (it != slots_.slots_.end()) + return it->second.state_ == reduce_relay::SlotState::Counting; + + return false; } std::set getSelected(PublicKey const& validator) { - return slots_.getSelected(validator); + auto const& it = slots_.slots_.find(validator); + if (it == slots_.slots_.end()) + return {}; + + std::set r; + for (auto const& [id, info] : it->second.peers_) + if (info.state == reduce_relay::PeerState::Selected) + r.insert(id); + + return r; } bool isSelected(PublicKey const& validator, Peer::id_t peer) { - auto selected = slots_.getSelected(validator); + auto selected = getSelected(validator); return selected.find(peer) != selected.end(); } id_t getSelectedPeer(PublicKey const& validator) { - auto selected = slots_.getSelected(validator); + auto selected = getSelected(validator); assert(selected.size()); return *selected.begin(); } - std::unordered_map< - id_t, - std::tuple< - reduce_relay::PeerState, - std::uint16_t, - std::uint32_t, - std::uint32_t>> + std::unordered_map::PeerInfo> getPeers(PublicKey const& validator) { - return slots_.getPeers(validator); + auto const& it = slots_.slots_.find(validator); + if (it == slots_.slots_.end()) + return {}; + + auto r = std:: + unordered_map::PeerInfo>(); + for (auto const& [id, info] : it->second.peers_) + r.emplace(std::make_pair(id, info)); + + return r; } std::uint16_t @@ -684,6 +658,13 @@ private: if (auto it = peers_.find(id); it != peers_.end()) squelch_(validator, it->second, squelchDuration); } + + void + squelchAll(PublicKey const& validator, std::uint32_t duration) override + { + for (auto const& [id, peer] : peers_) + squelch_(validator, peer, duration); + } void unsquelch(PublicKey const& validator, Peer::id_t id) const override { @@ -874,8 +855,7 @@ public: for (auto& [_, v] : peers) { (void)_; - if (std::get(v) == - reduce_relay::PeerState::Squelched) + if (v.state == reduce_relay::PeerState::Squelched) return false; } } @@ -887,7 +867,7 @@ private: std::vector validators_; }; -class reduce_relay_test : public beast::unit_test::suite +class base_squelch_test : public beast::unit_test::suite { using Slot = reduce_relay::Slot; using id_t = Peer::id_t; @@ -901,8 +881,7 @@ protected: << "num peers " << (int)network_.overlay().getNumPeers() << std::endl; for (auto& [k, v] : peers) - std::cout << k << ":" << (int)std::get(v) - << " "; + std::cout << k << ":" << to_string(v.state) << " "; std::cout << std::endl; } @@ -1074,7 +1053,10 @@ protected: network_.overlay().isSelected(*event.key_, event.peer_); auto peers = network_.overlay().getPeers(*event.key_); auto d = reduce_relay::epoch(now).count() - - std::get<3>(peers[event.peer_]); + reduce_relay::epoch( + peers[event.peer_].lastMessage) + .count(); + mustHandle = event.isSelected_ && d > milliseconds(reduce_relay::IDLED).count() && network_.overlay().inState( @@ -1296,7 +1278,7 @@ protected: [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; }); - auto peers = network_.overlay().getPeers(network_.validator(0)); + BEAST_EXPECT( unsquelched == MAX_PEERS - @@ -1317,8 +1299,7 @@ protected: BEAST_EXPECT(propagateAndSquelch(log, true, false)); auto peers = network_.overlay().getPeers(network_.validator(0)); auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) { - return std::get(it.second) == - reduce_relay::PeerState::Squelched; + return it.second.state == reduce_relay::PeerState::Squelched; }); assert(it != peers.end()); std::uint16_t unsquelched = 0; @@ -1514,7 +1495,7 @@ vp_base_squelch_max_selected_peers=2 auto peers = network_.overlay().getPeers(network_.validator(0)); // first message changes Slot state to Counting and is not counted, // hence '-1'. - BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1)); + BEAST_EXPECT(peers[0].count == (nMessages - 1)); // add duplicate uint256 key(nMessages - 1); network_.overlay().updateSlotAndSquelch( @@ -1524,7 +1505,7 @@ vp_base_squelch_max_selected_peers=2 [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); // confirm the same number of messages peers = network_.overlay().getPeers(network_.validator(0)); - BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1)); + BEAST_EXPECT(peers[0].count == (nMessages - 1)); // advance the clock ManualClock::advance(reduce_relay::IDLED + seconds(1)); network_.overlay().updateSlotAndSquelch( @@ -1534,7 +1515,7 @@ vp_base_squelch_max_selected_peers=2 [&](PublicKey const&, PeerWPtr, std::uint32_t) {}); peers = network_.overlay().getPeers(network_.validator(0)); // confirm message number increased - BEAST_EXPECT(std::get<1>(peers[0]) == nMessages); + BEAST_EXPECT(peers[0].count == nMessages); }); } @@ -1550,6 +1531,12 @@ vp_base_squelch_max_selected_peers=2 if (duration > maxDuration_) maxDuration_ = duration; } + + void + squelchAll(PublicKey const&, std::uint32_t) override + { + } + void unsquelch(PublicKey const&, Peer::id_t) const override { @@ -1582,10 +1569,7 @@ vp_base_squelch_max_selected_peers=2 std::uint64_t mid = m * 1000 + peer; uint256 const message{mid}; slots.updateSlotAndSquelch( - message, - validator, - peer, - protocol::MessageType::mtVALIDATION); + message, validator, peer, true); } } // make Slot's internal hash router expire all messages @@ -1703,7 +1687,7 @@ vp_base_squelch_max_selected_peers=2 Network network_; public: - reduce_relay_test() + base_squelch_test() : env_(*this, jtx::envconfig([](std::unique_ptr cfg) { cfg->VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = true; cfg->VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS = 6; @@ -1732,7 +1716,7 @@ public: } }; -class reduce_relay_simulate_test : public reduce_relay_test +class base_squelch_simulate_test : public base_squelch_test { void testRandom(bool log) @@ -1748,8 +1732,8 @@ class reduce_relay_simulate_test : public reduce_relay_test } }; -BEAST_DEFINE_TESTSUITE(reduce_relay, ripple_data, ripple); -BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, ripple_data, ripple); +BEAST_DEFINE_TESTSUITE(base_squelch, ripple_data, ripple); +BEAST_DEFINE_TESTSUITE_MANUAL(base_squelch_simulate, ripple_data, ripple); } // namespace test diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index 12c1375154..3c2bc49e6a 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -29,17 +29,23 @@ #include #include #include +#include #include #include #include +#include #include -#include -#include #include #include namespace ripple { +// used to make private members of Slots class accessible for testing +namespace test { +class enhanced_squelch_test; +class base_squelch_test; +class OverlaySim; +} // namespace test namespace reduce_relay { @@ -143,8 +149,10 @@ public: template class Slot final { -private: friend class Slots; + friend class test::enhanced_squelch_test; + friend class test::OverlaySim; + using id_t = Peer::id_t; using time_point = typename clock_type::time_point; @@ -215,32 +223,6 @@ private: return lastSelected_; } - /** Return number of peers in state */ - std::uint16_t - inState(PeerState state) const; - - /** Return number of peers not in state */ - std::uint16_t - notInState(PeerState state) const; - - /** Return Slot's state */ - SlotState - getState() const - { - return state_; - } - - /** Return selected peers */ - std::set - getSelected() const; - - /** Get peers info. Return map of peer's state, count, squelch - * expiration milsec, and last message time milsec. - */ - std:: - unordered_map> - getPeers() const; - /** Check if peers stopped relaying messages. If a peer is * selected peer then call unsquelch handler for all * currently squelched peers and switch the slot to @@ -258,7 +240,6 @@ private: std::chrono::seconds getSquelchDuration(std::size_t npeers); -private: /** Reset counts of peers in Selected or Counting state */ void resetCounts(); @@ -584,65 +565,18 @@ Slot::initCounting() resetCounts(); } -template -std::uint16_t -Slot::inState(PeerState state) const -{ - return std::count_if(peers_.begin(), peers_.end(), [&](auto const& it) { - return (it.second.state == state); - }); -} - -template -std::uint16_t -Slot::notInState(PeerState state) const -{ - return std::count_if(peers_.begin(), peers_.end(), [&](auto const& it) { - return (it.second.state != state); - }); -} - -template -std::set -Slot::getSelected() const -{ - std::set r; - for (auto const& [id, info] : peers_) - if (info.state == PeerState::Selected) - r.insert(id); - return r; -} - -template -std::unordered_map< - typename Peer::id_t, - std::tuple> -Slot::getPeers() const -{ - using namespace std::chrono; - auto r = std::unordered_map< - id_t, - std::tuple>(); - - for (auto const& [id, info] : peers_) - r.emplace(std::make_pair( - id, - std::move(std::make_tuple( - info.state, - info.count, - epoch(info.expire).count(), - epoch(info.lastMessage).count())))); - - return r; -} - /** Slots is a container for validator's Slot and handles Slot update * when a message is received from a validator. It also handles Slot aging - * and checks for peers which are disconnected or stopped relaying the messages. + * and checks for peers which are disconnected or stopped relaying the + * messages. */ template class Slots final { + friend class test::enhanced_squelch_test; + friend class test::base_squelch_test; + friend class test::OverlaySim; + using time_point = typename clock_type::time_point; using id_t = typename Peer::id_t; using messages = beast::aged_unordered_map< @@ -767,71 +701,6 @@ public: */ void deleteIdlePeers(); - - /** Return number of peers in state */ - std::optional - inState(PublicKey const& validator, PeerState state) const - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.inState(state); - return {}; - } - - /** Return number of peers not in state */ - std::optional - notInState(PublicKey const& validator, PeerState state) const - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.notInState(state); - return {}; - } - - /** Return true if Slot is in state */ - bool - inState(PublicKey const& validator, SlotState state) const - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.state_ == state; - return false; - } - - /** Get selected peers */ - std::set - getSelected(PublicKey const& validator) - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.getSelected(); - return {}; - } - - /** Get peers info. Return map of peer's state, count, and squelch - * expiration milliseconds. - */ - std::unordered_map< - typename Peer::id_t, - std::tuple> - getPeers(PublicKey const& validator) - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.getPeers(); - return {}; - } - - /** Get Slot's state */ - std::optional - getState(PublicKey const& validator) - { - auto const& it = slots_.find(validator); - if (it != slots_.end()) - return it->second.getState(); - return {}; - } - /** Called when a peer is deleted. If the peer was selected to be the * source of messages from the validator then squelched peers have to be * unsquelched.