Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/processor_tests.cpp
// Copyright (c) 2018-2020 The Bitcoin developers | // Copyright (c) 2018-2020 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <avalanche/peermanager.h> | #include <avalanche/peermanager.h> | ||||
#include <avalanche/test/util.h> | #include <avalanche/proofbuilder.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <net_processing.h> // For PeerLogicValidation | #include <net_processing.h> // For PeerLogicValidation | ||||
#include <util/time.h> | #include <util/time.h> | ||||
// D6970 moved LookupBlockIndex from chain.h to validation.h TODO: remove this | // D6970 moved LookupBlockIndex from chain.h to validation.h TODO: remove this | ||||
// when LookupBlockIndex is refactored out of validation | // when LookupBlockIndex is refactored out of validation | ||||
#include <validation.h> | #include <validation.h> | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | CService ip(uint32_t i) { | ||||
s.s_addr = i; | s.s_addr = i; | ||||
return CService(CNetAddr(s), Params().GetDefaultPort()); | return CService(CNetAddr(s), Params().GetDefaultPort()); | ||||
} | } | ||||
struct AvalancheTestingSetup : public TestChain100Setup { | struct AvalancheTestingSetup : public TestChain100Setup { | ||||
const Config &config; | const Config &config; | ||||
CConnmanTest *m_connman; | CConnmanTest *m_connman; | ||||
AvalancheTestingSetup() : TestChain100Setup(), config(GetConfig()) { | CKey masterpriv; | ||||
AvalancheTestingSetup() | |||||
: TestChain100Setup(), config(GetConfig()), masterpriv() { | |||||
// Deterministic randomness for tests. | // Deterministic randomness for tests. | ||||
auto connman = std::make_unique<CConnmanTest>(config, 0x1337, 0x1337); | auto connman = std::make_unique<CConnmanTest>(config, 0x1337, 0x1337); | ||||
m_connman = connman.get(); | m_connman = connman.get(); | ||||
m_node.connman = std::move(connman); | m_node.connman = std::move(connman); | ||||
m_node.peer_logic = std::make_unique<PeerLogicValidation>( | m_node.peer_logic = std::make_unique<PeerLogicValidation>( | ||||
m_connman, m_node.banman.get(), *m_node.scheduler); | m_connman, m_node.banman.get(), *m_node.scheduler); | ||||
// The master private key we delegate to. | |||||
masterpriv.MakeNewKey(true); | |||||
} | } | ||||
~AvalancheTestingSetup() { m_connman->ClearNodes(); } | ~AvalancheTestingSetup() { m_connman->ClearNodes(); } | ||||
CNode *ConnectNode(ServiceFlags nServices) { | CNode *ConnectNode(ServiceFlags nServices) { | ||||
static NodeId id = 0; | static NodeId id = 0; | ||||
CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE); | CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE); | ||||
auto node = new CNode(id++, ServiceFlags(NODE_NETWORK), 0, | auto node = new CNode(id++, ServiceFlags(NODE_NETWORK), 0, | ||||
INVALID_SOCKET, addr, 0, 0, CAddress(), "", | INVALID_SOCKET, addr, 0, 0, CAddress(), "", | ||||
/*fInboundIn=*/false); | /*fInboundIn=*/false); | ||||
node->SetSendVersion(PROTOCOL_VERSION); | node->SetSendVersion(PROTOCOL_VERSION); | ||||
node->nServices = nServices; | node->nServices = nServices; | ||||
m_node.peer_logic->InitializeNode(config, node); | m_node.peer_logic->InitializeNode(config, node); | ||||
node->nVersion = 1; | node->nVersion = 1; | ||||
node->fSuccessfullyConnected = true; | node->fSuccessfullyConnected = true; | ||||
m_connman->AddNode(*node); | m_connman->AddNode(*node); | ||||
return node; | return node; | ||||
} | } | ||||
size_t next_coinbase = 0; | |||||
Proof GetProof() { | |||||
size_t current_coinbase = next_coinbase++; | |||||
const CTransaction &coinbase = *m_coinbase_txns[current_coinbase]; | |||||
ProofBuilder pb(0, 0, masterpriv.GetPubKey()); | |||||
BOOST_CHECK(pb.addUTXO(COutPoint(coinbase.GetId(), 0), | |||||
coinbase.vout[0].nValue, current_coinbase + 1, | |||||
true, coinbaseKey)); | |||||
return pb.build(); | |||||
} | |||||
std::array<CNode *, 8> ConnectNodes(Processor &p) { | std::array<CNode *, 8> ConnectNodes(Processor &p) { | ||||
PeerManager &pm = AvalancheTest::getPeerManager(p); | PeerManager &pm = AvalancheTest::getPeerManager(p); | ||||
Proof proof = buildRandomProof(100); | |||||
Proof proof = GetProof(); | |||||
std::array<CNode *, 8> nodes; | std::array<CNode *, 8> nodes; | ||||
for (CNode *&n : nodes) { | for (CNode *&n : nodes) { | ||||
n = ConnectNode(NODE_AVALANCHE); | n = ConnectNode(NODE_AVALANCHE); | ||||
BOOST_CHECK(pm.addNode(n->GetId(), proof, CPubKey())); | BOOST_CHECK(pm.addNode(n->GetId(), proof, masterpriv.GetPubKey())); | ||||
} | } | ||||
return nodes; | return nodes; | ||||
} | } | ||||
}; | }; | ||||
} // namespace | } // namespace | ||||
BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheTestingSetup) | BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheTestingSetup) | ||||
▲ Show 20 Lines • Show All 402 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(poll_and_response) { | ||||
// There is no node to query. | // There is no node to query. | ||||
BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), NO_NODE); | BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), NO_NODE); | ||||
// Create a node that supports avalanche and one that doesn't. | // Create a node that supports avalanche and one that doesn't. | ||||
ConnectNode(NODE_NONE); | ConnectNode(NODE_NONE); | ||||
auto avanode = ConnectNode(NODE_AVALANCHE); | auto avanode = ConnectNode(NODE_AVALANCHE); | ||||
NodeId avanodeid = avanode->GetId(); | NodeId avanodeid = avanode->GetId(); | ||||
BOOST_CHECK(p.addNode(avanodeid, buildRandomProof(100), CPubKey())); | BOOST_CHECK(p.addNode(avanodeid, GetProof(), CPubKey())); | ||||
// It returns the avalanche peer. | // It returns the avalanche peer. | ||||
BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); | BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); | ||||
// Register a block and check it is added to the list of elements to poll. | // Register a block and check it is added to the list of elements to poll. | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex)); | BOOST_CHECK(p.addBlockToReconcile(pindex)); | ||||
auto invs = AvalancheTest::getInvsForNextPoll(p); | auto invs = AvalancheTest::getInvsForNextPoll(p); | ||||
BOOST_CHECK_EQUAL(invs.size(), 1); | BOOST_CHECK_EQUAL(invs.size(), 1); | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(poll_inflight_timeout, *boost::unit_test::timeout(60)) { | ||||
} | } | ||||
// Add the block | // Add the block | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex)); | BOOST_CHECK(p.addBlockToReconcile(pindex)); | ||||
// Create a node that supports avalanche. | // Create a node that supports avalanche. | ||||
auto avanode = ConnectNode(NODE_AVALANCHE); | auto avanode = ConnectNode(NODE_AVALANCHE); | ||||
NodeId avanodeid = avanode->GetId(); | NodeId avanodeid = avanode->GetId(); | ||||
BOOST_CHECK(p.addNode(avanodeid, buildRandomProof(100), CPubKey())); | BOOST_CHECK(p.addNode(avanodeid, GetProof(), CPubKey())); | ||||
// Expire requests after some time. | // Expire requests after some time. | ||||
auto queryTimeDuration = std::chrono::milliseconds(10); | auto queryTimeDuration = std::chrono::milliseconds(10); | ||||
p.setQueryTimeoutDuration(queryTimeDuration); | p.setQueryTimeoutDuration(queryTimeDuration); | ||||
for (int i = 0; i < 10; i++) { | for (int i = 0; i < 10; i++) { | ||||
Response resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; | Response resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; | ||||
auto start = std::chrono::steady_clock::now(); | auto start = std::chrono::steady_clock::now(); | ||||
Show All 23 Lines | BOOST_AUTO_TEST_CASE(poll_inflight_timeout, *boost::unit_test::timeout(60)) { | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(poll_inflight_count) { | BOOST_AUTO_TEST_CASE(poll_inflight_count) { | ||||
Processor p(m_node.connman.get()); | Processor p(m_node.connman.get()); | ||||
// Create enough nodes so that we run into the inflight request limit. | // Create enough nodes so that we run into the inflight request limit. | ||||
PeerManager &pm = AvalancheTest::getPeerManager(p); | PeerManager &pm = AvalancheTest::getPeerManager(p); | ||||
Proof proof = buildRandomProof(100); | Proof proof = GetProof(); | ||||
std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes; | std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes; | ||||
for (auto &n : nodes) { | for (auto &n : nodes) { | ||||
n = ConnectNode(NODE_AVALANCHE); | n = ConnectNode(NODE_AVALANCHE); | ||||
BOOST_CHECK(pm.addNode(n->GetId(), proof, CPubKey())); | BOOST_CHECK(pm.addNode(n->GetId(), proof, CPubKey())); | ||||
} | } | ||||
// Add a block to poll | // Add a block to poll | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(event_loop) { | ||||
BOOST_CHECK(!p.startEventLoop(s)); | BOOST_CHECK(!p.startEventLoop(s)); | ||||
// Start the scheduler thread. | // Start the scheduler thread. | ||||
std::thread schedulerThread(std::bind(&CScheduler::serviceQueue, &s)); | std::thread schedulerThread(std::bind(&CScheduler::serviceQueue, &s)); | ||||
// Create a node that supports avalanche. | // Create a node that supports avalanche. | ||||
auto avanode = ConnectNode(NODE_AVALANCHE); | auto avanode = ConnectNode(NODE_AVALANCHE); | ||||
NodeId nodeid = avanode->GetId(); | NodeId nodeid = avanode->GetId(); | ||||
BOOST_CHECK(p.addNode(nodeid, buildRandomProof(100), CPubKey())); | BOOST_CHECK(p.addNode(nodeid, GetProof(), CPubKey())); | ||||
// There is no query in flight at the moment. | // There is no query in flight at the moment. | ||||
BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), nodeid); | BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), nodeid); | ||||
// Add a new block. Check it is added to the polls. | // Add a new block. Check it is added to the polls. | ||||
uint64_t queryRound = AvalancheTest::getRound(p); | uint64_t queryRound = AvalancheTest::getRound(p); | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex)); | BOOST_CHECK(p.addBlockToReconcile(pindex)); | ||||
▲ Show 20 Lines • Show All 70 Lines • Show Last 20 Lines |