Extract common test chain setup code (#4076)

This commit is contained in:
Piotr Wójcik 2023-01-27 01:33:43 +01:00 committed by GitHub
commit 8ccee5d599
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 234 additions and 255 deletions

View file

@ -1,6 +1,7 @@
#include <nano/lib/jsonconfig.hpp>
#include <nano/node/election.hpp>
#include <nano/node/transport/inproc.hpp>
#include <nano/test_common/chains.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
@ -1407,94 +1408,6 @@ TEST (active_transactions, fifo)
ASSERT_TIMELY (1s, node.active.election (receive2->qualified_root ()) != nullptr);
}
namespace
{
/*
* Sends `amount` raw from genesis chain into a new account and makes it a representative
*/
nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount)
{
auto latest = node.latest (nano::dev::genesis_key.pub);
auto balance = node.balance (nano::dev::genesis_key.pub);
nano::keypair key;
nano::block_builder builder;
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (balance - amount)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
auto open = builder
.open ()
.source (send->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open }));
return key;
}
/*
* Creates `count` 1 raw sends from genesis to unique accounts and corresponding open blocks.
* The genesis chain is then confirmed, but leaves open blocks unconfirmed.
*/
std::vector<std::shared_ptr<nano::block>> setup_independent_blocks (nano::test::system & system, nano::node & node, int count)
{
std::vector<std::shared_ptr<nano::block>> blocks;
auto latest = node.latest (nano::dev::genesis_key.pub);
auto balance = node.balance (nano::dev::genesis_key.pub);
for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;
balance -= 1;
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (balance)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
latest = send->hash ();
auto open = builder
.open ()
.source (send->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger
blocks.push_back (open);
}
// Confirm whole genesis chain at once
EXPECT_TIMELY (5s, nano::test::confirm (node, { latest }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest }));
return blocks;
}
}
/*
* Ensures we limit the number of vote hinted elections in AEC
*/
@ -1511,10 +1424,10 @@ TEST (active_transactions, limit_vote_hinted_elections)
// Setup representatives
// Enough weight to trigger election hinting but not enough to confirm block on its own
const auto amount = ((node.online_reps.trended () / 100) * node.config.election_hint_weight_percent) + 1000 * nano::Gxrb_ratio;
nano::keypair rep1 = setup_rep (system, node, amount / 2);
nano::keypair rep2 = setup_rep (system, node, amount / 2);
nano::keypair rep1 = nano::test::setup_rep (system, node, amount / 2);
nano::keypair rep2 = nano::test::setup_rep (system, node, amount / 2);
auto blocks = setup_independent_blocks (system, node, 2);
auto blocks = nano::test::setup_independent_blocks (system, node, 2);
auto open0 = blocks[0];
auto open1 = blocks[1];
@ -1573,7 +1486,7 @@ TEST (active_transactions, allow_limited_overflow)
config.active_elections_hinted_limit_percentage = 20; // Should give us a limit of 4 hinted elections
auto & node = *system.add_node (config);
auto blocks = setup_independent_blocks (system, node, aec_limit * 4);
auto blocks = nano::test::setup_independent_blocks (system, node, aec_limit * 4);
// Split blocks in two halves
std::vector<std::shared_ptr<nano::block>> blocks1 (blocks.begin (), blocks.begin () + blocks.size () / 2);
@ -1622,7 +1535,7 @@ TEST (active_transactions, allow_limited_overflow_adapt)
config.active_elections_hinted_limit_percentage = 20; // Should give us a limit of 4 hinted elections
auto & node = *system.add_node (config);
auto blocks = setup_independent_blocks (system, node, aec_limit * 4);
auto blocks = nano::test::setup_independent_blocks (system, node, aec_limit * 4);
// Split blocks in two halves
std::vector<std::shared_ptr<nano::block>> blocks1 (blocks.begin (), blocks.begin () + blocks.size () / 2);

View file

@ -1,4 +1,5 @@
#include <nano/node/active_transactions.hpp>
#include <nano/test_common/chains.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
@ -8,65 +9,6 @@
using namespace std::chrono_literals;
namespace
{
using block_list_t = std::vector<std::shared_ptr<nano::block>>;
/*
* Creates `count` 1 raw sends from genesis to unique accounts and corresponding open blocks.
* The genesis chain is then confirmed, but leaves open blocks unconfirmed
* The list of unconfirmed open blocks is returned.
*/
block_list_t setup_independent_blocks (nano::test::system & system, nano::node & node, int count)
{
std::vector<std::shared_ptr<nano::block>> blocks;
auto latest = node.latest (nano::dev::genesis_key.pub);
auto balance = node.balance (nano::dev::genesis_key.pub);
for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;
balance -= 1;
auto send = builder
.state ()
.account (nano::dev::genesis_key.pub)
.previous (latest)
.representative (nano::dev::genesis_key.pub)
.balance (balance)
.link (key.pub)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
latest = send->hash ();
auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.balance (1)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger
blocks.push_back (open);
}
// Confirm whole genesis chain at once
EXPECT_TIMELY (5s, nano::test::confirm (node, { latest }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest }));
return blocks;
}
}
/*
* Ensures all not confirmed accounts get activated by backlog scan periodically
*/
@ -74,6 +16,7 @@ TEST (backlog, population)
{
nano::mutex mutex;
std::unordered_set<nano::account> activated;
nano::test::system system{};
auto & node = *system.add_node ();
@ -83,7 +26,7 @@ TEST (backlog, population)
activated.insert (account);
});
auto blocks = setup_independent_blocks (system, node, 256);
auto blocks = nano::test::setup_independent_blocks (system, node, 256);
// Checks if `activated` set contains all accounts we previously set up
auto all_activated = [&] () {

View file

@ -1,3 +1,4 @@
#include <nano/test_common/chains.hpp>
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
@ -9,98 +10,6 @@ using namespace std::chrono_literals;
namespace
{
using block_list_t = std::vector<std::shared_ptr<nano::block>>;
/**
* Creates `block_count` random send blocks in an account chain
*/
block_list_t setup_chain (nano::test::system & system, nano::node & node, nano::keypair key, int block_count)
{
auto latest = node.latest (key.pub);
auto balance = node.balance (key.pub);
std::vector<std::shared_ptr<nano::block>> blocks;
for (int n = 0; n < block_count; ++n)
{
nano::keypair throwaway;
nano::block_builder builder;
balance -= 1;
auto send = builder
.send ()
.previous (latest)
.destination (throwaway.pub)
.balance (balance)
.sign (key.prv, key.pub)
.work (*system.work.generate (latest))
.build_shared ();
latest = send->hash ();
blocks.push_back (send);
}
EXPECT_TRUE (nano::test::process (node, blocks));
// Confirm whole chain at once
EXPECT_TIMELY (5s, nano::test::confirm (node, { blocks.back () }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, blocks));
return blocks;
}
/**
* Creates `count` account chains, each with `block_count` blocks
*/
std::vector<std::pair<nano::account, block_list_t>> setup_chains (nano::test::system & system, nano::node & node, int count, int block_count)
{
auto latest = node.latest (nano::dev::genesis_key.pub);
auto balance = node.balance (nano::dev::genesis_key.pub);
std::vector<std::pair<nano::account, block_list_t>> chains;
for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;
balance -= block_count * 2; // Send enough to later create `block_count` blocks
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (balance)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
auto open = builder
.open ()
.source (send->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
latest = send->hash ();
// Ensure blocks are in the ledger and confirmed
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open }));
auto added_blocks = setup_chain (system, node, key, block_count);
auto blocks = block_list_t{ open };
blocks.insert (blocks.end (), added_blocks.begin (), added_blocks.end ());
chains.emplace_back (key.pub, blocks);
}
return chains;
}
/**
* Helper to track responses in thread safe way
*/
class responses_helper final
{
public:
@ -160,7 +69,7 @@ TEST (bootstrap_server, serve_account_blocks)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 128);
auto chains = nano::test::setup_chains (system, node, 1, 128);
auto [first_account, first_blocks] = chains.front ();
// Request blocks from account root
@ -204,11 +113,11 @@ TEST (bootstrap_server, serve_hash)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 256);
auto chains = nano::test::setup_chains (system, node, 1, 256);
auto [account, blocks] = chains.front ();
// Skip a few blocks to request hash in the middle of the chain
blocks = block_list_t (std::next (blocks.begin (), 9), blocks.end ());
blocks = nano::block_list_t{ std::next (blocks.begin (), 9), blocks.end () };
// Request blocks from the middle of the chain
nano::asc_pull_req request{ node.network_params.network };
@ -251,11 +160,11 @@ TEST (bootstrap_server, serve_hash_one)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 256);
auto chains = nano::test::setup_chains (system, node, 1, 256);
auto [account, blocks] = chains.front ();
// Skip a few blocks to request hash in the middle of the chain
blocks = block_list_t (std::next (blocks.begin (), 9), blocks.end ());
blocks = nano::block_list_t{ std::next (blocks.begin (), 9), blocks.end () };
// Request blocks from the middle of the chain
nano::asc_pull_req request{ node.network_params.network };
@ -295,7 +204,7 @@ TEST (bootstrap_server, serve_end_of_chain)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 128);
auto chains = nano::test::setup_chains (system, node, 1, 128);
auto [account, blocks] = chains.front ();
// Request blocks from account frontier
@ -337,7 +246,7 @@ TEST (bootstrap_server, serve_missing)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 128);
auto chains = nano::test::setup_chains (system, node, 1, 128);
// Request blocks from account frontier
nano::asc_pull_req request{ node.network_params.network };
@ -377,7 +286,7 @@ TEST (bootstrap_server, serve_multiple)
responses.add (response);
});
auto chains = setup_chains (system, node, 32, 16);
auto chains = nano::test::setup_chains (system, node, 32, 16);
{
// Request blocks from multiple chains at once
@ -440,7 +349,7 @@ TEST (bootstrap_server, serve_account_info)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 128);
auto chains = nano::test::setup_chains (system, node, 1, 128);
auto [account, blocks] = chains.front ();
// Request blocks from account root
@ -488,7 +397,7 @@ TEST (bootstrap_server, serve_account_info_missing)
responses.add (response);
});
auto chains = setup_chains (system, node, 1, 128);
auto chains = nano::test::setup_chains (system, node, 1, 128);
auto [account, blocks] = chains.front ();
// Request blocks from account root

View file

@ -128,6 +128,9 @@ protected:
private:
nano::block_hash generate_hash () const;
};
using block_list_t = std::vector<std::shared_ptr<nano::block>>;
class send_hashables
{
public:

View file

@ -1,5 +1,7 @@
add_library(
test_common
chains.hpp
chains.cpp
ledger.hpp
ledger.cpp
network.hpp

169
nano/test_common/chains.cpp Normal file
View file

@ -0,0 +1,169 @@
#include <nano/test_common/chains.hpp>
using namespace std::chrono_literals;
nano::block_list_t nano::test::setup_chain (nano::test::system & system, nano::node & node, int count, nano::keypair target)
{
auto latest = node.latest (target.pub);
auto balance = node.balance (target.pub);
std::vector<std::shared_ptr<nano::block>> blocks;
for (int n = 0; n < count; ++n)
{
nano::keypair throwaway;
nano::block_builder builder;
balance -= 1;
auto send = builder
.send ()
.previous (latest)
.destination (throwaway.pub)
.balance (balance)
.sign (target.prv, target.pub)
.work (*system.work.generate (latest))
.build_shared ();
latest = send->hash ();
blocks.push_back (send);
}
EXPECT_TRUE (nano::test::process (node, blocks));
// Confirm whole chain at once
EXPECT_TIMELY (5s, nano::test::confirm (node, { blocks.back () }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, blocks));
return blocks;
}
std::vector<std::pair<nano::account, nano::block_list_t>> nano::test::setup_chains (nano::test::system & system, nano::node & node, int chain_count, int block_count, nano::keypair source)
{
auto latest = node.latest (source.pub);
auto balance = node.balance (source.pub);
std::vector<std::pair<nano::account, block_list_t>> chains;
for (int n = 0; n < chain_count; ++n)
{
nano::keypair key;
nano::block_builder builder;
balance -= block_count * 2; // Send enough to later create `block_count` blocks
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (balance)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
auto open = builder
.open ()
.source (send->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
latest = send->hash ();
// Ensure blocks are in the ledger and confirmed
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open }));
auto added_blocks = nano::test::setup_chain (system, node, block_count, key);
auto blocks = block_list_t{ open };
blocks.insert (blocks.end (), added_blocks.begin (), added_blocks.end ());
chains.emplace_back (key.pub, blocks);
}
return chains;
}
nano::block_list_t nano::test::setup_independent_blocks (nano::test::system & system, nano::node & node, int count, nano::keypair source)
{
std::vector<std::shared_ptr<nano::block>> blocks;
auto latest = node.latest (source.pub);
auto balance = node.balance (source.pub);
for (int n = 0; n < count; ++n)
{
nano::keypair key;
nano::block_builder builder;
balance -= 1;
auto send = builder
.state ()
.account (nano::dev::genesis_key.pub)
.previous (latest)
.representative (nano::dev::genesis_key.pub)
.balance (balance)
.link (key.pub)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
latest = send->hash ();
auto open = builder
.state ()
.account (key.pub)
.previous (0)
.representative (key.pub)
.balance (1)
.link (send->hash ())
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::exists (node, { send, open })); // Ensure blocks are in the ledger
blocks.push_back (open);
}
// Confirm whole genesis chain at once
EXPECT_TIMELY (5s, nano::test::confirm (node, { latest }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { latest }));
return blocks;
}
nano::keypair nano::test::setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t const amount, nano::keypair source)
{
auto latest = node.latest (source.pub);
auto balance = node.balance (source.pub);
nano::keypair key;
nano::block_builder builder;
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (balance - amount)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
auto open = builder
.open ()
.source (send->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
EXPECT_TRUE (nano::test::process (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirm (node, { send, open }));
EXPECT_TIMELY (5s, nano::test::confirmed (node, { send, open }));
return key;
}

View file

@ -0,0 +1,40 @@
#pragma once
#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
#include <memory>
#include <vector>
/*
* Helper functions to deal with common chain setup scenarios
*/
namespace nano::test
{
/**
* Creates `count` random 1 raw send blocks in a `target` account chain
* @returns created blocks
*/
nano::block_list_t setup_chain (nano::test::system & system, nano::node & node, int count, nano::keypair target = nano::dev::genesis_key);
/**
* Creates `chain_count` account chains, each with `block_count` 1 raw random send blocks, all accounts are seeded from `source` account
* @returns list of created accounts and their blocks
*/
std::vector<std::pair<nano::account, nano::block_list_t>> setup_chains (nano::test::system & system, nano::node & node, int chain_count, int block_count, nano::keypair source = nano::dev::genesis_key);
/**
* Creates `count` 1 raw send blocks from `source` account, each to randomly created account
* The `source` account chain is then confirmed, but leaves open blocks unconfirmed
* @returns list of unconfirmed (open) blocks
*/
nano::block_list_t setup_independent_blocks (nano::test::system & system, nano::node & node, int count, nano::keypair source = nano::dev::genesis_key);
/**
* Sends `amount` raw from `source` account chain into a newly created account and sets that account as its own representative
* @return created representative
*/
nano::keypair setup_rep (nano::test::system & system, nano::node & node, nano::uint128_t amount, nano::keypair source = nano::dev::genesis_key);
}