Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/processor_tests.cpp
Show First 20 Lines • Show All 513 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE_TEMPLATE(vote_item_register, T, voteItemTestingContexts) { | ||||
BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid); | BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid); | ||||
updates.clear(); | updates.clear(); | ||||
// Once the decision is finalized, there is no poll for it. | // Once the decision is finalized, there is no poll for it. | ||||
invs = getInvsForNextPoll(); | invs = getInvsForNextPoll(); | ||||
BOOST_CHECK_EQUAL(invs.size(), 0); | BOOST_CHECK_EQUAL(invs.size(), 0); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(multi_block_register) { | BOOST_AUTO_TEST_CASE_TEMPLATE(multi_item_register, T, voteItemTestingContexts) { | ||||
CBlockIndex indexA, indexB; | T context(this); | ||||
auto &updates = context.updates; | |||||
const uint32_t invType = context.invType; | |||||
std::vector<BlockUpdate> updates; | auto itemA = context.buildVoteItem(); | ||||
auto itemidA = context.getVoteItemId(itemA); | |||||
auto itemB = context.buildVoteItem(); | |||||
auto itemidB = context.getVoteItemId(itemB); | |||||
// Create several nodes that support avalanche. | // Create several nodes that support avalanche. | ||||
auto avanodes = ConnectNodes(); | auto avanodes = ConnectNodes(); | ||||
// Make sure the block has a hash. | // Querying for random item returns false. | ||||
CBlock blockA = CreateAndProcessBlock({}, CScript()); | BOOST_CHECK(!m_processor->isAccepted(itemA)); | ||||
const BlockHash blockHashA = blockA.GetHash(); | BOOST_CHECK(!m_processor->isAccepted(itemB)); | ||||
CBlock blockB = CreateAndProcessBlock({}, CScript()); | |||||
const BlockHash blockHashB = blockB.GetHash(); | |||||
const CBlockIndex *pindexA; | |||||
const CBlockIndex *pindexB; | |||||
{ | |||||
LOCK(cs_main); | |||||
pindexA = LookupBlockIndex(blockHashA); | |||||
pindexB = LookupBlockIndex(blockHashB); | |||||
} | |||||
// Querying for random block returns false. | |||||
BOOST_CHECK(!m_processor->isAccepted(pindexA)); | |||||
BOOST_CHECK(!m_processor->isAccepted(pindexB)); | |||||
// Start voting on block A. | // Start voting on item A. | ||||
BOOST_CHECK(m_processor->addBlockToReconcile(pindexA)); | BOOST_CHECK(context.addToReconcile(itemA)); | ||||
auto invs = getInvsForNextPoll(); | auto invs = getInvsForNextPoll(); | ||||
BOOST_CHECK_EQUAL(invs.size(), 1); | BOOST_CHECK_EQUAL(invs.size(), 1); | ||||
BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[0].type, invType); | ||||
BOOST_CHECK(invs[0].hash == blockHashA); | BOOST_CHECK(invs[0].hash == itemidA); | ||||
uint64_t round = getRound(); | uint64_t round = getRound(); | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK(registerVotes(avanodes[0]->GetId(), | BOOST_CHECK(context.registerVotes(avanodes[0]->GetId(), | ||||
{round, 0, {Vote(0, blockHashA)}}, updates)); | {round, 0, {Vote(0, itemidA)}})); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
// Start voting on block B after one vote. | // Start voting on item B after one vote. | ||||
Response resp{round + 1, 0, {Vote(0, blockHashB), Vote(0, blockHashA)}}; | Response resp{round + 1, 0, {Vote(0, itemidB), Vote(0, itemidA)}}; | ||||
BOOST_CHECK(m_processor->addBlockToReconcile(pindexB)); | BOOST_CHECK(context.addToReconcile(itemB)); | ||||
invs = getInvsForNextPoll(); | invs = getInvsForNextPoll(); | ||||
BOOST_CHECK_EQUAL(invs.size(), 2); | BOOST_CHECK_EQUAL(invs.size(), 2); | ||||
if (invType == MSG_BLOCK) { | |||||
// Ensure B comes before A because it has accumulated more PoW. | // Ensure B comes before A because it has accumulated more PoW. | ||||
BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[0].type, invType); | ||||
BOOST_CHECK(invs[0].hash == blockHashB); | BOOST_CHECK(invs[0].hash == itemidB); | ||||
BOOST_CHECK_EQUAL(invs[1].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[1].type, invType); | ||||
BOOST_CHECK(invs[1].hash == blockHashA); | BOOST_CHECK(invs[1].hash == itemidA); | ||||
} | |||||
// Let's vote for these blocks a few times. | // Let's vote for these items a few times. | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
NodeId nodeid = getSuitableNodeToQuery(); | NodeId nodeid = getSuitableNodeToQuery(); | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK(registerVotes(nodeid, next(resp), updates)); | BOOST_CHECK(context.registerVotes(nodeid, next(resp))); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Now it is accepted, but we can vote for it numerous times. | // Now it is accepted, but we can vote for it numerous times. | ||||
for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) { | for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) { | ||||
NodeId nodeid = getSuitableNodeToQuery(); | NodeId nodeid = getSuitableNodeToQuery(); | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK(registerVotes(nodeid, next(resp), updates)); | BOOST_CHECK(context.registerVotes(nodeid, next(resp))); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Running two iterration of the event loop so that vote gets triggered on A | // Running two iterration of the event loop so that vote gets triggered on A | ||||
// and B. | // and B. | ||||
NodeId firstNodeid = getSuitableNodeToQuery(); | NodeId firstNodeid = getSuitableNodeToQuery(); | ||||
runEventLoop(); | runEventLoop(); | ||||
NodeId secondNodeid = getSuitableNodeToQuery(); | NodeId secondNodeid = getSuitableNodeToQuery(); | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK(firstNodeid != secondNodeid); | BOOST_CHECK(firstNodeid != secondNodeid); | ||||
// Next vote will finalize block A. | // Next vote will finalize block A. | ||||
BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates)); | BOOST_CHECK(context.registerVotes(firstNodeid, next(resp))); | ||||
BOOST_CHECK_EQUAL(updates.size(), 1); | BOOST_CHECK_EQUAL(updates.size(), 1); | ||||
BOOST_CHECK(updates[0].getVoteItem() == pindexA); | BOOST_CHECK(updates[0].getVoteItem() == itemA); | ||||
BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized); | BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized); | ||||
updates = {}; | updates = {}; | ||||
// We do not vote on A anymore. | // We do not vote on A anymore. | ||||
invs = getInvsForNextPoll(); | invs = getInvsForNextPoll(); | ||||
BOOST_CHECK_EQUAL(invs.size(), 1); | BOOST_CHECK_EQUAL(invs.size(), 1); | ||||
BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[0].type, invType); | ||||
BOOST_CHECK(invs[0].hash == blockHashB); | BOOST_CHECK(invs[0].hash == itemidB); | ||||
// Next vote will finalize block B. | // Next vote will finalize item B. | ||||
BOOST_CHECK(registerVotes(secondNodeid, resp, updates)); | BOOST_CHECK(context.registerVotes(secondNodeid, resp)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 1); | BOOST_CHECK_EQUAL(updates.size(), 1); | ||||
BOOST_CHECK(updates[0].getVoteItem() == pindexB); | BOOST_CHECK(updates[0].getVoteItem() == itemB); | ||||
BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized); | BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized); | ||||
updates = {}; | updates = {}; | ||||
// There is nothing left to vote on. | // There is nothing left to vote on. | ||||
invs = getInvsForNextPoll(); | invs = getInvsForNextPoll(); | ||||
BOOST_CHECK_EQUAL(invs.size(), 0); | BOOST_CHECK_EQUAL(invs.size(), 0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 463 Lines • Show Last 20 Lines |