dncurrency/nano/core_test/gap_cache.cpp
Dimitrios Siganos 78631a6b1c
Move test code into namespace nano::test (#3890)
* Move nano::establish_tcp into nano::test namespace
* Move system.hpp declarations into namespace nano::test
* Move telemetry test code to namespace nano::test
* Move testutil declarations into namespace nano::test
2022-08-10 20:48:31 +01:00

171 lines
5.8 KiB
C++

#include <nano/test_common/system.hpp>
#include <nano/test_common/testutil.hpp>
#include <gtest/gtest.h>
using namespace std::chrono_literals;
TEST (gap_cache, add_new)
{
nano::test::system system (1);
nano::gap_cache cache (*system.nodes[0]);
nano::block_builder builder;
auto block1 = builder
.send ()
.previous (0)
.destination (1)
.balance (2)
.sign (nano::keypair ().prv, 4)
.work (5)
.build_shared ();
cache.add (block1->hash ());
}
TEST (gap_cache, add_existing)
{
nano::test::system system (1);
nano::gap_cache cache (*system.nodes[0]);
nano::block_builder builder;
auto block1 = builder
.send ()
.previous (0)
.destination (1)
.balance (2)
.sign (nano::keypair ().prv, 4)
.work (5)
.build_shared ();
cache.add (block1->hash ());
nano::unique_lock<nano::mutex> lock (cache.mutex);
auto existing1 (cache.blocks.get<1> ().find (block1->hash ()));
ASSERT_NE (cache.blocks.get<1> ().end (), existing1);
auto arrival (existing1->arrival);
lock.unlock ();
ASSERT_TIMELY (20s, arrival != std::chrono::steady_clock::now ());
cache.add (block1->hash ());
ASSERT_EQ (1, cache.size ());
lock.lock ();
auto existing2 (cache.blocks.get<1> ().find (block1->hash ()));
ASSERT_NE (cache.blocks.get<1> ().end (), existing2);
ASSERT_GT (existing2->arrival, arrival);
}
TEST (gap_cache, comparison)
{
nano::test::system system (1);
nano::gap_cache cache (*system.nodes[0]);
nano::block_builder builder;
auto block1 = builder
.send ()
.previous (1)
.destination (0)
.balance (2)
.sign (nano::keypair ().prv, 4)
.work (5)
.build_shared ();
cache.add (block1->hash ());
nano::unique_lock<nano::mutex> lock (cache.mutex);
auto existing1 (cache.blocks.get<1> ().find (block1->hash ()));
ASSERT_NE (cache.blocks.get<1> ().end (), existing1);
auto arrival (existing1->arrival);
lock.unlock ();
ASSERT_TIMELY (20s, std::chrono::steady_clock::now () != arrival);
auto block3 = builder
.send ()
.previous (0)
.destination (42)
.balance (1)
.sign (nano::keypair ().prv, 3)
.work (4)
.build_shared ();
cache.add (block3->hash ());
ASSERT_EQ (2, cache.size ());
lock.lock ();
auto existing2 (cache.blocks.get<1> ().find (block3->hash ()));
ASSERT_NE (cache.blocks.get<1> ().end (), existing2);
ASSERT_GT (existing2->arrival, arrival);
ASSERT_EQ (arrival, cache.blocks.get<1> ().begin ()->arrival);
}
// Upon receiving enough votes for a gapped block, a lazy bootstrap should be initiated
TEST (gap_cache, gap_bootstrap)
{
nano::node_flags node_flags;
node_flags.disable_legacy_bootstrap = true;
node_flags.disable_request_loop = true; // to avoid fallback behavior of broadcasting blocks
nano::test::system system (2, nano::transport::transport_type::tcp, node_flags);
auto & node1 (*system.nodes[0]);
auto & node2 (*system.nodes[1]);
nano::block_hash latest (node1.latest (nano::dev::genesis_key.pub));
nano::keypair key;
nano::block_builder builder;
auto send = builder
.send ()
.previous (latest)
.destination (key.pub)
.balance (nano::dev::constants.genesis_amount - 100)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (latest))
.build_shared ();
ASSERT_EQ (nano::process_result::progress, node1.process (*send).code);
ASSERT_EQ (nano::dev::constants.genesis_amount - 100, node1.balance (nano::dev::genesis->account ()));
ASSERT_EQ (nano::dev::constants.genesis_amount, node2.balance (nano::dev::genesis->account ()));
// Confirm send block, allowing voting on the upcoming block
node1.block_confirm (send);
auto election = node1.active.election (send->qualified_root ());
ASSERT_NE (nullptr, election);
election->force_confirm ();
ASSERT_TIMELY (2s, node1.block_confirmed (send->hash ()));
node1.active.erase (*send);
system.wallet (0)->insert_adhoc (nano::dev::genesis_key.prv);
auto latest_block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key.pub, 100));
ASSERT_NE (nullptr, latest_block);
ASSERT_EQ (nano::dev::constants.genesis_amount - 200, node1.balance (nano::dev::genesis->account ()));
ASSERT_EQ (nano::dev::constants.genesis_amount, node2.balance (nano::dev::genesis->account ()));
ASSERT_TIMELY (10s, node2.balance (nano::dev::genesis->account ()) == nano::dev::constants.genesis_amount - 200);
}
TEST (gap_cache, two_dependencies)
{
nano::test::system system (1);
auto & node1 (*system.nodes[0]);
nano::keypair key;
nano::block_builder builder;
auto send1 = builder
.send ()
.previous (nano::dev::genesis->hash ())
.destination (key.pub)
.balance (1)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (nano::dev::genesis->hash ()))
.build_shared ();
auto send2 = builder
.send ()
.previous (send1->hash ())
.destination (key.pub)
.balance (0)
.sign (nano::dev::genesis_key.prv, nano::dev::genesis_key.pub)
.work (*system.work.generate (send1->hash ()))
.build_shared ();
auto open = builder
.open ()
.source (send1->hash ())
.representative (key.pub)
.account (key.pub)
.sign (key.prv, key.pub)
.work (*system.work.generate (key.pub))
.build_shared ();
ASSERT_EQ (0, node1.gap_cache.size ());
node1.block_processor.add (send2);
node1.block_processor.flush ();
ASSERT_EQ (1, node1.gap_cache.size ());
node1.block_processor.add (open);
node1.block_processor.flush ();
ASSERT_EQ (2, node1.gap_cache.size ());
node1.block_processor.add (send1);
node1.block_processor.flush ();
ASSERT_TIMELY (5s, node1.gap_cache.size () == 0);
ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), send1->hash ()));
ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), send2->hash ()));
ASSERT_TIMELY (5s, node1.store.block.exists (node1.store.tx_begin_read (), open->hash ()));
}