Fix tests

This commit is contained in:
Piotr Wójcik 2024-03-20 18:34:14 +01:00
commit 0fa894f19d
6 changed files with 102 additions and 108 deletions

View file

@ -235,7 +235,7 @@ TEST (active_transactions, keep_local)
// ASSERT_EQ (1, node.scheduler.size ());
}
TEST (active_transactions, inactive_votes_cache)
TEST (inactive_votes_cache, basic)
{
nano::test::system system (1);
auto & node = *system.nodes[0];
@ -259,7 +259,7 @@ TEST (active_transactions, inactive_votes_cache)
/**
* This test case confirms that a non final vote cannot cause an election to become confirmed
*/
TEST (active_transactions, inactive_votes_cache_non_final)
TEST (inactive_votes_cache, non_final)
{
nano::test::system system (1);
auto & node = *system.nodes[0];
@ -285,7 +285,7 @@ TEST (active_transactions, inactive_votes_cache_non_final)
ASSERT_FALSE (election->confirmed ());
}
TEST (active_transactions, inactive_votes_cache_fork)
TEST (inactive_votes_cache, fork)
{
nano::test::system system{ 1 };
auto & node = *system.nodes[0];
@ -325,7 +325,7 @@ TEST (active_transactions, inactive_votes_cache_fork)
ASSERT_EQ (1, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
}
TEST (active_transactions, inactive_votes_cache_existing_vote)
TEST (inactive_votes_cache, existing_vote)
{
nano::test::system system;
nano::node_config node_config = system.default_config ();
@ -365,12 +365,13 @@ TEST (active_transactions, inactive_votes_cache_existing_vote)
ASSERT_EQ (send->hash (), last_vote1.hash);
ASSERT_EQ (nano::vote::timestamp_min * 1, last_vote1.timestamp);
// Attempt to change vote with inactive_votes_cache
nano::unique_lock<nano::mutex> active_lock (node.active.mutex);
node.vote_cache.vote (send->hash (), vote1);
auto cache = node.vote_cache.find (send->hash ());
ASSERT_TRUE (cache);
ASSERT_EQ (1, cache->voters ().size ());
cache->fill (election);
node.vote_cache.vote (vote1);
auto cached = node.vote_cache.find (send->hash ());
ASSERT_EQ (1, cached.size ());
for (auto const & cached_vote : cached)
{
node.active.vote (cached_vote);
}
// Check that election data is not changed
ASSERT_EQ (2, election->votes ().size ());
auto last_vote2 (election->votes ()[key.pub]);
@ -380,7 +381,7 @@ TEST (active_transactions, inactive_votes_cache_existing_vote)
ASSERT_EQ (0, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
}
TEST (active_transactions, inactive_votes_cache_multiple_votes)
TEST (inactive_votes_cache, multiple_votes)
{
nano::test::system system;
nano::node_config node_config = system.default_config ();
@ -426,8 +427,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes)
auto vote2 = nano::test::make_vote (nano::dev::genesis_key, { send1 }, 0, 0);
node.vote_processor.vote (vote2, std::make_shared<nano::transport::inproc::channel> (node, node));
ASSERT_TIMELY (5s, node.vote_cache.find (send1->hash ()));
ASSERT_TIMELY_EQ (5s, node.vote_cache.find (send1->hash ())->voters ().size (), 2);
ASSERT_TIMELY_EQ (5s, node.vote_cache.find (send1->hash ()).size (), 2);
ASSERT_EQ (1, node.vote_cache.size ());
node.scheduler.priority.activate (nano::dev::genesis_key.pub, node.store.tx_begin_read ());
std::shared_ptr<nano::election> election;
@ -436,7 +436,7 @@ TEST (active_transactions, inactive_votes_cache_multiple_votes)
ASSERT_EQ (2, node.stats.count (nano::stat::type::election, nano::stat::detail::vote_cached));
}
TEST (active_transactions, inactive_votes_cache_election_start)
TEST (inactive_votes_cache, election_start)
{
nano::test::system system;
nano::node_config node_config = system.default_config ();
@ -528,8 +528,7 @@ TEST (active_transactions, inactive_votes_cache_election_start)
// A late block arrival also checks the inactive votes cache
ASSERT_TRUE (node.active.empty ());
auto send4_cache (node.vote_cache.find (send4->hash ()));
ASSERT_TRUE (send4_cache);
ASSERT_EQ (3, send4_cache->voters ().size ());
ASSERT_EQ (3, send4_cache.size ());
node.process_active (send3);
// An election is started for send6 but does not
ASSERT_FALSE (node.block_confirmed_or_being_confirmed (send3->hash ()));
@ -982,8 +981,7 @@ TEST (active_transactions, fork_replacement_tally)
node1.vote_processor.vote (vote, std::make_shared<nano::transport::inproc::channel> (node1, node1));
node1.vote_processor.flush ();
// ensure vote arrives before the block
ASSERT_TIMELY (5s, node1.vote_cache.find (send_last->hash ()));
ASSERT_TIMELY_EQ (5s, 1, node1.vote_cache.find (send_last->hash ())->size ());
ASSERT_TIMELY_EQ (5s, 1, node1.vote_cache.find (send_last->hash ()).size ());
node1.network.publish_filter.clear ();
node2.network.flood_block (send_last);
ASSERT_TIMELY (5s, node1.stats.count (nano::stat::type::message, nano::stat::detail::publish, nano::stat::dir::in) > 1);
@ -1537,7 +1535,7 @@ TEST (active_transactions, allow_limited_overflow)
{
// Non-final vote, so it stays in the AEC without getting confirmed
auto vote = nano::test::make_vote (nano::dev::genesis_key, { block });
node.vote_cache.vote (block->hash (), vote);
node.vote_cache.vote (vote);
}
// Ensure active elections overfill AEC only up to normal + hinted limit
@ -1575,7 +1573,7 @@ TEST (active_transactions, allow_limited_overflow_adapt)
{
// Non-final vote, so it stays in the AEC without getting confirmed
auto vote = nano::test::make_vote (nano::dev::genesis_key, { block });
node.vote_cache.vote (block->hash (), vote);
node.vote_cache.vote (vote);
}
// Ensure hinted election amount is bounded by hinted limit

View file

@ -42,7 +42,7 @@ TEST (vote_cache, construction)
ASSERT_EQ (0, vote_cache.size ());
ASSERT_TRUE (vote_cache.empty ());
auto hash1 = nano::test::random_hash ();
ASSERT_FALSE (vote_cache.find (hash1));
ASSERT_TRUE (vote_cache.find (hash1).empty ());
}
/*
@ -57,16 +57,12 @@ TEST (vote_cache, insert_one_hash)
auto rep1 = create_rep (7);
auto hash1 = nano::test::random_hash ();
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
ASSERT_EQ (1, vote_cache.size ());
auto peek1 = vote_cache.find (hash1);
ASSERT_TRUE (peek1);
ASSERT_EQ (peek1->hash (), hash1);
ASSERT_EQ (peek1->voters ().size (), 1);
ASSERT_EQ (peek1->voters ().front ().representative, rep1.pub); // account
ASSERT_EQ (peek1->voters ().front ().timestamp, 1024 * 1024); // timestamp
ASSERT_EQ (peek1->tally (), 7);
ASSERT_EQ (peek1.size (), 1);
ASSERT_EQ (peek1.front (), vote1);
auto tops = vote_cache.top (0);
ASSERT_EQ (tops.size (), 1);
@ -92,17 +88,17 @@ TEST (vote_cache, insert_one_hash_many_votes)
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1 * 1024 * 1024);
auto vote2 = nano::test::make_vote (rep2, { hash1 }, 2 * 1024 * 1024);
auto vote3 = nano::test::make_vote (rep3, { hash1 }, 3 * 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote3->hashes.front (), vote3);
vote_cache.vote (vote1);
vote_cache.vote (vote2);
vote_cache.vote (vote3);
// We have 3 votes but for a single hash, so just one entry in vote cache
ASSERT_EQ (1, vote_cache.size ());
auto peek1 = vote_cache.find (hash1);
ASSERT_TRUE (peek1);
ASSERT_EQ (peek1->voters ().size (), 3);
// Tally must be the sum of rep weights
ASSERT_EQ (peek1->tally (), 7 + 9 + 11);
ASSERT_EQ (peek1.size (), 3);
// Verify each vote is present
ASSERT_TRUE (std::find (peek1.begin (), peek1.end (), vote1) != peek1.end ());
ASSERT_TRUE (std::find (peek1.begin (), peek1.end (), vote2) != peek1.end ());
ASSERT_TRUE (std::find (peek1.begin (), peek1.end (), vote3) != peek1.end ());
auto tops = vote_cache.top (0);
ASSERT_EQ (tops.size (), 1);
@ -136,14 +132,14 @@ TEST (vote_cache, insert_many_hashes_many_votes)
auto vote3 = nano::test::make_vote (rep3, { hash3 }, 1024 * 1024);
auto vote4 = nano::test::make_vote (rep4, { hash1 }, 1024 * 1024);
// Insert first 3 votes in cache
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote3->hashes.front (), vote3);
vote_cache.vote (vote1);
vote_cache.vote (vote2);
vote_cache.vote (vote3);
// Ensure all of those are properly inserted
ASSERT_EQ (3, vote_cache.size ());
ASSERT_TRUE (vote_cache.find (hash1));
ASSERT_TRUE (vote_cache.find (hash2));
ASSERT_TRUE (vote_cache.find (hash3));
ASSERT_EQ (1, vote_cache.find (hash1).size ());
ASSERT_EQ (1, vote_cache.find (hash2).size ());
ASSERT_EQ (1, vote_cache.find (hash3).size ());
// Ensure that first entry in queue is the one for hash3 (rep3 has the highest weight of the first 3 reps)
auto tops1 = vote_cache.top (0);
@ -151,14 +147,12 @@ TEST (vote_cache, insert_many_hashes_many_votes)
ASSERT_EQ (tops1[0].hash, hash3);
ASSERT_EQ (tops1[0].tally, 11);
auto peek1 = vote_cache.find (tops1[0].hash);
ASSERT_TRUE (peek1);
ASSERT_EQ (peek1->voters ().size (), 1);
ASSERT_EQ (peek1->tally (), 11);
ASSERT_EQ (peek1->hash (), hash3);
auto peek1 = vote_cache.find (hash3);
ASSERT_EQ (peek1.size (), 1);
ASSERT_EQ (peek1.front (), vote3);
// Now add a vote from rep4 with the highest voting weight
vote_cache.vote (vote4->hashes.front (), vote4);
vote_cache.vote (vote4);
// Ensure that the first entry in queue is now the one for hash1 (rep1 + rep4 tally weight)
auto tops2 = vote_cache.top (0);
@ -166,31 +160,26 @@ TEST (vote_cache, insert_many_hashes_many_votes)
ASSERT_EQ (tops2[0].hash, hash1);
ASSERT_EQ (tops2[0].tally, 7 + 13);
auto pop1 = vote_cache.find (tops2[0].hash);
ASSERT_TRUE (pop1);
ASSERT_EQ ((*pop1).voters ().size (), 2);
ASSERT_EQ ((*pop1).tally (), 7 + 13);
ASSERT_EQ ((*pop1).hash (), hash1);
auto pop1 = vote_cache.find (hash1);
ASSERT_EQ (pop1.size (), 2);
ASSERT_TRUE (std::find (pop1.begin (), pop1.end (), vote1) != pop1.end ());
ASSERT_TRUE (std::find (pop1.begin (), pop1.end (), vote4) != pop1.end ());
// The next entry in queue should be hash3 (rep3 tally weight)
ASSERT_EQ (tops2[1].hash, hash3);
ASSERT_EQ (tops2[1].tally, 11);
auto pop2 = vote_cache.find (tops2[1].hash);
ASSERT_EQ ((*pop2).voters ().size (), 1);
ASSERT_EQ ((*pop2).tally (), 11);
ASSERT_EQ ((*pop2).hash (), hash3);
ASSERT_TRUE (vote_cache.find (hash3));
auto pop2 = vote_cache.find (hash3);
ASSERT_EQ (pop2.size (), 1);
ASSERT_EQ (pop2.front (), vote3);
// And last one should be hash2 with rep2 tally weight
ASSERT_EQ (tops2[2].hash, hash2);
ASSERT_EQ (tops2[2].tally, 9);
auto pop3 = vote_cache.find (tops2[2].hash);
ASSERT_EQ ((*pop3).voters ().size (), 1);
ASSERT_EQ ((*pop3).tally (), 9);
ASSERT_EQ ((*pop3).hash (), hash2);
ASSERT_TRUE (vote_cache.find (hash2));
auto pop3 = vote_cache.find (hash2);
ASSERT_EQ (pop3.size (), 1);
ASSERT_EQ (pop3.front (), vote2);
}
/*
@ -206,8 +195,8 @@ TEST (vote_cache, insert_duplicate)
auto rep1 = create_rep (9);
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1 * 1024 * 1024);
auto vote2 = nano::test::make_vote (rep1, { hash1 }, 1 * 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote1);
vote_cache.vote (vote2);
ASSERT_EQ (1, vote_cache.size ());
}
@ -223,18 +212,15 @@ TEST (vote_cache, insert_newer)
auto hash1 = nano::test::random_hash ();
auto rep1 = create_rep (9);
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1 * 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
auto peek1 = vote_cache.find (hash1);
ASSERT_TRUE (peek1);
ASSERT_EQ (peek1.size (), 1);
ASSERT_EQ (peek1.front (), vote1);
auto vote2 = nano::test::make_final_vote (rep1, { hash1 });
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote2);
auto peek2 = vote_cache.find (hash1);
ASSERT_TRUE (peek2);
ASSERT_EQ (1, vote_cache.size ());
ASSERT_EQ (1, peek2->voters ().size ());
// Second entry should have timestamp greater than the first one
ASSERT_GT (peek2->voters ().front ().timestamp, peek1->voters ().front ().timestamp);
ASSERT_EQ (peek2->voters ().front ().timestamp, std::numeric_limits<uint64_t>::max ()); // final timestamp
ASSERT_EQ (peek2.size (), 1);
ASSERT_EQ (peek2.front (), vote2); // vote2 should replace vote1 as it has a higher timestamp
}
/*
@ -249,16 +235,15 @@ TEST (vote_cache, insert_older)
auto hash1 = nano::test::random_hash ();
auto rep1 = create_rep (9);
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 2 * 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
auto peek1 = vote_cache.find (hash1);
ASSERT_TRUE (peek1);
ASSERT_EQ (peek1.size (), 1);
ASSERT_EQ (peek1.front (), vote1);
auto vote2 = nano::test::make_vote (rep1, { hash1 }, 1 * 1024 * 1024);
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote2);
auto peek2 = vote_cache.find (hash1);
ASSERT_TRUE (peek2);
ASSERT_EQ (1, vote_cache.size ());
ASSERT_EQ (1, peek2->voters ().size ());
ASSERT_EQ (peek2->voters ().front ().timestamp, peek1->voters ().front ().timestamp); // timestamp2 == timestamp1
ASSERT_EQ (peek2.size (), 1);
ASSERT_EQ (peek2.front (), vote1); // vote1 should still be in cache as it has a higher timestamp
}
/*
@ -280,24 +265,24 @@ TEST (vote_cache, erase)
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1024 * 1024);
auto vote2 = nano::test::make_vote (rep2, { hash2 }, 1024 * 1024);
auto vote3 = nano::test::make_vote (rep3, { hash3 }, 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote2->hashes.front (), vote2);
vote_cache.vote (vote3->hashes.front (), vote3);
vote_cache.vote (vote1);
vote_cache.vote (vote2);
vote_cache.vote (vote3);
ASSERT_EQ (3, vote_cache.size ());
ASSERT_FALSE (vote_cache.empty ());
ASSERT_TRUE (vote_cache.find (hash1));
ASSERT_TRUE (vote_cache.find (hash2));
ASSERT_TRUE (vote_cache.find (hash3));
ASSERT_FALSE (vote_cache.find (hash1).empty ());
ASSERT_FALSE (vote_cache.find (hash2).empty ());
ASSERT_FALSE (vote_cache.find (hash3).empty ());
vote_cache.erase (hash2);
ASSERT_EQ (2, vote_cache.size ());
ASSERT_TRUE (vote_cache.find (hash1));
ASSERT_FALSE (vote_cache.find (hash2));
ASSERT_TRUE (vote_cache.find (hash3));
ASSERT_FALSE (vote_cache.find (hash1).empty ());
ASSERT_TRUE (vote_cache.find (hash2).empty ());
ASSERT_FALSE (vote_cache.find (hash3).empty ());
vote_cache.erase (hash1);
vote_cache.erase (hash3);
ASSERT_FALSE (vote_cache.find (hash1));
ASSERT_FALSE (vote_cache.find (hash2));
ASSERT_FALSE (vote_cache.find (hash3));
ASSERT_TRUE (vote_cache.find (hash1).empty ());
ASSERT_TRUE (vote_cache.find (hash2).empty ());
ASSERT_TRUE (vote_cache.find (hash3).empty ());
ASSERT_TRUE (vote_cache.empty ());
}
@ -319,7 +304,7 @@ TEST (vote_cache, overfill)
auto rep1 = create_rep (count - n);
auto hash1 = nano::test::random_hash ();
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
}
ASSERT_LT (vote_cache.size (), count);
// Check that oldest votes are dropped first
@ -343,7 +328,7 @@ TEST (vote_cache, overfill_entry)
{
auto rep1 = create_rep (9);
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 1024 * 1024);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
}
ASSERT_EQ (1, vote_cache.size ());
}
@ -359,9 +344,9 @@ TEST (vote_cache, age_cutoff)
auto hash1 = nano::test::random_hash ();
auto rep1 = create_rep (9);
auto vote1 = nano::test::make_vote (rep1, { hash1 }, 3);
vote_cache.vote (vote1->hashes.front (), vote1);
vote_cache.vote (vote1);
ASSERT_EQ (1, vote_cache.size ());
ASSERT_TRUE (vote_cache.find (hash1));
ASSERT_FALSE (vote_cache.find (hash1).empty ());
auto tops1 = vote_cache.top (0);
ASSERT_EQ (tops1.size (), 1);

View file

@ -15,8 +15,14 @@ using namespace std::chrono_literals;
TEST (vote_processor, codes)
{
nano::test::system system (1);
auto & node (*system.nodes[0]);
nano::test::system system;
auto node_config = system.default_config ();
// Disable all election schedulers
node_config.frontiers_confirmation = nano::frontiers_confirmation_mode::disabled;
node_config.hinted_scheduler.enabled = false;
node_config.optimistic_scheduler.enabled = false;
auto & node = *system.add_node (node_config);
auto blocks = nano::test::setup_chain (system, node, 1, nano::dev::genesis_key, false);
auto vote = nano::test::make_vote (nano::dev::genesis_key, { blocks[0] }, nano::vote::timestamp_min * 1, 0);
auto vote_invalid = std::make_shared<nano::vote> (*vote);
@ -48,7 +54,7 @@ TEST (vote_processor, codes)
ASSERT_EQ (nano::vote_code::invalid, node.vote_processor.vote_blocking (vote_invalid, channel));
// Once the election is removed (confirmed / dropped) the vote is again indeterminate
node.active.erase (*blocks[0]);
ASSERT_TRUE (node.active.erase (blocks[0]->qualified_root ()));
ASSERT_EQ (nano::vote_code::indeterminate, node.vote_processor.vote_blocking (vote, channel));
}

View file

@ -549,26 +549,29 @@ std::shared_ptr<nano::block> nano::active_transactions::winner (nano::block_hash
return result;
}
void nano::active_transactions::erase (nano::block const & block_a)
bool nano::active_transactions::erase (nano::block const & block_a)
{
erase (block_a.qualified_root ());
return erase (block_a.qualified_root ());
}
void nano::active_transactions::erase (nano::qualified_root const & root_a)
bool nano::active_transactions::erase (nano::qualified_root const & root_a)
{
nano::unique_lock<nano::mutex> lock{ mutex };
auto root_it (roots.get<tag_root> ().find (root_a));
if (root_it != roots.get<tag_root> ().end ())
{
cleanup_election (lock, root_it->election);
return true;
}
return false;
}
void nano::active_transactions::erase_hash (nano::block_hash const & hash_a)
bool nano::active_transactions::erase_hash (nano::block_hash const & hash_a)
{
nano::unique_lock<nano::mutex> lock{ mutex };
[[maybe_unused]] auto erased (blocks.erase (hash_a));
debug_assert (erased == 1);
return erased == 1;
}
void nano::active_transactions::erase_oldest ()

View file

@ -164,8 +164,9 @@ public:
std::shared_ptr<nano::block> winner (nano::block_hash const &) const;
// Returns a list of elections sorted by difficulty
std::vector<std::shared_ptr<nano::election>> list_active (std::size_t = std::numeric_limits<std::size_t>::max ());
void erase (nano::block const &);
void erase_hash (nano::block_hash const &);
bool erase (nano::block const &);
bool erase (nano::qualified_root const &);
bool erase_hash (nano::block_hash const &);
void erase_oldest ();
bool empty () const;
std::size_t size () const;
@ -193,7 +194,6 @@ private:
void trim ();
void request_loop ();
void request_confirm (nano::unique_lock<nano::mutex> &);
void erase (nano::qualified_root const &);
// Erase all blocks from active and, if not confirmed, clear digests from network filters
void cleanup_election (nano::unique_lock<nano::mutex> & lock_a, std::shared_ptr<nano::election>);
nano::stat::type completion_type (nano::election const & election) const;

View file

@ -106,7 +106,9 @@ public:
/**
* Adds a new vote to cache
*/
void vote (std::shared_ptr<nano::vote> const & vote, std::function<bool (nano::block_hash const &)> const & filter);
void vote (
std::shared_ptr<nano::vote> const & vote,
std::function<bool (nano::block_hash const &)> const & filter = [] (nano::block_hash const &) { return true; });
/**
* Tries to find an entry associated with block hash