Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/test/processor_tests.cpp
Show First 20 Lines • Show All 624 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE_TEMPLATE(multi_item_register, T, voteItemTestingContexts) { | ||||
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); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(poll_and_response) { | BOOST_AUTO_TEST_CASE_TEMPLATE(poll_and_response, T, voteItemTestingContexts) { | ||||
std::vector<BlockUpdate> updates; | T context(this); | ||||
auto &updates = context.updates; | |||||
const uint32_t invType = context.invType; | |||||
CBlock block = CreateAndProcessBlock({}, CScript()); | const auto item = context.buildVoteItem(); | ||||
const BlockHash blockHash = block.GetHash(); | const auto itemid = context.getVoteItemId(item); | ||||
const CBlockIndex *pindex; | |||||
{ | |||||
LOCK(cs_main); | |||||
pindex = LookupBlockIndex(blockHash); | |||||
} | |||||
// There is no node to query. | // There is no node to query. | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), 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(addNode(avanodeid)); | BOOST_CHECK(addNode(avanodeid)); | ||||
// It returns the avalanche peer. | // It returns the avalanche peer. | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
// Register a block and check it is added to the list of elements to poll. | // Register an item and check it is added to the list of elements to poll. | ||||
BOOST_CHECK(m_processor->addBlockToReconcile(pindex)); | BOOST_CHECK(context.addToReconcile(item)); | ||||
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 == blockHash); | BOOST_CHECK(invs[0].hash == itemid); | ||||
// Trigger a poll on avanode. | // Trigger a poll on avanode. | ||||
uint64_t round = getRound(); | uint64_t round = getRound(); | ||||
runEventLoop(); | runEventLoop(); | ||||
// There is no more suitable peer available, so return nothing. | // There is no more suitable peer available, so return nothing. | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE); | ||||
// Respond to the request. | // Respond to the request. | ||||
Response resp = {round, 0, {Vote(0, blockHash)}}; | Response resp = {round, 0, {Vote(0, itemid)}}; | ||||
BOOST_CHECK(registerVotes(avanodeid, resp, updates)); | BOOST_CHECK(context.registerVotes(avanodeid, resp)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
// Now that avanode fullfilled his request, it is added back to the list of | // Now that avanode fullfilled his request, it is added back to the list of | ||||
// queriable nodes. | // queriable nodes. | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
auto checkRegisterVotesError = [&](NodeId nodeid, | auto checkRegisterVotesError = [&](NodeId nodeid, | ||||
const avalanche::Response &response, | const avalanche::Response &response, | ||||
const std::string &expectedError) { | const std::string &expectedError) { | ||||
int banscore; | |||||
std::string error; | std::string error; | ||||
BOOST_CHECK(!m_processor->registerVotes(nodeid, response, updates, | BOOST_CHECK(!context.registerVotes(nodeid, response, error)); | ||||
banscore, error)); | |||||
BOOST_CHECK_EQUAL(error, expectedError); | BOOST_CHECK_EQUAL(error, expectedError); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
}; | }; | ||||
// Sending a response when not polled fails. | // Sending a response when not polled fails. | ||||
checkRegisterVotesError(avanodeid, next(resp), "unexpected-ava-response"); | checkRegisterVotesError(avanodeid, next(resp), "unexpected-ava-response"); | ||||
// Trigger a poll on avanode. | // Trigger a poll on avanode. | ||||
round = getRound(); | round = getRound(); | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE); | ||||
// Sending responses that do not match the request also fails. | // Sending responses that do not match the request also fails. | ||||
// 1. Too many results. | // 1. Too many results. | ||||
resp = {round, 0, {Vote(0, blockHash), Vote(0, blockHash)}}; | resp = {round, 0, {Vote(0, itemid), Vote(0, itemid)}}; | ||||
runEventLoop(); | runEventLoop(); | ||||
checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size"); | checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size"); | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
// 2. Not enough results. | // 2. Not enough results. | ||||
resp = {getRound(), 0, {}}; | resp = {getRound(), 0, {}}; | ||||
runEventLoop(); | runEventLoop(); | ||||
checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size"); | checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size"); | ||||
Show All 12 Lines | BOOST_AUTO_TEST_CASE_TEMPLATE(poll_and_response, T, voteItemTestingContexts) { | ||||
resp = {queryRound + 1, 0, {Vote()}}; | resp = {queryRound + 1, 0, {Vote()}}; | ||||
checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response"); | checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response"); | ||||
resp = {queryRound - 1, 0, {Vote()}}; | resp = {queryRound - 1, 0, {Vote()}}; | ||||
checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response"); | checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response"); | ||||
// 5. Making request for invalid nodes do not work. Request is not | // 5. Making request for invalid nodes do not work. Request is not | ||||
// discarded. | // discarded. | ||||
resp = {queryRound, 0, {Vote(0, blockHash)}}; | resp = {queryRound, 0, {Vote(0, itemid)}}; | ||||
checkRegisterVotesError(avanodeid + 1234, resp, "unexpected-ava-response"); | checkRegisterVotesError(avanodeid + 1234, resp, "unexpected-ava-response"); | ||||
// Proper response gets processed and avanode is available again. | // Proper response gets processed and avanode is available again. | ||||
resp = {queryRound, 0, {Vote(0, blockHash)}}; | resp = {queryRound, 0, {Vote(0, itemid)}}; | ||||
BOOST_CHECK(registerVotes(avanodeid, resp, updates)); | BOOST_CHECK(context.registerVotes(avanodeid, resp)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
// Out of order response are rejected. | // Out of order response are rejected. | ||||
CBlock block2 = CreateAndProcessBlock({}, CScript()); | const auto item2 = context.buildVoteItem(); | ||||
const BlockHash blockHash2 = block2.GetHash(); | BOOST_CHECK(context.addToReconcile(item2)); | ||||
CBlockIndex *pindex2; | |||||
{ | |||||
LOCK(cs_main); | |||||
pindex2 = LookupBlockIndex(blockHash2); | |||||
} | |||||
BOOST_CHECK(m_processor->addBlockToReconcile(pindex2)); | |||||
resp = {getRound(), 0, {Vote(0, blockHash), Vote(0, blockHash2)}}; | std::vector<Vote> votes = context.buildVotesForItems(0, {item, item2}); | ||||
resp = {getRound(), 0, {votes[1], votes[0]}}; | |||||
runEventLoop(); | runEventLoop(); | ||||
checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-content"); | checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-content"); | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
// But they are accepted in order. | // But they are accepted in order. | ||||
resp = {getRound(), 0, {Vote(0, blockHash2), Vote(0, blockHash)}}; | resp = {getRound(), 0, votes}; | ||||
runEventLoop(); | runEventLoop(); | ||||
BOOST_CHECK(registerVotes(avanodeid, resp, updates)); | BOOST_CHECK(context.registerVotes(avanodeid, resp)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(dont_poll_invalid_block) { | BOOST_AUTO_TEST_CASE(dont_poll_invalid_block) { | ||||
std::vector<BlockUpdate> updates; | std::vector<BlockUpdate> updates; | ||||
CBlock blockA = CreateAndProcessBlock({}, CScript()); | CBlock blockA = CreateAndProcessBlock({}, CScript()); | ||||
▲ Show 20 Lines • Show All 384 Lines • Show Last 20 Lines |